diff options
40 files changed, 10146 insertions, 8832 deletions
diff --git a/mesalib/.gitattributes b/mesalib/.gitattributes new file mode 100644 index 000000000..23c6280f6 --- /dev/null +++ b/mesalib/.gitattributes @@ -0,0 +1,4 @@ +*.dsp -crlf +*.dsw -crlf +*.sln -crlf +*.vcproj -crlf diff --git a/mesalib/configure.ac b/mesalib/configure.ac index f19f6478b..dde13c9b5 100644 --- a/mesalib/configure.ac +++ b/mesalib/configure.ac @@ -22,8 +22,8 @@ LIBDRM_REQUIRED=2.4.24 LIBDRM_RADEON_REQUIRED=2.4.24 LIBDRM_INTEL_REQUIRED=2.4.24 LIBDRM_NOUVEAU_REQUIRED=0.6 -DRI2PROTO_REQUIRED=2.1 -GLPROTO_REQUIRED=1.4.11 +DRI2PROTO_REQUIRED=2.6 +GLPROTO_REQUIRED=1.4.14 LIBDRM_XORG_REQUIRED=2.4.24 LIBKMS_XORG_REQUIRED=1.0.0 diff --git a/mesalib/docs/GL3.txt b/mesalib/docs/GL3.txt index 49b48472a..135bc4bab 100644 --- a/mesalib/docs/GL3.txt +++ b/mesalib/docs/GL3.txt @@ -19,7 +19,7 @@ Clamping controls (GL_ARB_color_buffer_float) DONE Float textures, renderbuffers (GL_ARB_texture_float) DONE (gallium r300) GL_EXT_packed_float DONE (gallium r600) GL_EXT_texture_shared_exponent DONE (gallium, swrast) -Float depth buffers (GL_ARB_depth_buffer_float) not started +Float depth buffers (GL_ARB_depth_buffer_float) DONE Framebuffer objects (GL_EXT_framebuffer_object) DONE Half-float DONE Multisample blit DONE diff --git a/mesalib/src/gallium/auxiliary/util/u_pack_color.h b/mesalib/src/gallium/auxiliary/util/u_pack_color.h index c51cc7bcb..9391f1b80 100644 --- a/mesalib/src/gallium/auxiliary/util/u_pack_color.h +++ b/mesalib/src/gallium/auxiliary/util/u_pack_color.h @@ -1,584 +1,648 @@ -/**************************************************************************
- *
- * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- **************************************************************************/
-
-/**
- * @file
- * Functions to produce packed colors/Z from floats.
- */
-
-
-#ifndef U_PACK_COLOR_H
-#define U_PACK_COLOR_H
-
-
-#include "pipe/p_compiler.h"
-#include "pipe/p_format.h"
-#include "util/u_debug.h"
-#include "util/u_format.h"
-#include "util/u_math.h"
-
-
-/**
- * Helper union for packing pixel values.
- * Will often contain values in formats which are too complex to be described
- * in simple terms, hence might just effectively contain a number of bytes.
- * Must be big enough to hold data for all formats (currently 256 bits).
- */
-union util_color {
- ubyte ub;
- ushort us;
- uint ui;
- float f[4];
- double d[4];
-};
-
-/**
- * Pack ubyte R,G,B,A into dest pixel.
- */
-static INLINE void
-util_pack_color_ub(ubyte r, ubyte g, ubyte b, ubyte a,
- enum pipe_format format, union util_color *uc)
-{
- switch (format) {
- case PIPE_FORMAT_A8B8G8R8_UNORM:
- {
- uc->ui = (r << 24) | (g << 16) | (b << 8) | a;
- }
- return;
- case PIPE_FORMAT_X8B8G8R8_UNORM:
- {
- uc->ui = (r << 24) | (g << 16) | (b << 8) | 0xff;
- }
- return;
- case PIPE_FORMAT_B8G8R8A8_UNORM:
- {
- uc->ui = (a << 24) | (r << 16) | (g << 8) | b;
- }
- return;
- case PIPE_FORMAT_B8G8R8X8_UNORM:
- {
- uc->ui = (0xff << 24) | (r << 16) | (g << 8) | b;
- }
- return;
- case PIPE_FORMAT_A8R8G8B8_UNORM:
- {
- uc->ui = (b << 24) | (g << 16) | (r << 8) | a;
- }
- return;
- case PIPE_FORMAT_X8R8G8B8_UNORM:
- {
- uc->ui = (b << 24) | (g << 16) | (r << 8) | 0xff;
- }
- return;
- case PIPE_FORMAT_B5G6R5_UNORM:
- {
- uc->us = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | (b >> 3);
- }
- return;
- case PIPE_FORMAT_B5G5R5X1_UNORM:
- {
- uc->us = ((0x80) << 8) | ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | (b >> 3);
- }
- return;
- case PIPE_FORMAT_B5G5R5A1_UNORM:
- {
- uc->us = ((a & 0x80) << 8) | ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | (b >> 3);
- }
- return;
- case PIPE_FORMAT_B4G4R4A4_UNORM:
- {
- uc->us = ((a & 0xf0) << 8) | ((r & 0xf0) << 4) | ((g & 0xf0) << 0) | (b >> 4);
- }
- return;
- case PIPE_FORMAT_A8_UNORM:
- {
- uc->ub = a;
- }
- return;
- case PIPE_FORMAT_L8_UNORM:
- case PIPE_FORMAT_I8_UNORM:
- {
- uc->ub = a;
- }
- return;
- case PIPE_FORMAT_R32G32B32A32_FLOAT:
- {
- uc->f[0] = (float)r / 255.0f;
- uc->f[1] = (float)g / 255.0f;
- uc->f[2] = (float)b / 255.0f;
- uc->f[3] = (float)a / 255.0f;
- }
- return;
- case PIPE_FORMAT_R32G32B32_FLOAT:
- {
- uc->f[0] = (float)r / 255.0f;
- uc->f[1] = (float)g / 255.0f;
- uc->f[2] = (float)b / 255.0f;
- }
- return;
-
- /* Handle other cases with a generic function.
- */
- default:
- {
- ubyte src[4];
-
- src[0] = r;
- src[1] = g;
- src[2] = b;
- src[3] = a;
- util_format_write_4ub(format, src, 0, uc, 0, 0, 0, 1, 1);
- }
- }
-}
-
-
-/**
- * Unpack RGBA from a packed pixel, returning values as ubytes in [0,255].
- */
-static INLINE void
-util_unpack_color_ub(enum pipe_format format, union util_color *uc,
- ubyte *r, ubyte *g, ubyte *b, ubyte *a)
-{
- switch (format) {
- case PIPE_FORMAT_A8B8G8R8_UNORM:
- {
- uint p = uc->ui;
- *r = (ubyte) ((p >> 24) & 0xff);
- *g = (ubyte) ((p >> 16) & 0xff);
- *b = (ubyte) ((p >> 8) & 0xff);
- *a = (ubyte) ((p >> 0) & 0xff);
- }
- return;
- case PIPE_FORMAT_X8B8G8R8_UNORM:
- {
- uint p = uc->ui;
- *r = (ubyte) ((p >> 24) & 0xff);
- *g = (ubyte) ((p >> 16) & 0xff);
- *b = (ubyte) ((p >> 8) & 0xff);
- *a = (ubyte) 0xff;
- }
- return;
- case PIPE_FORMAT_B8G8R8A8_UNORM:
- {
- uint p = uc->ui;
- *r = (ubyte) ((p >> 16) & 0xff);
- *g = (ubyte) ((p >> 8) & 0xff);
- *b = (ubyte) ((p >> 0) & 0xff);
- *a = (ubyte) ((p >> 24) & 0xff);
- }
- return;
- case PIPE_FORMAT_B8G8R8X8_UNORM:
- {
- uint p = uc->ui;
- *r = (ubyte) ((p >> 16) & 0xff);
- *g = (ubyte) ((p >> 8) & 0xff);
- *b = (ubyte) ((p >> 0) & 0xff);
- *a = (ubyte) 0xff;
- }
- return;
- case PIPE_FORMAT_A8R8G8B8_UNORM:
- {
- uint p = uc->ui;
- *r = (ubyte) ((p >> 8) & 0xff);
- *g = (ubyte) ((p >> 16) & 0xff);
- *b = (ubyte) ((p >> 24) & 0xff);
- *a = (ubyte) ((p >> 0) & 0xff);
- }
- return;
- case PIPE_FORMAT_X8R8G8B8_UNORM:
- {
- uint p = uc->ui;
- *r = (ubyte) ((p >> 8) & 0xff);
- *g = (ubyte) ((p >> 16) & 0xff);
- *b = (ubyte) ((p >> 24) & 0xff);
- *a = (ubyte) 0xff;
- }
- return;
- case PIPE_FORMAT_B5G6R5_UNORM:
- {
- ushort p = uc->us;
- *r = (ubyte) (((p >> 8) & 0xf8) | ((p >> 13) & 0x7));
- *g = (ubyte) (((p >> 3) & 0xfc) | ((p >> 9) & 0x3));
- *b = (ubyte) (((p << 3) & 0xf8) | ((p >> 2) & 0x7));
- *a = (ubyte) 0xff;
- }
- return;
- case PIPE_FORMAT_B5G5R5X1_UNORM:
- {
- ushort p = uc->us;
- *r = (ubyte) (((p >> 7) & 0xf8) | ((p >> 12) & 0x7));
- *g = (ubyte) (((p >> 2) & 0xf8) | ((p >> 7) & 0x7));
- *b = (ubyte) (((p << 3) & 0xf8) | ((p >> 2) & 0x7));
- *a = (ubyte) 0xff;
- }
- return;
- case PIPE_FORMAT_B5G5R5A1_UNORM:
- {
- ushort p = uc->us;
- *r = (ubyte) (((p >> 7) & 0xf8) | ((p >> 12) & 0x7));
- *g = (ubyte) (((p >> 2) & 0xf8) | ((p >> 7) & 0x7));
- *b = (ubyte) (((p << 3) & 0xf8) | ((p >> 2) & 0x7));
- *a = (ubyte) (0xff * (p >> 15));
- }
- return;
- case PIPE_FORMAT_B4G4R4A4_UNORM:
- {
- ushort p = uc->us;
- *r = (ubyte) (((p >> 4) & 0xf0) | ((p >> 8) & 0xf));
- *g = (ubyte) (((p >> 0) & 0xf0) | ((p >> 4) & 0xf));
- *b = (ubyte) (((p << 4) & 0xf0) | ((p >> 0) & 0xf));
- *a = (ubyte) (((p >> 8) & 0xf0) | ((p >> 12) & 0xf));
- }
- return;
- case PIPE_FORMAT_A8_UNORM:
- {
- ubyte p = uc->ub;
- *r = *g = *b = (ubyte) 0xff;
- *a = p;
- }
- return;
- case PIPE_FORMAT_L8_UNORM:
- {
- ubyte p = uc->ub;
- *r = *g = *b = p;
- *a = (ubyte) 0xff;
- }
- return;
- case PIPE_FORMAT_I8_UNORM:
- {
- ubyte p = uc->ub;
- *r = *g = *b = *a = p;
- }
- return;
- case PIPE_FORMAT_R32G32B32A32_FLOAT:
- {
- const float *p = &uc->f[0];
- *r = float_to_ubyte(p[0]);
- *g = float_to_ubyte(p[1]);
- *b = float_to_ubyte(p[2]);
- *a = float_to_ubyte(p[3]);
- }
- return;
- case PIPE_FORMAT_R32G32B32_FLOAT:
- {
- const float *p = &uc->f[0];
- *r = float_to_ubyte(p[0]);
- *g = float_to_ubyte(p[1]);
- *b = float_to_ubyte(p[2]);
- *a = (ubyte) 0xff;
- }
- return;
-
- case PIPE_FORMAT_R32G32_FLOAT:
- {
- const float *p = &uc->f[0];
- *r = float_to_ubyte(p[0]);
- *g = float_to_ubyte(p[1]);
- *b = *a = (ubyte) 0xff;
- }
- return;
-
- case PIPE_FORMAT_R32_FLOAT:
- {
- const float *p = &uc->f[0];
- *r = float_to_ubyte(p[0]);
- *g = *b = *a = (ubyte) 0xff;
- }
- return;
-
- /* Handle other cases with a generic function.
- */
- default:
- {
- ubyte dst[4];
-
- util_format_read_4ub(format, dst, 0, uc, 0, 0, 0, 1, 1);
- *r = dst[0];
- *g = dst[1];
- *b = dst[2];
- *a = dst[3];
- }
- }
-}
-
-
-/**
- * Note rgba outside [0,1] will be clamped for int pixel formats.
- */
-static INLINE void
-util_pack_color(const float rgba[4], enum pipe_format format, union util_color *uc)
-{
- ubyte r = 0;
- ubyte g = 0;
- ubyte b = 0;
- ubyte a = 0;
-
- if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_RGB, 0) <= 8) {
- /* format uses 8-bit components or less */
- r = float_to_ubyte(rgba[0]);
- g = float_to_ubyte(rgba[1]);
- b = float_to_ubyte(rgba[2]);
- a = float_to_ubyte(rgba[3]);
- }
-
- switch (format) {
- case PIPE_FORMAT_A8B8G8R8_UNORM:
- {
- uc->ui = (r << 24) | (g << 16) | (b << 8) | a;
- }
- return;
- case PIPE_FORMAT_X8B8G8R8_UNORM:
- {
- uc->ui = (r << 24) | (g << 16) | (b << 8) | 0xff;
- }
- return;
- case PIPE_FORMAT_B8G8R8A8_UNORM:
- {
- uc->ui = (a << 24) | (r << 16) | (g << 8) | b;
- }
- return;
- case PIPE_FORMAT_B8G8R8X8_UNORM:
- {
- uc->ui = (0xff << 24) | (r << 16) | (g << 8) | b;
- }
- return;
- case PIPE_FORMAT_A8R8G8B8_UNORM:
- {
- uc->ui = (b << 24) | (g << 16) | (r << 8) | a;
- }
- return;
- case PIPE_FORMAT_X8R8G8B8_UNORM:
- {
- uc->ui = (b << 24) | (g << 16) | (r << 8) | 0xff;
- }
- return;
- case PIPE_FORMAT_B5G6R5_UNORM:
- {
- uc->us = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | (b >> 3);
- }
- return;
- case PIPE_FORMAT_B5G5R5X1_UNORM:
- {
- uc->us = ((0x80) << 8) | ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | (b >> 3);
- }
- return;
- case PIPE_FORMAT_B5G5R5A1_UNORM:
- {
- uc->us = ((a & 0x80) << 8) | ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | (b >> 3);
- }
- return;
- case PIPE_FORMAT_B4G4R4A4_UNORM:
- {
- uc->us = ((a & 0xf0) << 8) | ((r & 0xf0) << 4) | ((g & 0xf0) << 0) | (b >> 4);
- }
- return;
- case PIPE_FORMAT_A8_UNORM:
- {
- uc->ub = a;
- }
- return;
- case PIPE_FORMAT_L8_UNORM:
- case PIPE_FORMAT_I8_UNORM:
- {
- uc->ub = r;
- }
- return;
- case PIPE_FORMAT_R32G32B32A32_FLOAT:
- {
- uc->f[0] = rgba[0];
- uc->f[1] = rgba[1];
- uc->f[2] = rgba[2];
- uc->f[3] = rgba[3];
- }
- return;
- case PIPE_FORMAT_R32G32B32_FLOAT:
- {
- uc->f[0] = rgba[0];
- uc->f[1] = rgba[1];
- uc->f[2] = rgba[2];
- }
- return;
-
- /* Handle other cases with a generic function.
- */
- default:
- util_format_write_4f(format, rgba, 0, uc, 0, 0, 0, 1, 1);
- }
-}
-
-/* Integer versions of util_pack_z and util_pack_z_stencil - useful for
- * constructing clear masks.
- */
-static INLINE uint32_t
-util_pack_mask_z(enum pipe_format format, uint32_t z)
-{
- switch (format) {
- case PIPE_FORMAT_Z16_UNORM:
- return z & 0xffff;
- case PIPE_FORMAT_Z32_UNORM:
- case PIPE_FORMAT_Z32_FLOAT:
- return z;
- case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
- case PIPE_FORMAT_Z24X8_UNORM:
- return z & 0xffffff;
- case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
- case PIPE_FORMAT_X8Z24_UNORM:
- return (z & 0xffffff) << 8;
- case PIPE_FORMAT_S8_USCALED:
- return 0;
- default:
- debug_print_format("gallium: unhandled format in util_pack_mask_z()", format);
- assert(0);
- return 0;
- }
-}
-
-static INLINE uint32_t
-util_pack_mask_z_stencil(enum pipe_format format, uint32_t z, uint8_t s)
-{
- uint32_t packed = util_pack_mask_z(format, z);
-
- switch (format) {
- case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
- packed |= (uint32_t)s << 24;
- break;
- case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
- packed |= s;
- break;
- case PIPE_FORMAT_S8_USCALED:
- packed |= s;
- break;
- default:
- break;
- }
-
- return packed;
-}
-
-
-
-/**
- * Note: it's assumed that z is in [0,1]
- */
-static INLINE uint32_t
-util_pack_z(enum pipe_format format, double z)
-{
- union fi fui;
-
- if (z == 0.0)
- return 0;
-
- switch (format) {
- case PIPE_FORMAT_Z16_UNORM:
- if (z == 1.0)
- return 0xffff;
- return (uint32_t) (z * 0xffff);
- case PIPE_FORMAT_Z32_UNORM:
- /* special-case to avoid overflow */
- if (z == 1.0)
- return 0xffffffff;
- return (uint32_t) (z * 0xffffffff);
- case PIPE_FORMAT_Z32_FLOAT:
- fui.f = (float)z;
- return fui.ui;
- case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
- case PIPE_FORMAT_Z24X8_UNORM:
- if (z == 1.0)
- return 0xffffff;
- return (uint32_t) (z * 0xffffff);
- case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
- case PIPE_FORMAT_X8Z24_UNORM:
- if (z == 1.0)
- return 0xffffff00;
- return ((uint32_t) (z * 0xffffff)) << 8;
- case PIPE_FORMAT_S8_USCALED:
- /* this case can get it via util_pack_z_stencil() */
- return 0;
- default:
- debug_print_format("gallium: unhandled format in util_pack_z()", format);
- assert(0);
- return 0;
- }
-}
-
-
-/**
- * Pack Z and/or stencil values into a 32-bit value described by format.
- * Note: it's assumed that z is in [0,1] and s in [0,255]
- */
-static INLINE uint32_t
-util_pack_z_stencil(enum pipe_format format, double z, uint8_t s)
-{
- uint32_t packed = util_pack_z(format, z);
-
- switch (format) {
- case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
- packed |= (uint32_t)s << 24;
- break;
- case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
- packed |= s;
- break;
- case PIPE_FORMAT_S8_USCALED:
- packed |= s;
- break;
- default:
- break;
- }
-
- return packed;
-}
-
-
-/**
- * Pack 4 ubytes into a 4-byte word
- */
-static INLINE unsigned
-pack_ub4(ubyte b0, ubyte b1, ubyte b2, ubyte b3)
-{
- return ((((unsigned int)b0) << 0) |
- (((unsigned int)b1) << 8) |
- (((unsigned int)b2) << 16) |
- (((unsigned int)b3) << 24));
-}
-
-
-/**
- * Pack/convert 4 floats into one 4-byte word.
- */
-static INLINE unsigned
-pack_ui32_float4(float a, float b, float c, float d)
-{
- return pack_ub4( float_to_ubyte(a),
- float_to_ubyte(b),
- float_to_ubyte(c),
- float_to_ubyte(d) );
-}
-
-
-
-#endif /* U_PACK_COLOR_H */
+/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/** + * @file + * Functions to produce packed colors/Z from floats. + */ + + +#ifndef U_PACK_COLOR_H +#define U_PACK_COLOR_H + + +#include "pipe/p_compiler.h" +#include "pipe/p_format.h" +#include "util/u_debug.h" +#include "util/u_format.h" +#include "util/u_math.h" + + +/** + * Helper union for packing pixel values. + * Will often contain values in formats which are too complex to be described + * in simple terms, hence might just effectively contain a number of bytes. + * Must be big enough to hold data for all formats (currently 256 bits). + */ +union util_color { + ubyte ub; + ushort us; + uint ui; + float f[4]; + double d[4]; +}; + +/** + * Pack ubyte R,G,B,A into dest pixel. + */ +static INLINE void +util_pack_color_ub(ubyte r, ubyte g, ubyte b, ubyte a, + enum pipe_format format, union util_color *uc) +{ + switch (format) { + case PIPE_FORMAT_A8B8G8R8_UNORM: + { + uc->ui = (r << 24) | (g << 16) | (b << 8) | a; + } + return; + case PIPE_FORMAT_X8B8G8R8_UNORM: + { + uc->ui = (r << 24) | (g << 16) | (b << 8) | 0xff; + } + return; + case PIPE_FORMAT_B8G8R8A8_UNORM: + { + uc->ui = (a << 24) | (r << 16) | (g << 8) | b; + } + return; + case PIPE_FORMAT_B8G8R8X8_UNORM: + { + uc->ui = (0xff << 24) | (r << 16) | (g << 8) | b; + } + return; + case PIPE_FORMAT_A8R8G8B8_UNORM: + { + uc->ui = (b << 24) | (g << 16) | (r << 8) | a; + } + return; + case PIPE_FORMAT_X8R8G8B8_UNORM: + { + uc->ui = (b << 24) | (g << 16) | (r << 8) | 0xff; + } + return; + case PIPE_FORMAT_B5G6R5_UNORM: + { + uc->us = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | (b >> 3); + } + return; + case PIPE_FORMAT_B5G5R5X1_UNORM: + { + uc->us = ((0x80) << 8) | ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | (b >> 3); + } + return; + case PIPE_FORMAT_B5G5R5A1_UNORM: + { + uc->us = ((a & 0x80) << 8) | ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | (b >> 3); + } + return; + case PIPE_FORMAT_B4G4R4A4_UNORM: + { + uc->us = ((a & 0xf0) << 8) | ((r & 0xf0) << 4) | ((g & 0xf0) << 0) | (b >> 4); + } + return; + case PIPE_FORMAT_A8_UNORM: + { + uc->ub = a; + } + return; + case PIPE_FORMAT_L8_UNORM: + case PIPE_FORMAT_I8_UNORM: + { + uc->ub = a; + } + return; + case PIPE_FORMAT_R32G32B32A32_FLOAT: + { + uc->f[0] = (float)r / 255.0f; + uc->f[1] = (float)g / 255.0f; + uc->f[2] = (float)b / 255.0f; + uc->f[3] = (float)a / 255.0f; + } + return; + case PIPE_FORMAT_R32G32B32_FLOAT: + { + uc->f[0] = (float)r / 255.0f; + uc->f[1] = (float)g / 255.0f; + uc->f[2] = (float)b / 255.0f; + } + return; + + /* Handle other cases with a generic function. + */ + default: + { + ubyte src[4]; + + src[0] = r; + src[1] = g; + src[2] = b; + src[3] = a; + util_format_write_4ub(format, src, 0, uc, 0, 0, 0, 1, 1); + } + } +} + + +/** + * Unpack RGBA from a packed pixel, returning values as ubytes in [0,255]. + */ +static INLINE void +util_unpack_color_ub(enum pipe_format format, union util_color *uc, + ubyte *r, ubyte *g, ubyte *b, ubyte *a) +{ + switch (format) { + case PIPE_FORMAT_A8B8G8R8_UNORM: + { + uint p = uc->ui; + *r = (ubyte) ((p >> 24) & 0xff); + *g = (ubyte) ((p >> 16) & 0xff); + *b = (ubyte) ((p >> 8) & 0xff); + *a = (ubyte) ((p >> 0) & 0xff); + } + return; + case PIPE_FORMAT_X8B8G8R8_UNORM: + { + uint p = uc->ui; + *r = (ubyte) ((p >> 24) & 0xff); + *g = (ubyte) ((p >> 16) & 0xff); + *b = (ubyte) ((p >> 8) & 0xff); + *a = (ubyte) 0xff; + } + return; + case PIPE_FORMAT_B8G8R8A8_UNORM: + { + uint p = uc->ui; + *r = (ubyte) ((p >> 16) & 0xff); + *g = (ubyte) ((p >> 8) & 0xff); + *b = (ubyte) ((p >> 0) & 0xff); + *a = (ubyte) ((p >> 24) & 0xff); + } + return; + case PIPE_FORMAT_B8G8R8X8_UNORM: + { + uint p = uc->ui; + *r = (ubyte) ((p >> 16) & 0xff); + *g = (ubyte) ((p >> 8) & 0xff); + *b = (ubyte) ((p >> 0) & 0xff); + *a = (ubyte) 0xff; + } + return; + case PIPE_FORMAT_A8R8G8B8_UNORM: + { + uint p = uc->ui; + *r = (ubyte) ((p >> 8) & 0xff); + *g = (ubyte) ((p >> 16) & 0xff); + *b = (ubyte) ((p >> 24) & 0xff); + *a = (ubyte) ((p >> 0) & 0xff); + } + return; + case PIPE_FORMAT_X8R8G8B8_UNORM: + { + uint p = uc->ui; + *r = (ubyte) ((p >> 8) & 0xff); + *g = (ubyte) ((p >> 16) & 0xff); + *b = (ubyte) ((p >> 24) & 0xff); + *a = (ubyte) 0xff; + } + return; + case PIPE_FORMAT_B5G6R5_UNORM: + { + ushort p = uc->us; + *r = (ubyte) (((p >> 8) & 0xf8) | ((p >> 13) & 0x7)); + *g = (ubyte) (((p >> 3) & 0xfc) | ((p >> 9) & 0x3)); + *b = (ubyte) (((p << 3) & 0xf8) | ((p >> 2) & 0x7)); + *a = (ubyte) 0xff; + } + return; + case PIPE_FORMAT_B5G5R5X1_UNORM: + { + ushort p = uc->us; + *r = (ubyte) (((p >> 7) & 0xf8) | ((p >> 12) & 0x7)); + *g = (ubyte) (((p >> 2) & 0xf8) | ((p >> 7) & 0x7)); + *b = (ubyte) (((p << 3) & 0xf8) | ((p >> 2) & 0x7)); + *a = (ubyte) 0xff; + } + return; + case PIPE_FORMAT_B5G5R5A1_UNORM: + { + ushort p = uc->us; + *r = (ubyte) (((p >> 7) & 0xf8) | ((p >> 12) & 0x7)); + *g = (ubyte) (((p >> 2) & 0xf8) | ((p >> 7) & 0x7)); + *b = (ubyte) (((p << 3) & 0xf8) | ((p >> 2) & 0x7)); + *a = (ubyte) (0xff * (p >> 15)); + } + return; + case PIPE_FORMAT_B4G4R4A4_UNORM: + { + ushort p = uc->us; + *r = (ubyte) (((p >> 4) & 0xf0) | ((p >> 8) & 0xf)); + *g = (ubyte) (((p >> 0) & 0xf0) | ((p >> 4) & 0xf)); + *b = (ubyte) (((p << 4) & 0xf0) | ((p >> 0) & 0xf)); + *a = (ubyte) (((p >> 8) & 0xf0) | ((p >> 12) & 0xf)); + } + return; + case PIPE_FORMAT_A8_UNORM: + { + ubyte p = uc->ub; + *r = *g = *b = (ubyte) 0xff; + *a = p; + } + return; + case PIPE_FORMAT_L8_UNORM: + { + ubyte p = uc->ub; + *r = *g = *b = p; + *a = (ubyte) 0xff; + } + return; + case PIPE_FORMAT_I8_UNORM: + { + ubyte p = uc->ub; + *r = *g = *b = *a = p; + } + return; + case PIPE_FORMAT_R32G32B32A32_FLOAT: + { + const float *p = &uc->f[0]; + *r = float_to_ubyte(p[0]); + *g = float_to_ubyte(p[1]); + *b = float_to_ubyte(p[2]); + *a = float_to_ubyte(p[3]); + } + return; + case PIPE_FORMAT_R32G32B32_FLOAT: + { + const float *p = &uc->f[0]; + *r = float_to_ubyte(p[0]); + *g = float_to_ubyte(p[1]); + *b = float_to_ubyte(p[2]); + *a = (ubyte) 0xff; + } + return; + + case PIPE_FORMAT_R32G32_FLOAT: + { + const float *p = &uc->f[0]; + *r = float_to_ubyte(p[0]); + *g = float_to_ubyte(p[1]); + *b = *a = (ubyte) 0xff; + } + return; + + case PIPE_FORMAT_R32_FLOAT: + { + const float *p = &uc->f[0]; + *r = float_to_ubyte(p[0]); + *g = *b = *a = (ubyte) 0xff; + } + return; + + /* Handle other cases with a generic function. + */ + default: + { + ubyte dst[4]; + + util_format_read_4ub(format, dst, 0, uc, 0, 0, 0, 1, 1); + *r = dst[0]; + *g = dst[1]; + *b = dst[2]; + *a = dst[3]; + } + } +} + + +/** + * Note rgba outside [0,1] will be clamped for int pixel formats. + */ +static INLINE void +util_pack_color(const float rgba[4], enum pipe_format format, union util_color *uc) +{ + ubyte r = 0; + ubyte g = 0; + ubyte b = 0; + ubyte a = 0; + + if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_RGB, 0) <= 8) { + /* format uses 8-bit components or less */ + r = float_to_ubyte(rgba[0]); + g = float_to_ubyte(rgba[1]); + b = float_to_ubyte(rgba[2]); + a = float_to_ubyte(rgba[3]); + } + + switch (format) { + case PIPE_FORMAT_A8B8G8R8_UNORM: + { + uc->ui = (r << 24) | (g << 16) | (b << 8) | a; + } + return; + case PIPE_FORMAT_X8B8G8R8_UNORM: + { + uc->ui = (r << 24) | (g << 16) | (b << 8) | 0xff; + } + return; + case PIPE_FORMAT_B8G8R8A8_UNORM: + { + uc->ui = (a << 24) | (r << 16) | (g << 8) | b; + } + return; + case PIPE_FORMAT_B8G8R8X8_UNORM: + { + uc->ui = (0xff << 24) | (r << 16) | (g << 8) | b; + } + return; + case PIPE_FORMAT_A8R8G8B8_UNORM: + { + uc->ui = (b << 24) | (g << 16) | (r << 8) | a; + } + return; + case PIPE_FORMAT_X8R8G8B8_UNORM: + { + uc->ui = (b << 24) | (g << 16) | (r << 8) | 0xff; + } + return; + case PIPE_FORMAT_B5G6R5_UNORM: + { + uc->us = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | (b >> 3); + } + return; + case PIPE_FORMAT_B5G5R5X1_UNORM: + { + uc->us = ((0x80) << 8) | ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | (b >> 3); + } + return; + case PIPE_FORMAT_B5G5R5A1_UNORM: + { + uc->us = ((a & 0x80) << 8) | ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | (b >> 3); + } + return; + case PIPE_FORMAT_B4G4R4A4_UNORM: + { + uc->us = ((a & 0xf0) << 8) | ((r & 0xf0) << 4) | ((g & 0xf0) << 0) | (b >> 4); + } + return; + case PIPE_FORMAT_A8_UNORM: + { + uc->ub = a; + } + return; + case PIPE_FORMAT_L8_UNORM: + case PIPE_FORMAT_I8_UNORM: + { + uc->ub = r; + } + return; + case PIPE_FORMAT_R32G32B32A32_FLOAT: + { + uc->f[0] = rgba[0]; + uc->f[1] = rgba[1]; + uc->f[2] = rgba[2]; + uc->f[3] = rgba[3]; + } + return; + case PIPE_FORMAT_R32G32B32_FLOAT: + { + uc->f[0] = rgba[0]; + uc->f[1] = rgba[1]; + uc->f[2] = rgba[2]; + } + return; + + /* Handle other cases with a generic function. + */ + default: + util_format_write_4f(format, rgba, 0, uc, 0, 0, 0, 1, 1); + } +} + +/* Integer versions of util_pack_z and util_pack_z_stencil - useful for + * constructing clear masks. + */ +static INLINE uint32_t +util_pack_mask_z(enum pipe_format format, uint32_t z) +{ + switch (format) { + case PIPE_FORMAT_Z16_UNORM: + return z & 0xffff; + case PIPE_FORMAT_Z32_UNORM: + case PIPE_FORMAT_Z32_FLOAT: + return z; + case PIPE_FORMAT_Z24_UNORM_S8_USCALED: + case PIPE_FORMAT_Z24X8_UNORM: + return z & 0xffffff; + case PIPE_FORMAT_S8_USCALED_Z24_UNORM: + case PIPE_FORMAT_X8Z24_UNORM: + return (z & 0xffffff) << 8; + case PIPE_FORMAT_S8_USCALED: + return 0; + default: + debug_print_format("gallium: unhandled format in util_pack_mask_z()", format); + assert(0); + return 0; + } +} + + +static INLINE uint64_t +util_pack64_mask_z(enum pipe_format format, uint32_t z) +{ + switch (format) { + case PIPE_FORMAT_Z32_FLOAT_S8X24_USCALED: + return z; + default: + return util_pack_mask_z(format, z); + } +} + + +static INLINE uint32_t +util_pack_mask_z_stencil(enum pipe_format format, uint32_t z, uint8_t s) +{ + uint32_t packed = util_pack_mask_z(format, z); + + switch (format) { + case PIPE_FORMAT_Z24_UNORM_S8_USCALED: + packed |= (uint32_t)s << 24; + break; + case PIPE_FORMAT_S8_USCALED_Z24_UNORM: + packed |= s; + break; + case PIPE_FORMAT_S8_USCALED: + packed |= s; + break; + default: + break; + } + + return packed; +} + + +static INLINE uint64_t +util_pack64_mask_z_stencil(enum pipe_format format, uint32_t z, uint8_t s) +{ + uint64_t packed; + + switch (format) { + case PIPE_FORMAT_Z32_FLOAT_S8X24_USCALED: + packed = util_pack64_mask_z(format, z); + packed |= (uint64_t)s << 32ull; + return packed; + default: + return util_pack_mask_z_stencil(format, z, s); + } +} + + +/** + * Note: it's assumed that z is in [0,1] + */ +static INLINE uint32_t +util_pack_z(enum pipe_format format, double z) +{ + union fi fui; + + if (z == 0.0) + return 0; + + switch (format) { + case PIPE_FORMAT_Z16_UNORM: + if (z == 1.0) + return 0xffff; + return (uint32_t) (z * 0xffff); + case PIPE_FORMAT_Z32_UNORM: + /* special-case to avoid overflow */ + if (z == 1.0) + return 0xffffffff; + return (uint32_t) (z * 0xffffffff); + case PIPE_FORMAT_Z32_FLOAT: + fui.f = (float)z; + return fui.ui; + case PIPE_FORMAT_Z24_UNORM_S8_USCALED: + case PIPE_FORMAT_Z24X8_UNORM: + if (z == 1.0) + return 0xffffff; + return (uint32_t) (z * 0xffffff); + case PIPE_FORMAT_S8_USCALED_Z24_UNORM: + case PIPE_FORMAT_X8Z24_UNORM: + if (z == 1.0) + return 0xffffff00; + return ((uint32_t) (z * 0xffffff)) << 8; + case PIPE_FORMAT_S8_USCALED: + /* this case can get it via util_pack_z_stencil() */ + return 0; + default: + debug_print_format("gallium: unhandled format in util_pack_z()", format); + assert(0); + return 0; + } +} + + +static INLINE uint64_t +util_pack64_z(enum pipe_format format, double z) +{ + union fi fui; + + if (z == 0) + return 0; + + switch (format) { + case PIPE_FORMAT_Z32_FLOAT_S8X24_USCALED: + fui.f = (float)z; + return fui.ui; + default: + return util_pack_z(format, z); + } +} + + +/** + * Pack Z and/or stencil values into a 32-bit value described by format. + * Note: it's assumed that z is in [0,1] and s in [0,255] + */ +static INLINE uint32_t +util_pack_z_stencil(enum pipe_format format, double z, uint8_t s) +{ + uint32_t packed = util_pack_z(format, z); + + switch (format) { + case PIPE_FORMAT_Z24_UNORM_S8_USCALED: + packed |= (uint32_t)s << 24; + break; + case PIPE_FORMAT_S8_USCALED_Z24_UNORM: + packed |= s; + break; + case PIPE_FORMAT_S8_USCALED: + packed |= s; + break; + default: + break; + } + + return packed; +} + + +static INLINE uint64_t +util_pack64_z_stencil(enum pipe_format format, double z, uint8_t s) +{ + uint64_t packed; + + switch (format) { + case PIPE_FORMAT_Z32_FLOAT_S8X24_USCALED: + packed = util_pack64_z(format, z); + packed |= (uint64_t)s << 32ull; + break; + default: + return util_pack_z_stencil(format, z, s); + } + + return packed; +} + + +/** + * Pack 4 ubytes into a 4-byte word + */ +static INLINE unsigned +pack_ub4(ubyte b0, ubyte b1, ubyte b2, ubyte b3) +{ + return ((((unsigned int)b0) << 0) | + (((unsigned int)b1) << 8) | + (((unsigned int)b2) << 16) | + (((unsigned int)b3) << 24)); +} + + +/** + * Pack/convert 4 floats into one 4-byte word. + */ +static INLINE unsigned +pack_ui32_float4(float a, float b, float c, float d) +{ + return pack_ub4( float_to_ubyte(a), + float_to_ubyte(b), + float_to_ubyte(c), + float_to_ubyte(d) ); +} + + + +#endif /* U_PACK_COLOR_H */ diff --git a/mesalib/src/gallium/auxiliary/util/u_surface.c b/mesalib/src/gallium/auxiliary/util/u_surface.c index 26f2aee99..8e123867d 100644 --- a/mesalib/src/gallium/auxiliary/util/u_surface.c +++ b/mesalib/src/gallium/auxiliary/util/u_surface.c @@ -1,371 +1,404 @@ -/**************************************************************************
- *
- * Copyright 2009 VMware, Inc. All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- **************************************************************************/
-
-/**
- * @file
- * Surface utility functions.
- *
- * @author Brian Paul
- */
-
-
-#include "pipe/p_defines.h"
-#include "pipe/p_screen.h"
-#include "pipe/p_state.h"
-
-#include "util/u_format.h"
-#include "util/u_inlines.h"
-#include "util/u_rect.h"
-#include "util/u_surface.h"
-#include "util/u_pack_color.h"
-
-void
-u_surface_default_template(struct pipe_surface *view,
- const struct pipe_resource *texture,
- unsigned bind)
-{
- view->format = texture->format;
- view->u.tex.level = 0;
- view->u.tex.first_layer = 0;
- view->u.tex.last_layer = 0;
- /* XXX should filter out all non-rt/ds bind flags ? */
- view->usage = bind;
-}
-
-/**
- * Helper to quickly create an RGBA rendering surface of a certain size.
- * \param textureOut returns the new texture
- * \param surfaceOut returns the new surface
- * \return TRUE for success, FALSE if failure
- */
-boolean
-util_create_rgba_surface(struct pipe_context *pipe,
- uint width, uint height,
- uint bind,
- struct pipe_resource **textureOut,
- struct pipe_surface **surfaceOut)
-{
- static const enum pipe_format rgbaFormats[] = {
- PIPE_FORMAT_B8G8R8A8_UNORM,
- PIPE_FORMAT_A8R8G8B8_UNORM,
- PIPE_FORMAT_A8B8G8R8_UNORM,
- PIPE_FORMAT_NONE
- };
- const uint target = PIPE_TEXTURE_2D;
- enum pipe_format format = PIPE_FORMAT_NONE;
- struct pipe_resource templ;
- struct pipe_surface surf_templ;
- struct pipe_screen *screen = pipe->screen;
- uint i;
-
- /* Choose surface format */
- for (i = 0; rgbaFormats[i]; i++) {
- if (screen->is_format_supported(screen, rgbaFormats[i],
- target, 0, bind)) {
- format = rgbaFormats[i];
- break;
- }
- }
- if (format == PIPE_FORMAT_NONE)
- return FALSE; /* unable to get an rgba format!?! */
-
- /* create texture */
- memset(&templ, 0, sizeof(templ));
- templ.target = target;
- templ.format = format;
- templ.last_level = 0;
- templ.width0 = width;
- templ.height0 = height;
- templ.depth0 = 1;
- templ.array_size = 1;
- templ.bind = bind;
-
- *textureOut = screen->resource_create(screen, &templ);
- if (!*textureOut)
- return FALSE;
-
- /* create surface */
- memset(&surf_templ, 0, sizeof(surf_templ));
- u_surface_default_template(&surf_templ, *textureOut, bind);
- /* create surface / view into texture */
- *surfaceOut = pipe->create_surface(pipe,
- *textureOut,
- &surf_templ);
- if (!*surfaceOut) {
- pipe_resource_reference(textureOut, NULL);
- return FALSE;
- }
-
- return TRUE;
-}
-
-
-/**
- * Release the surface and texture from util_create_rgba_surface().
- */
-void
-util_destroy_rgba_surface(struct pipe_resource *texture,
- struct pipe_surface *surface)
-{
- pipe_surface_reference(&surface, NULL);
- pipe_resource_reference(&texture, NULL);
-}
-
-
-
-/**
- * Fallback function for pipe->resource_copy_region().
- * Note: (X,Y)=(0,0) is always the upper-left corner.
- */
-void
-util_resource_copy_region(struct pipe_context *pipe,
- struct pipe_resource *dst,
- unsigned dst_level,
- unsigned dst_x, unsigned dst_y, unsigned dst_z,
- struct pipe_resource *src,
- unsigned src_level,
- const struct pipe_box *src_box)
-{
- struct pipe_transfer *src_trans, *dst_trans;
- void *dst_map;
- const void *src_map;
- enum pipe_format src_format, dst_format;
- unsigned w = src_box->width;
- unsigned h = src_box->height;
-
- assert(src && dst);
- assert((src->target == PIPE_BUFFER && dst->target == PIPE_BUFFER) ||
- (src->target != PIPE_BUFFER && dst->target != PIPE_BUFFER));
-
- if (!src || !dst)
- return;
-
- src_format = src->format;
- dst_format = dst->format;
-
- src_trans = pipe_get_transfer(pipe,
- src,
- src_level,
- src_box->z,
- PIPE_TRANSFER_READ,
- src_box->x, src_box->y, w, h);
-
- dst_trans = pipe_get_transfer(pipe,
- dst,
- dst_level,
- dst_z,
- PIPE_TRANSFER_WRITE,
- dst_x, dst_y, w, h);
-
- assert(util_format_get_blocksize(dst_format) == util_format_get_blocksize(src_format));
- assert(util_format_get_blockwidth(dst_format) == util_format_get_blockwidth(src_format));
- assert(util_format_get_blockheight(dst_format) == util_format_get_blockheight(src_format));
-
- src_map = pipe->transfer_map(pipe, src_trans);
- dst_map = pipe->transfer_map(pipe, dst_trans);
-
- assert(src_map);
- assert(dst_map);
-
- if (src_map && dst_map) {
- if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) {
- memcpy(dst_map, src_map, w);
- } else {
- util_copy_rect(dst_map,
- dst_format,
- dst_trans->stride,
- 0, 0,
- w, h,
- src_map,
- src_trans->stride,
- 0,
- 0);
- }
- }
-
- pipe->transfer_unmap(pipe, src_trans);
- pipe->transfer_unmap(pipe, dst_trans);
-
- pipe->transfer_destroy(pipe, src_trans);
- pipe->transfer_destroy(pipe, dst_trans);
-}
-
-
-
-#define UBYTE_TO_USHORT(B) ((B) | ((B) << 8))
-
-
-/**
- * Fallback for pipe->clear_render_target() function.
- * XXX this looks too hackish to be really useful.
- * cpp > 4 looks like a gross hack at best...
- * Plus can't use these transfer fallbacks when clearing
- * multisampled surfaces for instance.
- */
-void
-util_clear_render_target(struct pipe_context *pipe,
- struct pipe_surface *dst,
- const float *rgba,
- unsigned dstx, unsigned dsty,
- unsigned width, unsigned height)
-{
- struct pipe_transfer *dst_trans;
- void *dst_map;
- union util_color uc;
-
- assert(dst->texture);
- if (!dst->texture)
- return;
- /* XXX: should handle multiple layers */
- dst_trans = pipe_get_transfer(pipe,
- dst->texture,
- dst->u.tex.level,
- dst->u.tex.first_layer,
- PIPE_TRANSFER_WRITE,
- dstx, dsty, width, height);
-
- dst_map = pipe->transfer_map(pipe, dst_trans);
-
- assert(dst_map);
-
- if (dst_map) {
- assert(dst_trans->stride > 0);
-
- util_pack_color(rgba, dst->texture->format, &uc);
- util_fill_rect(dst_map, dst->texture->format,
- dst_trans->stride,
- 0, 0, width, height, &uc);
- }
-
- pipe->transfer_unmap(pipe, dst_trans);
- pipe->transfer_destroy(pipe, dst_trans);
-}
-
-/**
- * Fallback for pipe->clear_stencil() function.
- * sw fallback doesn't look terribly useful here.
- * Plus can't use these transfer fallbacks when clearing
- * multisampled surfaces for instance.
- */
-void
-util_clear_depth_stencil(struct pipe_context *pipe,
- struct pipe_surface *dst,
- unsigned clear_flags,
- double depth,
- unsigned stencil,
- unsigned dstx, unsigned dsty,
- unsigned width, unsigned height)
-{
- struct pipe_transfer *dst_trans;
- ubyte *dst_map;
- boolean need_rmw = FALSE;
-
- if ((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) &&
- ((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) != PIPE_CLEAR_DEPTHSTENCIL) &&
- util_format_is_depth_and_stencil(dst->format))
- need_rmw = TRUE;
-
- assert(dst->texture);
- if (!dst->texture)
- return;
- dst_trans = pipe_get_transfer(pipe,
- dst->texture,
- dst->u.tex.level,
- dst->u.tex.first_layer,
- (need_rmw ? PIPE_TRANSFER_READ_WRITE :
- PIPE_TRANSFER_WRITE),
- dstx, dsty, width, height);
-
- dst_map = pipe->transfer_map(pipe, dst_trans);
-
- assert(dst_map);
-
- if (dst_map) {
- unsigned dst_stride = dst_trans->stride;
- unsigned zstencil = util_pack_z_stencil(dst->texture->format, depth, stencil);
- unsigned i, j;
- assert(dst_trans->stride > 0);
-
- switch (util_format_get_blocksize(dst->format)) {
- case 1:
- assert(dst->format == PIPE_FORMAT_S8_USCALED);
- if(dst_stride == width)
- memset(dst_map, (ubyte) zstencil, height * width);
- else {
- for (i = 0; i < height; i++) {
- memset(dst_map, (ubyte) zstencil, width);
- dst_map += dst_stride;
- }
- }
- break;
- case 2:
- assert(dst->format == PIPE_FORMAT_Z16_UNORM);
- for (i = 0; i < height; i++) {
- uint16_t *row = (uint16_t *)dst_map;
- for (j = 0; j < width; j++)
- *row++ = (uint16_t) zstencil;
- dst_map += dst_stride;
- }
- break;
- case 4:
- if (!need_rmw) {
- for (i = 0; i < height; i++) {
- uint32_t *row = (uint32_t *)dst_map;
- for (j = 0; j < width; j++)
- *row++ = zstencil;
- dst_map += dst_stride;
- }
- }
- else {
- uint32_t dst_mask;
- if (dst->format == PIPE_FORMAT_Z24_UNORM_S8_USCALED)
- dst_mask = 0xffffff00;
- else {
- assert(dst->format == PIPE_FORMAT_S8_USCALED_Z24_UNORM);
- dst_mask = 0xffffff;
- }
- if (clear_flags & PIPE_CLEAR_DEPTH)
- dst_mask = ~dst_mask;
- for (i = 0; i < height; i++) {
- uint32_t *row = (uint32_t *)dst_map;
- for (j = 0; j < width; j++) {
- uint32_t tmp = *row & dst_mask;
- *row++ = tmp | (zstencil & ~dst_mask);
- }
- dst_map += dst_stride;
- }
- }
- break;
- case 8:
- default:
- assert(0);
- break;
- }
- }
-
- pipe->transfer_unmap(pipe, dst_trans);
- pipe->transfer_destroy(pipe, dst_trans);
-}
+/************************************************************************** + * + * Copyright 2009 VMware, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/** + * @file + * Surface utility functions. + * + * @author Brian Paul + */ + + +#include "pipe/p_defines.h" +#include "pipe/p_screen.h" +#include "pipe/p_state.h" + +#include "util/u_format.h" +#include "util/u_inlines.h" +#include "util/u_rect.h" +#include "util/u_surface.h" +#include "util/u_pack_color.h" + +void +u_surface_default_template(struct pipe_surface *view, + const struct pipe_resource *texture, + unsigned bind) +{ + view->format = texture->format; + view->u.tex.level = 0; + view->u.tex.first_layer = 0; + view->u.tex.last_layer = 0; + /* XXX should filter out all non-rt/ds bind flags ? */ + view->usage = bind; +} + +/** + * Helper to quickly create an RGBA rendering surface of a certain size. + * \param textureOut returns the new texture + * \param surfaceOut returns the new surface + * \return TRUE for success, FALSE if failure + */ +boolean +util_create_rgba_surface(struct pipe_context *pipe, + uint width, uint height, + uint bind, + struct pipe_resource **textureOut, + struct pipe_surface **surfaceOut) +{ + static const enum pipe_format rgbaFormats[] = { + PIPE_FORMAT_B8G8R8A8_UNORM, + PIPE_FORMAT_A8R8G8B8_UNORM, + PIPE_FORMAT_A8B8G8R8_UNORM, + PIPE_FORMAT_NONE + }; + const uint target = PIPE_TEXTURE_2D; + enum pipe_format format = PIPE_FORMAT_NONE; + struct pipe_resource templ; + struct pipe_surface surf_templ; + struct pipe_screen *screen = pipe->screen; + uint i; + + /* Choose surface format */ + for (i = 0; rgbaFormats[i]; i++) { + if (screen->is_format_supported(screen, rgbaFormats[i], + target, 0, bind)) { + format = rgbaFormats[i]; + break; + } + } + if (format == PIPE_FORMAT_NONE) + return FALSE; /* unable to get an rgba format!?! */ + + /* create texture */ + memset(&templ, 0, sizeof(templ)); + templ.target = target; + templ.format = format; + templ.last_level = 0; + templ.width0 = width; + templ.height0 = height; + templ.depth0 = 1; + templ.array_size = 1; + templ.bind = bind; + + *textureOut = screen->resource_create(screen, &templ); + if (!*textureOut) + return FALSE; + + /* create surface */ + memset(&surf_templ, 0, sizeof(surf_templ)); + u_surface_default_template(&surf_templ, *textureOut, bind); + /* create surface / view into texture */ + *surfaceOut = pipe->create_surface(pipe, + *textureOut, + &surf_templ); + if (!*surfaceOut) { + pipe_resource_reference(textureOut, NULL); + return FALSE; + } + + return TRUE; +} + + +/** + * Release the surface and texture from util_create_rgba_surface(). + */ +void +util_destroy_rgba_surface(struct pipe_resource *texture, + struct pipe_surface *surface) +{ + pipe_surface_reference(&surface, NULL); + pipe_resource_reference(&texture, NULL); +} + + + +/** + * Fallback function for pipe->resource_copy_region(). + * Note: (X,Y)=(0,0) is always the upper-left corner. + */ +void +util_resource_copy_region(struct pipe_context *pipe, + struct pipe_resource *dst, + unsigned dst_level, + unsigned dst_x, unsigned dst_y, unsigned dst_z, + struct pipe_resource *src, + unsigned src_level, + const struct pipe_box *src_box) +{ + struct pipe_transfer *src_trans, *dst_trans; + void *dst_map; + const void *src_map; + enum pipe_format src_format, dst_format; + unsigned w = src_box->width; + unsigned h = src_box->height; + + assert(src && dst); + assert((src->target == PIPE_BUFFER && dst->target == PIPE_BUFFER) || + (src->target != PIPE_BUFFER && dst->target != PIPE_BUFFER)); + + if (!src || !dst) + return; + + src_format = src->format; + dst_format = dst->format; + + src_trans = pipe_get_transfer(pipe, + src, + src_level, + src_box->z, + PIPE_TRANSFER_READ, + src_box->x, src_box->y, w, h); + + dst_trans = pipe_get_transfer(pipe, + dst, + dst_level, + dst_z, + PIPE_TRANSFER_WRITE, + dst_x, dst_y, w, h); + + assert(util_format_get_blocksize(dst_format) == util_format_get_blocksize(src_format)); + assert(util_format_get_blockwidth(dst_format) == util_format_get_blockwidth(src_format)); + assert(util_format_get_blockheight(dst_format) == util_format_get_blockheight(src_format)); + + src_map = pipe->transfer_map(pipe, src_trans); + dst_map = pipe->transfer_map(pipe, dst_trans); + + assert(src_map); + assert(dst_map); + + if (src_map && dst_map) { + if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) { + memcpy(dst_map, src_map, w); + } else { + util_copy_rect(dst_map, + dst_format, + dst_trans->stride, + 0, 0, + w, h, + src_map, + src_trans->stride, + 0, + 0); + } + } + + pipe->transfer_unmap(pipe, src_trans); + pipe->transfer_unmap(pipe, dst_trans); + + pipe->transfer_destroy(pipe, src_trans); + pipe->transfer_destroy(pipe, dst_trans); +} + + + +#define UBYTE_TO_USHORT(B) ((B) | ((B) << 8)) + + +/** + * Fallback for pipe->clear_render_target() function. + * XXX this looks too hackish to be really useful. + * cpp > 4 looks like a gross hack at best... + * Plus can't use these transfer fallbacks when clearing + * multisampled surfaces for instance. + */ +void +util_clear_render_target(struct pipe_context *pipe, + struct pipe_surface *dst, + const float *rgba, + unsigned dstx, unsigned dsty, + unsigned width, unsigned height) +{ + struct pipe_transfer *dst_trans; + void *dst_map; + union util_color uc; + + assert(dst->texture); + if (!dst->texture) + return; + /* XXX: should handle multiple layers */ + dst_trans = pipe_get_transfer(pipe, + dst->texture, + dst->u.tex.level, + dst->u.tex.first_layer, + PIPE_TRANSFER_WRITE, + dstx, dsty, width, height); + + dst_map = pipe->transfer_map(pipe, dst_trans); + + assert(dst_map); + + if (dst_map) { + assert(dst_trans->stride > 0); + + util_pack_color(rgba, dst->texture->format, &uc); + util_fill_rect(dst_map, dst->texture->format, + dst_trans->stride, + 0, 0, width, height, &uc); + } + + pipe->transfer_unmap(pipe, dst_trans); + pipe->transfer_destroy(pipe, dst_trans); +} + +/** + * Fallback for pipe->clear_stencil() function. + * sw fallback doesn't look terribly useful here. + * Plus can't use these transfer fallbacks when clearing + * multisampled surfaces for instance. + */ +void +util_clear_depth_stencil(struct pipe_context *pipe, + struct pipe_surface *dst, + unsigned clear_flags, + double depth, + unsigned stencil, + unsigned dstx, unsigned dsty, + unsigned width, unsigned height) +{ + struct pipe_transfer *dst_trans; + ubyte *dst_map; + boolean need_rmw = FALSE; + + if ((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) && + ((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) != PIPE_CLEAR_DEPTHSTENCIL) && + util_format_is_depth_and_stencil(dst->format)) + need_rmw = TRUE; + + assert(dst->texture); + if (!dst->texture) + return; + dst_trans = pipe_get_transfer(pipe, + dst->texture, + dst->u.tex.level, + dst->u.tex.first_layer, + (need_rmw ? PIPE_TRANSFER_READ_WRITE : + PIPE_TRANSFER_WRITE), + dstx, dsty, width, height); + + dst_map = pipe->transfer_map(pipe, dst_trans); + + assert(dst_map); + + if (dst_map) { + unsigned dst_stride = dst_trans->stride; + unsigned zstencil = util_pack_z_stencil(dst->texture->format, depth, stencil); + unsigned i, j; + assert(dst_trans->stride > 0); + + switch (util_format_get_blocksize(dst->format)) { + case 1: + assert(dst->format == PIPE_FORMAT_S8_USCALED); + if(dst_stride == width) + memset(dst_map, (ubyte) zstencil, height * width); + else { + for (i = 0; i < height; i++) { + memset(dst_map, (ubyte) zstencil, width); + dst_map += dst_stride; + } + } + break; + case 2: + assert(dst->format == PIPE_FORMAT_Z16_UNORM); + for (i = 0; i < height; i++) { + uint16_t *row = (uint16_t *)dst_map; + for (j = 0; j < width; j++) + *row++ = (uint16_t) zstencil; + dst_map += dst_stride; + } + break; + case 4: + if (!need_rmw) { + for (i = 0; i < height; i++) { + uint32_t *row = (uint32_t *)dst_map; + for (j = 0; j < width; j++) + *row++ = zstencil; + dst_map += dst_stride; + } + } + else { + uint32_t dst_mask; + if (dst->format == PIPE_FORMAT_Z24_UNORM_S8_USCALED) + dst_mask = 0xffffff00; + else { + assert(dst->format == PIPE_FORMAT_S8_USCALED_Z24_UNORM); + dst_mask = 0xffffff; + } + if (clear_flags & PIPE_CLEAR_DEPTH) + dst_mask = ~dst_mask; + for (i = 0; i < height; i++) { + uint32_t *row = (uint32_t *)dst_map; + for (j = 0; j < width; j++) { + uint32_t tmp = *row & dst_mask; + *row++ = tmp | (zstencil & ~dst_mask); + } + dst_map += dst_stride; + } + } + break; + case 8: + { + uint64_t zstencil = util_pack64_z_stencil(dst->texture->format, + depth, stencil); + + assert(dst->format == PIPE_FORMAT_Z32_FLOAT_S8X24_USCALED); + + if (!need_rmw) { + for (i = 0; i < height; i++) { + uint64_t *row = (uint64_t *)dst_map; + for (j = 0; j < width; j++) + *row++ = zstencil; + dst_map += dst_stride; + } + } + else { + uint64_t src_mask; + + if (clear_flags & PIPE_CLEAR_DEPTH) + src_mask = 0x00000000ffffffffull; + else + src_mask = 0x000000ff00000000ull; + + for (i = 0; i < height; i++) { + uint64_t *row = (uint64_t *)dst_map; + for (j = 0; j < width; j++) { + uint64_t tmp = *row & ~src_mask; + *row++ = tmp | (zstencil & src_mask); + } + dst_map += dst_stride; + } + } + break; + } + default: + assert(0); + break; + } + } + + pipe->transfer_unmap(pipe, dst_trans); + pipe->transfer_destroy(pipe, dst_trans); +} diff --git a/mesalib/src/gallium/auxiliary/util/u_tile.c b/mesalib/src/gallium/auxiliary/util/u_tile.c index 54f634948..23f12e5f4 100644 --- a/mesalib/src/gallium/auxiliary/util/u_tile.c +++ b/mesalib/src/gallium/auxiliary/util/u_tile.c @@ -1,655 +1,690 @@ -/**************************************************************************
- *
- * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- **************************************************************************/
-
-/**
- * RGBA/float tile get/put functions.
- * Usable both by drivers and state trackers.
- */
-
-
-#include "pipe/p_defines.h"
-#include "util/u_inlines.h"
-
-#include "util/u_format.h"
-#include "util/u_math.h"
-#include "util/u_memory.h"
-#include "util/u_rect.h"
-#include "util/u_tile.h"
-
-
-/**
- * Move raw block of pixels from transfer object to user memory.
- */
-void
-pipe_get_tile_raw(struct pipe_context *pipe,
- struct pipe_transfer *pt,
- uint x, uint y, uint w, uint h,
- void *dst, int dst_stride)
-{
- const void *src;
-
- if (dst_stride == 0)
- dst_stride = util_format_get_stride(pt->resource->format, w);
-
- if (u_clip_tile(x, y, &w, &h, &pt->box))
- return;
-
- src = pipe->transfer_map(pipe, pt);
- assert(src);
- if(!src)
- return;
-
- util_copy_rect(dst, pt->resource->format, dst_stride, 0, 0, w, h, src, pt->stride, x, y);
-
- pipe->transfer_unmap(pipe, pt);
-}
-
-
-/**
- * Move raw block of pixels from user memory to transfer object.
- */
-void
-pipe_put_tile_raw(struct pipe_context *pipe,
- struct pipe_transfer *pt,
- uint x, uint y, uint w, uint h,
- const void *src, int src_stride)
-{
- void *dst;
- enum pipe_format format = pt->resource->format;
-
- if (src_stride == 0)
- src_stride = util_format_get_stride(format, w);
-
- if (u_clip_tile(x, y, &w, &h, &pt->box))
- return;
-
- dst = pipe->transfer_map(pipe, pt);
- assert(dst);
- if(!dst)
- return;
-
- util_copy_rect(dst, format, pt->stride, x, y, w, h, src, src_stride, 0, 0);
-
- pipe->transfer_unmap(pipe, pt);
-}
-
-
-
-
-/** Convert short in [-32768,32767] to GLfloat in [-1.0,1.0] */
-#define SHORT_TO_FLOAT(S) ((2.0F * (S) + 1.0F) * (1.0F/65535.0F))
-
-#define UNCLAMPED_FLOAT_TO_SHORT(us, f) \
- us = ( (short) ( CLAMP((f), -1.0, 1.0) * 32767.0F) )
-
-
-
-/*** PIPE_FORMAT_Z16_UNORM ***/
-
-/**
- * Return each Z value as four floats in [0,1].
- */
-static void
-z16_get_tile_rgba(const ushort *src,
- unsigned w, unsigned h,
- float *p,
- unsigned dst_stride)
-{
- const float scale = 1.0f / 65535.0f;
- unsigned i, j;
-
- for (i = 0; i < h; i++) {
- float *pRow = p;
- for (j = 0; j < w; j++, pRow += 4) {
- pRow[0] =
- pRow[1] =
- pRow[2] =
- pRow[3] = *src++ * scale;
- }
- p += dst_stride;
- }
-}
-
-
-
-
-/*** PIPE_FORMAT_Z32_UNORM ***/
-
-/**
- * Return each Z value as four floats in [0,1].
- */
-static void
-z32_get_tile_rgba(const unsigned *src,
- unsigned w, unsigned h,
- float *p,
- unsigned dst_stride)
-{
- const double scale = 1.0 / (double) 0xffffffff;
- unsigned i, j;
-
- for (i = 0; i < h; i++) {
- float *pRow = p;
- for (j = 0; j < w; j++, pRow += 4) {
- pRow[0] =
- pRow[1] =
- pRow[2] =
- pRow[3] = (float) (*src++ * scale);
- }
- p += dst_stride;
- }
-}
-
-
-/*** PIPE_FORMAT_Z24_UNORM_S8_USCALED ***/
-
-/**
- * Return Z component as four float in [0,1]. Stencil part ignored.
- */
-static void
-s8z24_get_tile_rgba(const unsigned *src,
- unsigned w, unsigned h,
- float *p,
- unsigned dst_stride)
-{
- const double scale = 1.0 / ((1 << 24) - 1);
- unsigned i, j;
-
- for (i = 0; i < h; i++) {
- float *pRow = p;
- for (j = 0; j < w; j++, pRow += 4) {
- pRow[0] =
- pRow[1] =
- pRow[2] =
- pRow[3] = (float) (scale * (*src++ & 0xffffff));
- }
- p += dst_stride;
- }
-}
-
-
-/*** PIPE_FORMAT_S8_USCALED_Z24_UNORM ***/
-
-/**
- * Return Z component as four float in [0,1]. Stencil part ignored.
- */
-static void
-z24s8_get_tile_rgba(const unsigned *src,
- unsigned w, unsigned h,
- float *p,
- unsigned dst_stride)
-{
- const double scale = 1.0 / ((1 << 24) - 1);
- unsigned i, j;
-
- for (i = 0; i < h; i++) {
- float *pRow = p;
- for (j = 0; j < w; j++, pRow += 4) {
- pRow[0] =
- pRow[1] =
- pRow[2] =
- pRow[3] = (float) (scale * (*src++ >> 8));
- }
- p += dst_stride;
- }
-}
-
-/*** PIPE_FORMAT_S8X24_USCALED ***/
-
-/**
- * Return S component as four uint32_t in [0..255]. Z part ignored.
- */
-static void
-s8x24_get_tile_rgba(const unsigned *src,
- unsigned w, unsigned h,
- float *p,
- unsigned dst_stride)
-{
- unsigned i, j;
-
- for (i = 0; i < h; i++) {
- float *pRow = p;
-
- for (j = 0; j < w; j++, pRow += 4) {
- pRow[0] =
- pRow[1] =
- pRow[2] =
- pRow[3] = (float)((*src++ >> 24) & 0xff);
- }
-
- p += dst_stride;
- }
-}
-
-/*** PIPE_FORMAT_X24S8_USCALED ***/
-
-/**
- * Return S component as four uint32_t in [0..255]. Z part ignored.
- */
-static void
-x24s8_get_tile_rgba(const unsigned *src,
- unsigned w, unsigned h,
- float *p,
- unsigned dst_stride)
-{
- unsigned i, j;
-
- for (i = 0; i < h; i++) {
- float *pRow = p;
- for (j = 0; j < w; j++, pRow += 4) {
- pRow[0] =
- pRow[1] =
- pRow[2] =
- pRow[3] = (float)(*src++ & 0xff);
- }
- p += dst_stride;
- }
-}
-
-
-/**
- * Return S component as four uint32_t in [0..255]. Z part ignored.
- */
-static void
-s8_get_tile_rgba(const unsigned char *src,
- unsigned w, unsigned h,
- float *p,
- unsigned dst_stride)
-{
- unsigned i, j;
-
- for (i = 0; i < h; i++) {
- float *pRow = p;
- for (j = 0; j < w; j++, pRow += 4) {
- pRow[0] =
- pRow[1] =
- pRow[2] =
- pRow[3] = (float)(*src++ & 0xff);
- }
- p += dst_stride;
- }
-}
-
-/*** PIPE_FORMAT_Z32_FLOAT ***/
-
-/**
- * Return each Z value as four floats in [0,1].
- */
-static void
-z32f_get_tile_rgba(const float *src,
- unsigned w, unsigned h,
- float *p,
- unsigned dst_stride)
-{
- unsigned i, j;
-
- for (i = 0; i < h; i++) {
- float *pRow = p;
- for (j = 0; j < w; j++, pRow += 4) {
- pRow[0] =
- pRow[1] =
- pRow[2] =
- pRow[3] = *src++;
- }
- p += dst_stride;
- }
-}
-
-
-void
-pipe_tile_raw_to_rgba(enum pipe_format format,
- void *src,
- uint w, uint h,
- float *dst, unsigned dst_stride)
-{
- switch (format) {
- case PIPE_FORMAT_Z16_UNORM:
- z16_get_tile_rgba((ushort *) src, w, h, dst, dst_stride);
- break;
- case PIPE_FORMAT_Z32_UNORM:
- z32_get_tile_rgba((unsigned *) src, w, h, dst, dst_stride);
- break;
- case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
- case PIPE_FORMAT_Z24X8_UNORM:
- s8z24_get_tile_rgba((unsigned *) src, w, h, dst, dst_stride);
- break;
- case PIPE_FORMAT_S8_USCALED:
- s8_get_tile_rgba((unsigned char *) src, w, h, dst, dst_stride);
- break;
- case PIPE_FORMAT_X24S8_USCALED:
- s8x24_get_tile_rgba((unsigned *) src, w, h, dst, dst_stride);
- break;
- case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
- case PIPE_FORMAT_X8Z24_UNORM:
- z24s8_get_tile_rgba((unsigned *) src, w, h, dst, dst_stride);
- break;
- case PIPE_FORMAT_S8X24_USCALED:
- x24s8_get_tile_rgba((unsigned *) src, w, h, dst, dst_stride);
- break;
- case PIPE_FORMAT_Z32_FLOAT:
- z32f_get_tile_rgba((float *) src, w, h, dst, dst_stride);
- break;
- default:
- util_format_read_4f(format,
- dst, dst_stride * sizeof(float),
- src, util_format_get_stride(format, w),
- 0, 0, w, h);
- }
-}
-
-
-void
-pipe_get_tile_rgba(struct pipe_context *pipe,
- struct pipe_transfer *pt,
- uint x, uint y, uint w, uint h,
- float *p)
-{
- pipe_get_tile_rgba_format(pipe, pt, x, y, w, h, pt->resource->format, p);
-}
-
-
-void
-pipe_get_tile_rgba_format(struct pipe_context *pipe,
- struct pipe_transfer *pt,
- uint x, uint y, uint w, uint h,
- enum pipe_format format,
- float *p)
-{
- unsigned dst_stride = w * 4;
- void *packed;
-
- if (u_clip_tile(x, y, &w, &h, &pt->box)) {
- return;
- }
-
- packed = MALLOC(util_format_get_nblocks(format, w, h) * util_format_get_blocksize(format));
- if (!packed) {
- return;
- }
-
- if (format == PIPE_FORMAT_UYVY || format == PIPE_FORMAT_YUYV) {
- assert((x & 1) == 0);
- }
-
- pipe_get_tile_raw(pipe, pt, x, y, w, h, packed, 0);
-
- pipe_tile_raw_to_rgba(format, packed, w, h, p, dst_stride);
-
- FREE(packed);
-}
-
-
-void
-pipe_put_tile_rgba(struct pipe_context *pipe,
- struct pipe_transfer *pt,
- uint x, uint y, uint w, uint h,
- const float *p)
-{
- pipe_put_tile_rgba_format(pipe, pt, x, y, w, h, pt->resource->format, p);
-}
-
-
-void
-pipe_put_tile_rgba_format(struct pipe_context *pipe,
- struct pipe_transfer *pt,
- uint x, uint y, uint w, uint h,
- enum pipe_format format,
- const float *p)
-{
- unsigned src_stride = w * 4;
- void *packed;
-
- if (u_clip_tile(x, y, &w, &h, &pt->box))
- return;
-
- packed = MALLOC(util_format_get_nblocks(format, w, h) * util_format_get_blocksize(format));
-
- if (!packed)
- return;
-
- switch (format) {
- case PIPE_FORMAT_Z16_UNORM:
- /*z16_put_tile_rgba((ushort *) packed, w, h, p, src_stride);*/
- break;
- case PIPE_FORMAT_Z32_UNORM:
- /*z32_put_tile_rgba((unsigned *) packed, w, h, p, src_stride);*/
- break;
- case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
- case PIPE_FORMAT_Z24X8_UNORM:
- /*s8z24_put_tile_rgba((unsigned *) packed, w, h, p, src_stride);*/
- break;
- case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
- case PIPE_FORMAT_X8Z24_UNORM:
- /*z24s8_put_tile_rgba((unsigned *) packed, w, h, p, src_stride);*/
- break;
- default:
- util_format_write_4f(format,
- p, src_stride * sizeof(float),
- packed, util_format_get_stride(format, w),
- 0, 0, w, h);
- }
-
- pipe_put_tile_raw(pipe, pt, x, y, w, h, packed, 0);
-
- FREE(packed);
-}
-
-
-/**
- * Get a block of Z values, converted to 32-bit range.
- */
-void
-pipe_get_tile_z(struct pipe_context *pipe,
- struct pipe_transfer *pt,
- uint x, uint y, uint w, uint h,
- uint *z)
-{
- const uint dstStride = w;
- ubyte *map;
- uint *pDest = z;
- uint i, j;
- enum pipe_format format = pt->resource->format;
-
- if (u_clip_tile(x, y, &w, &h, &pt->box))
- return;
-
- map = (ubyte *)pipe->transfer_map(pipe, pt);
- if (!map) {
- assert(0);
- return;
- }
-
- switch (format) {
- case PIPE_FORMAT_Z32_UNORM:
- {
- const uint *ptrc
- = (const uint *)(map + y * pt->stride + x*4);
- for (i = 0; i < h; i++) {
- memcpy(pDest, ptrc, 4 * w);
- pDest += dstStride;
- ptrc += pt->stride/4;
- }
- }
- break;
- case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
- case PIPE_FORMAT_Z24X8_UNORM:
- {
- const uint *ptrc
- = (const uint *)(map + y * pt->stride + x*4);
- for (i = 0; i < h; i++) {
- for (j = 0; j < w; j++) {
- /* convert 24-bit Z to 32-bit Z */
- pDest[j] = (ptrc[j] << 8) | ((ptrc[j] >> 16) & 0xff);
- }
- pDest += dstStride;
- ptrc += pt->stride/4;
- }
- }
- break;
- case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
- case PIPE_FORMAT_X8Z24_UNORM:
- {
- const uint *ptrc
- = (const uint *)(map + y * pt->stride + x*4);
- for (i = 0; i < h; i++) {
- for (j = 0; j < w; j++) {
- /* convert 24-bit Z to 32-bit Z */
- pDest[j] = (ptrc[j] & 0xffffff00) | ((ptrc[j] >> 24) & 0xff);
- }
- pDest += dstStride;
- ptrc += pt->stride/4;
- }
- }
- break;
- case PIPE_FORMAT_Z16_UNORM:
- {
- const ushort *ptrc
- = (const ushort *)(map + y * pt->stride + x*2);
- for (i = 0; i < h; i++) {
- for (j = 0; j < w; j++) {
- /* convert 16-bit Z to 32-bit Z */
- pDest[j] = (ptrc[j] << 16) | ptrc[j];
- }
- pDest += dstStride;
- ptrc += pt->stride/2;
- }
- }
- break;
- default:
- assert(0);
- }
-
- pipe->transfer_unmap(pipe, pt);
-}
-
-
-void
-pipe_put_tile_z(struct pipe_context *pipe,
- struct pipe_transfer *pt,
- uint x, uint y, uint w, uint h,
- const uint *zSrc)
-{
- const uint srcStride = w;
- const uint *ptrc = zSrc;
- ubyte *map;
- uint i, j;
- enum pipe_format format = pt->resource->format;
-
- if (u_clip_tile(x, y, &w, &h, &pt->box))
- return;
-
- map = (ubyte *)pipe->transfer_map(pipe, pt);
- if (!map) {
- assert(0);
- return;
- }
-
- switch (format) {
- case PIPE_FORMAT_Z32_UNORM:
- {
- uint *pDest = (uint *) (map + y * pt->stride + x*4);
- for (i = 0; i < h; i++) {
- memcpy(pDest, ptrc, 4 * w);
- pDest += pt->stride/4;
- ptrc += srcStride;
- }
- }
- break;
- case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
- {
- uint *pDest = (uint *) (map + y * pt->stride + x*4);
- /*assert((pt->usage & PIPE_TRANSFER_READ_WRITE) == PIPE_TRANSFER_READ_WRITE);*/
- for (i = 0; i < h; i++) {
- for (j = 0; j < w; j++) {
- /* convert 32-bit Z to 24-bit Z, preserve stencil */
- pDest[j] = (pDest[j] & 0xff000000) | ptrc[j] >> 8;
- }
- pDest += pt->stride/4;
- ptrc += srcStride;
- }
- }
- break;
- case PIPE_FORMAT_Z24X8_UNORM:
- {
- uint *pDest = (uint *) (map + y * pt->stride + x*4);
- for (i = 0; i < h; i++) {
- for (j = 0; j < w; j++) {
- /* convert 32-bit Z to 24-bit Z (0 stencil) */
- pDest[j] = ptrc[j] >> 8;
- }
- pDest += pt->stride/4;
- ptrc += srcStride;
- }
- }
- break;
- case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
- {
- uint *pDest = (uint *) (map + y * pt->stride + x*4);
- /*assert((pt->usage & PIPE_TRANSFER_READ_WRITE) == PIPE_TRANSFER_READ_WRITE);*/
- for (i = 0; i < h; i++) {
- for (j = 0; j < w; j++) {
- /* convert 32-bit Z to 24-bit Z, preserve stencil */
- pDest[j] = (pDest[j] & 0xff) | (ptrc[j] & 0xffffff00);
- }
- pDest += pt->stride/4;
- ptrc += srcStride;
- }
- }
- break;
- case PIPE_FORMAT_X8Z24_UNORM:
- {
- uint *pDest = (uint *) (map + y * pt->stride + x*4);
- for (i = 0; i < h; i++) {
- for (j = 0; j < w; j++) {
- /* convert 32-bit Z to 24-bit Z (0 stencil) */
- pDest[j] = ptrc[j] & 0xffffff00;
- }
- pDest += pt->stride/4;
- ptrc += srcStride;
- }
- }
- break;
- case PIPE_FORMAT_Z16_UNORM:
- {
- ushort *pDest = (ushort *) (map + y * pt->stride + x*2);
- for (i = 0; i < h; i++) {
- for (j = 0; j < w; j++) {
- /* convert 32-bit Z to 16-bit Z */
- pDest[j] = ptrc[j] >> 16;
- }
- pDest += pt->stride/2;
- ptrc += srcStride;
- }
- }
- break;
- default:
- assert(0);
- }
-
- pipe->transfer_unmap(pipe, pt);
-}
-
-
+/************************************************************************** + * + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/** + * RGBA/float tile get/put functions. + * Usable both by drivers and state trackers. + */ + + +#include "pipe/p_defines.h" +#include "util/u_inlines.h" + +#include "util/u_format.h" +#include "util/u_math.h" +#include "util/u_memory.h" +#include "util/u_rect.h" +#include "util/u_tile.h" + + +/** + * Move raw block of pixels from transfer object to user memory. + */ +void +pipe_get_tile_raw(struct pipe_context *pipe, + struct pipe_transfer *pt, + uint x, uint y, uint w, uint h, + void *dst, int dst_stride) +{ + const void *src; + + if (dst_stride == 0) + dst_stride = util_format_get_stride(pt->resource->format, w); + + if (u_clip_tile(x, y, &w, &h, &pt->box)) + return; + + src = pipe->transfer_map(pipe, pt); + assert(src); + if(!src) + return; + + util_copy_rect(dst, pt->resource->format, dst_stride, 0, 0, w, h, src, pt->stride, x, y); + + pipe->transfer_unmap(pipe, pt); +} + + +/** + * Move raw block of pixels from user memory to transfer object. + */ +void +pipe_put_tile_raw(struct pipe_context *pipe, + struct pipe_transfer *pt, + uint x, uint y, uint w, uint h, + const void *src, int src_stride) +{ + void *dst; + enum pipe_format format = pt->resource->format; + + if (src_stride == 0) + src_stride = util_format_get_stride(format, w); + + if (u_clip_tile(x, y, &w, &h, &pt->box)) + return; + + dst = pipe->transfer_map(pipe, pt); + assert(dst); + if(!dst) + return; + + util_copy_rect(dst, format, pt->stride, x, y, w, h, src, src_stride, 0, 0); + + pipe->transfer_unmap(pipe, pt); +} + + + + +/** Convert short in [-32768,32767] to GLfloat in [-1.0,1.0] */ +#define SHORT_TO_FLOAT(S) ((2.0F * (S) + 1.0F) * (1.0F/65535.0F)) + +#define UNCLAMPED_FLOAT_TO_SHORT(us, f) \ + us = ( (short) ( CLAMP((f), -1.0, 1.0) * 32767.0F) ) + + + +/*** PIPE_FORMAT_Z16_UNORM ***/ + +/** + * Return each Z value as four floats in [0,1]. + */ +static void +z16_get_tile_rgba(const ushort *src, + unsigned w, unsigned h, + float *p, + unsigned dst_stride) +{ + const float scale = 1.0f / 65535.0f; + unsigned i, j; + + for (i = 0; i < h; i++) { + float *pRow = p; + for (j = 0; j < w; j++, pRow += 4) { + pRow[0] = + pRow[1] = + pRow[2] = + pRow[3] = *src++ * scale; + } + p += dst_stride; + } +} + + + + +/*** PIPE_FORMAT_Z32_UNORM ***/ + +/** + * Return each Z value as four floats in [0,1]. + */ +static void +z32_get_tile_rgba(const unsigned *src, + unsigned w, unsigned h, + float *p, + unsigned dst_stride) +{ + const double scale = 1.0 / (double) 0xffffffff; + unsigned i, j; + + for (i = 0; i < h; i++) { + float *pRow = p; + for (j = 0; j < w; j++, pRow += 4) { + pRow[0] = + pRow[1] = + pRow[2] = + pRow[3] = (float) (*src++ * scale); + } + p += dst_stride; + } +} + + +/*** PIPE_FORMAT_Z24_UNORM_S8_USCALED ***/ + +/** + * Return Z component as four float in [0,1]. Stencil part ignored. + */ +static void +s8z24_get_tile_rgba(const unsigned *src, + unsigned w, unsigned h, + float *p, + unsigned dst_stride) +{ + const double scale = 1.0 / ((1 << 24) - 1); + unsigned i, j; + + for (i = 0; i < h; i++) { + float *pRow = p; + for (j = 0; j < w; j++, pRow += 4) { + pRow[0] = + pRow[1] = + pRow[2] = + pRow[3] = (float) (scale * (*src++ & 0xffffff)); + } + p += dst_stride; + } +} + + +/*** PIPE_FORMAT_S8_USCALED_Z24_UNORM ***/ + +/** + * Return Z component as four float in [0,1]. Stencil part ignored. + */ +static void +z24s8_get_tile_rgba(const unsigned *src, + unsigned w, unsigned h, + float *p, + unsigned dst_stride) +{ + const double scale = 1.0 / ((1 << 24) - 1); + unsigned i, j; + + for (i = 0; i < h; i++) { + float *pRow = p; + for (j = 0; j < w; j++, pRow += 4) { + pRow[0] = + pRow[1] = + pRow[2] = + pRow[3] = (float) (scale * (*src++ >> 8)); + } + p += dst_stride; + } +} + +/*** PIPE_FORMAT_S8X24_USCALED ***/ + +/** + * Return S component as four uint32_t in [0..255]. Z part ignored. + */ +static void +s8x24_get_tile_rgba(const unsigned *src, + unsigned w, unsigned h, + float *p, + unsigned dst_stride) +{ + unsigned i, j; + + for (i = 0; i < h; i++) { + float *pRow = p; + + for (j = 0; j < w; j++, pRow += 4) { + pRow[0] = + pRow[1] = + pRow[2] = + pRow[3] = (float)((*src++ >> 24) & 0xff); + } + + p += dst_stride; + } +} + +/*** PIPE_FORMAT_X24S8_USCALED ***/ + +/** + * Return S component as four uint32_t in [0..255]. Z part ignored. + */ +static void +x24s8_get_tile_rgba(const unsigned *src, + unsigned w, unsigned h, + float *p, + unsigned dst_stride) +{ + unsigned i, j; + + for (i = 0; i < h; i++) { + float *pRow = p; + for (j = 0; j < w; j++, pRow += 4) { + pRow[0] = + pRow[1] = + pRow[2] = + pRow[3] = (float)(*src++ & 0xff); + } + p += dst_stride; + } +} + + +/** + * Return S component as four uint32_t in [0..255]. Z part ignored. + */ +static void +s8_get_tile_rgba(const unsigned char *src, + unsigned w, unsigned h, + float *p, + unsigned dst_stride) +{ + unsigned i, j; + + for (i = 0; i < h; i++) { + float *pRow = p; + for (j = 0; j < w; j++, pRow += 4) { + pRow[0] = + pRow[1] = + pRow[2] = + pRow[3] = (float)(*src++ & 0xff); + } + p += dst_stride; + } +} + +/*** PIPE_FORMAT_Z32_FLOAT ***/ + +/** + * Return each Z value as four floats in [0,1]. + */ +static void +z32f_get_tile_rgba(const float *src, + unsigned w, unsigned h, + float *p, + unsigned dst_stride) +{ + unsigned i, j; + + for (i = 0; i < h; i++) { + float *pRow = p; + for (j = 0; j < w; j++, pRow += 4) { + pRow[0] = + pRow[1] = + pRow[2] = + pRow[3] = *src++; + } + p += dst_stride; + } +} + +/*** PIPE_FORMAT_Z32_FLOAT_S8X24_USCALED ***/ + +/** + * Return each Z value as four floats in [0,1]. + */ +static void +z32f_x24s8_get_tile_rgba(const float *src, + unsigned w, unsigned h, + float *p, + unsigned dst_stride) +{ + unsigned i, j; + + for (i = 0; i < h; i++) { + float *pRow = p; + for (j = 0; j < w; j++, pRow += 4) { + pRow[0] = + pRow[1] = + pRow[2] = + pRow[3] = *src; + src += 2; + } + p += dst_stride; + } +} + + +void +pipe_tile_raw_to_rgba(enum pipe_format format, + void *src, + uint w, uint h, + float *dst, unsigned dst_stride) +{ + switch (format) { + case PIPE_FORMAT_Z16_UNORM: + z16_get_tile_rgba((ushort *) src, w, h, dst, dst_stride); + break; + case PIPE_FORMAT_Z32_UNORM: + z32_get_tile_rgba((unsigned *) src, w, h, dst, dst_stride); + break; + case PIPE_FORMAT_Z24_UNORM_S8_USCALED: + case PIPE_FORMAT_Z24X8_UNORM: + s8z24_get_tile_rgba((unsigned *) src, w, h, dst, dst_stride); + break; + case PIPE_FORMAT_S8_USCALED: + s8_get_tile_rgba((unsigned char *) src, w, h, dst, dst_stride); + break; + case PIPE_FORMAT_X24S8_USCALED: + s8x24_get_tile_rgba((unsigned *) src, w, h, dst, dst_stride); + break; + case PIPE_FORMAT_S8_USCALED_Z24_UNORM: + case PIPE_FORMAT_X8Z24_UNORM: + z24s8_get_tile_rgba((unsigned *) src, w, h, dst, dst_stride); + break; + case PIPE_FORMAT_S8X24_USCALED: + x24s8_get_tile_rgba((unsigned *) src, w, h, dst, dst_stride); + break; + case PIPE_FORMAT_Z32_FLOAT: + z32f_get_tile_rgba((float *) src, w, h, dst, dst_stride); + break; + case PIPE_FORMAT_Z32_FLOAT_S8X24_USCALED: + z32f_x24s8_get_tile_rgba((float *) src, w, h, dst, dst_stride); + break; + default: + util_format_read_4f(format, + dst, dst_stride * sizeof(float), + src, util_format_get_stride(format, w), + 0, 0, w, h); + } +} + + +void +pipe_get_tile_rgba(struct pipe_context *pipe, + struct pipe_transfer *pt, + uint x, uint y, uint w, uint h, + float *p) +{ + pipe_get_tile_rgba_format(pipe, pt, x, y, w, h, pt->resource->format, p); +} + + +void +pipe_get_tile_rgba_format(struct pipe_context *pipe, + struct pipe_transfer *pt, + uint x, uint y, uint w, uint h, + enum pipe_format format, + float *p) +{ + unsigned dst_stride = w * 4; + void *packed; + + if (u_clip_tile(x, y, &w, &h, &pt->box)) { + return; + } + + packed = MALLOC(util_format_get_nblocks(format, w, h) * util_format_get_blocksize(format)); + if (!packed) { + return; + } + + if (format == PIPE_FORMAT_UYVY || format == PIPE_FORMAT_YUYV) { + assert((x & 1) == 0); + } + + pipe_get_tile_raw(pipe, pt, x, y, w, h, packed, 0); + + pipe_tile_raw_to_rgba(format, packed, w, h, p, dst_stride); + + FREE(packed); +} + + +void +pipe_put_tile_rgba(struct pipe_context *pipe, + struct pipe_transfer *pt, + uint x, uint y, uint w, uint h, + const float *p) +{ + pipe_put_tile_rgba_format(pipe, pt, x, y, w, h, pt->resource->format, p); +} + + +void +pipe_put_tile_rgba_format(struct pipe_context *pipe, + struct pipe_transfer *pt, + uint x, uint y, uint w, uint h, + enum pipe_format format, + const float *p) +{ + unsigned src_stride = w * 4; + void *packed; + + if (u_clip_tile(x, y, &w, &h, &pt->box)) + return; + + packed = MALLOC(util_format_get_nblocks(format, w, h) * util_format_get_blocksize(format)); + + if (!packed) + return; + + switch (format) { + case PIPE_FORMAT_Z16_UNORM: + /*z16_put_tile_rgba((ushort *) packed, w, h, p, src_stride);*/ + break; + case PIPE_FORMAT_Z32_UNORM: + /*z32_put_tile_rgba((unsigned *) packed, w, h, p, src_stride);*/ + break; + case PIPE_FORMAT_Z24_UNORM_S8_USCALED: + case PIPE_FORMAT_Z24X8_UNORM: + /*s8z24_put_tile_rgba((unsigned *) packed, w, h, p, src_stride);*/ + break; + case PIPE_FORMAT_S8_USCALED_Z24_UNORM: + case PIPE_FORMAT_X8Z24_UNORM: + /*z24s8_put_tile_rgba((unsigned *) packed, w, h, p, src_stride);*/ + break; + case PIPE_FORMAT_Z32_FLOAT: + /*z32f_put_tile_rgba((unsigned *) packed, w, h, p, src_stride);*/ + break; + case PIPE_FORMAT_Z32_FLOAT_S8X24_USCALED: + /*z32f_s8x24_put_tile_rgba((unsigned *) packed, w, h, p, src_stride);*/ + break; + default: + util_format_write_4f(format, + p, src_stride * sizeof(float), + packed, util_format_get_stride(format, w), + 0, 0, w, h); + } + + pipe_put_tile_raw(pipe, pt, x, y, w, h, packed, 0); + + FREE(packed); +} + + +/** + * Get a block of Z values, converted to 32-bit range. + */ +void +pipe_get_tile_z(struct pipe_context *pipe, + struct pipe_transfer *pt, + uint x, uint y, uint w, uint h, + uint *z) +{ + const uint dstStride = w; + ubyte *map; + uint *pDest = z; + uint i, j; + enum pipe_format format = pt->resource->format; + + if (u_clip_tile(x, y, &w, &h, &pt->box)) + return; + + map = (ubyte *)pipe->transfer_map(pipe, pt); + if (!map) { + assert(0); + return; + } + + switch (format) { + case PIPE_FORMAT_Z32_UNORM: + { + const uint *ptrc + = (const uint *)(map + y * pt->stride + x*4); + for (i = 0; i < h; i++) { + memcpy(pDest, ptrc, 4 * w); + pDest += dstStride; + ptrc += pt->stride/4; + } + } + break; + case PIPE_FORMAT_Z24_UNORM_S8_USCALED: + case PIPE_FORMAT_Z24X8_UNORM: + { + const uint *ptrc + = (const uint *)(map + y * pt->stride + x*4); + for (i = 0; i < h; i++) { + for (j = 0; j < w; j++) { + /* convert 24-bit Z to 32-bit Z */ + pDest[j] = (ptrc[j] << 8) | ((ptrc[j] >> 16) & 0xff); + } + pDest += dstStride; + ptrc += pt->stride/4; + } + } + break; + case PIPE_FORMAT_S8_USCALED_Z24_UNORM: + case PIPE_FORMAT_X8Z24_UNORM: + { + const uint *ptrc + = (const uint *)(map + y * pt->stride + x*4); + for (i = 0; i < h; i++) { + for (j = 0; j < w; j++) { + /* convert 24-bit Z to 32-bit Z */ + pDest[j] = (ptrc[j] & 0xffffff00) | ((ptrc[j] >> 24) & 0xff); + } + pDest += dstStride; + ptrc += pt->stride/4; + } + } + break; + case PIPE_FORMAT_Z16_UNORM: + { + const ushort *ptrc + = (const ushort *)(map + y * pt->stride + x*2); + for (i = 0; i < h; i++) { + for (j = 0; j < w; j++) { + /* convert 16-bit Z to 32-bit Z */ + pDest[j] = (ptrc[j] << 16) | ptrc[j]; + } + pDest += dstStride; + ptrc += pt->stride/2; + } + } + break; + default: + assert(0); + } + + pipe->transfer_unmap(pipe, pt); +} + + +void +pipe_put_tile_z(struct pipe_context *pipe, + struct pipe_transfer *pt, + uint x, uint y, uint w, uint h, + const uint *zSrc) +{ + const uint srcStride = w; + const uint *ptrc = zSrc; + ubyte *map; + uint i, j; + enum pipe_format format = pt->resource->format; + + if (u_clip_tile(x, y, &w, &h, &pt->box)) + return; + + map = (ubyte *)pipe->transfer_map(pipe, pt); + if (!map) { + assert(0); + return; + } + + switch (format) { + case PIPE_FORMAT_Z32_UNORM: + { + uint *pDest = (uint *) (map + y * pt->stride + x*4); + for (i = 0; i < h; i++) { + memcpy(pDest, ptrc, 4 * w); + pDest += pt->stride/4; + ptrc += srcStride; + } + } + break; + case PIPE_FORMAT_Z24_UNORM_S8_USCALED: + { + uint *pDest = (uint *) (map + y * pt->stride + x*4); + /*assert((pt->usage & PIPE_TRANSFER_READ_WRITE) == PIPE_TRANSFER_READ_WRITE);*/ + for (i = 0; i < h; i++) { + for (j = 0; j < w; j++) { + /* convert 32-bit Z to 24-bit Z, preserve stencil */ + pDest[j] = (pDest[j] & 0xff000000) | ptrc[j] >> 8; + } + pDest += pt->stride/4; + ptrc += srcStride; + } + } + break; + case PIPE_FORMAT_Z24X8_UNORM: + { + uint *pDest = (uint *) (map + y * pt->stride + x*4); + for (i = 0; i < h; i++) { + for (j = 0; j < w; j++) { + /* convert 32-bit Z to 24-bit Z (0 stencil) */ + pDest[j] = ptrc[j] >> 8; + } + pDest += pt->stride/4; + ptrc += srcStride; + } + } + break; + case PIPE_FORMAT_S8_USCALED_Z24_UNORM: + { + uint *pDest = (uint *) (map + y * pt->stride + x*4); + /*assert((pt->usage & PIPE_TRANSFER_READ_WRITE) == PIPE_TRANSFER_READ_WRITE);*/ + for (i = 0; i < h; i++) { + for (j = 0; j < w; j++) { + /* convert 32-bit Z to 24-bit Z, preserve stencil */ + pDest[j] = (pDest[j] & 0xff) | (ptrc[j] & 0xffffff00); + } + pDest += pt->stride/4; + ptrc += srcStride; + } + } + break; + case PIPE_FORMAT_X8Z24_UNORM: + { + uint *pDest = (uint *) (map + y * pt->stride + x*4); + for (i = 0; i < h; i++) { + for (j = 0; j < w; j++) { + /* convert 32-bit Z to 24-bit Z (0 stencil) */ + pDest[j] = ptrc[j] & 0xffffff00; + } + pDest += pt->stride/4; + ptrc += srcStride; + } + } + break; + case PIPE_FORMAT_Z16_UNORM: + { + ushort *pDest = (ushort *) (map + y * pt->stride + x*2); + for (i = 0; i < h; i++) { + for (j = 0; j < w; j++) { + /* convert 32-bit Z to 16-bit Z */ + pDest[j] = ptrc[j] >> 16; + } + pDest += pt->stride/2; + ptrc += srcStride; + } + } + break; + default: + assert(0); + } + + pipe->transfer_unmap(pipe, pt); +} + + diff --git a/mesalib/src/glsl/ir_optimization.h b/mesalib/src/glsl/ir_optimization.h index dd265673c..59a040751 100644 --- a/mesalib/src/glsl/ir_optimization.h +++ b/mesalib/src/glsl/ir_optimization.h @@ -56,10 +56,8 @@ bool do_if_simplification(exec_list *instructions); bool do_discard_simplification(exec_list *instructions); bool lower_if_to_cond_assign(exec_list *instructions, unsigned max_depth = 0); bool do_mat_op_to_vec(exec_list *instructions); -bool do_mod_to_fract(exec_list *instructions); bool do_noop_swizzle(exec_list *instructions); bool do_structure_splitting(exec_list *instructions); -bool do_sub_to_add_neg(exec_list *instructions); bool do_swizzle_swizzle(exec_list *instructions); bool do_tree_grafting(exec_list *instructions); bool do_vec_index_to_cond_assign(exec_list *instructions); diff --git a/mesalib/src/glsl/ir_reader.cpp b/mesalib/src/glsl/ir_reader.cpp index 201e436be..f3a621734 100644 --- a/mesalib/src/glsl/ir_reader.cpp +++ b/mesalib/src/glsl/ir_reader.cpp @@ -1,1005 +1,1007 @@ -/*
- * Copyright © 2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#include "ir_reader.h"
-#include "glsl_parser_extras.h"
-#include "glsl_types.h"
-#include "s_expression.h"
-
-const static bool debug = false;
-
-class ir_reader {
-public:
- ir_reader(_mesa_glsl_parse_state *);
-
- void read(exec_list *instructions, const char *src, bool scan_for_protos);
-
-private:
- void *mem_ctx;
- _mesa_glsl_parse_state *state;
-
- void ir_read_error(s_expression *, const char *fmt, ...);
-
- const glsl_type *read_type(s_expression *);
-
- void scan_for_prototypes(exec_list *, s_expression *);
- ir_function *read_function(s_expression *, bool skip_body);
- void read_function_sig(ir_function *, s_expression *, bool skip_body);
-
- void read_instructions(exec_list *, s_expression *, ir_loop *);
- ir_instruction *read_instruction(s_expression *, ir_loop *);
- ir_variable *read_declaration(s_expression *);
- ir_if *read_if(s_expression *, ir_loop *);
- ir_loop *read_loop(s_expression *);
- ir_return *read_return(s_expression *);
- ir_rvalue *read_rvalue(s_expression *);
- ir_assignment *read_assignment(s_expression *);
- ir_expression *read_expression(s_expression *);
- ir_call *read_call(s_expression *);
- ir_swizzle *read_swizzle(s_expression *);
- ir_constant *read_constant(s_expression *);
- ir_texture *read_texture(s_expression *);
-
- ir_dereference *read_dereference(s_expression *);
-};
-
-ir_reader::ir_reader(_mesa_glsl_parse_state *state) : state(state)
-{
- this->mem_ctx = state;
-}
-
-void
-_mesa_glsl_read_ir(_mesa_glsl_parse_state *state, exec_list *instructions,
- const char *src, bool scan_for_protos)
-{
- ir_reader r(state);
- r.read(instructions, src, scan_for_protos);
-}
-
-void
-ir_reader::read(exec_list *instructions, const char *src, bool scan_for_protos)
-{
- s_expression *expr = s_expression::read_expression(mem_ctx, src);
- if (expr == NULL) {
- ir_read_error(NULL, "couldn't parse S-Expression.");
- return;
- }
-
- if (scan_for_protos) {
- scan_for_prototypes(instructions, expr);
- if (state->error)
- return;
- }
-
- read_instructions(instructions, expr, NULL);
- ralloc_free(expr);
-
- if (debug)
- validate_ir_tree(instructions);
-}
-
-void
-ir_reader::ir_read_error(s_expression *expr, const char *fmt, ...)
-{
- va_list ap;
-
- state->error = true;
-
- if (state->current_function != NULL)
- ralloc_asprintf_append(&state->info_log, "In function %s:\n",
- state->current_function->function_name());
- ralloc_strcat(&state->info_log, "error: ");
-
- va_start(ap, fmt);
- ralloc_vasprintf_append(&state->info_log, fmt, ap);
- va_end(ap);
- ralloc_strcat(&state->info_log, "\n");
-
- if (expr != NULL) {
- ralloc_strcat(&state->info_log, "...in this context:\n ");
- expr->print();
- ralloc_strcat(&state->info_log, "\n\n");
- }
-}
-
-const glsl_type *
-ir_reader::read_type(s_expression *expr)
-{
- s_expression *s_base_type;
- s_int *s_size;
-
- s_pattern pat[] = { "array", s_base_type, s_size };
- if (MATCH(expr, pat)) {
- const glsl_type *base_type = read_type(s_base_type);
- if (base_type == NULL) {
- ir_read_error(NULL, "when reading base type of array type");
- return NULL;
- }
-
- return glsl_type::get_array_instance(base_type, s_size->value());
- }
-
- s_symbol *type_sym = SX_AS_SYMBOL(expr);
- if (type_sym == NULL) {
- ir_read_error(expr, "expected <type>");
- return NULL;
- }
-
- const glsl_type *type = state->symbols->get_type(type_sym->value());
- if (type == NULL)
- ir_read_error(expr, "invalid type: %s", type_sym->value());
-
- return type;
-}
-
-
-void
-ir_reader::scan_for_prototypes(exec_list *instructions, s_expression *expr)
-{
- s_list *list = SX_AS_LIST(expr);
- if (list == NULL) {
- ir_read_error(expr, "Expected (<instruction> ...); found an atom.");
- return;
- }
-
- foreach_iter(exec_list_iterator, it, list->subexpressions) {
- s_list *sub = SX_AS_LIST(it.get());
- if (sub == NULL)
- continue; // not a (function ...); ignore it.
-
- s_symbol *tag = SX_AS_SYMBOL(sub->subexpressions.get_head());
- if (tag == NULL || strcmp(tag->value(), "function") != 0)
- continue; // not a (function ...); ignore it.
-
- ir_function *f = read_function(sub, true);
- if (f == NULL)
- return;
- instructions->push_tail(f);
- }
-}
-
-ir_function *
-ir_reader::read_function(s_expression *expr, bool skip_body)
-{
- bool added = false;
- s_symbol *name;
-
- s_pattern pat[] = { "function", name };
- if (!PARTIAL_MATCH(expr, pat)) {
- ir_read_error(expr, "Expected (function <name> (signature ...) ...)");
- return NULL;
- }
-
- ir_function *f = state->symbols->get_function(name->value());
- if (f == NULL) {
- f = new(mem_ctx) ir_function(name->value());
- added = state->symbols->add_function(f);
- assert(added);
- }
-
- exec_list_iterator it = ((s_list *) expr)->subexpressions.iterator();
- it.next(); // skip "function" tag
- it.next(); // skip function name
- for (/* nothing */; it.has_next(); it.next()) {
- s_expression *s_sig = (s_expression *) it.get();
- read_function_sig(f, s_sig, skip_body);
- }
- return added ? f : NULL;
-}
-
-void
-ir_reader::read_function_sig(ir_function *f, s_expression *expr, bool skip_body)
-{
- s_expression *type_expr;
- s_list *paramlist;
- s_list *body_list;
-
- s_pattern pat[] = { "signature", type_expr, paramlist, body_list };
- if (!MATCH(expr, pat)) {
- ir_read_error(expr, "Expected (signature <type> (parameters ...) "
- "(<instruction> ...))");
- return;
- }
-
- const glsl_type *return_type = read_type(type_expr);
- if (return_type == NULL)
- return;
-
- s_symbol *paramtag = SX_AS_SYMBOL(paramlist->subexpressions.get_head());
- if (paramtag == NULL || strcmp(paramtag->value(), "parameters") != 0) {
- ir_read_error(paramlist, "Expected (parameters ...)");
- return;
- }
-
- // Read the parameters list into a temporary place.
- exec_list hir_parameters;
- state->symbols->push_scope();
-
- exec_list_iterator it = paramlist->subexpressions.iterator();
- for (it.next() /* skip "parameters" */; it.has_next(); it.next()) {
- ir_variable *var = read_declaration((s_expression *) it.get());
- if (var == NULL)
- return;
-
- hir_parameters.push_tail(var);
- }
-
- ir_function_signature *sig = f->exact_matching_signature(&hir_parameters);
- if (sig == NULL && skip_body) {
- /* If scanning for prototypes, generate a new signature. */
- sig = new(mem_ctx) ir_function_signature(return_type);
- sig->is_builtin = true;
- f->add_signature(sig);
- } else if (sig != NULL) {
- const char *badvar = sig->qualifiers_match(&hir_parameters);
- if (badvar != NULL) {
- ir_read_error(expr, "function `%s' parameter `%s' qualifiers "
- "don't match prototype", f->name, badvar);
- return;
- }
-
- if (sig->return_type != return_type) {
- ir_read_error(expr, "function `%s' return type doesn't "
- "match prototype", f->name);
- return;
- }
- } else {
- /* No prototype for this body exists - skip it. */
- state->symbols->pop_scope();
- return;
- }
- assert(sig != NULL);
-
- sig->replace_parameters(&hir_parameters);
-
- if (!skip_body && !body_list->subexpressions.is_empty()) {
- if (sig->is_defined) {
- ir_read_error(expr, "function %s redefined", f->name);
- return;
- }
- state->current_function = sig;
- read_instructions(&sig->body, body_list, NULL);
- state->current_function = NULL;
- sig->is_defined = true;
- }
-
- state->symbols->pop_scope();
-}
-
-void
-ir_reader::read_instructions(exec_list *instructions, s_expression *expr,
- ir_loop *loop_ctx)
-{
- // Read in a list of instructions
- s_list *list = SX_AS_LIST(expr);
- if (list == NULL) {
- ir_read_error(expr, "Expected (<instruction> ...); found an atom.");
- return;
- }
-
- foreach_iter(exec_list_iterator, it, list->subexpressions) {
- s_expression *sub = (s_expression*) it.get();
- ir_instruction *ir = read_instruction(sub, loop_ctx);
- if (ir != NULL) {
- /* Global variable declarations should be moved to the top, before
- * any functions that might use them. Functions are added to the
- * instruction stream when scanning for prototypes, so without this
- * hack, they always appear before variable declarations.
- */
- if (state->current_function == NULL && ir->as_variable() != NULL)
- instructions->push_head(ir);
- else
- instructions->push_tail(ir);
- }
- }
-}
-
-
-ir_instruction *
-ir_reader::read_instruction(s_expression *expr, ir_loop *loop_ctx)
-{
- s_symbol *symbol = SX_AS_SYMBOL(expr);
- if (symbol != NULL) {
- if (strcmp(symbol->value(), "break") == 0 && loop_ctx != NULL)
- return new(mem_ctx) ir_loop_jump(ir_loop_jump::jump_break);
- if (strcmp(symbol->value(), "continue") == 0 && loop_ctx != NULL)
- return new(mem_ctx) ir_loop_jump(ir_loop_jump::jump_continue);
- }
-
- s_list *list = SX_AS_LIST(expr);
- if (list == NULL || list->subexpressions.is_empty()) {
- ir_read_error(expr, "Invalid instruction.\n");
- return NULL;
- }
-
- s_symbol *tag = SX_AS_SYMBOL(list->subexpressions.get_head());
- if (tag == NULL) {
- ir_read_error(expr, "expected instruction tag");
- return NULL;
- }
-
- ir_instruction *inst = NULL;
- if (strcmp(tag->value(), "declare") == 0) {
- inst = read_declaration(list);
- } else if (strcmp(tag->value(), "assign") == 0) {
- inst = read_assignment(list);
- } else if (strcmp(tag->value(), "if") == 0) {
- inst = read_if(list, loop_ctx);
- } else if (strcmp(tag->value(), "loop") == 0) {
- inst = read_loop(list);
- } else if (strcmp(tag->value(), "return") == 0) {
- inst = read_return(list);
- } else if (strcmp(tag->value(), "function") == 0) {
- inst = read_function(list, false);
- } else {
- inst = read_rvalue(list);
- if (inst == NULL)
- ir_read_error(NULL, "when reading instruction");
- }
- return inst;
-}
-
-ir_variable *
-ir_reader::read_declaration(s_expression *expr)
-{
- s_list *s_quals;
- s_expression *s_type;
- s_symbol *s_name;
-
- s_pattern pat[] = { "declare", s_quals, s_type, s_name };
- if (!MATCH(expr, pat)) {
- ir_read_error(expr, "expected (declare (<qualifiers>) <type> <name>)");
- return NULL;
- }
-
- const glsl_type *type = read_type(s_type);
- if (type == NULL)
- return NULL;
-
- ir_variable *var = new(mem_ctx) ir_variable(type, s_name->value(),
- ir_var_auto);
-
- foreach_iter(exec_list_iterator, it, s_quals->subexpressions) {
- s_symbol *qualifier = SX_AS_SYMBOL(it.get());
- if (qualifier == NULL) {
- ir_read_error(expr, "qualifier list must contain only symbols");
- return NULL;
- }
-
- // FINISHME: Check for duplicate/conflicting qualifiers.
- if (strcmp(qualifier->value(), "centroid") == 0) {
- var->centroid = 1;
- } else if (strcmp(qualifier->value(), "invariant") == 0) {
- var->invariant = 1;
- } else if (strcmp(qualifier->value(), "uniform") == 0) {
- var->mode = ir_var_uniform;
- } else if (strcmp(qualifier->value(), "auto") == 0) {
- var->mode = ir_var_auto;
- } else if (strcmp(qualifier->value(), "in") == 0) {
- var->mode = ir_var_in;
- } else if (strcmp(qualifier->value(), "const_in") == 0) {
- var->mode = ir_var_const_in;
- } else if (strcmp(qualifier->value(), "out") == 0) {
- var->mode = ir_var_out;
- } else if (strcmp(qualifier->value(), "inout") == 0) {
- var->mode = ir_var_inout;
- } else if (strcmp(qualifier->value(), "smooth") == 0) {
- var->interpolation = ir_var_smooth;
- } else if (strcmp(qualifier->value(), "flat") == 0) {
- var->interpolation = ir_var_flat;
- } else if (strcmp(qualifier->value(), "noperspective") == 0) {
- var->interpolation = ir_var_noperspective;
- } else {
- ir_read_error(expr, "unknown qualifier: %s", qualifier->value());
- return NULL;
- }
- }
-
- // Add the variable to the symbol table
- state->symbols->add_variable(var);
-
- return var;
-}
-
-
-ir_if *
-ir_reader::read_if(s_expression *expr, ir_loop *loop_ctx)
-{
- s_expression *s_cond;
- s_expression *s_then;
- s_expression *s_else;
-
- s_pattern pat[] = { "if", s_cond, s_then, s_else };
- if (!MATCH(expr, pat)) {
- ir_read_error(expr, "expected (if <condition> (<then>...) (<else>...))");
- return NULL;
- }
-
- ir_rvalue *condition = read_rvalue(s_cond);
- if (condition == NULL) {
- ir_read_error(NULL, "when reading condition of (if ...)");
- return NULL;
- }
-
- ir_if *iff = new(mem_ctx) ir_if(condition);
-
- read_instructions(&iff->then_instructions, s_then, loop_ctx);
- read_instructions(&iff->else_instructions, s_else, loop_ctx);
- if (state->error) {
- delete iff;
- iff = NULL;
- }
- return iff;
-}
-
-
-ir_loop *
-ir_reader::read_loop(s_expression *expr)
-{
- s_expression *s_counter, *s_from, *s_to, *s_inc, *s_body;
-
- s_pattern pat[] = { "loop", s_counter, s_from, s_to, s_inc, s_body };
- if (!MATCH(expr, pat)) {
- ir_read_error(expr, "expected (loop <counter> <from> <to> "
- "<increment> <body>)");
- return NULL;
- }
-
- // FINISHME: actually read the count/from/to fields.
-
- ir_loop *loop = new(mem_ctx) ir_loop;
- read_instructions(&loop->body_instructions, s_body, loop);
- if (state->error) {
- delete loop;
- loop = NULL;
- }
- return loop;
-}
-
-
-ir_return *
-ir_reader::read_return(s_expression *expr)
-{
- s_expression *s_retval;
-
- s_pattern pat[] = { "return", s_retval};
- if (!MATCH(expr, pat)) {
- ir_read_error(expr, "expected (return <rvalue>)");
- return NULL;
- }
-
- ir_rvalue *retval = read_rvalue(s_retval);
- if (retval == NULL) {
- ir_read_error(NULL, "when reading return value");
- return NULL;
- }
-
- return new(mem_ctx) ir_return(retval);
-}
-
-
-ir_rvalue *
-ir_reader::read_rvalue(s_expression *expr)
-{
- s_list *list = SX_AS_LIST(expr);
- if (list == NULL || list->subexpressions.is_empty())
- return NULL;
-
- s_symbol *tag = SX_AS_SYMBOL(list->subexpressions.get_head());
- if (tag == NULL) {
- ir_read_error(expr, "expected rvalue tag");
- return NULL;
- }
-
- ir_rvalue *rvalue = read_dereference(list);
- if (rvalue != NULL || state->error)
- return rvalue;
- else if (strcmp(tag->value(), "swiz") == 0) {
- rvalue = read_swizzle(list);
- } else if (strcmp(tag->value(), "expression") == 0) {
- rvalue = read_expression(list);
- } else if (strcmp(tag->value(), "call") == 0) {
- rvalue = read_call(list);
- } else if (strcmp(tag->value(), "constant") == 0) {
- rvalue = read_constant(list);
- } else {
- rvalue = read_texture(list);
- if (rvalue == NULL && !state->error)
- ir_read_error(expr, "unrecognized rvalue tag: %s", tag->value());
- }
-
- return rvalue;
-}
-
-ir_assignment *
-ir_reader::read_assignment(s_expression *expr)
-{
- s_expression *cond_expr = NULL;
- s_expression *lhs_expr, *rhs_expr;
- s_list *mask_list;
-
- s_pattern pat4[] = { "assign", mask_list, lhs_expr, rhs_expr };
- s_pattern pat5[] = { "assign", cond_expr, mask_list, lhs_expr, rhs_expr };
- if (!MATCH(expr, pat4) && !MATCH(expr, pat5)) {
- ir_read_error(expr, "expected (assign [<condition>] (<write mask>) "
- "<lhs> <rhs>)");
- return NULL;
- }
-
- ir_rvalue *condition = NULL;
- if (cond_expr != NULL) {
- condition = read_rvalue(cond_expr);
- if (condition == NULL) {
- ir_read_error(NULL, "when reading condition of assignment");
- return NULL;
- }
- }
-
- unsigned mask = 0;
-
- s_symbol *mask_symbol;
- s_pattern mask_pat[] = { mask_symbol };
- if (MATCH(mask_list, mask_pat)) {
- const char *mask_str = mask_symbol->value();
- unsigned mask_length = strlen(mask_str);
- if (mask_length > 4) {
- ir_read_error(expr, "invalid write mask: %s", mask_str);
- return NULL;
- }
-
- const unsigned idx_map[] = { 3, 0, 1, 2 }; /* w=bit 3, x=0, y=1, z=2 */
-
- for (unsigned i = 0; i < mask_length; i++) {
- if (mask_str[i] < 'w' || mask_str[i] > 'z') {
- ir_read_error(expr, "write mask contains invalid character: %c",
- mask_str[i]);
- return NULL;
- }
- mask |= 1 << idx_map[mask_str[i] - 'w'];
- }
- } else if (!mask_list->subexpressions.is_empty()) {
- ir_read_error(mask_list, "expected () or (<write mask>)");
- return NULL;
- }
-
- ir_dereference *lhs = read_dereference(lhs_expr);
- if (lhs == NULL) {
- ir_read_error(NULL, "when reading left-hand side of assignment");
- return NULL;
- }
-
- ir_rvalue *rhs = read_rvalue(rhs_expr);
- if (rhs == NULL) {
- ir_read_error(NULL, "when reading right-hand side of assignment");
- return NULL;
- }
-
- if (mask == 0 && (lhs->type->is_vector() || lhs->type->is_scalar())) {
- ir_read_error(expr, "non-zero write mask required.");
- return NULL;
- }
-
- return new(mem_ctx) ir_assignment(lhs, rhs, condition, mask);
-}
-
-ir_call *
-ir_reader::read_call(s_expression *expr)
-{
- s_symbol *name;
- s_list *params;
-
- s_pattern pat[] = { "call", name, params };
- if (!MATCH(expr, pat)) {
- ir_read_error(expr, "expected (call <name> (<param> ...))");
- return NULL;
- }
-
- exec_list parameters;
-
- foreach_iter(exec_list_iterator, it, params->subexpressions) {
- s_expression *expr = (s_expression*) it.get();
- ir_rvalue *param = read_rvalue(expr);
- if (param == NULL) {
- ir_read_error(expr, "when reading parameter to function call");
- return NULL;
- }
- parameters.push_tail(param);
- }
-
- ir_function *f = state->symbols->get_function(name->value());
- if (f == NULL) {
- ir_read_error(expr, "found call to undefined function %s",
- name->value());
- return NULL;
- }
-
- ir_function_signature *callee = f->matching_signature(¶meters);
- if (callee == NULL) {
- ir_read_error(expr, "couldn't find matching signature for function "
- "%s", name->value());
- return NULL;
- }
-
- return new(mem_ctx) ir_call(callee, ¶meters);
-}
-
-ir_expression *
-ir_reader::read_expression(s_expression *expr)
-{
- s_expression *s_type;
- s_symbol *s_op;
- s_expression *s_arg1;
-
- s_pattern pat[] = { "expression", s_type, s_op, s_arg1 };
- if (!PARTIAL_MATCH(expr, pat)) {
- ir_read_error(expr, "expected (expression <type> <operator> "
- "<operand> [<operand>])");
- return NULL;
- }
- s_expression *s_arg2 = (s_expression *) s_arg1->next; // may be tail sentinel
-
- const glsl_type *type = read_type(s_type);
- if (type == NULL)
- return NULL;
-
- /* Read the operator */
- ir_expression_operation op = ir_expression::get_operator(s_op->value());
- if (op == (ir_expression_operation) -1) {
- ir_read_error(expr, "invalid operator: %s", s_op->value());
- return NULL;
- }
-
- unsigned num_operands = ir_expression::get_num_operands(op);
- if (num_operands == 1 && !s_arg1->next->is_tail_sentinel()) {
- ir_read_error(expr, "expected (expression <type> %s <operand>)",
- s_op->value());
- return NULL;
- }
-
- ir_rvalue *arg1 = read_rvalue(s_arg1);
- ir_rvalue *arg2 = NULL;
- if (arg1 == NULL) {
- ir_read_error(NULL, "when reading first operand of %s", s_op->value());
- return NULL;
- }
-
- if (num_operands == 2) {
- if (s_arg2->is_tail_sentinel() || !s_arg2->next->is_tail_sentinel()) {
- ir_read_error(expr, "expected (expression <type> %s <operand> "
- "<operand>)", s_op->value());
- return NULL;
- }
- arg2 = read_rvalue(s_arg2);
- if (arg2 == NULL) {
- ir_read_error(NULL, "when reading second operand of %s",
- s_op->value());
- return NULL;
- }
- }
-
- return new(mem_ctx) ir_expression(op, type, arg1, arg2);
-}
-
-ir_swizzle *
-ir_reader::read_swizzle(s_expression *expr)
-{
- s_symbol *swiz;
- s_expression *sub;
-
- s_pattern pat[] = { "swiz", swiz, sub };
- if (!MATCH(expr, pat)) {
- ir_read_error(expr, "expected (swiz <swizzle> <rvalue>)");
- return NULL;
- }
-
- if (strlen(swiz->value()) > 4) {
- ir_read_error(expr, "expected a valid swizzle; found %s", swiz->value());
- return NULL;
- }
-
- ir_rvalue *rvalue = read_rvalue(sub);
- if (rvalue == NULL)
- return NULL;
-
- ir_swizzle *ir = ir_swizzle::create(rvalue, swiz->value(),
- rvalue->type->vector_elements);
- if (ir == NULL)
- ir_read_error(expr, "invalid swizzle");
-
- return ir;
-}
-
-ir_constant *
-ir_reader::read_constant(s_expression *expr)
-{
- s_expression *type_expr;
- s_list *values;
-
- s_pattern pat[] = { "constant", type_expr, values };
- if (!MATCH(expr, pat)) {
- ir_read_error(expr, "expected (constant <type> (...))");
- return NULL;
- }
-
- const glsl_type *type = read_type(type_expr);
- if (type == NULL)
- return NULL;
-
- if (values == NULL) {
- ir_read_error(expr, "expected (constant <type> (...))");
- return NULL;
- }
-
- if (type->is_array()) {
- unsigned elements_supplied = 0;
- exec_list elements;
- foreach_iter(exec_list_iterator, it, values->subexpressions) {
- s_expression *elt = (s_expression *) it.get();
- ir_constant *ir_elt = read_constant(elt);
- if (ir_elt == NULL)
- return NULL;
- elements.push_tail(ir_elt);
- elements_supplied++;
- }
-
- if (elements_supplied != type->length) {
- ir_read_error(values, "expected exactly %u array elements, "
- "given %u", type->length, elements_supplied);
- return NULL;
- }
- return new(mem_ctx) ir_constant(type, &elements);
- }
-
- const glsl_type *const base_type = type->get_base_type();
-
- ir_constant_data data = { { 0 } };
-
- // Read in list of values (at most 16).
- int k = 0;
- foreach_iter(exec_list_iterator, it, values->subexpressions) {
- if (k >= 16) {
- ir_read_error(values, "expected at most 16 numbers");
- return NULL;
- }
-
- s_expression *expr = (s_expression*) it.get();
-
- if (base_type->base_type == GLSL_TYPE_FLOAT) {
- s_number *value = SX_AS_NUMBER(expr);
- if (value == NULL) {
- ir_read_error(values, "expected numbers");
- return NULL;
- }
- data.f[k] = value->fvalue();
- } else {
- s_int *value = SX_AS_INT(expr);
- if (value == NULL) {
- ir_read_error(values, "expected integers");
- return NULL;
- }
-
- switch (base_type->base_type) {
- case GLSL_TYPE_UINT: {
- data.u[k] = value->value();
- break;
- }
- case GLSL_TYPE_INT: {
- data.i[k] = value->value();
- break;
- }
- case GLSL_TYPE_BOOL: {
- data.b[k] = value->value();
- break;
- }
- default:
- ir_read_error(values, "unsupported constant type");
- return NULL;
- }
- }
- ++k;
- }
-
- return new(mem_ctx) ir_constant(type, &data);
-}
-
-ir_dereference *
-ir_reader::read_dereference(s_expression *expr)
-{
- s_symbol *s_var;
- s_expression *s_subject;
- s_expression *s_index;
- s_symbol *s_field;
-
- s_pattern var_pat[] = { "var_ref", s_var };
- s_pattern array_pat[] = { "array_ref", s_subject, s_index };
- s_pattern record_pat[] = { "record_ref", s_subject, s_field };
-
- if (MATCH(expr, var_pat)) {
- ir_variable *var = state->symbols->get_variable(s_var->value());
- if (var == NULL) {
- ir_read_error(expr, "undeclared variable: %s", s_var->value());
- return NULL;
- }
- return new(mem_ctx) ir_dereference_variable(var);
- } else if (MATCH(expr, array_pat)) {
- ir_rvalue *subject = read_rvalue(s_subject);
- if (subject == NULL) {
- ir_read_error(NULL, "when reading the subject of an array_ref");
- return NULL;
- }
-
- ir_rvalue *idx = read_rvalue(s_index);
- if (subject == NULL) {
- ir_read_error(NULL, "when reading the index of an array_ref");
- return NULL;
- }
- return new(mem_ctx) ir_dereference_array(subject, idx);
- } else if (MATCH(expr, record_pat)) {
- ir_rvalue *subject = read_rvalue(s_subject);
- if (subject == NULL) {
- ir_read_error(NULL, "when reading the subject of a record_ref");
- return NULL;
- }
- return new(mem_ctx) ir_dereference_record(subject, s_field->value());
- }
- return NULL;
-}
-
-ir_texture *
-ir_reader::read_texture(s_expression *expr)
-{
- s_symbol *tag = NULL;
- s_expression *s_type = NULL;
- s_expression *s_sampler = NULL;
- s_expression *s_coord = NULL;
- s_expression *s_offset = NULL;
- s_expression *s_proj = NULL;
- s_list *s_shadow = NULL;
- s_expression *s_lod = NULL;
-
- ir_texture_opcode op = ir_tex; /* silence warning */
-
- s_pattern tex_pattern[] =
- { "tex", s_type, s_sampler, s_coord, s_offset, s_proj, s_shadow };
- s_pattern txf_pattern[] =
- { "txf", s_type, s_sampler, s_coord, s_offset, s_lod };
- s_pattern other_pattern[] =
- { tag, s_type, s_sampler, s_coord, s_offset, s_proj, s_shadow, s_lod };
-
- if (MATCH(expr, tex_pattern)) {
- op = ir_tex;
- } else if (MATCH(expr, txf_pattern)) {
- op = ir_txf;
- } else if (MATCH(expr, other_pattern)) {
- op = ir_texture::get_opcode(tag->value());
- if (op == -1)
- return NULL;
- } else {
- ir_read_error(NULL, "unexpected texture pattern");
- return NULL;
- }
-
- ir_texture *tex = new(mem_ctx) ir_texture(op);
-
- // Read return type
- const glsl_type *type = read_type(s_type);
- if (type == NULL) {
- ir_read_error(NULL, "when reading type in (%s ...)",
- tex->opcode_string());
- return NULL;
- }
-
- // Read sampler (must be a deref)
- ir_dereference *sampler = read_dereference(s_sampler);
- if (sampler == NULL) {
- ir_read_error(NULL, "when reading sampler in (%s ...)",
- tex->opcode_string());
- return NULL;
- }
- tex->set_sampler(sampler, type);
-
- // Read coordinate (any rvalue)
- tex->coordinate = read_rvalue(s_coord);
- if (tex->coordinate == NULL) {
- ir_read_error(NULL, "when reading coordinate in (%s ...)",
- tex->opcode_string());
- return NULL;
- }
-
- // Read texel offset - either 0 or an rvalue.
- s_int *si_offset = SX_AS_INT(s_offset);
- if (si_offset == NULL || si_offset->value() != 0) {
- tex->offset = read_rvalue(s_offset);
- if (tex->offset == NULL) {
- ir_read_error(s_offset, "expected 0 or an expression");
- return NULL;
- }
- }
-
- if (op != ir_txf) {
- s_int *proj_as_int = SX_AS_INT(s_proj);
- if (proj_as_int && proj_as_int->value() == 1) {
- tex->projector = NULL;
- } else {
- tex->projector = read_rvalue(s_proj);
- if (tex->projector == NULL) {
- ir_read_error(NULL, "when reading projective divide in (%s ..)",
- tex->opcode_string());
- return NULL;
- }
- }
-
- if (s_shadow->subexpressions.is_empty()) {
- tex->shadow_comparitor = NULL;
- } else {
- tex->shadow_comparitor = read_rvalue(s_shadow);
- if (tex->shadow_comparitor == NULL) {
- ir_read_error(NULL, "when reading shadow comparitor in (%s ..)",
- tex->opcode_string());
- return NULL;
- }
- }
- }
-
- switch (op) {
- case ir_txb:
- tex->lod_info.bias = read_rvalue(s_lod);
- if (tex->lod_info.bias == NULL) {
- ir_read_error(NULL, "when reading LOD bias in (txb ...)");
- return NULL;
- }
- break;
- case ir_txl:
- case ir_txf:
- tex->lod_info.lod = read_rvalue(s_lod);
- if (tex->lod_info.lod == NULL) {
- ir_read_error(NULL, "when reading LOD in (%s ...)",
- tex->opcode_string());
- return NULL;
- }
- break;
- case ir_txd: {
- s_expression *s_dx, *s_dy;
- s_pattern dxdy_pat[] = { s_dx, s_dy };
- if (!MATCH(s_lod, dxdy_pat)) {
- ir_read_error(s_lod, "expected (dPdx dPdy) in (txd ...)");
- return NULL;
- }
- tex->lod_info.grad.dPdx = read_rvalue(s_dx);
- if (tex->lod_info.grad.dPdx == NULL) {
- ir_read_error(NULL, "when reading dPdx in (txd ...)");
- return NULL;
- }
- tex->lod_info.grad.dPdy = read_rvalue(s_dy);
- if (tex->lod_info.grad.dPdy == NULL) {
- ir_read_error(NULL, "when reading dPdy in (txd ...)");
- return NULL;
- }
- break;
- }
- default:
- // tex doesn't have any extra parameters.
- break;
- };
- return tex;
-}
+/* + * Copyright © 2010 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "ir_reader.h" +#include "glsl_parser_extras.h" +#include "glsl_types.h" +#include "s_expression.h" + +const static bool debug = false; + +class ir_reader { +public: + ir_reader(_mesa_glsl_parse_state *); + + void read(exec_list *instructions, const char *src, bool scan_for_protos); + +private: + void *mem_ctx; + _mesa_glsl_parse_state *state; + + void ir_read_error(s_expression *, const char *fmt, ...); + + const glsl_type *read_type(s_expression *); + + void scan_for_prototypes(exec_list *, s_expression *); + ir_function *read_function(s_expression *, bool skip_body); + void read_function_sig(ir_function *, s_expression *, bool skip_body); + + void read_instructions(exec_list *, s_expression *, ir_loop *); + ir_instruction *read_instruction(s_expression *, ir_loop *); + ir_variable *read_declaration(s_expression *); + ir_if *read_if(s_expression *, ir_loop *); + ir_loop *read_loop(s_expression *); + ir_return *read_return(s_expression *); + ir_rvalue *read_rvalue(s_expression *); + ir_assignment *read_assignment(s_expression *); + ir_expression *read_expression(s_expression *); + ir_call *read_call(s_expression *); + ir_swizzle *read_swizzle(s_expression *); + ir_constant *read_constant(s_expression *); + ir_texture *read_texture(s_expression *); + + ir_dereference *read_dereference(s_expression *); +}; + +ir_reader::ir_reader(_mesa_glsl_parse_state *state) : state(state) +{ + this->mem_ctx = state; +} + +void +_mesa_glsl_read_ir(_mesa_glsl_parse_state *state, exec_list *instructions, + const char *src, bool scan_for_protos) +{ + ir_reader r(state); + r.read(instructions, src, scan_for_protos); +} + +void +ir_reader::read(exec_list *instructions, const char *src, bool scan_for_protos) +{ + s_expression *expr = s_expression::read_expression(mem_ctx, src); + if (expr == NULL) { + ir_read_error(NULL, "couldn't parse S-Expression."); + return; + } + + if (scan_for_protos) { + scan_for_prototypes(instructions, expr); + if (state->error) + return; + } + + read_instructions(instructions, expr, NULL); + ralloc_free(expr); + + if (debug) + validate_ir_tree(instructions); +} + +void +ir_reader::ir_read_error(s_expression *expr, const char *fmt, ...) +{ + va_list ap; + + state->error = true; + + if (state->current_function != NULL) + ralloc_asprintf_append(&state->info_log, "In function %s:\n", + state->current_function->function_name()); + ralloc_strcat(&state->info_log, "error: "); + + va_start(ap, fmt); + ralloc_vasprintf_append(&state->info_log, fmt, ap); + va_end(ap); + ralloc_strcat(&state->info_log, "\n"); + + if (expr != NULL) { + ralloc_strcat(&state->info_log, "...in this context:\n "); + expr->print(); + ralloc_strcat(&state->info_log, "\n\n"); + } +} + +const glsl_type * +ir_reader::read_type(s_expression *expr) +{ + s_expression *s_base_type; + s_int *s_size; + + s_pattern pat[] = { "array", s_base_type, s_size }; + if (MATCH(expr, pat)) { + const glsl_type *base_type = read_type(s_base_type); + if (base_type == NULL) { + ir_read_error(NULL, "when reading base type of array type"); + return NULL; + } + + return glsl_type::get_array_instance(base_type, s_size->value()); + } + + s_symbol *type_sym = SX_AS_SYMBOL(expr); + if (type_sym == NULL) { + ir_read_error(expr, "expected <type>"); + return NULL; + } + + const glsl_type *type = state->symbols->get_type(type_sym->value()); + if (type == NULL) + ir_read_error(expr, "invalid type: %s", type_sym->value()); + + return type; +} + + +void +ir_reader::scan_for_prototypes(exec_list *instructions, s_expression *expr) +{ + s_list *list = SX_AS_LIST(expr); + if (list == NULL) { + ir_read_error(expr, "Expected (<instruction> ...); found an atom."); + return; + } + + foreach_iter(exec_list_iterator, it, list->subexpressions) { + s_list *sub = SX_AS_LIST(it.get()); + if (sub == NULL) + continue; // not a (function ...); ignore it. + + s_symbol *tag = SX_AS_SYMBOL(sub->subexpressions.get_head()); + if (tag == NULL || strcmp(tag->value(), "function") != 0) + continue; // not a (function ...); ignore it. + + ir_function *f = read_function(sub, true); + if (f == NULL) + return; + instructions->push_tail(f); + } +} + +ir_function * +ir_reader::read_function(s_expression *expr, bool skip_body) +{ + bool added = false; + s_symbol *name; + + s_pattern pat[] = { "function", name }; + if (!PARTIAL_MATCH(expr, pat)) { + ir_read_error(expr, "Expected (function <name> (signature ...) ...)"); + return NULL; + } + + ir_function *f = state->symbols->get_function(name->value()); + if (f == NULL) { + f = new(mem_ctx) ir_function(name->value()); + added = state->symbols->add_function(f); + assert(added); + } + + exec_list_iterator it = ((s_list *) expr)->subexpressions.iterator(); + it.next(); // skip "function" tag + it.next(); // skip function name + for (/* nothing */; it.has_next(); it.next()) { + s_expression *s_sig = (s_expression *) it.get(); + read_function_sig(f, s_sig, skip_body); + } + return added ? f : NULL; +} + +void +ir_reader::read_function_sig(ir_function *f, s_expression *expr, bool skip_body) +{ + s_expression *type_expr; + s_list *paramlist; + s_list *body_list; + + s_pattern pat[] = { "signature", type_expr, paramlist, body_list }; + if (!MATCH(expr, pat)) { + ir_read_error(expr, "Expected (signature <type> (parameters ...) " + "(<instruction> ...))"); + return; + } + + const glsl_type *return_type = read_type(type_expr); + if (return_type == NULL) + return; + + s_symbol *paramtag = SX_AS_SYMBOL(paramlist->subexpressions.get_head()); + if (paramtag == NULL || strcmp(paramtag->value(), "parameters") != 0) { + ir_read_error(paramlist, "Expected (parameters ...)"); + return; + } + + // Read the parameters list into a temporary place. + exec_list hir_parameters; + state->symbols->push_scope(); + + exec_list_iterator it = paramlist->subexpressions.iterator(); + for (it.next() /* skip "parameters" */; it.has_next(); it.next()) { + ir_variable *var = read_declaration((s_expression *) it.get()); + if (var == NULL) + return; + + hir_parameters.push_tail(var); + } + + ir_function_signature *sig = f->exact_matching_signature(&hir_parameters); + if (sig == NULL && skip_body) { + /* If scanning for prototypes, generate a new signature. */ + sig = new(mem_ctx) ir_function_signature(return_type); + sig->is_builtin = true; + f->add_signature(sig); + } else if (sig != NULL) { + const char *badvar = sig->qualifiers_match(&hir_parameters); + if (badvar != NULL) { + ir_read_error(expr, "function `%s' parameter `%s' qualifiers " + "don't match prototype", f->name, badvar); + return; + } + + if (sig->return_type != return_type) { + ir_read_error(expr, "function `%s' return type doesn't " + "match prototype", f->name); + return; + } + } else { + /* No prototype for this body exists - skip it. */ + state->symbols->pop_scope(); + return; + } + assert(sig != NULL); + + sig->replace_parameters(&hir_parameters); + + if (!skip_body && !body_list->subexpressions.is_empty()) { + if (sig->is_defined) { + ir_read_error(expr, "function %s redefined", f->name); + return; + } + state->current_function = sig; + read_instructions(&sig->body, body_list, NULL); + state->current_function = NULL; + sig->is_defined = true; + } + + state->symbols->pop_scope(); +} + +void +ir_reader::read_instructions(exec_list *instructions, s_expression *expr, + ir_loop *loop_ctx) +{ + // Read in a list of instructions + s_list *list = SX_AS_LIST(expr); + if (list == NULL) { + ir_read_error(expr, "Expected (<instruction> ...); found an atom."); + return; + } + + foreach_iter(exec_list_iterator, it, list->subexpressions) { + s_expression *sub = (s_expression*) it.get(); + ir_instruction *ir = read_instruction(sub, loop_ctx); + if (ir != NULL) { + /* Global variable declarations should be moved to the top, before + * any functions that might use them. Functions are added to the + * instruction stream when scanning for prototypes, so without this + * hack, they always appear before variable declarations. + */ + if (state->current_function == NULL && ir->as_variable() != NULL) + instructions->push_head(ir); + else + instructions->push_tail(ir); + } + } +} + + +ir_instruction * +ir_reader::read_instruction(s_expression *expr, ir_loop *loop_ctx) +{ + s_symbol *symbol = SX_AS_SYMBOL(expr); + if (symbol != NULL) { + if (strcmp(symbol->value(), "break") == 0 && loop_ctx != NULL) + return new(mem_ctx) ir_loop_jump(ir_loop_jump::jump_break); + if (strcmp(symbol->value(), "continue") == 0 && loop_ctx != NULL) + return new(mem_ctx) ir_loop_jump(ir_loop_jump::jump_continue); + } + + s_list *list = SX_AS_LIST(expr); + if (list == NULL || list->subexpressions.is_empty()) { + ir_read_error(expr, "Invalid instruction.\n"); + return NULL; + } + + s_symbol *tag = SX_AS_SYMBOL(list->subexpressions.get_head()); + if (tag == NULL) { + ir_read_error(expr, "expected instruction tag"); + return NULL; + } + + ir_instruction *inst = NULL; + if (strcmp(tag->value(), "declare") == 0) { + inst = read_declaration(list); + } else if (strcmp(tag->value(), "assign") == 0) { + inst = read_assignment(list); + } else if (strcmp(tag->value(), "if") == 0) { + inst = read_if(list, loop_ctx); + } else if (strcmp(tag->value(), "loop") == 0) { + inst = read_loop(list); + } else if (strcmp(tag->value(), "return") == 0) { + inst = read_return(list); + } else if (strcmp(tag->value(), "function") == 0) { + inst = read_function(list, false); + } else { + inst = read_rvalue(list); + if (inst == NULL) + ir_read_error(NULL, "when reading instruction"); + } + return inst; +} + +ir_variable * +ir_reader::read_declaration(s_expression *expr) +{ + s_list *s_quals; + s_expression *s_type; + s_symbol *s_name; + + s_pattern pat[] = { "declare", s_quals, s_type, s_name }; + if (!MATCH(expr, pat)) { + ir_read_error(expr, "expected (declare (<qualifiers>) <type> <name>)"); + return NULL; + } + + const glsl_type *type = read_type(s_type); + if (type == NULL) + return NULL; + + ir_variable *var = new(mem_ctx) ir_variable(type, s_name->value(), + ir_var_auto); + + foreach_iter(exec_list_iterator, it, s_quals->subexpressions) { + s_symbol *qualifier = SX_AS_SYMBOL(it.get()); + if (qualifier == NULL) { + ir_read_error(expr, "qualifier list must contain only symbols"); + return NULL; + } + + // FINISHME: Check for duplicate/conflicting qualifiers. + if (strcmp(qualifier->value(), "centroid") == 0) { + var->centroid = 1; + } else if (strcmp(qualifier->value(), "invariant") == 0) { + var->invariant = 1; + } else if (strcmp(qualifier->value(), "uniform") == 0) { + var->mode = ir_var_uniform; + } else if (strcmp(qualifier->value(), "auto") == 0) { + var->mode = ir_var_auto; + } else if (strcmp(qualifier->value(), "in") == 0) { + var->mode = ir_var_in; + } else if (strcmp(qualifier->value(), "const_in") == 0) { + var->mode = ir_var_const_in; + } else if (strcmp(qualifier->value(), "out") == 0) { + var->mode = ir_var_out; + } else if (strcmp(qualifier->value(), "inout") == 0) { + var->mode = ir_var_inout; + } else if (strcmp(qualifier->value(), "smooth") == 0) { + var->interpolation = ir_var_smooth; + } else if (strcmp(qualifier->value(), "flat") == 0) { + var->interpolation = ir_var_flat; + } else if (strcmp(qualifier->value(), "noperspective") == 0) { + var->interpolation = ir_var_noperspective; + } else { + ir_read_error(expr, "unknown qualifier: %s", qualifier->value()); + return NULL; + } + } + + // Add the variable to the symbol table + state->symbols->add_variable(var); + + return var; +} + + +ir_if * +ir_reader::read_if(s_expression *expr, ir_loop *loop_ctx) +{ + s_expression *s_cond; + s_expression *s_then; + s_expression *s_else; + + s_pattern pat[] = { "if", s_cond, s_then, s_else }; + if (!MATCH(expr, pat)) { + ir_read_error(expr, "expected (if <condition> (<then>...) (<else>...))"); + return NULL; + } + + ir_rvalue *condition = read_rvalue(s_cond); + if (condition == NULL) { + ir_read_error(NULL, "when reading condition of (if ...)"); + return NULL; + } + + ir_if *iff = new(mem_ctx) ir_if(condition); + + read_instructions(&iff->then_instructions, s_then, loop_ctx); + read_instructions(&iff->else_instructions, s_else, loop_ctx); + if (state->error) { + delete iff; + iff = NULL; + } + return iff; +} + + +ir_loop * +ir_reader::read_loop(s_expression *expr) +{ + s_expression *s_counter, *s_from, *s_to, *s_inc, *s_body; + + s_pattern pat[] = { "loop", s_counter, s_from, s_to, s_inc, s_body }; + if (!MATCH(expr, pat)) { + ir_read_error(expr, "expected (loop <counter> <from> <to> " + "<increment> <body>)"); + return NULL; + } + + // FINISHME: actually read the count/from/to fields. + + ir_loop *loop = new(mem_ctx) ir_loop; + read_instructions(&loop->body_instructions, s_body, loop); + if (state->error) { + delete loop; + loop = NULL; + } + return loop; +} + + +ir_return * +ir_reader::read_return(s_expression *expr) +{ + s_expression *s_retval; + + s_pattern return_value_pat[] = { "return", s_retval}; + s_pattern return_void_pat[] = { "return" }; + if (MATCH(expr, return_value_pat)) { + ir_rvalue *retval = read_rvalue(s_retval); + if (retval == NULL) { + ir_read_error(NULL, "when reading return value"); + return NULL; + } + return new(mem_ctx) ir_return(retval); + } else if (MATCH(expr, return_void_pat)) { + return new(mem_ctx) ir_return; + } else { + ir_read_error(expr, "expected (return <rvalue>) or (return)"); + return NULL; + } +} + + +ir_rvalue * +ir_reader::read_rvalue(s_expression *expr) +{ + s_list *list = SX_AS_LIST(expr); + if (list == NULL || list->subexpressions.is_empty()) + return NULL; + + s_symbol *tag = SX_AS_SYMBOL(list->subexpressions.get_head()); + if (tag == NULL) { + ir_read_error(expr, "expected rvalue tag"); + return NULL; + } + + ir_rvalue *rvalue = read_dereference(list); + if (rvalue != NULL || state->error) + return rvalue; + else if (strcmp(tag->value(), "swiz") == 0) { + rvalue = read_swizzle(list); + } else if (strcmp(tag->value(), "expression") == 0) { + rvalue = read_expression(list); + } else if (strcmp(tag->value(), "call") == 0) { + rvalue = read_call(list); + } else if (strcmp(tag->value(), "constant") == 0) { + rvalue = read_constant(list); + } else { + rvalue = read_texture(list); + if (rvalue == NULL && !state->error) + ir_read_error(expr, "unrecognized rvalue tag: %s", tag->value()); + } + + return rvalue; +} + +ir_assignment * +ir_reader::read_assignment(s_expression *expr) +{ + s_expression *cond_expr = NULL; + s_expression *lhs_expr, *rhs_expr; + s_list *mask_list; + + s_pattern pat4[] = { "assign", mask_list, lhs_expr, rhs_expr }; + s_pattern pat5[] = { "assign", cond_expr, mask_list, lhs_expr, rhs_expr }; + if (!MATCH(expr, pat4) && !MATCH(expr, pat5)) { + ir_read_error(expr, "expected (assign [<condition>] (<write mask>) " + "<lhs> <rhs>)"); + return NULL; + } + + ir_rvalue *condition = NULL; + if (cond_expr != NULL) { + condition = read_rvalue(cond_expr); + if (condition == NULL) { + ir_read_error(NULL, "when reading condition of assignment"); + return NULL; + } + } + + unsigned mask = 0; + + s_symbol *mask_symbol; + s_pattern mask_pat[] = { mask_symbol }; + if (MATCH(mask_list, mask_pat)) { + const char *mask_str = mask_symbol->value(); + unsigned mask_length = strlen(mask_str); + if (mask_length > 4) { + ir_read_error(expr, "invalid write mask: %s", mask_str); + return NULL; + } + + const unsigned idx_map[] = { 3, 0, 1, 2 }; /* w=bit 3, x=0, y=1, z=2 */ + + for (unsigned i = 0; i < mask_length; i++) { + if (mask_str[i] < 'w' || mask_str[i] > 'z') { + ir_read_error(expr, "write mask contains invalid character: %c", + mask_str[i]); + return NULL; + } + mask |= 1 << idx_map[mask_str[i] - 'w']; + } + } else if (!mask_list->subexpressions.is_empty()) { + ir_read_error(mask_list, "expected () or (<write mask>)"); + return NULL; + } + + ir_dereference *lhs = read_dereference(lhs_expr); + if (lhs == NULL) { + ir_read_error(NULL, "when reading left-hand side of assignment"); + return NULL; + } + + ir_rvalue *rhs = read_rvalue(rhs_expr); + if (rhs == NULL) { + ir_read_error(NULL, "when reading right-hand side of assignment"); + return NULL; + } + + if (mask == 0 && (lhs->type->is_vector() || lhs->type->is_scalar())) { + ir_read_error(expr, "non-zero write mask required."); + return NULL; + } + + return new(mem_ctx) ir_assignment(lhs, rhs, condition, mask); +} + +ir_call * +ir_reader::read_call(s_expression *expr) +{ + s_symbol *name; + s_list *params; + + s_pattern pat[] = { "call", name, params }; + if (!MATCH(expr, pat)) { + ir_read_error(expr, "expected (call <name> (<param> ...))"); + return NULL; + } + + exec_list parameters; + + foreach_iter(exec_list_iterator, it, params->subexpressions) { + s_expression *expr = (s_expression*) it.get(); + ir_rvalue *param = read_rvalue(expr); + if (param == NULL) { + ir_read_error(expr, "when reading parameter to function call"); + return NULL; + } + parameters.push_tail(param); + } + + ir_function *f = state->symbols->get_function(name->value()); + if (f == NULL) { + ir_read_error(expr, "found call to undefined function %s", + name->value()); + return NULL; + } + + ir_function_signature *callee = f->matching_signature(¶meters); + if (callee == NULL) { + ir_read_error(expr, "couldn't find matching signature for function " + "%s", name->value()); + return NULL; + } + + return new(mem_ctx) ir_call(callee, ¶meters); +} + +ir_expression * +ir_reader::read_expression(s_expression *expr) +{ + s_expression *s_type; + s_symbol *s_op; + s_expression *s_arg1; + + s_pattern pat[] = { "expression", s_type, s_op, s_arg1 }; + if (!PARTIAL_MATCH(expr, pat)) { + ir_read_error(expr, "expected (expression <type> <operator> " + "<operand> [<operand>])"); + return NULL; + } + s_expression *s_arg2 = (s_expression *) s_arg1->next; // may be tail sentinel + + const glsl_type *type = read_type(s_type); + if (type == NULL) + return NULL; + + /* Read the operator */ + ir_expression_operation op = ir_expression::get_operator(s_op->value()); + if (op == (ir_expression_operation) -1) { + ir_read_error(expr, "invalid operator: %s", s_op->value()); + return NULL; + } + + unsigned num_operands = ir_expression::get_num_operands(op); + if (num_operands == 1 && !s_arg1->next->is_tail_sentinel()) { + ir_read_error(expr, "expected (expression <type> %s <operand>)", + s_op->value()); + return NULL; + } + + ir_rvalue *arg1 = read_rvalue(s_arg1); + ir_rvalue *arg2 = NULL; + if (arg1 == NULL) { + ir_read_error(NULL, "when reading first operand of %s", s_op->value()); + return NULL; + } + + if (num_operands == 2) { + if (s_arg2->is_tail_sentinel() || !s_arg2->next->is_tail_sentinel()) { + ir_read_error(expr, "expected (expression <type> %s <operand> " + "<operand>)", s_op->value()); + return NULL; + } + arg2 = read_rvalue(s_arg2); + if (arg2 == NULL) { + ir_read_error(NULL, "when reading second operand of %s", + s_op->value()); + return NULL; + } + } + + return new(mem_ctx) ir_expression(op, type, arg1, arg2); +} + +ir_swizzle * +ir_reader::read_swizzle(s_expression *expr) +{ + s_symbol *swiz; + s_expression *sub; + + s_pattern pat[] = { "swiz", swiz, sub }; + if (!MATCH(expr, pat)) { + ir_read_error(expr, "expected (swiz <swizzle> <rvalue>)"); + return NULL; + } + + if (strlen(swiz->value()) > 4) { + ir_read_error(expr, "expected a valid swizzle; found %s", swiz->value()); + return NULL; + } + + ir_rvalue *rvalue = read_rvalue(sub); + if (rvalue == NULL) + return NULL; + + ir_swizzle *ir = ir_swizzle::create(rvalue, swiz->value(), + rvalue->type->vector_elements); + if (ir == NULL) + ir_read_error(expr, "invalid swizzle"); + + return ir; +} + +ir_constant * +ir_reader::read_constant(s_expression *expr) +{ + s_expression *type_expr; + s_list *values; + + s_pattern pat[] = { "constant", type_expr, values }; + if (!MATCH(expr, pat)) { + ir_read_error(expr, "expected (constant <type> (...))"); + return NULL; + } + + const glsl_type *type = read_type(type_expr); + if (type == NULL) + return NULL; + + if (values == NULL) { + ir_read_error(expr, "expected (constant <type> (...))"); + return NULL; + } + + if (type->is_array()) { + unsigned elements_supplied = 0; + exec_list elements; + foreach_iter(exec_list_iterator, it, values->subexpressions) { + s_expression *elt = (s_expression *) it.get(); + ir_constant *ir_elt = read_constant(elt); + if (ir_elt == NULL) + return NULL; + elements.push_tail(ir_elt); + elements_supplied++; + } + + if (elements_supplied != type->length) { + ir_read_error(values, "expected exactly %u array elements, " + "given %u", type->length, elements_supplied); + return NULL; + } + return new(mem_ctx) ir_constant(type, &elements); + } + + const glsl_type *const base_type = type->get_base_type(); + + ir_constant_data data = { { 0 } }; + + // Read in list of values (at most 16). + int k = 0; + foreach_iter(exec_list_iterator, it, values->subexpressions) { + if (k >= 16) { + ir_read_error(values, "expected at most 16 numbers"); + return NULL; + } + + s_expression *expr = (s_expression*) it.get(); + + if (base_type->base_type == GLSL_TYPE_FLOAT) { + s_number *value = SX_AS_NUMBER(expr); + if (value == NULL) { + ir_read_error(values, "expected numbers"); + return NULL; + } + data.f[k] = value->fvalue(); + } else { + s_int *value = SX_AS_INT(expr); + if (value == NULL) { + ir_read_error(values, "expected integers"); + return NULL; + } + + switch (base_type->base_type) { + case GLSL_TYPE_UINT: { + data.u[k] = value->value(); + break; + } + case GLSL_TYPE_INT: { + data.i[k] = value->value(); + break; + } + case GLSL_TYPE_BOOL: { + data.b[k] = value->value(); + break; + } + default: + ir_read_error(values, "unsupported constant type"); + return NULL; + } + } + ++k; + } + + return new(mem_ctx) ir_constant(type, &data); +} + +ir_dereference * +ir_reader::read_dereference(s_expression *expr) +{ + s_symbol *s_var; + s_expression *s_subject; + s_expression *s_index; + s_symbol *s_field; + + s_pattern var_pat[] = { "var_ref", s_var }; + s_pattern array_pat[] = { "array_ref", s_subject, s_index }; + s_pattern record_pat[] = { "record_ref", s_subject, s_field }; + + if (MATCH(expr, var_pat)) { + ir_variable *var = state->symbols->get_variable(s_var->value()); + if (var == NULL) { + ir_read_error(expr, "undeclared variable: %s", s_var->value()); + return NULL; + } + return new(mem_ctx) ir_dereference_variable(var); + } else if (MATCH(expr, array_pat)) { + ir_rvalue *subject = read_rvalue(s_subject); + if (subject == NULL) { + ir_read_error(NULL, "when reading the subject of an array_ref"); + return NULL; + } + + ir_rvalue *idx = read_rvalue(s_index); + if (subject == NULL) { + ir_read_error(NULL, "when reading the index of an array_ref"); + return NULL; + } + return new(mem_ctx) ir_dereference_array(subject, idx); + } else if (MATCH(expr, record_pat)) { + ir_rvalue *subject = read_rvalue(s_subject); + if (subject == NULL) { + ir_read_error(NULL, "when reading the subject of a record_ref"); + return NULL; + } + return new(mem_ctx) ir_dereference_record(subject, s_field->value()); + } + return NULL; +} + +ir_texture * +ir_reader::read_texture(s_expression *expr) +{ + s_symbol *tag = NULL; + s_expression *s_type = NULL; + s_expression *s_sampler = NULL; + s_expression *s_coord = NULL; + s_expression *s_offset = NULL; + s_expression *s_proj = NULL; + s_list *s_shadow = NULL; + s_expression *s_lod = NULL; + + ir_texture_opcode op = ir_tex; /* silence warning */ + + s_pattern tex_pattern[] = + { "tex", s_type, s_sampler, s_coord, s_offset, s_proj, s_shadow }; + s_pattern txf_pattern[] = + { "txf", s_type, s_sampler, s_coord, s_offset, s_lod }; + s_pattern other_pattern[] = + { tag, s_type, s_sampler, s_coord, s_offset, s_proj, s_shadow, s_lod }; + + if (MATCH(expr, tex_pattern)) { + op = ir_tex; + } else if (MATCH(expr, txf_pattern)) { + op = ir_txf; + } else if (MATCH(expr, other_pattern)) { + op = ir_texture::get_opcode(tag->value()); + if (op == -1) + return NULL; + } else { + ir_read_error(NULL, "unexpected texture pattern"); + return NULL; + } + + ir_texture *tex = new(mem_ctx) ir_texture(op); + + // Read return type + const glsl_type *type = read_type(s_type); + if (type == NULL) { + ir_read_error(NULL, "when reading type in (%s ...)", + tex->opcode_string()); + return NULL; + } + + // Read sampler (must be a deref) + ir_dereference *sampler = read_dereference(s_sampler); + if (sampler == NULL) { + ir_read_error(NULL, "when reading sampler in (%s ...)", + tex->opcode_string()); + return NULL; + } + tex->set_sampler(sampler, type); + + // Read coordinate (any rvalue) + tex->coordinate = read_rvalue(s_coord); + if (tex->coordinate == NULL) { + ir_read_error(NULL, "when reading coordinate in (%s ...)", + tex->opcode_string()); + return NULL; + } + + // Read texel offset - either 0 or an rvalue. + s_int *si_offset = SX_AS_INT(s_offset); + if (si_offset == NULL || si_offset->value() != 0) { + tex->offset = read_rvalue(s_offset); + if (tex->offset == NULL) { + ir_read_error(s_offset, "expected 0 or an expression"); + return NULL; + } + } + + if (op != ir_txf) { + s_int *proj_as_int = SX_AS_INT(s_proj); + if (proj_as_int && proj_as_int->value() == 1) { + tex->projector = NULL; + } else { + tex->projector = read_rvalue(s_proj); + if (tex->projector == NULL) { + ir_read_error(NULL, "when reading projective divide in (%s ..)", + tex->opcode_string()); + return NULL; + } + } + + if (s_shadow->subexpressions.is_empty()) { + tex->shadow_comparitor = NULL; + } else { + tex->shadow_comparitor = read_rvalue(s_shadow); + if (tex->shadow_comparitor == NULL) { + ir_read_error(NULL, "when reading shadow comparitor in (%s ..)", + tex->opcode_string()); + return NULL; + } + } + } + + switch (op) { + case ir_txb: + tex->lod_info.bias = read_rvalue(s_lod); + if (tex->lod_info.bias == NULL) { + ir_read_error(NULL, "when reading LOD bias in (txb ...)"); + return NULL; + } + break; + case ir_txl: + case ir_txf: + tex->lod_info.lod = read_rvalue(s_lod); + if (tex->lod_info.lod == NULL) { + ir_read_error(NULL, "when reading LOD in (%s ...)", + tex->opcode_string()); + return NULL; + } + break; + case ir_txd: { + s_expression *s_dx, *s_dy; + s_pattern dxdy_pat[] = { s_dx, s_dy }; + if (!MATCH(s_lod, dxdy_pat)) { + ir_read_error(s_lod, "expected (dPdx dPdy) in (txd ...)"); + return NULL; + } + tex->lod_info.grad.dPdx = read_rvalue(s_dx); + if (tex->lod_info.grad.dPdx == NULL) { + ir_read_error(NULL, "when reading dPdx in (txd ...)"); + return NULL; + } + tex->lod_info.grad.dPdy = read_rvalue(s_dy); + if (tex->lod_info.grad.dPdy == NULL) { + ir_read_error(NULL, "when reading dPdy in (txd ...)"); + return NULL; + } + break; + } + default: + // tex doesn't have any extra parameters. + break; + }; + return tex; +} diff --git a/mesalib/src/glsl/linker.cpp b/mesalib/src/glsl/linker.cpp index 265da84e5..34b64837a 100644 --- a/mesalib/src/glsl/linker.cpp +++ b/mesalib/src/glsl/linker.cpp @@ -1248,7 +1248,7 @@ assign_attribute_or_color_locations(gl_shader_program *prog, */ const int generic_base = (target_index == MESA_SHADER_VERTEX) - ? VERT_ATTRIB_GENERIC0 : FRAG_RESULT_DATA0; + ? (int) VERT_ATTRIB_GENERIC0 : (int) FRAG_RESULT_DATA0; const enum ir_variable_mode direction = (target_index == MESA_SHADER_VERTEX) ? ir_var_in : ir_var_out; diff --git a/mesalib/src/glsl/lower_jumps.cpp b/mesalib/src/glsl/lower_jumps.cpp index 17be39f5b..61874990a 100644 --- a/mesalib/src/glsl/lower_jumps.cpp +++ b/mesalib/src/glsl/lower_jumps.cpp @@ -1,570 +1,1010 @@ -/*
- * Copyright © 2010 Luca Barbieri
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * \file lower_jumps.cpp
- *
- * This pass lowers jumps (break, continue, and return) to if/else structures.
- *
- * It can be asked to:
- * 1. Pull jumps out of ifs where possible
- * 2. Remove all "continue"s, replacing them with an "execute flag"
- * 3. Replace all "break" with a single conditional one at the end of the loop
- * 4. Replace all "return"s with a single return at the end of the function,
- * for the main function and/or other functions
- *
- * Applying this pass gives several benefits:
- * 1. All functions can be inlined.
- * 2. nv40 and other pre-DX10 chips without "continue" can be supported
- * 3. nv30 and other pre-DX10 chips with no control flow at all are better
- * supported
- *
- * Continues are lowered by adding a per-loop "execute flag", initialized to
- * true, that when cleared inhibits all execution until the end of the loop.
- *
- * Breaks are lowered to continues, plus setting a "break flag" that is checked
- * at the end of the loop, and trigger the unique "break".
- *
- * Returns are lowered to breaks/continues, plus adding a "return flag" that
- * causes loops to break again out of their enclosing loops until all the
- * loops are exited: then the "execute flag" logic will ignore everything
- * until the end of the function.
- *
- * Note that "continue" and "return" can also be implemented by adding
- * a dummy loop and using break.
- * However, this is bad for hardware with limited nesting depth, and
- * prevents further optimization, and thus is not currently performed.
- */
-
-#include "glsl_types.h"
-#include <string.h>
-#include "ir.h"
-
-enum jump_strength
-{
- strength_none,
- strength_always_clears_execute_flag,
- strength_continue,
- strength_break,
- strength_return
-};
-
-struct block_record
-{
- /* minimum jump strength (of lowered IR, not pre-lowering IR)
- *
- * If the block ends with a jump, must be the strength of the jump.
- * Otherwise, the jump would be dead and have been deleted before)
- *
- * If the block doesn't end with a jump, it can be different than strength_none if all paths before it lead to some jump
- * (e.g. an if with a return in one branch, and a break in the other, while not lowering them)
- * Note that identical jumps are usually unified though.
- */
- jump_strength min_strength;
-
- /* can anything clear the execute flag? */
- bool may_clear_execute_flag;
-
- block_record()
- {
- this->min_strength = strength_none;
- this->may_clear_execute_flag = false;
- }
-};
-
-struct loop_record
-{
- ir_function_signature* signature;
- ir_loop* loop;
-
- /* used to avoid lowering the break used to represent lowered breaks */
- unsigned nesting_depth;
- bool in_if_at_the_end_of_the_loop;
-
- bool may_set_return_flag;
-
- ir_variable* break_flag;
- ir_variable* execute_flag; /* cleared to emulate continue */
-
- loop_record(ir_function_signature* p_signature = 0, ir_loop* p_loop = 0)
- {
- this->signature = p_signature;
- this->loop = p_loop;
- this->nesting_depth = 0;
- this->in_if_at_the_end_of_the_loop = false;
- this->may_set_return_flag = false;
- this->break_flag = 0;
- this->execute_flag = 0;
- }
-
- ir_variable* get_execute_flag()
- {
- /* also supported for the "function loop" */
- if(!this->execute_flag) {
- exec_list& list = this->loop ? this->loop->body_instructions : signature->body;
- this->execute_flag = new(this->signature) ir_variable(glsl_type::bool_type, "execute_flag", ir_var_temporary);
- list.push_head(new(this->signature) ir_assignment(new(this->signature) ir_dereference_variable(execute_flag), new(this->signature) ir_constant(true), 0));
- list.push_head(this->execute_flag);
- }
- return this->execute_flag;
- }
-
- ir_variable* get_break_flag()
- {
- assert(this->loop);
- if(!this->break_flag) {
- this->break_flag = new(this->signature) ir_variable(glsl_type::bool_type, "break_flag", ir_var_temporary);
- this->loop->insert_before(this->break_flag);
- this->loop->insert_before(new(this->signature) ir_assignment(new(this->signature) ir_dereference_variable(break_flag), new(this->signature) ir_constant(false), 0));
- }
- return this->break_flag;
- }
-};
-
-struct function_record
-{
- ir_function_signature* signature;
- ir_variable* return_flag; /* used to break out of all loops and then jump to the return instruction */
- ir_variable* return_value;
- bool is_main;
- unsigned nesting_depth;
-
- function_record(ir_function_signature* p_signature = 0)
- {
- this->signature = p_signature;
- this->return_flag = 0;
- this->return_value = 0;
- this->nesting_depth = 0;
- this->is_main = this->signature && (strcmp(this->signature->function_name(), "main") == 0);
- }
-
- ir_variable* get_return_flag()
- {
- if(!this->return_flag) {
- this->return_flag = new(this->signature) ir_variable(glsl_type::bool_type, "return_flag", ir_var_temporary);
- this->signature->body.push_head(new(this->signature) ir_assignment(new(this->signature) ir_dereference_variable(return_flag), new(this->signature) ir_constant(false), 0));
- this->signature->body.push_head(this->return_flag);
- }
- return this->return_flag;
- }
-
- ir_variable* get_return_value()
- {
- if(!this->return_value) {
- assert(!this->signature->return_type->is_void());
- return_value = new(this->signature) ir_variable(this->signature->return_type, "return_value", ir_var_temporary);
- this->signature->body.push_head(this->return_value);
- }
- return this->return_value;
- }
-};
-
-struct ir_lower_jumps_visitor : public ir_control_flow_visitor {
- bool progress;
-
- struct function_record function;
- struct loop_record loop;
- struct block_record block;
-
- bool pull_out_jumps;
- bool lower_continue;
- bool lower_break;
- bool lower_sub_return;
- bool lower_main_return;
-
- ir_lower_jumps_visitor()
- {
- this->progress = false;
- }
-
- void truncate_after_instruction(exec_node *ir)
- {
- if (!ir)
- return;
-
- while (!ir->get_next()->is_tail_sentinel()) {
- ((ir_instruction *)ir->get_next())->remove();
- this->progress = true;
- }
- }
-
- void move_outer_block_inside(ir_instruction *ir, exec_list *inner_block)
- {
- while (!ir->get_next()->is_tail_sentinel()) {
- ir_instruction *move_ir = (ir_instruction *)ir->get_next();
-
- move_ir->remove();
- inner_block->push_tail(move_ir);
- }
- }
-
- virtual void visit(class ir_loop_jump * ir)
- {
- truncate_after_instruction(ir);
- this->block.min_strength = ir->is_break() ? strength_break : strength_continue;
- }
-
- virtual void visit(class ir_return * ir)
- {
- truncate_after_instruction(ir);
- this->block.min_strength = strength_return;
- }
-
- virtual void visit(class ir_discard * ir)
- {
- }
-
- enum jump_strength get_jump_strength(ir_instruction* ir)
- {
- if(!ir)
- return strength_none;
- else if(ir->ir_type == ir_type_loop_jump) {
- if(((ir_loop_jump*)ir)->is_break())
- return strength_break;
- else
- return strength_continue;
- } else if(ir->ir_type == ir_type_return)
- return strength_return;
- else
- return strength_none;
- }
-
- bool should_lower_jump(ir_jump* ir)
- {
- unsigned strength = get_jump_strength(ir);
- bool lower;
- switch(strength)
- {
- case strength_none:
- lower = false; /* don't change this, code relies on it */
- break;
- case strength_continue:
- lower = lower_continue;
- break;
- case strength_break:
- assert(this->loop.loop);
- /* never lower "canonical break" */
- if(ir->get_next()->is_tail_sentinel() && (this->loop.nesting_depth == 0
- || (this->loop.nesting_depth == 1 && this->loop.in_if_at_the_end_of_the_loop)))
- lower = false;
- else
- lower = lower_break;
- break;
- case strength_return:
- /* never lower return at the end of a this->function */
- if(this->function.nesting_depth == 0 && ir->get_next()->is_tail_sentinel())
- lower = false;
- else if (this->function.is_main)
- lower = lower_main_return;
- else
- lower = lower_sub_return;
- break;
- }
- return lower;
- }
-
- block_record visit_block(exec_list* list)
- {
- block_record saved_block = this->block;
- this->block = block_record();
- visit_exec_list(list, this);
- block_record ret = this->block;
- this->block = saved_block;
- return ret;
- }
-
- virtual void visit(ir_if *ir)
- {
- if(this->loop.nesting_depth == 0 && ir->get_next()->is_tail_sentinel())
- this->loop.in_if_at_the_end_of_the_loop = true;
-
- ++this->function.nesting_depth;
- ++this->loop.nesting_depth;
-
- block_record block_records[2];
- ir_jump* jumps[2];
-
- block_records[0] = visit_block(&ir->then_instructions);
- block_records[1] = visit_block(&ir->else_instructions);
-
-retry: /* we get here if we put code after the if inside a branch */
- for(unsigned i = 0; i < 2; ++i) {
- exec_list& list = i ? ir->else_instructions : ir->then_instructions;
- jumps[i] = 0;
- if(!list.is_empty() && get_jump_strength((ir_instruction*)list.get_tail()))
- jumps[i] = (ir_jump*)list.get_tail();
- }
-
- for(;;) {
- jump_strength jump_strengths[2];
-
- for(unsigned i = 0; i < 2; ++i) {
- if(jumps[i]) {
- jump_strengths[i] = block_records[i].min_strength;
- assert(jump_strengths[i] == get_jump_strength(jumps[i]));
- } else
- jump_strengths[i] = strength_none;
- }
-
- /* move both jumps out if possible */
- if(pull_out_jumps && jump_strengths[0] == jump_strengths[1]) {
- bool unify = true;
- if(jump_strengths[0] == strength_continue)
- ir->insert_after(new(ir) ir_loop_jump(ir_loop_jump::jump_continue));
- else if(jump_strengths[0] == strength_break)
- ir->insert_after(new(ir) ir_loop_jump(ir_loop_jump::jump_break));
- /* FINISHME: unify returns with identical expressions */
- else if(jump_strengths[0] == strength_return && this->function.signature->return_type->is_void())
- ir->insert_after(new(ir) ir_return(NULL));
- else
- unify = false;
-
- if(unify) {
- jumps[0]->remove();
- jumps[1]->remove();
- this->progress = true;
-
- jumps[0] = 0;
- jumps[1] = 0;
- block_records[0].min_strength = strength_none;
- block_records[1].min_strength = strength_none;
- break;
- }
- }
-
- /* lower a jump: if both need to lowered, start with the strongest one, so that
- * we might later unify the lowered version with the other one
- */
- bool should_lower[2];
- for(unsigned i = 0; i < 2; ++i)
- should_lower[i] = should_lower_jump(jumps[i]);
-
- int lower;
- if(should_lower[1] && should_lower[0])
- lower = jump_strengths[1] > jump_strengths[0];
- else if(should_lower[0])
- lower = 0;
- else if(should_lower[1])
- lower = 1;
- else
- break;
-
- if(jump_strengths[lower] == strength_return) {
- ir_variable* return_flag = this->function.get_return_flag();
- if(!this->function.signature->return_type->is_void()) {
- ir_variable* return_value = this->function.get_return_value();
- jumps[lower]->insert_before(new(ir) ir_assignment(new (ir) ir_dereference_variable(return_value), ((ir_return*)jumps[lower])->value, NULL));
- }
- jumps[lower]->insert_before(new(ir) ir_assignment(new (ir) ir_dereference_variable(return_flag), new (ir) ir_constant(true), NULL));
- this->loop.may_set_return_flag = true;
- if(this->loop.loop) {
- ir_loop_jump* lowered = 0;
- lowered = new(ir) ir_loop_jump(ir_loop_jump::jump_break);
- block_records[lower].min_strength = strength_break;
- jumps[lower]->replace_with(lowered);
- jumps[lower] = lowered;
- } else
- goto lower_continue;
- this->progress = true;
- } else if(jump_strengths[lower] == strength_break) {
- /* We can't lower to an actual continue because that would execute the increment.
- *
- * In the lowered code, we instead put the break check between the this->loop body and the increment,
- * which is impossible with a real continue as defined by the GLSL IR currently.
- *
- * Smarter options (such as undoing the increment) are possible but it's not worth implementing them,
- * because if break is lowered, continue is almost surely lowered too.
- */
- jumps[lower]->insert_before(new(ir) ir_assignment(new (ir) ir_dereference_variable(this->loop.get_break_flag()), new (ir) ir_constant(true), 0));
- goto lower_continue;
- } else if(jump_strengths[lower] == strength_continue) {
-lower_continue:
- ir_variable* execute_flag = this->loop.get_execute_flag();
- jumps[lower]->replace_with(new(ir) ir_assignment(new (ir) ir_dereference_variable(execute_flag), new (ir) ir_constant(false), 0));
- jumps[lower] = 0;
- block_records[lower].min_strength = strength_always_clears_execute_flag;
- block_records[lower].may_clear_execute_flag = true;
- this->progress = true;
- break;
- }
- }
-
- /* move out a jump out if possible */
- if(pull_out_jumps) {
- int move_out = -1;
- if(jumps[0] && block_records[1].min_strength >= strength_continue)
- move_out = 0;
- else if(jumps[1] && block_records[0].min_strength >= strength_continue)
- move_out = 1;
-
- if(move_out >= 0)
- {
- jumps[move_out]->remove();
- ir->insert_after(jumps[move_out]);
- jumps[move_out] = 0;
- block_records[move_out].min_strength = strength_none;
- this->progress = true;
- }
- }
-
- if(block_records[0].min_strength < block_records[1].min_strength)
- this->block.min_strength = block_records[0].min_strength;
- else
- this->block.min_strength = block_records[1].min_strength;
- this->block.may_clear_execute_flag = this->block.may_clear_execute_flag || block_records[0].may_clear_execute_flag || block_records[1].may_clear_execute_flag;
-
- if(this->block.min_strength)
- truncate_after_instruction(ir);
- else if(this->block.may_clear_execute_flag)
- {
- int move_into = -1;
- if(block_records[0].min_strength && !block_records[1].may_clear_execute_flag)
- move_into = 1;
- else if(block_records[1].min_strength && !block_records[0].may_clear_execute_flag)
- move_into = 0;
-
- if(move_into >= 0) {
- assert(!block_records[move_into].min_strength && !block_records[move_into].may_clear_execute_flag); /* otherwise, we just truncated */
-
- exec_list* list = move_into ? &ir->else_instructions : &ir->then_instructions;
- exec_node* next = ir->get_next();
- if(!next->is_tail_sentinel()) {
- move_outer_block_inside(ir, list);
-
- exec_list list;
- list.head = next;
- block_records[move_into] = visit_block(&list);
-
- this->progress = true;
- goto retry;
- }
- } else {
- ir_instruction* ir_after;
- for(ir_after = (ir_instruction*)ir->get_next(); !ir_after->is_tail_sentinel();)
- {
- ir_if* ir_if = ir_after->as_if();
- if(ir_if && ir_if->else_instructions.is_empty()) {
- ir_dereference_variable* ir_if_cond_deref = ir_if->condition->as_dereference_variable();
- if(ir_if_cond_deref && ir_if_cond_deref->var == this->loop.execute_flag) {
- ir_instruction* ir_next = (ir_instruction*)ir_after->get_next();
- ir_after->insert_before(&ir_if->then_instructions);
- ir_after->remove();
- ir_after = ir_next;
- continue;
- }
- }
- ir_after = (ir_instruction*)ir_after->get_next();
-
- /* only set this if we find any unprotected instruction */
- this->progress = true;
- }
-
- if(!ir->get_next()->is_tail_sentinel()) {
- assert(this->loop.execute_flag);
- ir_if* if_execute = new(ir) ir_if(new(ir) ir_dereference_variable(this->loop.execute_flag));
- move_outer_block_inside(ir, &if_execute->then_instructions);
- ir->insert_after(if_execute);
- }
- }
- }
- --this->loop.nesting_depth;
- --this->function.nesting_depth;
- }
-
- virtual void visit(ir_loop *ir)
- {
- ++this->function.nesting_depth;
- loop_record saved_loop = this->loop;
- this->loop = loop_record(this->function.signature, ir);
-
- block_record body = visit_block(&ir->body_instructions);
-
- if(body.min_strength >= strength_break) {
- /* FINISHME: turn the this->loop into an if, or replace it with its body */
- }
-
- if(this->loop.break_flag) {
- ir_if* break_if = new(ir) ir_if(new(ir) ir_dereference_variable(this->loop.break_flag));
- break_if->then_instructions.push_tail(new(ir) ir_loop_jump(ir_loop_jump::jump_break));
- ir->body_instructions.push_tail(break_if);
- }
-
- if(this->loop.may_set_return_flag) {
- assert(this->function.return_flag);
- ir_if* return_if = new(ir) ir_if(new(ir) ir_dereference_variable(this->function.return_flag));
- saved_loop.may_set_return_flag = true;
- if(saved_loop.loop)
- return_if->then_instructions.push_tail(new(ir) ir_loop_jump(ir_loop_jump::jump_break));
- else
- move_outer_block_inside(ir, &return_if->else_instructions);
- ir->insert_after(return_if);
- }
-
- this->loop = saved_loop;
- --this->function.nesting_depth;
- }
-
- virtual void visit(ir_function_signature *ir)
- {
- /* these are not strictly necessary */
- assert(!this->function.signature);
- assert(!this->loop.loop);
-
- function_record saved_function = this->function;
- loop_record saved_loop = this->loop;
- this->function = function_record(ir);
- this->loop = loop_record(ir);
-
- assert(!this->loop.loop);
- visit_block(&ir->body);
-
- if(this->function.return_value)
- ir->body.push_tail(new(ir) ir_return(new (ir) ir_dereference_variable(this->function.return_value)));
-
- this->loop = saved_loop;
- this->function = saved_function;
- }
-
- virtual void visit(class ir_function * ir)
- {
- visit_block(&ir->signatures);
- }
-};
-
-bool
-do_lower_jumps(exec_list *instructions, bool pull_out_jumps, bool lower_sub_return, bool lower_main_return, bool lower_continue, bool lower_break)
-{
- ir_lower_jumps_visitor v;
- v.pull_out_jumps = pull_out_jumps;
- v.lower_continue = lower_continue;
- v.lower_break = lower_break;
- v.lower_sub_return = lower_sub_return;
- v.lower_main_return = lower_main_return;
-
- do {
- v.progress = false;
- visit_exec_list(instructions, &v);
- } while (v.progress);
-
- return v.progress;
-}
+/* + * Copyright © 2010 Luca Barbieri + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/** + * \file lower_jumps.cpp + * + * This pass lowers jumps (break, continue, and return) to if/else structures. + * + * It can be asked to: + * 1. Pull jumps out of ifs where possible + * 2. Remove all "continue"s, replacing them with an "execute flag" + * 3. Replace all "break" with a single conditional one at the end of the loop + * 4. Replace all "return"s with a single return at the end of the function, + * for the main function and/or other functions + * + * Applying this pass gives several benefits: + * 1. All functions can be inlined. + * 2. nv40 and other pre-DX10 chips without "continue" can be supported + * 3. nv30 and other pre-DX10 chips with no control flow at all are better + * supported + * + * Continues are lowered by adding a per-loop "execute flag", initialized to + * true, that when cleared inhibits all execution until the end of the loop. + * + * Breaks are lowered to continues, plus setting a "break flag" that is checked + * at the end of the loop, and trigger the unique "break". + * + * Returns are lowered to breaks/continues, plus adding a "return flag" that + * causes loops to break again out of their enclosing loops until all the + * loops are exited: then the "execute flag" logic will ignore everything + * until the end of the function. + * + * Note that "continue" and "return" can also be implemented by adding + * a dummy loop and using break. + * However, this is bad for hardware with limited nesting depth, and + * prevents further optimization, and thus is not currently performed. + */ + +#include "glsl_types.h" +#include <string.h> +#include "ir.h" + +/** + * Enum recording the result of analyzing how control flow might exit + * an IR node. + * + * Each possible value of jump_strength indicates a strictly stronger + * guarantee on control flow than the previous value. + * + * The ordering of strengths roughly reflects the way jumps are + * lowered: jumps with higher strength tend to be lowered to jumps of + * lower strength. Accordingly, strength is used as a heuristic to + * determine which lowering to perform first. + * + * This enum is also used by get_jump_strength() to categorize + * instructions as either break, continue, return, or other. When + * used in this fashion, strength_always_clears_execute_flag is not + * used. + * + * The control flow analysis made by this optimization pass makes two + * simplifying assumptions: + * + * - It ignores discard instructions, since they are lowered by a + * separate pass (lower_discard.cpp). + * + * - It assumes it is always possible for control to flow from a loop + * to the instruction immediately following it. Technically, this + * is not true (since all execution paths through the loop might + * jump back to the top, or return from the function). + * + * Both of these simplifying assumtions are safe, since they can never + * cause reachable code to be incorrectly classified as unreachable; + * they can only do the opposite. + */ +enum jump_strength +{ + /** + * Analysis has produced no guarantee on how control flow might + * exit this IR node. It might fall out the bottom (with or + * without clearing the execute flag, if present), or it might + * continue to the top of the innermost enclosing loop, break out + * of it, or return from the function. + */ + strength_none, + + /** + * The only way control can fall out the bottom of this node is + * through a code path that clears the execute flag. It might also + * continue to the top of the innermost enclosing loop, break out + * of it, or return from the function. + */ + strength_always_clears_execute_flag, + + /** + * Control cannot fall out the bottom of this node. It might + * continue to the top of the innermost enclosing loop, break out + * of it, or return from the function. + */ + strength_continue, + + /** + * Control cannot fall out the bottom of this node, or continue the + * top of the innermost enclosing loop. It can only break out of + * it or return from the function. + */ + strength_break, + + /** + * Control cannot fall out the bottom of this node, continue to the + * top of the innermost enclosing loop, or break out of it. It can + * only return from the function. + */ + strength_return +}; + +struct block_record +{ + /* minimum jump strength (of lowered IR, not pre-lowering IR) + * + * If the block ends with a jump, must be the strength of the jump. + * Otherwise, the jump would be dead and have been deleted before) + * + * If the block doesn't end with a jump, it can be different than strength_none if all paths before it lead to some jump + * (e.g. an if with a return in one branch, and a break in the other, while not lowering them) + * Note that identical jumps are usually unified though. + */ + jump_strength min_strength; + + /* can anything clear the execute flag? */ + bool may_clear_execute_flag; + + block_record() + { + this->min_strength = strength_none; + this->may_clear_execute_flag = false; + } +}; + +struct loop_record +{ + ir_function_signature* signature; + ir_loop* loop; + + /* used to avoid lowering the break used to represent lowered breaks */ + unsigned nesting_depth; + bool in_if_at_the_end_of_the_loop; + + bool may_set_return_flag; + + ir_variable* break_flag; + ir_variable* execute_flag; /* cleared to emulate continue */ + + loop_record(ir_function_signature* p_signature = 0, ir_loop* p_loop = 0) + { + this->signature = p_signature; + this->loop = p_loop; + this->nesting_depth = 0; + this->in_if_at_the_end_of_the_loop = false; + this->may_set_return_flag = false; + this->break_flag = 0; + this->execute_flag = 0; + } + + ir_variable* get_execute_flag() + { + /* also supported for the "function loop" */ + if(!this->execute_flag) { + exec_list& list = this->loop ? this->loop->body_instructions : signature->body; + this->execute_flag = new(this->signature) ir_variable(glsl_type::bool_type, "execute_flag", ir_var_temporary); + list.push_head(new(this->signature) ir_assignment(new(this->signature) ir_dereference_variable(execute_flag), new(this->signature) ir_constant(true), 0)); + list.push_head(this->execute_flag); + } + return this->execute_flag; + } + + ir_variable* get_break_flag() + { + assert(this->loop); + if(!this->break_flag) { + this->break_flag = new(this->signature) ir_variable(glsl_type::bool_type, "break_flag", ir_var_temporary); + this->loop->insert_before(this->break_flag); + this->loop->insert_before(new(this->signature) ir_assignment(new(this->signature) ir_dereference_variable(break_flag), new(this->signature) ir_constant(false), 0)); + } + return this->break_flag; + } +}; + +struct function_record +{ + ir_function_signature* signature; + ir_variable* return_flag; /* used to break out of all loops and then jump to the return instruction */ + ir_variable* return_value; + bool lower_return; + unsigned nesting_depth; + + function_record(ir_function_signature* p_signature = 0, + bool lower_return = false) + { + this->signature = p_signature; + this->return_flag = 0; + this->return_value = 0; + this->nesting_depth = 0; + this->lower_return = lower_return; + } + + ir_variable* get_return_flag() + { + if(!this->return_flag) { + this->return_flag = new(this->signature) ir_variable(glsl_type::bool_type, "return_flag", ir_var_temporary); + this->signature->body.push_head(new(this->signature) ir_assignment(new(this->signature) ir_dereference_variable(return_flag), new(this->signature) ir_constant(false), 0)); + this->signature->body.push_head(this->return_flag); + } + return this->return_flag; + } + + ir_variable* get_return_value() + { + if(!this->return_value) { + assert(!this->signature->return_type->is_void()); + return_value = new(this->signature) ir_variable(this->signature->return_type, "return_value", ir_var_temporary); + this->signature->body.push_head(this->return_value); + } + return this->return_value; + } +}; + +struct ir_lower_jumps_visitor : public ir_control_flow_visitor { + /* Postconditions: on exit of any visit() function: + * + * ANALYSIS: this->block.min_strength, + * this->block.may_clear_execute_flag, and + * this->loop.may_set_return_flag are updated to reflect the + * characteristics of the visited statement. + * + * DEAD_CODE_ELIMINATION: If this->block.min_strength is not + * strength_none, the visited node is at the end of its exec_list. + * In other words, any unreachable statements that follow the + * visited statement in its exec_list have been removed. + * + * CONTAINED_JUMPS_LOWERED: If the visited statement contains other + * statements, then should_lower_jump() is false for all of the + * return, break, or continue statements it contains. + * + * Note that visiting a jump does not lower it. That is the + * responsibility of the statement (or function signature) that + * contains the jump. + */ + + bool progress; + + struct function_record function; + struct loop_record loop; + struct block_record block; + + bool pull_out_jumps; + bool lower_continue; + bool lower_break; + bool lower_sub_return; + bool lower_main_return; + + ir_lower_jumps_visitor() + { + this->progress = false; + } + + void truncate_after_instruction(exec_node *ir) + { + if (!ir) + return; + + while (!ir->get_next()->is_tail_sentinel()) { + ((ir_instruction *)ir->get_next())->remove(); + this->progress = true; + } + } + + void move_outer_block_inside(ir_instruction *ir, exec_list *inner_block) + { + while (!ir->get_next()->is_tail_sentinel()) { + ir_instruction *move_ir = (ir_instruction *)ir->get_next(); + + move_ir->remove(); + inner_block->push_tail(move_ir); + } + } + + /** + * Insert the instructions necessary to lower a return statement, + * before the given return instruction. + */ + void insert_lowered_return(ir_return *ir) + { + ir_variable* return_flag = this->function.get_return_flag(); + if(!this->function.signature->return_type->is_void()) { + ir_variable* return_value = this->function.get_return_value(); + ir->insert_before( + new(ir) ir_assignment( + new (ir) ir_dereference_variable(return_value), + ir->value)); + } + ir->insert_before( + new(ir) ir_assignment( + new (ir) ir_dereference_variable(return_flag), + new (ir) ir_constant(true))); + this->loop.may_set_return_flag = true; + } + + /** + * If the given instruction is a return, lower it to instructions + * that store the return value (if there is one), set the return + * flag, and then break. + * + * It is safe to pass NULL to this function. + */ + void lower_return_unconditionally(ir_instruction *ir) + { + if (get_jump_strength(ir) != strength_return) { + return; + } + insert_lowered_return((ir_return*)ir); + ir->replace_with(new(ir) ir_loop_jump(ir_loop_jump::jump_break)); + } + + /** + * Create the necessary instruction to replace a break instruction. + */ + ir_instruction *create_lowered_break() + { + void *ctx = this->function.signature; + return new(ctx) ir_assignment( + new(ctx) ir_dereference_variable(this->loop.get_break_flag()), + new(ctx) ir_constant(true), + 0); + } + + /** + * If the given instruction is a break, lower it to an instruction + * that sets the break flag, without consulting + * should_lower_jump(). + * + * It is safe to pass NULL to this function. + */ + void lower_break_unconditionally(ir_instruction *ir) + { + if (get_jump_strength(ir) != strength_break) { + return; + } + ir->replace_with(create_lowered_break()); + } + + /** + * If the block ends in a conditional or unconditional break, lower + * it, even though should_lower_jump() says it needn't be lowered. + */ + void lower_final_breaks(exec_list *block) + { + ir_instruction *ir = (ir_instruction *) block->get_tail(); + lower_break_unconditionally(ir); + ir_if *ir_if = ir->as_if(); + if (ir_if) { + lower_break_unconditionally( + (ir_instruction *) ir_if->then_instructions.get_tail()); + lower_break_unconditionally( + (ir_instruction *) ir_if->else_instructions.get_tail()); + } + } + + virtual void visit(class ir_loop_jump * ir) + { + /* Eliminate all instructions after each one, since they are + * unreachable. This satisfies the DEAD_CODE_ELIMINATION + * postcondition. + */ + truncate_after_instruction(ir); + + /* Set this->block.min_strength based on this instruction. This + * satisfies the ANALYSIS postcondition. It is not necessary to + * update this->block.may_clear_execute_flag or + * this->loop.may_set_return_flag, because an unlowered jump + * instruction can't change any flags. + */ + this->block.min_strength = ir->is_break() ? strength_break : strength_continue; + + /* The CONTAINED_JUMPS_LOWERED postcondition is already + * satisfied, because jump statements can't contain other + * statements. + */ + } + + virtual void visit(class ir_return * ir) + { + /* Eliminate all instructions after each one, since they are + * unreachable. This satisfies the DEAD_CODE_ELIMINATION + * postcondition. + */ + truncate_after_instruction(ir); + + /* Set this->block.min_strength based on this instruction. This + * satisfies the ANALYSIS postcondition. It is not necessary to + * update this->block.may_clear_execute_flag or + * this->loop.may_set_return_flag, because an unlowered return + * instruction can't change any flags. + */ + this->block.min_strength = strength_return; + + /* The CONTAINED_JUMPS_LOWERED postcondition is already + * satisfied, because jump statements can't contain other + * statements. + */ + } + + virtual void visit(class ir_discard * ir) + { + /* Nothing needs to be done. The ANALYSIS and + * DEAD_CODE_ELIMINATION postconditions are already satisfied, + * because discard statements are ignored by this optimization + * pass. The CONTAINED_JUMPS_LOWERED postcondition is already + * satisfied, because discard statements can't contain other + * statements. + */ + } + + enum jump_strength get_jump_strength(ir_instruction* ir) + { + if(!ir) + return strength_none; + else if(ir->ir_type == ir_type_loop_jump) { + if(((ir_loop_jump*)ir)->is_break()) + return strength_break; + else + return strength_continue; + } else if(ir->ir_type == ir_type_return) + return strength_return; + else + return strength_none; + } + + bool should_lower_jump(ir_jump* ir) + { + unsigned strength = get_jump_strength(ir); + bool lower; + switch(strength) + { + case strength_none: + lower = false; /* don't change this, code relies on it */ + break; + case strength_continue: + lower = lower_continue; + break; + case strength_break: + assert(this->loop.loop); + /* never lower "canonical break" */ + if(ir->get_next()->is_tail_sentinel() && (this->loop.nesting_depth == 0 + || (this->loop.nesting_depth == 1 && this->loop.in_if_at_the_end_of_the_loop))) + lower = false; + else + lower = lower_break; + break; + case strength_return: + /* never lower return at the end of a this->function */ + if(this->function.nesting_depth == 0 && ir->get_next()->is_tail_sentinel()) + lower = false; + else + lower = this->function.lower_return; + break; + } + return lower; + } + + block_record visit_block(exec_list* list) + { + /* Note: since visiting a node may change that node's next + * pointer, we can't use visit_exec_list(), because + * visit_exec_list() caches the node's next pointer before + * visiting it. So we use foreach_list() instead. + * + * foreach_list() isn't safe if the node being visited gets + * removed, but fortunately this visitor doesn't do that. + */ + + block_record saved_block = this->block; + this->block = block_record(); + foreach_list(node, list) { + ((ir_instruction *) node)->accept(this); + } + block_record ret = this->block; + this->block = saved_block; + return ret; + } + + virtual void visit(ir_if *ir) + { + if(this->loop.nesting_depth == 0 && ir->get_next()->is_tail_sentinel()) + this->loop.in_if_at_the_end_of_the_loop = true; + + ++this->function.nesting_depth; + ++this->loop.nesting_depth; + + block_record block_records[2]; + ir_jump* jumps[2]; + + /* Recursively lower nested jumps. This satisfies the + * CONTAINED_JUMPS_LOWERED postcondition, except in the case of + * unconditional jumps at the end of ir->then_instructions and + * ir->else_instructions, which are handled below. + */ + block_records[0] = visit_block(&ir->then_instructions); + block_records[1] = visit_block(&ir->else_instructions); + +retry: /* we get here if we put code after the if inside a branch */ + + /* Determine which of ir->then_instructions and + * ir->else_instructions end with an unconditional jump. + */ + for(unsigned i = 0; i < 2; ++i) { + exec_list& list = i ? ir->else_instructions : ir->then_instructions; + jumps[i] = 0; + if(!list.is_empty() && get_jump_strength((ir_instruction*)list.get_tail())) + jumps[i] = (ir_jump*)list.get_tail(); + } + + /* Loop until we have satisfied the CONTAINED_JUMPS_LOWERED + * postcondition by lowering jumps in both then_instructions and + * else_instructions. + */ + for(;;) { + /* Determine the types of the jumps that terminate + * ir->then_instructions and ir->else_instructions. + */ + jump_strength jump_strengths[2]; + + for(unsigned i = 0; i < 2; ++i) { + if(jumps[i]) { + jump_strengths[i] = block_records[i].min_strength; + assert(jump_strengths[i] == get_jump_strength(jumps[i])); + } else + jump_strengths[i] = strength_none; + } + + /* If both code paths end in a jump, and the jumps are the + * same, and we are pulling out jumps, replace them with a + * single jump that comes after the if instruction. The new + * jump will be visited next, and it will be lowered if + * necessary by the loop or conditional that encloses it. + */ + if(pull_out_jumps && jump_strengths[0] == jump_strengths[1]) { + bool unify = true; + if(jump_strengths[0] == strength_continue) + ir->insert_after(new(ir) ir_loop_jump(ir_loop_jump::jump_continue)); + else if(jump_strengths[0] == strength_break) + ir->insert_after(new(ir) ir_loop_jump(ir_loop_jump::jump_break)); + /* FINISHME: unify returns with identical expressions */ + else if(jump_strengths[0] == strength_return && this->function.signature->return_type->is_void()) + ir->insert_after(new(ir) ir_return(NULL)); + else + unify = false; + + if(unify) { + jumps[0]->remove(); + jumps[1]->remove(); + this->progress = true; + + /* Update jumps[] to reflect the fact that the jumps + * are gone, and update block_records[] to reflect the + * fact that control can now flow to the next + * instruction. + */ + jumps[0] = 0; + jumps[1] = 0; + block_records[0].min_strength = strength_none; + block_records[1].min_strength = strength_none; + + /* The CONTAINED_JUMPS_LOWERED postcondition is now + * satisfied, so we can break out of the loop. + */ + break; + } + } + + /* lower a jump: if both need to lowered, start with the strongest one, so that + * we might later unify the lowered version with the other one + */ + bool should_lower[2]; + for(unsigned i = 0; i < 2; ++i) + should_lower[i] = should_lower_jump(jumps[i]); + + int lower; + if(should_lower[1] && should_lower[0]) + lower = jump_strengths[1] > jump_strengths[0]; + else if(should_lower[0]) + lower = 0; + else if(should_lower[1]) + lower = 1; + else + /* Neither code path ends in a jump that needs to be + * lowered, so the CONTAINED_JUMPS_LOWERED postcondition + * is satisfied and we can break out of the loop. + */ + break; + + if(jump_strengths[lower] == strength_return) { + /* To lower a return, we create a return flag (if the + * function doesn't have one already) and add instructions + * that: 1. store the return value (if this function has a + * non-void return) and 2. set the return flag + */ + insert_lowered_return((ir_return*)jumps[lower]); + if(this->loop.loop) { + /* If we are in a loop, replace the return instruction + * with a break instruction, and then loop so that the + * break instruction can be lowered if necessary. + */ + ir_loop_jump* lowered = 0; + lowered = new(ir) ir_loop_jump(ir_loop_jump::jump_break); + /* Note: we must update block_records and jumps to + * reflect the fact that the control path has been + * altered from a return to a break. + */ + block_records[lower].min_strength = strength_break; + jumps[lower]->replace_with(lowered); + jumps[lower] = lowered; + } else { + /* If we are not in a loop, we then proceed as we would + * for a continue statement (set the execute flag to + * false to prevent the rest of the function from + * executing). + */ + goto lower_continue; + } + this->progress = true; + } else if(jump_strengths[lower] == strength_break) { + /* To lower a break, we create a break flag (if the loop + * doesn't have one already) and add an instruction that + * sets it. + * + * Then we proceed as we would for a continue statement + * (set the execute flag to false to prevent the rest of + * the loop body from executing). + * + * The visit() function for the loop will ensure that the + * break flag is checked after executing the loop body. + */ + jumps[lower]->insert_before(create_lowered_break()); + goto lower_continue; + } else if(jump_strengths[lower] == strength_continue) { +lower_continue: + /* To lower a continue, we create an execute flag (if the + * loop doesn't have one already) and replace the continue + * with an instruction that clears it. + * + * Note that this code path gets exercised when lowering + * return statements that are not inside a loop, so + * this->loop must be initialized even outside of loops. + */ + ir_variable* execute_flag = this->loop.get_execute_flag(); + jumps[lower]->replace_with(new(ir) ir_assignment(new (ir) ir_dereference_variable(execute_flag), new (ir) ir_constant(false), 0)); + /* Note: we must update block_records and jumps to reflect + * the fact that the control path has been altered to an + * instruction that clears the execute flag. + */ + jumps[lower] = 0; + block_records[lower].min_strength = strength_always_clears_execute_flag; + block_records[lower].may_clear_execute_flag = true; + this->progress = true; + + /* Let the loop run again, in case the other branch of the + * if needs to be lowered too. + */ + } + } + + /* move out a jump out if possible */ + if(pull_out_jumps) { + /* If one of the branches ends in a jump, and control cannot + * fall out the bottom of the other branch, then we can move + * the jump after the if. + * + * Set move_out to the branch we are moving a jump out of. + */ + int move_out = -1; + if(jumps[0] && block_records[1].min_strength >= strength_continue) + move_out = 0; + else if(jumps[1] && block_records[0].min_strength >= strength_continue) + move_out = 1; + + if(move_out >= 0) + { + jumps[move_out]->remove(); + ir->insert_after(jumps[move_out]); + /* Note: we must update block_records and jumps to reflect + * the fact that the jump has been moved out of the if. + */ + jumps[move_out] = 0; + block_records[move_out].min_strength = strength_none; + this->progress = true; + } + } + + /* Now satisfy the ANALYSIS postcondition by setting + * this->block.min_strength and + * this->block.may_clear_execute_flag based on the + * characteristics of the two branches. + */ + if(block_records[0].min_strength < block_records[1].min_strength) + this->block.min_strength = block_records[0].min_strength; + else + this->block.min_strength = block_records[1].min_strength; + this->block.may_clear_execute_flag = this->block.may_clear_execute_flag || block_records[0].may_clear_execute_flag || block_records[1].may_clear_execute_flag; + + /* Now we need to clean up the instructions that follow the + * if. + * + * If those instructions are unreachable, then satisfy the + * DEAD_CODE_ELIMINATION postcondition by eliminating them. + * Otherwise that postcondition is already satisfied. + */ + if(this->block.min_strength) + truncate_after_instruction(ir); + else if(this->block.may_clear_execute_flag) + { + /* If the "if" instruction might clear the execute flag, then + * we need to guard any instructions that follow so that they + * are only executed if the execute flag is set. + * + * If one of the branches of the "if" always clears the + * execute flag, and the other branch never clears it, then + * this is easy: just move all the instructions following the + * "if" into the branch that never clears it. + */ + int move_into = -1; + if(block_records[0].min_strength && !block_records[1].may_clear_execute_flag) + move_into = 1; + else if(block_records[1].min_strength && !block_records[0].may_clear_execute_flag) + move_into = 0; + + if(move_into >= 0) { + assert(!block_records[move_into].min_strength && !block_records[move_into].may_clear_execute_flag); /* otherwise, we just truncated */ + + exec_list* list = move_into ? &ir->else_instructions : &ir->then_instructions; + exec_node* next = ir->get_next(); + if(!next->is_tail_sentinel()) { + move_outer_block_inside(ir, list); + + /* If any instructions moved, then we need to visit + * them (since they are now inside the "if"). Since + * block_records[move_into] is in its default state + * (see assertion above), we can safely replace + * block_records[move_into] with the result of this + * analysis. + */ + exec_list list; + list.head = next; + block_records[move_into] = visit_block(&list); + + /* + * Then we need to re-start our jump lowering, since one + * of the instructions we moved might be a jump that + * needs to be lowered. + */ + this->progress = true; + goto retry; + } + } else { + /* If we get here, then the simple case didn't apply; we + * need to actually guard the instructions that follow. + * + * To avoid creating unnecessarily-deep nesting, first + * look through the instructions that follow and unwrap + * any instructions that that are already wrapped in the + * appropriate guard. + */ + ir_instruction* ir_after; + for(ir_after = (ir_instruction*)ir->get_next(); !ir_after->is_tail_sentinel();) + { + ir_if* ir_if = ir_after->as_if(); + if(ir_if && ir_if->else_instructions.is_empty()) { + ir_dereference_variable* ir_if_cond_deref = ir_if->condition->as_dereference_variable(); + if(ir_if_cond_deref && ir_if_cond_deref->var == this->loop.execute_flag) { + ir_instruction* ir_next = (ir_instruction*)ir_after->get_next(); + ir_after->insert_before(&ir_if->then_instructions); + ir_after->remove(); + ir_after = ir_next; + continue; + } + } + ir_after = (ir_instruction*)ir_after->get_next(); + + /* only set this if we find any unprotected instruction */ + this->progress = true; + } + + /* Then, wrap all the instructions that follow in a single + * guard. + */ + if(!ir->get_next()->is_tail_sentinel()) { + assert(this->loop.execute_flag); + ir_if* if_execute = new(ir) ir_if(new(ir) ir_dereference_variable(this->loop.execute_flag)); + move_outer_block_inside(ir, &if_execute->then_instructions); + ir->insert_after(if_execute); + } + } + } + --this->loop.nesting_depth; + --this->function.nesting_depth; + } + + virtual void visit(ir_loop *ir) + { + /* Visit the body of the loop, with a fresh data structure in + * this->loop so that the analysis we do here won't bleed into + * enclosing loops. + * + * We assume that all code after a loop is reachable from the + * loop (see comments on enum jump_strength), so the + * DEAD_CODE_ELIMINATION postcondition is automatically + * satisfied, as is the block.min_strength portion of the + * ANALYSIS postcondition. + * + * The block.may_clear_execute_flag portion of the ANALYSIS + * postcondition is automatically satisfied because execute + * flags do not propagate outside of loops. + * + * The loop.may_set_return_flag portion of the ANALYSIS + * postcondition is handled below. + */ + ++this->function.nesting_depth; + loop_record saved_loop = this->loop; + this->loop = loop_record(this->function.signature, ir); + + /* Recursively lower nested jumps. This satisfies the + * CONTAINED_JUMPS_LOWERED postcondition, except in the case of + * an unconditional continue or return at the bottom of the + * loop, which are handled below. + */ + block_record body = visit_block(&ir->body_instructions); + + /* If the loop ends in an unconditional continue, eliminate it + * because it is redundant. + */ + ir_instruction *ir_last + = (ir_instruction *) ir->body_instructions.get_tail(); + if (get_jump_strength(ir_last) == strength_continue) { + ir_last->remove(); + } + + /* If the loop ends in an unconditional return, and we are + * lowering returns, lower it. + */ + if (this->function.lower_return) + lower_return_unconditionally(ir_last); + + if(body.min_strength >= strength_break) { + /* FINISHME: If the min_strength of the loop body is + * strength_break or strength_return, that means that it + * isn't a loop at all, since control flow always leaves the + * body of the loop via break or return. In principle the + * loop could be eliminated in this case. This optimization + * is not implemented yet. + */ + } + + if(this->loop.break_flag) { + /* We only get here if we are lowering breaks */ + assert (lower_break); + + /* If a break flag was generated while visiting the body of + * the loop, then at least one break was lowered, so we need + * to generate an if statement at the end of the loop that + * does a "break" if the break flag is set. The break we + * generate won't violate the CONTAINED_JUMPS_LOWERED + * postcondition, because should_lower_jump() always returns + * false for a break that happens at the end of a loop. + * + * However, if the loop already ends in a conditional or + * unconditional break, then we need to lower that break, + * because it won't be at the end of the loop anymore. + */ + lower_final_breaks(&ir->body_instructions); + + ir_if* break_if = new(ir) ir_if(new(ir) ir_dereference_variable(this->loop.break_flag)); + break_if->then_instructions.push_tail(new(ir) ir_loop_jump(ir_loop_jump::jump_break)); + ir->body_instructions.push_tail(break_if); + } + + /* If the body of the loop may set the return flag, then at + * least one return was lowered to a break, so we need to ensure + * that the return flag is checked after the body of the loop is + * executed. + */ + if(this->loop.may_set_return_flag) { + assert(this->function.return_flag); + /* Generate the if statement to check the return flag */ + ir_if* return_if = new(ir) ir_if(new(ir) ir_dereference_variable(this->function.return_flag)); + /* Note: we also need to propagate the knowledge that the + * return flag may get set to the outer context. This + * satisfies the loop.may_set_return_flag part of the + * ANALYSIS postcondition. + */ + saved_loop.may_set_return_flag = true; + if(saved_loop.loop) + /* If this loop is nested inside another one, then the if + * statement that we generated should break out of that + * loop if the return flag is set. Caller will lower that + * break statement if necessary. + */ + return_if->then_instructions.push_tail(new(ir) ir_loop_jump(ir_loop_jump::jump_break)); + else + /* Otherwise, all we need to do is ensure that the + * instructions that follow are only executed if the + * return flag is clear. We can do that by moving those + * instructions into the else clause of the generated if + * statement. + */ + move_outer_block_inside(ir, &return_if->else_instructions); + ir->insert_after(return_if); + } + + this->loop = saved_loop; + --this->function.nesting_depth; + } + + virtual void visit(ir_function_signature *ir) + { + /* these are not strictly necessary */ + assert(!this->function.signature); + assert(!this->loop.loop); + + bool lower_return; + if (strcmp(ir->function_name(), "main") == 0) + lower_return = lower_main_return; + else + lower_return = lower_sub_return; + + function_record saved_function = this->function; + loop_record saved_loop = this->loop; + this->function = function_record(ir, lower_return); + this->loop = loop_record(ir); + + assert(!this->loop.loop); + + /* Visit the body of the function to lower any jumps that occur + * in it, except possibly an unconditional return statement at + * the end of it. + */ + visit_block(&ir->body); + + /* If the body ended in an unconditional return of non-void, + * then we don't need to lower it because it's the one canonical + * return. + * + * If the body ended in a return of void, eliminate it because + * it is redundant. + */ + if (ir->return_type->is_void() && + get_jump_strength((ir_instruction *) ir->body.get_tail())) { + ir_jump *jump = (ir_jump *) ir->body.get_tail(); + assert (jump->ir_type == ir_type_return); + jump->remove(); + } + + if(this->function.return_value) + ir->body.push_tail(new(ir) ir_return(new (ir) ir_dereference_variable(this->function.return_value))); + + this->loop = saved_loop; + this->function = saved_function; + } + + virtual void visit(class ir_function * ir) + { + visit_block(&ir->signatures); + } +}; + +bool +do_lower_jumps(exec_list *instructions, bool pull_out_jumps, bool lower_sub_return, bool lower_main_return, bool lower_continue, bool lower_break) +{ + ir_lower_jumps_visitor v; + v.pull_out_jumps = pull_out_jumps; + v.lower_continue = lower_continue; + v.lower_break = lower_break; + v.lower_sub_return = lower_sub_return; + v.lower_main_return = lower_main_return; + + do { + v.progress = false; + visit_exec_list(instructions, &v); + } while (v.progress); + + return v.progress; +} diff --git a/mesalib/src/mesa/main/depthstencil.c b/mesalib/src/mesa/main/depthstencil.c index ab62c97fe..4d0600050 100644 --- a/mesalib/src/mesa/main/depthstencil.c +++ b/mesalib/src/mesa/main/depthstencil.c @@ -393,6 +393,217 @@ _mesa_new_z24_renderbuffer_wrapper(struct gl_context *ctx, } +static void +get_row_z32f(struct gl_context *ctx, struct gl_renderbuffer *z32frb, GLuint count, + GLint x, GLint y, void *values) +{ + struct gl_renderbuffer *dsrb = z32frb->Wrapped; + GLfloat temp[MAX_WIDTH*2]; + GLfloat *dst = (GLfloat *) values; + const GLfloat *src = (const GLfloat *) dsrb->GetPointer(ctx, dsrb, x, y); + GLuint i; + ASSERT(z32frb->DataType == GL_FLOAT); + ASSERT(dsrb->DataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV); + ASSERT(dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8); + if (!src) { + dsrb->GetRow(ctx, dsrb, count, x, y, temp); + src = temp; + } + for (i = 0; i < count; i++) { + dst[i] = src[i*2]; + } +} + +static void +get_values_z32f(struct gl_context *ctx, struct gl_renderbuffer *z32frb, GLuint count, + const GLint x[], const GLint y[], void *values) +{ + struct gl_renderbuffer *dsrb = z32frb->Wrapped; + GLfloat temp[MAX_WIDTH*2]; + GLfloat *dst = (GLfloat *) values; + GLuint i; + ASSERT(z32frb->DataType == GL_FLOAT); + ASSERT(dsrb->DataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV); + ASSERT(dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8); + ASSERT(count <= MAX_WIDTH); + /* don't bother trying direct access */ + dsrb->GetValues(ctx, dsrb, count, x, y, temp); + for (i = 0; i < count; i++) { + dst[i] = temp[i*2]; + } +} + +static void +put_row_z32f(struct gl_context *ctx, struct gl_renderbuffer *z32frb, GLuint count, + GLint x, GLint y, const void *values, const GLubyte *mask) +{ + struct gl_renderbuffer *dsrb = z32frb->Wrapped; + const GLfloat *src = (const GLfloat *) values; + GLfloat *dst = (GLfloat *) dsrb->GetPointer(ctx, dsrb, x, y); + ASSERT(z32frb->DataType == GL_FLOAT); + ASSERT(dsrb->DataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV); + ASSERT(dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8); + if (dst) { + /* direct access */ + GLuint i; + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + dst[i*2] = src[i]; + } + } + } + else { + /* get, modify, put */ + GLfloat temp[MAX_WIDTH*2]; + GLuint i; + dsrb->GetRow(ctx, dsrb, count, x, y, temp); + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + temp[i*2] = src[i]; + } + } + dsrb->PutRow(ctx, dsrb, count, x, y, temp, mask); + } +} + +static void +put_mono_row_z32f(struct gl_context *ctx, struct gl_renderbuffer *z32frb, GLuint count, + GLint x, GLint y, const void *value, const GLubyte *mask) +{ + struct gl_renderbuffer *dsrb = z32frb->Wrapped; + GLfloat *dst = (GLfloat *) dsrb->GetPointer(ctx, dsrb, x, y); + ASSERT(z32frb->DataType == GL_FLOAT); + ASSERT(dsrb->DataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV); + ASSERT(dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8); + if (dst) { + /* direct access */ + GLuint i; + const GLfloat val = *(GLfloat*)value; + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + dst[i*2] = val; + } + } + } + else { + /* get, modify, put */ + GLfloat temp[MAX_WIDTH*2]; + GLuint i; + const GLfloat val = *(GLfloat *)value; + dsrb->GetRow(ctx, dsrb, count, x, y, temp); + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + temp[i*2] = val; + } + } + dsrb->PutRow(ctx, dsrb, count, x, y, temp, mask); + } +} + +static void +put_values_z32f(struct gl_context *ctx, struct gl_renderbuffer *z32frb, GLuint count, + const GLint x[], const GLint y[], + const void *values, const GLubyte *mask) +{ + struct gl_renderbuffer *dsrb = z32frb->Wrapped; + const GLfloat *src = (const GLfloat *) values; + ASSERT(z32frb->DataType == GL_FLOAT); + ASSERT(dsrb->DataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV); + ASSERT(dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8); + if (dsrb->GetPointer(ctx, dsrb, 0, 0)) { + /* direct access */ + GLuint i; + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + GLfloat *dst = (GLfloat *) dsrb->GetPointer(ctx, dsrb, x[i], y[i]); + *dst = src[i]; + } + } + } + else { + /* get, modify, put */ + GLfloat temp[MAX_WIDTH*2]; + GLuint i; + dsrb->GetValues(ctx, dsrb, count, x, y, temp); + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + temp[i*2] = src[i]; + } + } + dsrb->PutValues(ctx, dsrb, count, x, y, temp, mask); + } +} + +static void +put_mono_values_z32f(struct gl_context *ctx, struct gl_renderbuffer *z32frb, + GLuint count, const GLint x[], const GLint y[], + const void *value, const GLubyte *mask) +{ + struct gl_renderbuffer *dsrb = z32frb->Wrapped; + GLfloat temp[MAX_WIDTH*2]; + GLuint i; + const GLfloat val = *(GLfloat *)value; + ASSERT(z32frb->DataType == GL_FLOAT); + ASSERT(dsrb->DataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV); + ASSERT(dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8); + /* get, modify, put */ + dsrb->GetValues(ctx, dsrb, count, x, y, temp); + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + temp[i*2] = val; + } + } + dsrb->PutValues(ctx, dsrb, count, x, y, temp, mask); +} + + +/** + * Wrap the given GL_DEPTH_STENCIL renderbuffer so that it acts like + * a depth renderbuffer. + * \return new depth renderbuffer + */ +struct gl_renderbuffer * +_mesa_new_z32f_renderbuffer_wrapper(struct gl_context *ctx, + struct gl_renderbuffer *dsrb) +{ + struct gl_renderbuffer *z32frb; + + ASSERT(dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8); + ASSERT(dsrb->DataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV); + + z32frb = ctx->Driver.NewRenderbuffer(ctx, 0); + if (!z32frb) + return NULL; + + /* NOTE: need to do manual refcounting here */ + z32frb->Wrapped = dsrb; + dsrb->RefCount++; + + z32frb->Name = dsrb->Name; + z32frb->RefCount = 0; + z32frb->Width = dsrb->Width; + z32frb->Height = dsrb->Height; + z32frb->RowStride = dsrb->RowStride; + z32frb->InternalFormat = GL_DEPTH_COMPONENT32F; + z32frb->Format = MESA_FORMAT_Z32_FLOAT; + z32frb->_BaseFormat = GL_DEPTH_COMPONENT; + z32frb->DataType = GL_FLOAT; + z32frb->Data = NULL; + z32frb->Delete = delete_wrapper; + z32frb->AllocStorage = alloc_wrapper_storage; + z32frb->GetPointer = nop_get_pointer; + z32frb->GetRow = get_row_z32f; + z32frb->GetValues = get_values_z32f; + z32frb->PutRow = put_row_z32f; + z32frb->PutRowRGB = NULL; + z32frb->PutMonoRow = put_mono_row_z32f; + z32frb->PutValues = put_values_z32f; + z32frb->PutMonoValues = put_mono_values_z32f; + + return z32frb; +} + + /*====================================================================== * Stencil wrapper around depth/stencil renderbuffer */ @@ -402,16 +613,22 @@ get_row_s8(struct gl_context *ctx, struct gl_renderbuffer *s8rb, GLuint count, GLint x, GLint y, void *values) { struct gl_renderbuffer *dsrb = s8rb->Wrapped; - GLuint temp[MAX_WIDTH], i; + GLuint temp[MAX_WIDTH*2], i; GLubyte *dst = (GLubyte *) values; const GLuint *src = (const GLuint *) dsrb->GetPointer(ctx, dsrb, x, y); ASSERT(s8rb->DataType == GL_UNSIGNED_BYTE); - ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT); + ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT || + dsrb->DataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV); if (!src) { dsrb->GetRow(ctx, dsrb, count, x, y, temp); src = temp; } - if (dsrb->Format == MESA_FORMAT_Z24_S8) { + if (dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8) { + for (i = 0; i < count; i++) { + dst[i] = src[i*2+1] & 0xff; + } + } + else if (dsrb->Format == MESA_FORMAT_Z24_S8) { for (i = 0; i < count; i++) { dst[i] = src[i] & 0xff; } @@ -429,14 +646,20 @@ get_values_s8(struct gl_context *ctx, struct gl_renderbuffer *s8rb, GLuint count const GLint x[], const GLint y[], void *values) { struct gl_renderbuffer *dsrb = s8rb->Wrapped; - GLuint temp[MAX_WIDTH], i; + GLuint temp[MAX_WIDTH*2], i; GLubyte *dst = (GLubyte *) values; ASSERT(s8rb->DataType == GL_UNSIGNED_BYTE); - ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT); + ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT || + dsrb->DataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV); ASSERT(count <= MAX_WIDTH); /* don't bother trying direct access */ dsrb->GetValues(ctx, dsrb, count, x, y, temp); - if (dsrb->Format == MESA_FORMAT_Z24_S8) { + if (dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8) { + for (i = 0; i < count; i++) { + dst[i] = temp[i*2+1] & 0xff; + } + } + else if (dsrb->Format == MESA_FORMAT_Z24_S8) { for (i = 0; i < count; i++) { dst[i] = temp[i] & 0xff; } @@ -457,11 +680,19 @@ put_row_s8(struct gl_context *ctx, struct gl_renderbuffer *s8rb, GLuint count, const GLubyte *src = (const GLubyte *) values; GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x, y); ASSERT(s8rb->DataType == GL_UNSIGNED_BYTE); - ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT); + ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT || + dsrb->DataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV); if (dst) { /* direct access */ GLuint i; - if (dsrb->Format == MESA_FORMAT_Z24_S8) { + if (dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8) { + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + dst[i*2+1] = src[i]; + } + } + } + else if (dsrb->Format == MESA_FORMAT_Z24_S8) { for (i = 0; i < count; i++) { if (!mask || mask[i]) { dst[i] = (dst[i] & 0xffffff00) | src[i]; @@ -479,9 +710,16 @@ put_row_s8(struct gl_context *ctx, struct gl_renderbuffer *s8rb, GLuint count, } else { /* get, modify, put */ - GLuint temp[MAX_WIDTH], i; + GLuint temp[MAX_WIDTH*2], i; dsrb->GetRow(ctx, dsrb, count, x, y, temp); - if (dsrb->Format == MESA_FORMAT_Z24_S8) { + if (dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8) { + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + temp[i*2+1] = src[i]; + } + } + } + else if (dsrb->Format == MESA_FORMAT_Z24_S8) { for (i = 0; i < count; i++) { if (!mask || mask[i]) { temp[i] = (temp[i] & 0xffffff00) | src[i]; @@ -508,11 +746,19 @@ put_mono_row_s8(struct gl_context *ctx, struct gl_renderbuffer *s8rb, GLuint cou const GLubyte val = *((GLubyte *) value); GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x, y); ASSERT(s8rb->DataType == GL_UNSIGNED_BYTE); - ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT); + ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT || + dsrb->DataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV); if (dst) { /* direct access */ GLuint i; - if (dsrb->Format == MESA_FORMAT_Z24_S8) { + if (dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8) { + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + dst[i*2+1] = val; + } + } + } + else if (dsrb->Format == MESA_FORMAT_Z24_S8) { for (i = 0; i < count; i++) { if (!mask || mask[i]) { dst[i] = (dst[i] & 0xffffff00) | val; @@ -530,9 +776,16 @@ put_mono_row_s8(struct gl_context *ctx, struct gl_renderbuffer *s8rb, GLuint cou } else { /* get, modify, put */ - GLuint temp[MAX_WIDTH], i; + GLuint temp[MAX_WIDTH*2], i; dsrb->GetRow(ctx, dsrb, count, x, y, temp); - if (dsrb->Format == MESA_FORMAT_Z24_S8) { + if (dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8) { + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + temp[i*2+1] = val; + } + } + } + else if (dsrb->Format == MESA_FORMAT_Z24_S8) { for (i = 0; i < count; i++) { if (!mask || mask[i]) { temp[i] = (temp[i] & 0xffffff00) | val; @@ -559,11 +812,20 @@ put_values_s8(struct gl_context *ctx, struct gl_renderbuffer *s8rb, GLuint count struct gl_renderbuffer *dsrb = s8rb->Wrapped; const GLubyte *src = (const GLubyte *) values; ASSERT(s8rb->DataType == GL_UNSIGNED_BYTE); - ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT); + ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT || + dsrb->DataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV); if (dsrb->GetPointer(ctx, dsrb, 0, 0)) { /* direct access */ GLuint i; - if (dsrb->Format == MESA_FORMAT_Z24_S8) { + if (dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8) { + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x[i], y[i]); + dst[1] = src[i]; + } + } + } + else if (dsrb->Format == MESA_FORMAT_Z24_S8) { for (i = 0; i < count; i++) { if (!mask || mask[i]) { GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x[i], y[i]); @@ -583,9 +845,16 @@ put_values_s8(struct gl_context *ctx, struct gl_renderbuffer *s8rb, GLuint count } else { /* get, modify, put */ - GLuint temp[MAX_WIDTH], i; + GLuint temp[MAX_WIDTH*2], i; dsrb->GetValues(ctx, dsrb, count, x, y, temp); - if (dsrb->Format == MESA_FORMAT_Z24_S8) { + if (dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8) { + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + temp[i*2+1] = src[i]; + } + } + } + else if (dsrb->Format == MESA_FORMAT_Z24_S8) { for (i = 0; i < count; i++) { if (!mask || mask[i]) { temp[i] = (temp[i] & 0xffffff00) | src[i]; @@ -610,11 +879,18 @@ put_mono_values_s8(struct gl_context *ctx, struct gl_renderbuffer *s8rb, GLuint const void *value, const GLubyte *mask) { struct gl_renderbuffer *dsrb = s8rb->Wrapped; - GLuint temp[MAX_WIDTH], i; + GLuint temp[MAX_WIDTH*2], i; const GLubyte val = *((GLubyte *) value); /* get, modify, put */ dsrb->GetValues(ctx, dsrb, count, x, y, temp); - if (dsrb->Format == MESA_FORMAT_Z24_S8) { + if (dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8) { + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + temp[i*2+1] = val; + } + } + } + else if (dsrb->Format == MESA_FORMAT_Z24_S8) { for (i = 0; i < count; i++) { if (!mask || mask[i]) { temp[i] = (temp[i] & 0xffffff00) | val; @@ -644,8 +920,10 @@ _mesa_new_s8_renderbuffer_wrapper(struct gl_context *ctx, struct gl_renderbuffer struct gl_renderbuffer *s8rb; ASSERT(dsrb->Format == MESA_FORMAT_Z24_S8 || - dsrb->Format == MESA_FORMAT_S8_Z24); - ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT); + dsrb->Format == MESA_FORMAT_S8_Z24 || + dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8); + ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT || + dsrb->DataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV); s8rb = ctx->Driver.NewRenderbuffer(ctx, 0); if (!s8rb) diff --git a/mesalib/src/mesa/main/depthstencil.h b/mesalib/src/mesa/main/depthstencil.h index a86f54d96..b47a2e482 100644 --- a/mesalib/src/mesa/main/depthstencil.h +++ b/mesalib/src/mesa/main/depthstencil.h @@ -1,57 +1,62 @@ -/*
- * Mesa 3-D graphics library
- * Version: 6.5
- *
- * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-#ifndef DEPTHSTENCIL_H
-#define DEPTHSTENCIL_H
-
-struct gl_context;
-
-extern struct gl_renderbuffer *
-_mesa_new_z24_renderbuffer_wrapper(struct gl_context *ctx,
- struct gl_renderbuffer *dsrb);
-
-
-extern struct gl_renderbuffer *
-_mesa_new_s8_renderbuffer_wrapper(struct gl_context *ctx,
- struct gl_renderbuffer *dsrb);
-
-
-extern void
-_mesa_extract_stencil(struct gl_context *ctx,
- struct gl_renderbuffer *dsRb,
- struct gl_renderbuffer *stencilRb);
-
-
-extern void
-_mesa_insert_stencil(struct gl_context *ctx,
- struct gl_renderbuffer *dsRb,
- struct gl_renderbuffer *stencilRb);
-
-
-extern void
-_mesa_promote_stencil(struct gl_context *ctx, struct gl_renderbuffer *stencilRb);
-
-
-#endif /* DEPTHSTENCIL_H */
+/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef DEPTHSTENCIL_H +#define DEPTHSTENCIL_H + +struct gl_context; + +extern struct gl_renderbuffer * +_mesa_new_z24_renderbuffer_wrapper(struct gl_context *ctx, + struct gl_renderbuffer *dsrb); + + +extern struct gl_renderbuffer * +_mesa_new_z32f_renderbuffer_wrapper(struct gl_context *ctx, + struct gl_renderbuffer *dsrb); + + +extern struct gl_renderbuffer * +_mesa_new_s8_renderbuffer_wrapper(struct gl_context *ctx, + struct gl_renderbuffer *dsrb); + + +extern void +_mesa_extract_stencil(struct gl_context *ctx, + struct gl_renderbuffer *dsRb, + struct gl_renderbuffer *stencilRb); + + +extern void +_mesa_insert_stencil(struct gl_context *ctx, + struct gl_renderbuffer *dsRb, + struct gl_renderbuffer *stencilRb); + + +extern void +_mesa_promote_stencil(struct gl_context *ctx, struct gl_renderbuffer *stencilRb); + + +#endif /* DEPTHSTENCIL_H */ diff --git a/mesalib/src/mesa/main/fbobject.c b/mesalib/src/mesa/main/fbobject.c index 8cc3fd49a..84969360d 100644 --- a/mesalib/src/mesa/main/fbobject.c +++ b/mesalib/src/mesa/main/fbobject.c @@ -1131,6 +1131,16 @@ _mesa_base_fbo_format(struct gl_context *ctx, GLenum internalFormat) return GL_DEPTH_STENCIL_EXT; else return 0; + case GL_DEPTH_COMPONENT32F: + if (ctx->Extensions.ARB_depth_buffer_float) + return GL_DEPTH_COMPONENT; + else + return 0; + case GL_DEPTH32F_STENCIL8: + if (ctx->Extensions.ARB_depth_buffer_float) + return GL_DEPTH_STENCIL; + else + return 0; case GL_RED: case GL_R8: case GL_R16: @@ -2266,6 +2276,15 @@ _mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment, /* special cases */ *params = GL_INDEX; } + else if (format == MESA_FORMAT_Z32_FLOAT_X24S8) { + /* depends on the attachment parameter */ + if (attachment == GL_STENCIL_ATTACHMENT) { + *params = GL_INDEX; + } + else { + *params = GL_FLOAT; + } + } else { *params = _mesa_get_format_datatype(format); } @@ -2584,6 +2603,10 @@ _mesa_BlitFramebufferEXT(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, } } + if (!mask) { + return; + } + ASSERT(ctx->Driver.BlitFramebuffer); ctx->Driver.BlitFramebuffer(ctx, srcX0, srcY0, srcX1, srcY1, diff --git a/mesalib/src/mesa/main/formats.c b/mesalib/src/mesa/main/formats.c index e88ba4397..f58b19756 100644 --- a/mesalib/src/mesa/main/formats.c +++ b/mesalib/src/mesa/main/formats.c @@ -1091,6 +1091,25 @@ static struct gl_format_info format_info[MESA_FORMAT_COUNT] = 0, 0, 0, 0, 0, 1, 1, 4 }, + /* ARB_depth_buffer_float */ + { + MESA_FORMAT_Z32_FLOAT, /* Name */ + "MESA_FORMAT_Z32_FLOAT", /* StrName */ + GL_DEPTH_COMPONENT, /* BaseFormat */ + GL_FLOAT, /* DataType */ + 0, 0, 0, 0, /* Red/Green/Blue/AlphaBits */ + 0, 0, 0, 32, 0, /* Lum/Int/Index/Depth/StencilBits */ + 1, 1, 4 /* BlockWidth/Height,Bytes */ + }, + { + MESA_FORMAT_Z32_FLOAT_X24S8, /* Name */ + "MESA_FORMAT_Z32_FLOAT_X24S8", /* StrName */ + GL_DEPTH_STENCIL, /* BaseFormat */ + GL_NONE /* XXX */, /* DataType */ + 0, 0, 0, 0, /* Red/Green/Blue/AlphaBits */ + 0, 0, 0, 32, 8, /* Lum/Int/Index/Depth/StencilBits */ + 1, 1, 8 /* BlockWidth/Height,Bytes */ + }, }; @@ -1654,6 +1673,16 @@ _mesa_format_to_type_and_comps(gl_format format, *comps = 1; return; + case MESA_FORMAT_Z32_FLOAT: + *datatype = GL_FLOAT; + *comps = 1; + return; + + case MESA_FORMAT_Z32_FLOAT_X24S8: + *datatype = GL_FLOAT_32_UNSIGNED_INT_24_8_REV; + *comps = 1; + return; + case MESA_FORMAT_DUDV8: *datatype = GL_BYTE; *comps = 2; diff --git a/mesalib/src/mesa/main/formats.h b/mesalib/src/mesa/main/formats.h index 0640bbc4a..5b8c01781 100644 --- a/mesalib/src/mesa/main/formats.h +++ b/mesalib/src/mesa/main/formats.h @@ -209,6 +209,9 @@ typedef enum MESA_FORMAT_RGB9_E5_FLOAT, MESA_FORMAT_R11_G11_B10_FLOAT, + MESA_FORMAT_Z32_FLOAT, + MESA_FORMAT_Z32_FLOAT_X24S8, + MESA_FORMAT_COUNT } gl_format; diff --git a/mesalib/src/mesa/main/framebuffer.c b/mesalib/src/mesa/main/framebuffer.c index 66c9bd910..6e2ce7421 100644 --- a/mesalib/src/mesa/main/framebuffer.c +++ b/mesalib/src/mesa/main/framebuffer.c @@ -631,8 +631,14 @@ _mesa_update_depth_buffer(struct gl_context *ctx, || fb->_DepthBuffer->Wrapped != depthRb || _mesa_get_format_base_format(fb->_DepthBuffer->Format) != GL_DEPTH_COMPONENT) { /* need to update wrapper */ - struct gl_renderbuffer *wrapper - = _mesa_new_z24_renderbuffer_wrapper(ctx, depthRb); + struct gl_renderbuffer *wrapper; + + if (depthRb->Format == MESA_FORMAT_Z32_FLOAT_X24S8) { + wrapper = _mesa_new_z32f_renderbuffer_wrapper(ctx, depthRb); + } + else { + wrapper = _mesa_new_z24_renderbuffer_wrapper(ctx, depthRb); + } _mesa_reference_renderbuffer(&fb->_DepthBuffer, wrapper); ASSERT(fb->_DepthBuffer->Wrapped == depthRb); } diff --git a/mesalib/src/mesa/main/image.c b/mesalib/src/mesa/main/image.c index a5cd5ac03..37127dcb7 100644 --- a/mesalib/src/mesa/main/image.c +++ b/mesalib/src/mesa/main/image.c @@ -1,1935 +1,1949 @@ -/*
- * Mesa 3-D graphics library
- * Version: 7.5
- *
- * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
- * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-/**
- * \file image.c
- * Image handling.
- */
-
-
-#include "glheader.h"
-#include "colormac.h"
-#include "image.h"
-#include "imports.h"
-#include "macros.h"
-#include "mfeatures.h"
-#include "mtypes.h"
-
-
-/**
- * NOTE:
- * Normally, BYTE_TO_FLOAT(0) returns 0.00392 That causes problems when
- * we later convert the float to a packed integer value (such as for
- * GL_RGB5_A1) because we'll wind up with a non-zero value.
- *
- * We redefine the macros here so zero is handled correctly.
- */
-#undef BYTE_TO_FLOAT
-#define BYTE_TO_FLOAT(B) ((B) == 0 ? 0.0F : ((2.0F * (B) + 1.0F) * (1.0F/255.0F)))
-
-#undef SHORT_TO_FLOAT
-#define SHORT_TO_FLOAT(S) ((S) == 0 ? 0.0F : ((2.0F * (S) + 1.0F) * (1.0F/65535.0F)))
-
-
-
-/** Compute ceiling of integer quotient of A divided by B. */
-#define CEILING( A, B ) ( (A) % (B) == 0 ? (A)/(B) : (A)/(B)+1 )
-
-
-/**
- * \return GL_TRUE if type is packed pixel type, GL_FALSE otherwise.
- */
-GLboolean
-_mesa_type_is_packed(GLenum type)
-{
- switch (type) {
- case GL_UNSIGNED_BYTE_3_3_2:
- case GL_UNSIGNED_BYTE_2_3_3_REV:
- case MESA_UNSIGNED_BYTE_4_4:
- case GL_UNSIGNED_SHORT_5_6_5:
- case GL_UNSIGNED_SHORT_5_6_5_REV:
- case GL_UNSIGNED_SHORT_4_4_4_4:
- case GL_UNSIGNED_SHORT_4_4_4_4_REV:
- case GL_UNSIGNED_SHORT_5_5_5_1:
- case GL_UNSIGNED_SHORT_1_5_5_5_REV:
- case GL_UNSIGNED_INT_8_8_8_8:
- case GL_UNSIGNED_INT_8_8_8_8_REV:
- case GL_UNSIGNED_INT_10_10_10_2:
- case GL_UNSIGNED_INT_2_10_10_10_REV:
- case GL_UNSIGNED_SHORT_8_8_MESA:
- case GL_UNSIGNED_SHORT_8_8_REV_MESA:
- case GL_UNSIGNED_INT_24_8_EXT:
- case GL_UNSIGNED_INT_5_9_9_9_REV:
- case GL_UNSIGNED_INT_10F_11F_11F_REV:
- return GL_TRUE;
- }
-
- return GL_FALSE;
-}
-
-
-
-/**
- * Flip the order of the 2 bytes in each word in the given array.
- *
- * \param p array.
- * \param n number of words.
- */
-void
-_mesa_swap2( GLushort *p, GLuint n )
-{
- GLuint i;
- for (i = 0; i < n; i++) {
- p[i] = (p[i] >> 8) | ((p[i] << 8) & 0xff00);
- }
-}
-
-
-
-/*
- * Flip the order of the 4 bytes in each word in the given array.
- */
-void
-_mesa_swap4( GLuint *p, GLuint n )
-{
- GLuint i, a, b;
- for (i = 0; i < n; i++) {
- b = p[i];
- a = (b >> 24)
- | ((b >> 8) & 0xff00)
- | ((b << 8) & 0xff0000)
- | ((b << 24) & 0xff000000);
- p[i] = a;
- }
-}
-
-
-/**
- * Get the size of a GL data type.
- *
- * \param type GL data type.
- *
- * \return the size, in bytes, of the given data type, 0 if a GL_BITMAP, or -1
- * if an invalid type enum.
- */
-GLint
-_mesa_sizeof_type( GLenum type )
-{
- switch (type) {
- case GL_BITMAP:
- return 0;
- case GL_UNSIGNED_BYTE:
- return sizeof(GLubyte);
- case GL_BYTE:
- return sizeof(GLbyte);
- case GL_UNSIGNED_SHORT:
- return sizeof(GLushort);
- case GL_SHORT:
- return sizeof(GLshort);
- case GL_UNSIGNED_INT:
- return sizeof(GLuint);
- case GL_INT:
- return sizeof(GLint);
- case GL_FLOAT:
- return sizeof(GLfloat);
- case GL_DOUBLE:
- return sizeof(GLdouble);
- case GL_HALF_FLOAT_ARB:
- return sizeof(GLhalfARB);
- case GL_FIXED:
- return sizeof(GLfixed);
- default:
- return -1;
- }
-}
-
-
-/**
- * Same as _mesa_sizeof_type() but also accepting the packed pixel
- * format data types.
- */
-GLint
-_mesa_sizeof_packed_type( GLenum type )
-{
- switch (type) {
- case GL_BITMAP:
- return 0;
- case GL_UNSIGNED_BYTE:
- return sizeof(GLubyte);
- case GL_BYTE:
- return sizeof(GLbyte);
- case GL_UNSIGNED_SHORT:
- return sizeof(GLushort);
- case GL_SHORT:
- return sizeof(GLshort);
- case GL_UNSIGNED_INT:
- return sizeof(GLuint);
- case GL_INT:
- return sizeof(GLint);
- case GL_HALF_FLOAT_ARB:
- return sizeof(GLhalfARB);
- case GL_FLOAT:
- return sizeof(GLfloat);
- case GL_UNSIGNED_BYTE_3_3_2:
- return sizeof(GLubyte);
- case GL_UNSIGNED_BYTE_2_3_3_REV:
- return sizeof(GLubyte);
- case MESA_UNSIGNED_BYTE_4_4:
- return sizeof(GLubyte);
- case GL_UNSIGNED_SHORT_5_6_5:
- return sizeof(GLushort);
- case GL_UNSIGNED_SHORT_5_6_5_REV:
- return sizeof(GLushort);
- case GL_UNSIGNED_SHORT_4_4_4_4:
- return sizeof(GLushort);
- case GL_UNSIGNED_SHORT_4_4_4_4_REV:
- return sizeof(GLushort);
- case GL_UNSIGNED_SHORT_5_5_5_1:
- return sizeof(GLushort);
- case GL_UNSIGNED_SHORT_1_5_5_5_REV:
- return sizeof(GLushort);
- case GL_UNSIGNED_INT_8_8_8_8:
- return sizeof(GLuint);
- case GL_UNSIGNED_INT_8_8_8_8_REV:
- return sizeof(GLuint);
- case GL_UNSIGNED_INT_10_10_10_2:
- return sizeof(GLuint);
- case GL_UNSIGNED_INT_2_10_10_10_REV:
- return sizeof(GLuint);
- case GL_UNSIGNED_SHORT_8_8_MESA:
- case GL_UNSIGNED_SHORT_8_8_REV_MESA:
- return sizeof(GLushort);
- case GL_UNSIGNED_INT_24_8_EXT:
- return sizeof(GLuint);
- case GL_UNSIGNED_INT_5_9_9_9_REV:
- return sizeof(GLuint);
- case GL_UNSIGNED_INT_10F_11F_11F_REV:
- return sizeof(GLuint);
- default:
- return -1;
- }
-}
-
-
-/**
- * Get the number of components in a pixel format.
- *
- * \param format pixel format.
- *
- * \return the number of components in the given format, or -1 if a bad format.
- */
-GLint
-_mesa_components_in_format( GLenum format )
-{
- switch (format) {
- case GL_COLOR_INDEX:
- case GL_COLOR_INDEX1_EXT:
- case GL_COLOR_INDEX2_EXT:
- case GL_COLOR_INDEX4_EXT:
- case GL_COLOR_INDEX8_EXT:
- case GL_COLOR_INDEX12_EXT:
- case GL_COLOR_INDEX16_EXT:
- case GL_STENCIL_INDEX:
- case GL_DEPTH_COMPONENT:
- case GL_RED:
- case GL_RED_INTEGER_EXT:
- case GL_GREEN:
- case GL_GREEN_INTEGER_EXT:
- case GL_BLUE:
- case GL_BLUE_INTEGER_EXT:
- case GL_ALPHA:
- case GL_ALPHA_INTEGER_EXT:
- case GL_LUMINANCE:
- case GL_LUMINANCE_INTEGER_EXT:
- case GL_INTENSITY:
- return 1;
- case GL_LUMINANCE_ALPHA:
- case GL_LUMINANCE_ALPHA_INTEGER_EXT:
- case GL_RG:
- return 2;
- case GL_RGB:
- case GL_RGB_INTEGER_EXT:
- return 3;
- case GL_RGBA:
- case GL_RGBA_INTEGER_EXT:
- return 4;
- case GL_BGR:
- return 3;
- case GL_BGRA:
- return 4;
- case GL_ABGR_EXT:
- return 4;
- case GL_YCBCR_MESA:
- return 2;
- case GL_DEPTH_STENCIL_EXT:
- return 2;
- case GL_DUDV_ATI:
- case GL_DU8DV8_ATI:
- return 2;
- default:
- return -1;
- }
-}
-
-
-/**
- * Get the bytes per pixel of pixel format type pair.
- *
- * \param format pixel format.
- * \param type pixel type.
- *
- * \return bytes per pixel, or -1 if a bad format or type was given.
- */
-GLint
-_mesa_bytes_per_pixel( GLenum format, GLenum type )
-{
- GLint comps = _mesa_components_in_format( format );
- if (comps < 0)
- return -1;
-
- switch (type) {
- case GL_BITMAP:
- return 0; /* special case */
- case GL_BYTE:
- case GL_UNSIGNED_BYTE:
- return comps * sizeof(GLubyte);
- case GL_SHORT:
- case GL_UNSIGNED_SHORT:
- return comps * sizeof(GLshort);
- case GL_INT:
- case GL_UNSIGNED_INT:
- return comps * sizeof(GLint);
- case GL_FLOAT:
- return comps * sizeof(GLfloat);
- case GL_HALF_FLOAT_ARB:
- return comps * sizeof(GLhalfARB);
- case GL_UNSIGNED_BYTE_3_3_2:
- case GL_UNSIGNED_BYTE_2_3_3_REV:
- if (format == GL_RGB || format == GL_BGR ||
- format == GL_RGB_INTEGER_EXT || format == GL_BGR_INTEGER_EXT)
- return sizeof(GLubyte);
- else
- return -1; /* error */
- case GL_UNSIGNED_SHORT_5_6_5:
- case GL_UNSIGNED_SHORT_5_6_5_REV:
- if (format == GL_RGB || format == GL_BGR ||
- format == GL_RGB_INTEGER_EXT || format == GL_BGR_INTEGER_EXT)
- return sizeof(GLushort);
- else
- return -1; /* error */
- case GL_UNSIGNED_SHORT_4_4_4_4:
- case GL_UNSIGNED_SHORT_4_4_4_4_REV:
- case GL_UNSIGNED_SHORT_5_5_5_1:
- case GL_UNSIGNED_SHORT_1_5_5_5_REV:
- if (format == GL_RGBA || format == GL_BGRA || format == GL_ABGR_EXT ||
- format == GL_RGBA_INTEGER_EXT || format == GL_BGRA_INTEGER_EXT)
- return sizeof(GLushort);
- else
- return -1;
- case GL_UNSIGNED_INT_8_8_8_8:
- case GL_UNSIGNED_INT_8_8_8_8_REV:
- case GL_UNSIGNED_INT_10_10_10_2:
- case GL_UNSIGNED_INT_2_10_10_10_REV:
- if (format == GL_RGBA || format == GL_BGRA || format == GL_ABGR_EXT ||
- format == GL_RGBA_INTEGER_EXT || format == GL_BGRA_INTEGER_EXT)
- return sizeof(GLuint);
- else
- return -1;
- case GL_UNSIGNED_SHORT_8_8_MESA:
- case GL_UNSIGNED_SHORT_8_8_REV_MESA:
- if (format == GL_YCBCR_MESA)
- return sizeof(GLushort);
- else
- return -1;
- case GL_UNSIGNED_INT_24_8_EXT:
- if (format == GL_DEPTH_STENCIL_EXT)
- return sizeof(GLuint);
- else
- return -1;
- case GL_UNSIGNED_INT_5_9_9_9_REV:
- if (format == GL_RGB)
- return sizeof(GLuint);
- else
- return -1;
- case GL_UNSIGNED_INT_10F_11F_11F_REV:
- if (format == GL_RGB)
- return sizeof(GLuint);
- else
- return -1;
- default:
- return -1;
- }
-}
-
-
-/**
- * Test for a legal pixel format and type.
- *
- * \param format pixel format.
- * \param type pixel type.
- *
- * \return GL_TRUE if the given pixel format and type are legal, or GL_FALSE
- * otherwise.
- */
-GLboolean
-_mesa_is_legal_format_and_type(const struct gl_context *ctx,
- GLenum format, GLenum type)
-{
- switch (format) {
- case GL_COLOR_INDEX:
- case GL_STENCIL_INDEX:
- switch (type) {
- case GL_BITMAP:
- case GL_BYTE:
- case GL_UNSIGNED_BYTE:
- case GL_SHORT:
- case GL_UNSIGNED_SHORT:
- case GL_INT:
- case GL_UNSIGNED_INT:
- case GL_FLOAT:
- return GL_TRUE;
- case GL_HALF_FLOAT_ARB:
- return ctx->Extensions.ARB_half_float_pixel;
- default:
- return GL_FALSE;
- }
- case GL_RED:
- case GL_GREEN:
- case GL_BLUE:
- case GL_ALPHA:
-#if 0 /* not legal! see table 3.6 of the 1.5 spec */
- case GL_INTENSITY:
-#endif
- case GL_LUMINANCE:
- case GL_LUMINANCE_ALPHA:
- case GL_DEPTH_COMPONENT:
- switch (type) {
- case GL_BYTE:
- case GL_UNSIGNED_BYTE:
- case GL_SHORT:
- case GL_UNSIGNED_SHORT:
- case GL_INT:
- case GL_UNSIGNED_INT:
- case GL_FLOAT:
- return GL_TRUE;
- case GL_HALF_FLOAT_ARB:
- return ctx->Extensions.ARB_half_float_pixel;
- default:
- return GL_FALSE;
- }
- case GL_RG:
- if (!ctx->Extensions.ARB_texture_rg)
- return GL_FALSE;
-
- switch (type) {
- case GL_BYTE:
- case GL_UNSIGNED_BYTE:
- case GL_SHORT:
- case GL_UNSIGNED_SHORT:
- case GL_INT:
- case GL_UNSIGNED_INT:
- case GL_FLOAT:
- return GL_TRUE;
- case GL_HALF_FLOAT_ARB:
- return ctx->Extensions.ARB_half_float_pixel;
- default:
- return GL_FALSE;
- }
- case GL_RGB:
- switch (type) {
- case GL_BYTE:
- case GL_UNSIGNED_BYTE:
- case GL_SHORT:
- case GL_UNSIGNED_SHORT:
- case GL_INT:
- case GL_UNSIGNED_INT:
- case GL_FLOAT:
- case GL_UNSIGNED_BYTE_3_3_2:
- case GL_UNSIGNED_BYTE_2_3_3_REV:
- case GL_UNSIGNED_SHORT_5_6_5:
- case GL_UNSIGNED_SHORT_5_6_5_REV:
- return GL_TRUE;
- case GL_HALF_FLOAT_ARB:
- return ctx->Extensions.ARB_half_float_pixel;
- case GL_UNSIGNED_INT_5_9_9_9_REV:
- return ctx->Extensions.EXT_texture_shared_exponent;
- case GL_UNSIGNED_INT_10F_11F_11F_REV:
- return ctx->Extensions.EXT_packed_float;
- default:
- return GL_FALSE;
- }
- case GL_BGR:
- switch (type) {
- /* NOTE: no packed types are supported with BGR. That's
- * intentional, according to the GL spec.
- */
- case GL_BYTE:
- case GL_UNSIGNED_BYTE:
- case GL_SHORT:
- case GL_UNSIGNED_SHORT:
- case GL_INT:
- case GL_UNSIGNED_INT:
- case GL_FLOAT:
- return GL_TRUE;
- case GL_HALF_FLOAT_ARB:
- return ctx->Extensions.ARB_half_float_pixel;
- default:
- return GL_FALSE;
- }
- case GL_RGBA:
- case GL_BGRA:
- case GL_ABGR_EXT:
- switch (type) {
- case GL_BYTE:
- case GL_UNSIGNED_BYTE:
- case GL_SHORT:
- case GL_UNSIGNED_SHORT:
- case GL_INT:
- case GL_UNSIGNED_INT:
- case GL_FLOAT:
- case GL_UNSIGNED_SHORT_4_4_4_4:
- case GL_UNSIGNED_SHORT_4_4_4_4_REV:
- case GL_UNSIGNED_SHORT_5_5_5_1:
- case GL_UNSIGNED_SHORT_1_5_5_5_REV:
- case GL_UNSIGNED_INT_8_8_8_8:
- case GL_UNSIGNED_INT_8_8_8_8_REV:
- case GL_UNSIGNED_INT_10_10_10_2:
- case GL_UNSIGNED_INT_2_10_10_10_REV:
- return GL_TRUE;
- case GL_HALF_FLOAT_ARB:
- return ctx->Extensions.ARB_half_float_pixel;
- default:
- return GL_FALSE;
- }
- case GL_YCBCR_MESA:
- if (type == GL_UNSIGNED_SHORT_8_8_MESA ||
- type == GL_UNSIGNED_SHORT_8_8_REV_MESA)
- return GL_TRUE;
- else
- return GL_FALSE;
- case GL_DEPTH_STENCIL_EXT:
- if (ctx->Extensions.EXT_packed_depth_stencil
- && type == GL_UNSIGNED_INT_24_8_EXT)
- return GL_TRUE;
- else
- return GL_FALSE;
- case GL_DUDV_ATI:
- case GL_DU8DV8_ATI:
- switch (type) {
- case GL_BYTE:
- case GL_UNSIGNED_BYTE:
- case GL_SHORT:
- case GL_UNSIGNED_SHORT:
- case GL_INT:
- case GL_UNSIGNED_INT:
- case GL_FLOAT:
- return GL_TRUE;
- default:
- return GL_FALSE;
- }
-
- /* integer-valued formats */
- case GL_RED_INTEGER_EXT:
- case GL_GREEN_INTEGER_EXT:
- case GL_BLUE_INTEGER_EXT:
- case GL_ALPHA_INTEGER_EXT:
- switch (type) {
- case GL_BYTE:
- case GL_UNSIGNED_BYTE:
- case GL_SHORT:
- case GL_UNSIGNED_SHORT:
- case GL_INT:
- case GL_UNSIGNED_INT:
- return ctx->Extensions.EXT_texture_integer;
- default:
- return GL_FALSE;
- }
-
- case GL_RGB_INTEGER_EXT:
- switch (type) {
- case GL_BYTE:
- case GL_UNSIGNED_BYTE:
- case GL_SHORT:
- case GL_UNSIGNED_SHORT:
- case GL_INT:
- case GL_UNSIGNED_INT:
- case GL_UNSIGNED_BYTE_3_3_2:
- case GL_UNSIGNED_BYTE_2_3_3_REV:
- case GL_UNSIGNED_SHORT_5_6_5:
- case GL_UNSIGNED_SHORT_5_6_5_REV:
- return ctx->Extensions.EXT_texture_integer;
- default:
- return GL_FALSE;
- }
-
- case GL_BGR_INTEGER_EXT:
- switch (type) {
- case GL_BYTE:
- case GL_UNSIGNED_BYTE:
- case GL_SHORT:
- case GL_UNSIGNED_SHORT:
- case GL_INT:
- case GL_UNSIGNED_INT:
- /* NOTE: no packed formats w/ BGR format */
- return ctx->Extensions.EXT_texture_integer;
- default:
- return GL_FALSE;
- }
-
- case GL_RGBA_INTEGER_EXT:
- case GL_BGRA_INTEGER_EXT:
- switch (type) {
- case GL_BYTE:
- case GL_UNSIGNED_BYTE:
- case GL_SHORT:
- case GL_UNSIGNED_SHORT:
- case GL_INT:
- case GL_UNSIGNED_INT:
- case GL_UNSIGNED_SHORT_4_4_4_4:
- case GL_UNSIGNED_SHORT_4_4_4_4_REV:
- case GL_UNSIGNED_SHORT_5_5_5_1:
- case GL_UNSIGNED_SHORT_1_5_5_5_REV:
- case GL_UNSIGNED_INT_8_8_8_8:
- case GL_UNSIGNED_INT_8_8_8_8_REV:
- case GL_UNSIGNED_INT_10_10_10_2:
- case GL_UNSIGNED_INT_2_10_10_10_REV:
- return ctx->Extensions.EXT_texture_integer;
- default:
- return GL_FALSE;
- }
-
- case GL_LUMINANCE_INTEGER_EXT:
- case GL_LUMINANCE_ALPHA_INTEGER_EXT:
- switch (type) {
- case GL_BYTE:
- case GL_UNSIGNED_BYTE:
- case GL_SHORT:
- case GL_UNSIGNED_SHORT:
- case GL_INT:
- case GL_UNSIGNED_INT:
- return ctx->Extensions.EXT_texture_integer;
- default:
- return GL_FALSE;
- }
-
- default:
- ; /* fall-through */
- }
- return GL_FALSE;
-}
-
-
-/**
- * Test if the given image format is a color/RGBA format (i.e., not color
- * index, depth, stencil, etc).
- * \param format the image format value (may by an internal texture format)
- * \return GL_TRUE if its a color/RGBA format, GL_FALSE otherwise.
- */
-GLboolean
-_mesa_is_color_format(GLenum format)
-{
- switch (format) {
- case GL_RED:
- case GL_GREEN:
- case GL_BLUE:
- case GL_ALPHA:
- case GL_ALPHA4:
- case GL_ALPHA8:
- case GL_ALPHA12:
- case GL_ALPHA16:
- case 1:
- case GL_LUMINANCE:
- case GL_LUMINANCE4:
- case GL_LUMINANCE8:
- case GL_LUMINANCE12:
- case GL_LUMINANCE16:
- case 2:
- case GL_LUMINANCE_ALPHA:
- case GL_LUMINANCE4_ALPHA4:
- case GL_LUMINANCE6_ALPHA2:
- case GL_LUMINANCE8_ALPHA8:
- case GL_LUMINANCE12_ALPHA4:
- case GL_LUMINANCE12_ALPHA12:
- case GL_LUMINANCE16_ALPHA16:
- case GL_INTENSITY:
- case GL_INTENSITY4:
- case GL_INTENSITY8:
- case GL_INTENSITY12:
- case GL_INTENSITY16:
- case GL_R8:
- case GL_R16:
- case GL_RG:
- case GL_RG8:
- case GL_RG16:
- case 3:
- case GL_RGB:
- case GL_BGR:
- case GL_R3_G3_B2:
- case GL_RGB4:
- case GL_RGB5:
- case GL_RGB8:
- case GL_RGB10:
- case GL_RGB12:
- case GL_RGB16:
- case 4:
- case GL_ABGR_EXT:
- case GL_RGBA:
- case GL_BGRA:
- case GL_RGBA2:
- case GL_RGBA4:
- case GL_RGB5_A1:
- case GL_RGBA8:
- case GL_RGB10_A2:
- case GL_RGBA12:
- case GL_RGBA16:
- /* float texture formats */
- case GL_ALPHA16F_ARB:
- case GL_ALPHA32F_ARB:
- case GL_LUMINANCE16F_ARB:
- case GL_LUMINANCE32F_ARB:
- case GL_LUMINANCE_ALPHA16F_ARB:
- case GL_LUMINANCE_ALPHA32F_ARB:
- case GL_INTENSITY16F_ARB:
- case GL_INTENSITY32F_ARB:
- case GL_R16F:
- case GL_R32F:
- case GL_RG16F:
- case GL_RG32F:
- case GL_RGB16F_ARB:
- case GL_RGB32F_ARB:
- case GL_RGBA16F_ARB:
- case GL_RGBA32F_ARB:
- /* compressed formats */
- case GL_COMPRESSED_ALPHA:
- case GL_COMPRESSED_LUMINANCE:
- case GL_COMPRESSED_LUMINANCE_ALPHA:
- case GL_COMPRESSED_INTENSITY:
- case GL_COMPRESSED_RED:
- case GL_COMPRESSED_RG:
- case GL_COMPRESSED_RGB:
- case GL_COMPRESSED_RGBA:
- case GL_RGB_S3TC:
- case GL_RGB4_S3TC:
- case GL_RGBA_S3TC:
- case GL_RGBA4_S3TC:
- case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
- case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
- case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
- case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
- case GL_COMPRESSED_RGB_FXT1_3DFX:
- case GL_COMPRESSED_RGBA_FXT1_3DFX:
-#if FEATURE_EXT_texture_sRGB
- case GL_SRGB_EXT:
- case GL_SRGB8_EXT:
- case GL_SRGB_ALPHA_EXT:
- case GL_SRGB8_ALPHA8_EXT:
- case GL_SLUMINANCE_ALPHA_EXT:
- case GL_SLUMINANCE8_ALPHA8_EXT:
- case GL_SLUMINANCE_EXT:
- case GL_SLUMINANCE8_EXT:
- case GL_COMPRESSED_SRGB_EXT:
- case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
- case GL_COMPRESSED_SRGB_ALPHA_EXT:
- case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
- case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
- case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
- case GL_COMPRESSED_SLUMINANCE_EXT:
- case GL_COMPRESSED_SLUMINANCE_ALPHA_EXT:
-#endif /* FEATURE_EXT_texture_sRGB */
- case GL_COMPRESSED_RED_RGTC1:
- case GL_COMPRESSED_SIGNED_RED_RGTC1:
- case GL_COMPRESSED_RG_RGTC2:
- case GL_COMPRESSED_SIGNED_RG_RGTC2:
- case GL_COMPRESSED_LUMINANCE_LATC1_EXT:
- case GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT:
- case GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT:
- case GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT:
- case GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI:
- /* generic integer formats */
- case GL_RED_INTEGER_EXT:
- case GL_GREEN_INTEGER_EXT:
- case GL_BLUE_INTEGER_EXT:
- case GL_ALPHA_INTEGER_EXT:
- case GL_RGB_INTEGER_EXT:
- case GL_RGBA_INTEGER_EXT:
- case GL_BGR_INTEGER_EXT:
- case GL_BGRA_INTEGER_EXT:
- case GL_LUMINANCE_INTEGER_EXT:
- case GL_LUMINANCE_ALPHA_INTEGER_EXT:
- /* sized integer formats */
- case GL_RGBA32UI_EXT:
- case GL_RGB32UI_EXT:
- case GL_ALPHA32UI_EXT:
- case GL_INTENSITY32UI_EXT:
- case GL_LUMINANCE32UI_EXT:
- case GL_LUMINANCE_ALPHA32UI_EXT:
- case GL_RGBA16UI_EXT:
- case GL_RGB16UI_EXT:
- case GL_ALPHA16UI_EXT:
- case GL_INTENSITY16UI_EXT:
- case GL_LUMINANCE16UI_EXT:
- case GL_LUMINANCE_ALPHA16UI_EXT:
- case GL_RGBA8UI_EXT:
- case GL_RGB8UI_EXT:
- case GL_ALPHA8UI_EXT:
- case GL_INTENSITY8UI_EXT:
- case GL_LUMINANCE8UI_EXT:
- case GL_LUMINANCE_ALPHA8UI_EXT:
- case GL_RGBA32I_EXT:
- case GL_RGB32I_EXT:
- case GL_ALPHA32I_EXT:
- case GL_INTENSITY32I_EXT:
- case GL_LUMINANCE32I_EXT:
- case GL_LUMINANCE_ALPHA32I_EXT:
- case GL_RGBA16I_EXT:
- case GL_RGB16I_EXT:
- case GL_ALPHA16I_EXT:
- case GL_INTENSITY16I_EXT:
- case GL_LUMINANCE16I_EXT:
- case GL_LUMINANCE_ALPHA16I_EXT:
- case GL_RGBA8I_EXT:
- case GL_RGB8I_EXT:
- case GL_ALPHA8I_EXT:
- case GL_INTENSITY8I_EXT:
- case GL_LUMINANCE8I_EXT:
- case GL_LUMINANCE_ALPHA8I_EXT:
- /* signed, normalized texture formats */
- case GL_RED_SNORM:
- case GL_R8_SNORM:
- case GL_R16_SNORM:
- case GL_RG_SNORM:
- case GL_RG8_SNORM:
- case GL_RG16_SNORM:
- case GL_RGB_SNORM:
- case GL_RGB8_SNORM:
- case GL_RGB16_SNORM:
- case GL_RGBA_SNORM:
- case GL_RGBA8_SNORM:
- case GL_RGBA16_SNORM:
- case GL_ALPHA_SNORM:
- case GL_ALPHA8_SNORM:
- case GL_ALPHA16_SNORM:
- case GL_LUMINANCE_SNORM:
- case GL_LUMINANCE8_SNORM:
- case GL_LUMINANCE16_SNORM:
- case GL_LUMINANCE_ALPHA_SNORM:
- case GL_LUMINANCE8_ALPHA8_SNORM:
- case GL_LUMINANCE16_ALPHA16_SNORM:
- case GL_INTENSITY_SNORM:
- case GL_INTENSITY8_SNORM:
- case GL_INTENSITY16_SNORM:
- case GL_RGB9_E5:
- case GL_R11F_G11F_B10F:
- return GL_TRUE;
- case GL_YCBCR_MESA: /* not considered to be RGB */
- /* fall-through */
- default:
- return GL_FALSE;
- }
-}
-
-
-/**
- * Test if the given image format is a color index format.
- */
-GLboolean
-_mesa_is_index_format(GLenum format)
-{
- switch (format) {
- case GL_COLOR_INDEX:
- case GL_COLOR_INDEX1_EXT:
- case GL_COLOR_INDEX2_EXT:
- case GL_COLOR_INDEX4_EXT:
- case GL_COLOR_INDEX8_EXT:
- case GL_COLOR_INDEX12_EXT:
- case GL_COLOR_INDEX16_EXT:
- return GL_TRUE;
- default:
- return GL_FALSE;
- }
-}
-
-
-/**
- * Test if the given image format is a depth component format.
- */
-GLboolean
-_mesa_is_depth_format(GLenum format)
-{
- switch (format) {
- case GL_DEPTH_COMPONENT:
- case GL_DEPTH_COMPONENT16:
- case GL_DEPTH_COMPONENT24:
- case GL_DEPTH_COMPONENT32:
- return GL_TRUE;
- default:
- return GL_FALSE;
- }
-}
-
-
-/**
- * Test if the given image format is a stencil format.
- */
-GLboolean
-_mesa_is_stencil_format(GLenum format)
-{
- switch (format) {
- case GL_STENCIL_INDEX:
- case GL_DEPTH_STENCIL:
- return GL_TRUE;
- default:
- return GL_FALSE;
- }
-}
-
-
-/**
- * Test if the given image format is a YCbCr format.
- */
-GLboolean
-_mesa_is_ycbcr_format(GLenum format)
-{
- switch (format) {
- case GL_YCBCR_MESA:
- return GL_TRUE;
- default:
- return GL_FALSE;
- }
-}
-
-
-/**
- * Test if the given image format is a depth+stencil format.
- */
-GLboolean
-_mesa_is_depthstencil_format(GLenum format)
-{
- switch (format) {
- case GL_DEPTH24_STENCIL8_EXT:
- case GL_DEPTH_STENCIL_EXT:
- return GL_TRUE;
- default:
- return GL_FALSE;
- }
-}
-
-
-/**
- * Test if the given image format is a depth or stencil format.
- */
-GLboolean
-_mesa_is_depth_or_stencil_format(GLenum format)
-{
- switch (format) {
- case GL_DEPTH_COMPONENT:
- case GL_DEPTH_COMPONENT16:
- case GL_DEPTH_COMPONENT24:
- case GL_DEPTH_COMPONENT32:
- case GL_STENCIL_INDEX:
- case GL_STENCIL_INDEX1_EXT:
- case GL_STENCIL_INDEX4_EXT:
- case GL_STENCIL_INDEX8_EXT:
- case GL_STENCIL_INDEX16_EXT:
- case GL_DEPTH_STENCIL_EXT:
- case GL_DEPTH24_STENCIL8_EXT:
- return GL_TRUE;
- default:
- return GL_FALSE;
- }
-}
-
-
-/**
- * Test if the given image format is a dudv format.
- */
-GLboolean
-_mesa_is_dudv_format(GLenum format)
-{
- switch (format) {
- case GL_DUDV_ATI:
- case GL_DU8DV8_ATI:
- return GL_TRUE;
- default:
- return GL_FALSE;
- }
-}
-
-
-/**
- * Test if the given format is an integer (non-normalized) format.
- */
-GLboolean
-_mesa_is_integer_format(GLenum format)
-{
- switch (format) {
- /* generic integer formats */
- case GL_RED_INTEGER_EXT:
- case GL_GREEN_INTEGER_EXT:
- case GL_BLUE_INTEGER_EXT:
- case GL_ALPHA_INTEGER_EXT:
- case GL_RGB_INTEGER_EXT:
- case GL_RGBA_INTEGER_EXT:
- case GL_BGR_INTEGER_EXT:
- case GL_BGRA_INTEGER_EXT:
- case GL_LUMINANCE_INTEGER_EXT:
- case GL_LUMINANCE_ALPHA_INTEGER_EXT:
- /* specific integer formats */
- case GL_RGBA32UI_EXT:
- case GL_RGB32UI_EXT:
- case GL_ALPHA32UI_EXT:
- case GL_INTENSITY32UI_EXT:
- case GL_LUMINANCE32UI_EXT:
- case GL_LUMINANCE_ALPHA32UI_EXT:
- case GL_RGBA16UI_EXT:
- case GL_RGB16UI_EXT:
- case GL_ALPHA16UI_EXT:
- case GL_INTENSITY16UI_EXT:
- case GL_LUMINANCE16UI_EXT:
- case GL_LUMINANCE_ALPHA16UI_EXT:
- case GL_RGBA8UI_EXT:
- case GL_RGB8UI_EXT:
- case GL_ALPHA8UI_EXT:
- case GL_INTENSITY8UI_EXT:
- case GL_LUMINANCE8UI_EXT:
- case GL_LUMINANCE_ALPHA8UI_EXT:
- case GL_RGBA32I_EXT:
- case GL_RGB32I_EXT:
- case GL_ALPHA32I_EXT:
- case GL_INTENSITY32I_EXT:
- case GL_LUMINANCE32I_EXT:
- case GL_LUMINANCE_ALPHA32I_EXT:
- case GL_RGBA16I_EXT:
- case GL_RGB16I_EXT:
- case GL_ALPHA16I_EXT:
- case GL_INTENSITY16I_EXT:
- case GL_LUMINANCE16I_EXT:
- case GL_LUMINANCE_ALPHA16I_EXT:
- case GL_RGBA8I_EXT:
- case GL_RGB8I_EXT:
- case GL_ALPHA8I_EXT:
- case GL_INTENSITY8I_EXT:
- case GL_LUMINANCE8I_EXT:
- case GL_LUMINANCE_ALPHA8I_EXT:
- return GL_TRUE;
- default:
- return GL_FALSE;
- }
-}
-
-
-/**
- * Test if an image format is a supported compressed format.
- * \param format the internal format token provided by the user.
- * \return GL_TRUE if compressed, GL_FALSE if uncompressed
- */
-GLboolean
-_mesa_is_compressed_format(struct gl_context *ctx, GLenum format)
-{
- switch (format) {
- case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
- case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
- case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
- case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
- return ctx->Extensions.EXT_texture_compression_s3tc;
- case GL_RGB_S3TC:
- case GL_RGB4_S3TC:
- case GL_RGBA_S3TC:
- case GL_RGBA4_S3TC:
- return ctx->Extensions.S3_s3tc;
- case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
- case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
- case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
- case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
- return ctx->Extensions.EXT_texture_sRGB
- && ctx->Extensions.EXT_texture_compression_s3tc;
- case GL_COMPRESSED_RGB_FXT1_3DFX:
- case GL_COMPRESSED_RGBA_FXT1_3DFX:
- return ctx->Extensions.TDFX_texture_compression_FXT1;
- case GL_COMPRESSED_RED_RGTC1:
- case GL_COMPRESSED_SIGNED_RED_RGTC1:
- case GL_COMPRESSED_RG_RGTC2:
- case GL_COMPRESSED_SIGNED_RG_RGTC2:
- return ctx->Extensions.ARB_texture_compression_rgtc;
- case GL_COMPRESSED_LUMINANCE_LATC1_EXT:
- case GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT:
- case GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT:
- case GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT:
- return ctx->Extensions.EXT_texture_compression_latc;
- case GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI:
- return ctx->Extensions.ATI_texture_compression_3dc;
- default:
- return GL_FALSE;
- }
-}
-
-
-/**
- * Return the address of a specific pixel in an image (1D, 2D or 3D).
- *
- * Pixel unpacking/packing parameters are observed according to \p packing.
- *
- * \param dimensions either 1, 2 or 3 to indicate dimensionality of image
- * \param image starting address of image data
- * \param width the image width
- * \param height theimage height
- * \param format the pixel format
- * \param type the pixel data type
- * \param packing the pixelstore attributes
- * \param img which image in the volume (0 for 1D or 2D images)
- * \param row row of pixel in the image (0 for 1D images)
- * \param column column of pixel in the image
- *
- * \return address of pixel on success, or NULL on error.
- *
- * \sa gl_pixelstore_attrib.
- */
-GLvoid *
-_mesa_image_address( GLuint dimensions,
- const struct gl_pixelstore_attrib *packing,
- const GLvoid *image,
- GLsizei width, GLsizei height,
- GLenum format, GLenum type,
- GLint img, GLint row, GLint column )
-{
- GLint alignment; /* 1, 2 or 4 */
- GLint pixels_per_row;
- GLint rows_per_image;
- GLint skiprows;
- GLint skippixels;
- GLint skipimages; /* for 3-D volume images */
- GLubyte *pixel_addr;
-
- ASSERT(dimensions >= 1 && dimensions <= 3);
-
- alignment = packing->Alignment;
- if (packing->RowLength > 0) {
- pixels_per_row = packing->RowLength;
- }
- else {
- pixels_per_row = width;
- }
- if (packing->ImageHeight > 0) {
- rows_per_image = packing->ImageHeight;
- }
- else {
- rows_per_image = height;
- }
-
- skippixels = packing->SkipPixels;
- /* Note: SKIP_ROWS _is_ used for 1D images */
- skiprows = packing->SkipRows;
- /* Note: SKIP_IMAGES is only used for 3D images */
- skipimages = (dimensions == 3) ? packing->SkipImages : 0;
-
- if (type == GL_BITMAP) {
- /* BITMAP data */
- GLint comp_per_pixel; /* components per pixel */
- GLint bytes_per_comp; /* bytes per component */
- GLint bytes_per_row;
- GLint bytes_per_image;
-
- /* Compute bytes per component */
- bytes_per_comp = _mesa_sizeof_packed_type( type );
- if (bytes_per_comp < 0) {
- return NULL;
- }
-
- /* Compute number of components per pixel */
- comp_per_pixel = _mesa_components_in_format( format );
- if (comp_per_pixel < 0) {
- return NULL;
- }
-
- bytes_per_row = alignment
- * CEILING( comp_per_pixel*pixels_per_row, 8*alignment );
-
- bytes_per_image = bytes_per_row * rows_per_image;
-
- pixel_addr = (GLubyte *) image
- + (skipimages + img) * bytes_per_image
- + (skiprows + row) * bytes_per_row
- + (skippixels + column) / 8;
- }
- else {
- /* Non-BITMAP data */
- GLint bytes_per_pixel, bytes_per_row, remainder, bytes_per_image;
- GLint topOfImage;
-
- bytes_per_pixel = _mesa_bytes_per_pixel( format, type );
-
- /* The pixel type and format should have been error checked earlier */
- assert(bytes_per_pixel > 0);
-
- bytes_per_row = pixels_per_row * bytes_per_pixel;
- remainder = bytes_per_row % alignment;
- if (remainder > 0)
- bytes_per_row += (alignment - remainder);
-
- ASSERT(bytes_per_row % alignment == 0);
-
- bytes_per_image = bytes_per_row * rows_per_image;
-
- if (packing->Invert) {
- /* set pixel_addr to the last row */
- topOfImage = bytes_per_row * (height - 1);
- bytes_per_row = -bytes_per_row;
- }
- else {
- topOfImage = 0;
- }
-
- /* compute final pixel address */
- pixel_addr = (GLubyte *) image
- + (skipimages + img) * bytes_per_image
- + topOfImage
- + (skiprows + row) * bytes_per_row
- + (skippixels + column) * bytes_per_pixel;
- }
-
- return (GLvoid *) pixel_addr;
-}
-
-
-GLvoid *
-_mesa_image_address1d( const struct gl_pixelstore_attrib *packing,
- const GLvoid *image,
- GLsizei width,
- GLenum format, GLenum type,
- GLint column )
-{
- return _mesa_image_address(1, packing, image, width, 1,
- format, type, 0, 0, column);
-}
-
-
-GLvoid *
-_mesa_image_address2d( const struct gl_pixelstore_attrib *packing,
- const GLvoid *image,
- GLsizei width, GLsizei height,
- GLenum format, GLenum type,
- GLint row, GLint column )
-{
- return _mesa_image_address(2, packing, image, width, height,
- format, type, 0, row, column);
-}
-
-
-GLvoid *
-_mesa_image_address3d( const struct gl_pixelstore_attrib *packing,
- const GLvoid *image,
- GLsizei width, GLsizei height,
- GLenum format, GLenum type,
- GLint img, GLint row, GLint column )
-{
- return _mesa_image_address(3, packing, image, width, height,
- format, type, img, row, column);
-}
-
-
-
-/**
- * Compute the stride (in bytes) between image rows.
- *
- * \param packing the pixelstore attributes
- * \param width image width.
- * \param format pixel format.
- * \param type pixel data type.
- *
- * \return the stride in bytes for the given parameters, or -1 if error
- */
-GLint
-_mesa_image_row_stride( const struct gl_pixelstore_attrib *packing,
- GLint width, GLenum format, GLenum type )
-{
- GLint bytesPerRow, remainder;
-
- ASSERT(packing);
-
- if (type == GL_BITMAP) {
- if (packing->RowLength == 0) {
- bytesPerRow = (width + 7) / 8;
- }
- else {
- bytesPerRow = (packing->RowLength + 7) / 8;
- }
- }
- else {
- /* Non-BITMAP data */
- const GLint bytesPerPixel = _mesa_bytes_per_pixel(format, type);
- if (bytesPerPixel <= 0)
- return -1; /* error */
- if (packing->RowLength == 0) {
- bytesPerRow = bytesPerPixel * width;
- }
- else {
- bytesPerRow = bytesPerPixel * packing->RowLength;
- }
- }
-
- remainder = bytesPerRow % packing->Alignment;
- if (remainder > 0) {
- bytesPerRow += (packing->Alignment - remainder);
- }
-
- if (packing->Invert) {
- /* negate the bytes per row (negative row stride) */
- bytesPerRow = -bytesPerRow;
- }
-
- return bytesPerRow;
-}
-
-
-/*
- * Compute the stride between images in a 3D texture (in bytes) for the given
- * pixel packing parameters and image width, format and type.
- */
-GLint
-_mesa_image_image_stride( const struct gl_pixelstore_attrib *packing,
- GLint width, GLint height,
- GLenum format, GLenum type )
-{
- GLint bytesPerRow, bytesPerImage, remainder;
-
- ASSERT(packing);
-
- if (type == GL_BITMAP) {
- if (packing->RowLength == 0) {
- bytesPerRow = (width + 7) / 8;
- }
- else {
- bytesPerRow = (packing->RowLength + 7) / 8;
- }
- }
- else {
- const GLint bytesPerPixel = _mesa_bytes_per_pixel(format, type);
-
- if (bytesPerPixel <= 0)
- return -1; /* error */
- if (packing->RowLength == 0) {
- bytesPerRow = bytesPerPixel * width;
- }
- else {
- bytesPerRow = bytesPerPixel * packing->RowLength;
- }
- }
-
- remainder = bytesPerRow % packing->Alignment;
- if (remainder > 0)
- bytesPerRow += (packing->Alignment - remainder);
-
- if (packing->ImageHeight == 0)
- bytesPerImage = bytesPerRow * height;
- else
- bytesPerImage = bytesPerRow * packing->ImageHeight;
-
- return bytesPerImage;
-}
-
-
-
-/**
- * "Expand" a bitmap from 1-bit per pixel to 8-bits per pixel.
- * This is typically used to convert a bitmap into a GLubyte/pixel texture.
- * "On" bits will set texels to \p onValue.
- * "Off" bits will not modify texels.
- * \param width src bitmap width in pixels
- * \param height src bitmap height in pixels
- * \param unpack bitmap unpacking state
- * \param bitmap the src bitmap data
- * \param destBuffer start of dest buffer
- * \param destStride row stride in dest buffer
- * \param onValue if bit is 1, set destBuffer pixel to this value
- */
-void
-_mesa_expand_bitmap(GLsizei width, GLsizei height,
- const struct gl_pixelstore_attrib *unpack,
- const GLubyte *bitmap,
- GLubyte *destBuffer, GLint destStride,
- GLubyte onValue)
-{
- const GLubyte *srcRow = (const GLubyte *)
- _mesa_image_address2d(unpack, bitmap, width, height,
- GL_COLOR_INDEX, GL_BITMAP, 0, 0);
- const GLint srcStride = _mesa_image_row_stride(unpack, width,
- GL_COLOR_INDEX, GL_BITMAP);
- GLint row, col;
-
-#define SET_PIXEL(COL, ROW) \
- destBuffer[(ROW) * destStride + (COL)] = onValue;
-
- for (row = 0; row < height; row++) {
- const GLubyte *src = srcRow;
-
- if (unpack->LsbFirst) {
- /* Lsb first */
- GLubyte mask = 1U << (unpack->SkipPixels & 0x7);
- for (col = 0; col < width; col++) {
-
- if (*src & mask) {
- SET_PIXEL(col, row);
- }
-
- if (mask == 128U) {
- src++;
- mask = 1U;
- }
- else {
- mask = mask << 1;
- }
- }
-
- /* get ready for next row */
- if (mask != 1)
- src++;
- }
- else {
- /* Msb first */
- GLubyte mask = 128U >> (unpack->SkipPixels & 0x7);
- for (col = 0; col < width; col++) {
-
- if (*src & mask) {
- SET_PIXEL(col, row);
- }
-
- if (mask == 1U) {
- src++;
- mask = 128U;
- }
- else {
- mask = mask >> 1;
- }
- }
-
- /* get ready for next row */
- if (mask != 128)
- src++;
- }
-
- srcRow += srcStride;
- } /* row */
-
-#undef SET_PIXEL
-}
-
-
-
-
-/**
- * Convert an array of RGBA colors from one datatype to another.
- * NOTE: src may equal dst. In that case, we use a temporary buffer.
- */
-void
-_mesa_convert_colors(GLenum srcType, const GLvoid *src,
- GLenum dstType, GLvoid *dst,
- GLuint count, const GLubyte mask[])
-{
- GLuint tempBuffer[MAX_WIDTH][4];
- const GLboolean useTemp = (src == dst);
-
- ASSERT(srcType != dstType);
-
- switch (srcType) {
- case GL_UNSIGNED_BYTE:
- if (dstType == GL_UNSIGNED_SHORT) {
- const GLubyte (*src1)[4] = (const GLubyte (*)[4]) src;
- GLushort (*dst2)[4] = (GLushort (*)[4]) (useTemp ? tempBuffer : dst);
- GLuint i;
- for (i = 0; i < count; i++) {
- if (!mask || mask[i]) {
- dst2[i][RCOMP] = UBYTE_TO_USHORT(src1[i][RCOMP]);
- dst2[i][GCOMP] = UBYTE_TO_USHORT(src1[i][GCOMP]);
- dst2[i][BCOMP] = UBYTE_TO_USHORT(src1[i][BCOMP]);
- dst2[i][ACOMP] = UBYTE_TO_USHORT(src1[i][ACOMP]);
- }
- }
- if (useTemp)
- memcpy(dst, tempBuffer, count * 4 * sizeof(GLushort));
- }
- else {
- const GLubyte (*src1)[4] = (const GLubyte (*)[4]) src;
- GLfloat (*dst4)[4] = (GLfloat (*)[4]) (useTemp ? tempBuffer : dst);
- GLuint i;
- ASSERT(dstType == GL_FLOAT);
- for (i = 0; i < count; i++) {
- if (!mask || mask[i]) {
- dst4[i][RCOMP] = UBYTE_TO_FLOAT(src1[i][RCOMP]);
- dst4[i][GCOMP] = UBYTE_TO_FLOAT(src1[i][GCOMP]);
- dst4[i][BCOMP] = UBYTE_TO_FLOAT(src1[i][BCOMP]);
- dst4[i][ACOMP] = UBYTE_TO_FLOAT(src1[i][ACOMP]);
- }
- }
- if (useTemp)
- memcpy(dst, tempBuffer, count * 4 * sizeof(GLfloat));
- }
- break;
- case GL_UNSIGNED_SHORT:
- if (dstType == GL_UNSIGNED_BYTE) {
- const GLushort (*src2)[4] = (const GLushort (*)[4]) src;
- GLubyte (*dst1)[4] = (GLubyte (*)[4]) (useTemp ? tempBuffer : dst);
- GLuint i;
- for (i = 0; i < count; i++) {
- if (!mask || mask[i]) {
- dst1[i][RCOMP] = USHORT_TO_UBYTE(src2[i][RCOMP]);
- dst1[i][GCOMP] = USHORT_TO_UBYTE(src2[i][GCOMP]);
- dst1[i][BCOMP] = USHORT_TO_UBYTE(src2[i][BCOMP]);
- dst1[i][ACOMP] = USHORT_TO_UBYTE(src2[i][ACOMP]);
- }
- }
- if (useTemp)
- memcpy(dst, tempBuffer, count * 4 * sizeof(GLubyte));
- }
- else {
- const GLushort (*src2)[4] = (const GLushort (*)[4]) src;
- GLfloat (*dst4)[4] = (GLfloat (*)[4]) (useTemp ? tempBuffer : dst);
- GLuint i;
- ASSERT(dstType == GL_FLOAT);
- for (i = 0; i < count; i++) {
- if (!mask || mask[i]) {
- dst4[i][RCOMP] = USHORT_TO_FLOAT(src2[i][RCOMP]);
- dst4[i][GCOMP] = USHORT_TO_FLOAT(src2[i][GCOMP]);
- dst4[i][BCOMP] = USHORT_TO_FLOAT(src2[i][BCOMP]);
- dst4[i][ACOMP] = USHORT_TO_FLOAT(src2[i][ACOMP]);
- }
- }
- if (useTemp)
- memcpy(dst, tempBuffer, count * 4 * sizeof(GLfloat));
- }
- break;
- case GL_FLOAT:
- if (dstType == GL_UNSIGNED_BYTE) {
- const GLfloat (*src4)[4] = (const GLfloat (*)[4]) src;
- GLubyte (*dst1)[4] = (GLubyte (*)[4]) (useTemp ? tempBuffer : dst);
- GLuint i;
- for (i = 0; i < count; i++) {
- if (!mask || mask[i]) {
- UNCLAMPED_FLOAT_TO_UBYTE(dst1[i][RCOMP], src4[i][RCOMP]);
- UNCLAMPED_FLOAT_TO_UBYTE(dst1[i][GCOMP], src4[i][GCOMP]);
- UNCLAMPED_FLOAT_TO_UBYTE(dst1[i][BCOMP], src4[i][BCOMP]);
- UNCLAMPED_FLOAT_TO_UBYTE(dst1[i][ACOMP], src4[i][ACOMP]);
- }
- }
- if (useTemp)
- memcpy(dst, tempBuffer, count * 4 * sizeof(GLubyte));
- }
- else {
- const GLfloat (*src4)[4] = (const GLfloat (*)[4]) src;
- GLushort (*dst2)[4] = (GLushort (*)[4]) (useTemp ? tempBuffer : dst);
- GLuint i;
- ASSERT(dstType == GL_UNSIGNED_SHORT);
- for (i = 0; i < count; i++) {
- if (!mask || mask[i]) {
- UNCLAMPED_FLOAT_TO_USHORT(dst2[i][RCOMP], src4[i][RCOMP]);
- UNCLAMPED_FLOAT_TO_USHORT(dst2[i][GCOMP], src4[i][GCOMP]);
- UNCLAMPED_FLOAT_TO_USHORT(dst2[i][BCOMP], src4[i][BCOMP]);
- UNCLAMPED_FLOAT_TO_USHORT(dst2[i][ACOMP], src4[i][ACOMP]);
- }
- }
- if (useTemp)
- memcpy(dst, tempBuffer, count * 4 * sizeof(GLushort));
- }
- break;
- default:
- _mesa_problem(NULL, "Invalid datatype in _mesa_convert_colors");
- }
-}
-
-
-
-
-/**
- * Perform basic clipping for glDrawPixels. The image's position and size
- * and the unpack SkipPixels and SkipRows are adjusted so that the image
- * region is entirely within the window and scissor bounds.
- * NOTE: this will only work when glPixelZoom is (1, 1) or (1, -1).
- * If Pixel.ZoomY is -1, *destY will be changed to be the first row which
- * we'll actually write. Beforehand, *destY-1 is the first drawing row.
- *
- * \return GL_TRUE if image is ready for drawing or
- * GL_FALSE if image was completely clipped away (draw nothing)
- */
-GLboolean
-_mesa_clip_drawpixels(const struct gl_context *ctx,
- GLint *destX, GLint *destY,
- GLsizei *width, GLsizei *height,
- struct gl_pixelstore_attrib *unpack)
-{
- const struct gl_framebuffer *buffer = ctx->DrawBuffer;
-
- if (unpack->RowLength == 0) {
- unpack->RowLength = *width;
- }
-
- ASSERT(ctx->Pixel.ZoomX == 1.0F);
- ASSERT(ctx->Pixel.ZoomY == 1.0F || ctx->Pixel.ZoomY == -1.0F);
-
- /* left clipping */
- if (*destX < buffer->_Xmin) {
- unpack->SkipPixels += (buffer->_Xmin - *destX);
- *width -= (buffer->_Xmin - *destX);
- *destX = buffer->_Xmin;
- }
- /* right clipping */
- if (*destX + *width > buffer->_Xmax)
- *width -= (*destX + *width - buffer->_Xmax);
-
- if (*width <= 0)
- return GL_FALSE;
-
- if (ctx->Pixel.ZoomY == 1.0F) {
- /* bottom clipping */
- if (*destY < buffer->_Ymin) {
- unpack->SkipRows += (buffer->_Ymin - *destY);
- *height -= (buffer->_Ymin - *destY);
- *destY = buffer->_Ymin;
- }
- /* top clipping */
- if (*destY + *height > buffer->_Ymax)
- *height -= (*destY + *height - buffer->_Ymax);
- }
- else { /* upside down */
- /* top clipping */
- if (*destY > buffer->_Ymax) {
- unpack->SkipRows += (*destY - buffer->_Ymax);
- *height -= (*destY - buffer->_Ymax);
- *destY = buffer->_Ymax;
- }
- /* bottom clipping */
- if (*destY - *height < buffer->_Ymin)
- *height -= (buffer->_Ymin - (*destY - *height));
- /* adjust destY so it's the first row to write to */
- (*destY)--;
- }
-
- if (*height <= 0)
- return GL_FALSE;
-
- return GL_TRUE;
-}
-
-
-/**
- * Perform clipping for glReadPixels. The image's window position
- * and size, and the pack skipPixels, skipRows and rowLength are adjusted
- * so that the image region is entirely within the window bounds.
- * Note: this is different from _mesa_clip_drawpixels() in that the
- * scissor box is ignored, and we use the bounds of the current readbuffer
- * surface.
- *
- * \return GL_TRUE if region to read is in bounds
- * GL_FALSE if region is completely out of bounds (nothing to read)
- */
-GLboolean
-_mesa_clip_readpixels(const struct gl_context *ctx,
- GLint *srcX, GLint *srcY,
- GLsizei *width, GLsizei *height,
- struct gl_pixelstore_attrib *pack)
-{
- const struct gl_framebuffer *buffer = ctx->ReadBuffer;
-
- if (pack->RowLength == 0) {
- pack->RowLength = *width;
- }
-
- /* left clipping */
- if (*srcX < 0) {
- pack->SkipPixels += (0 - *srcX);
- *width -= (0 - *srcX);
- *srcX = 0;
- }
- /* right clipping */
- if (*srcX + *width > (GLsizei) buffer->Width)
- *width -= (*srcX + *width - buffer->Width);
-
- if (*width <= 0)
- return GL_FALSE;
-
- /* bottom clipping */
- if (*srcY < 0) {
- pack->SkipRows += (0 - *srcY);
- *height -= (0 - *srcY);
- *srcY = 0;
- }
- /* top clipping */
- if (*srcY + *height > (GLsizei) buffer->Height)
- *height -= (*srcY + *height - buffer->Height);
-
- if (*height <= 0)
- return GL_FALSE;
-
- return GL_TRUE;
-}
-
-
-/**
- * Do clipping for a glCopyTexSubImage call.
- * The framebuffer source region might extend outside the framebuffer
- * bounds. Clip the source region against the framebuffer bounds and
- * adjust the texture/dest position and size accordingly.
- *
- * \return GL_FALSE if region is totally clipped, GL_TRUE otherwise.
- */
-GLboolean
-_mesa_clip_copytexsubimage(const struct gl_context *ctx,
- GLint *destX, GLint *destY,
- GLint *srcX, GLint *srcY,
- GLsizei *width, GLsizei *height)
-{
- const struct gl_framebuffer *fb = ctx->ReadBuffer;
- const GLint srcX0 = *srcX, srcY0 = *srcY;
-
- if (_mesa_clip_to_region(0, 0, fb->Width, fb->Height,
- srcX, srcY, width, height)) {
- *destX = *destX + *srcX - srcX0;
- *destY = *destY + *srcY - srcY0;
-
- return GL_TRUE;
- }
- else {
- return GL_FALSE;
- }
-}
-
-
-
-/**
- * Clip the rectangle defined by (x, y, width, height) against the bounds
- * specified by [xmin, xmax) and [ymin, ymax).
- * \return GL_FALSE if rect is totally clipped, GL_TRUE otherwise.
- */
-GLboolean
-_mesa_clip_to_region(GLint xmin, GLint ymin,
- GLint xmax, GLint ymax,
- GLint *x, GLint *y,
- GLsizei *width, GLsizei *height )
-{
- /* left clipping */
- if (*x < xmin) {
- *width -= (xmin - *x);
- *x = xmin;
- }
-
- /* right clipping */
- if (*x + *width > xmax)
- *width -= (*x + *width - xmax);
-
- if (*width <= 0)
- return GL_FALSE;
-
- /* bottom (or top) clipping */
- if (*y < ymin) {
- *height -= (ymin - *y);
- *y = ymin;
- }
-
- /* top (or bottom) clipping */
- if (*y + *height > ymax)
- *height -= (*y + *height - ymax);
-
- if (*height <= 0)
- return GL_FALSE;
-
- return GL_TRUE;
-}
-
-
-/**
- * Clip dst coords against Xmax (or Ymax).
- */
-static INLINE void
-clip_right_or_top(GLint *srcX0, GLint *srcX1,
- GLint *dstX0, GLint *dstX1,
- GLint maxValue)
-{
- GLfloat t, bias;
-
- if (*dstX1 > maxValue) {
- /* X1 outside right edge */
- ASSERT(*dstX0 < maxValue); /* X0 should be inside right edge */
- t = (GLfloat) (maxValue - *dstX0) / (GLfloat) (*dstX1 - *dstX0);
- /* chop off [t, 1] part */
- ASSERT(t >= 0.0 && t <= 1.0);
- *dstX1 = maxValue;
- bias = (*srcX0 < *srcX1) ? 0.5F : -0.5F;
- *srcX1 = *srcX0 + (GLint) (t * (*srcX1 - *srcX0) + bias);
- }
- else if (*dstX0 > maxValue) {
- /* X0 outside right edge */
- ASSERT(*dstX1 < maxValue); /* X1 should be inside right edge */
- t = (GLfloat) (maxValue - *dstX1) / (GLfloat) (*dstX0 - *dstX1);
- /* chop off [t, 1] part */
- ASSERT(t >= 0.0 && t <= 1.0);
- *dstX0 = maxValue;
- bias = (*srcX0 < *srcX1) ? -0.5F : 0.5F;
- *srcX0 = *srcX1 + (GLint) (t * (*srcX0 - *srcX1) + bias);
- }
-}
-
-
-/**
- * Clip dst coords against Xmin (or Ymin).
- */
-static INLINE void
-clip_left_or_bottom(GLint *srcX0, GLint *srcX1,
- GLint *dstX0, GLint *dstX1,
- GLint minValue)
-{
- GLfloat t, bias;
-
- if (*dstX0 < minValue) {
- /* X0 outside left edge */
- ASSERT(*dstX1 > minValue); /* X1 should be inside left edge */
- t = (GLfloat) (minValue - *dstX0) / (GLfloat) (*dstX1 - *dstX0);
- /* chop off [0, t] part */
- ASSERT(t >= 0.0 && t <= 1.0);
- *dstX0 = minValue;
- bias = (*srcX0 < *srcX1) ? 0.5F : -0.5F; /* flipped??? */
- *srcX0 = *srcX0 + (GLint) (t * (*srcX1 - *srcX0) + bias);
- }
- else if (*dstX1 < minValue) {
- /* X1 outside left edge */
- ASSERT(*dstX0 > minValue); /* X0 should be inside left edge */
- t = (GLfloat) (minValue - *dstX1) / (GLfloat) (*dstX0 - *dstX1);
- /* chop off [0, t] part */
- ASSERT(t >= 0.0 && t <= 1.0);
- *dstX1 = minValue;
- bias = (*srcX0 < *srcX1) ? 0.5F : -0.5F;
- *srcX1 = *srcX1 + (GLint) (t * (*srcX0 - *srcX1) + bias);
- }
-}
-
-
-/**
- * Do clipping of blit src/dest rectangles.
- * The dest rect is clipped against both the buffer bounds and scissor bounds.
- * The src rect is just clipped against the buffer bounds.
- *
- * When either the src or dest rect is clipped, the other is also clipped
- * proportionately!
- *
- * Note that X0 need not be less than X1 (same for Y) for either the source
- * and dest rects. That makes the clipping a little trickier.
- *
- * \return GL_TRUE if anything is left to draw, GL_FALSE if totally clipped
- */
-GLboolean
-_mesa_clip_blit(struct gl_context *ctx,
- GLint *srcX0, GLint *srcY0, GLint *srcX1, GLint *srcY1,
- GLint *dstX0, GLint *dstY0, GLint *dstX1, GLint *dstY1)
-{
- const GLint srcXmin = 0;
- const GLint srcXmax = ctx->ReadBuffer->Width;
- const GLint srcYmin = 0;
- const GLint srcYmax = ctx->ReadBuffer->Height;
-
- /* these include scissor bounds */
- const GLint dstXmin = ctx->DrawBuffer->_Xmin;
- const GLint dstXmax = ctx->DrawBuffer->_Xmax;
- const GLint dstYmin = ctx->DrawBuffer->_Ymin;
- const GLint dstYmax = ctx->DrawBuffer->_Ymax;
-
- /*
- printf("PreClipX: src: %d .. %d dst: %d .. %d\n",
- *srcX0, *srcX1, *dstX0, *dstX1);
- printf("PreClipY: src: %d .. %d dst: %d .. %d\n",
- *srcY0, *srcY1, *dstY0, *dstY1);
- */
-
- /* trivial rejection tests */
- if (*dstX0 == *dstX1)
- return GL_FALSE; /* no width */
- if (*dstX0 <= dstXmin && *dstX1 <= dstXmin)
- return GL_FALSE; /* totally out (left) of bounds */
- if (*dstX0 >= dstXmax && *dstX1 >= dstXmax)
- return GL_FALSE; /* totally out (right) of bounds */
-
- if (*dstY0 == *dstY1)
- return GL_FALSE;
- if (*dstY0 <= dstYmin && *dstY1 <= dstYmin)
- return GL_FALSE;
- if (*dstY0 >= dstYmax && *dstY1 >= dstYmax)
- return GL_FALSE;
-
- if (*srcX0 == *srcX1)
- return GL_FALSE;
- if (*srcX0 <= srcXmin && *srcX1 <= srcXmin)
- return GL_FALSE;
- if (*srcX0 >= srcXmax && *srcX1 >= srcXmax)
- return GL_FALSE;
-
- if (*srcY0 == *srcY1)
- return GL_FALSE;
- if (*srcY0 <= srcYmin && *srcY1 <= srcYmin)
- return GL_FALSE;
- if (*srcY0 >= srcYmax && *srcY1 >= srcYmax)
- return GL_FALSE;
-
- /*
- * dest clip
- */
- clip_right_or_top(srcX0, srcX1, dstX0, dstX1, dstXmax);
- clip_right_or_top(srcY0, srcY1, dstY0, dstY1, dstYmax);
- clip_left_or_bottom(srcX0, srcX1, dstX0, dstX1, dstXmin);
- clip_left_or_bottom(srcY0, srcY1, dstY0, dstY1, dstYmin);
-
- /*
- * src clip (just swap src/dst values from above)
- */
- clip_right_or_top(dstX0, dstX1, srcX0, srcX1, srcXmax);
- clip_right_or_top(dstY0, dstY1, srcY0, srcY1, srcYmax);
- clip_left_or_bottom(dstX0, dstX1, srcX0, srcX1, srcXmin);
- clip_left_or_bottom(dstY0, dstY1, srcY0, srcY1, srcYmin);
-
- /*
- printf("PostClipX: src: %d .. %d dst: %d .. %d\n",
- *srcX0, *srcX1, *dstX0, *dstX1);
- printf("PostClipY: src: %d .. %d dst: %d .. %d\n",
- *srcY0, *srcY1, *dstY0, *dstY1);
- */
-
- ASSERT(*dstX0 >= dstXmin);
- ASSERT(*dstX0 <= dstXmax);
- ASSERT(*dstX1 >= dstXmin);
- ASSERT(*dstX1 <= dstXmax);
-
- ASSERT(*dstY0 >= dstYmin);
- ASSERT(*dstY0 <= dstYmax);
- ASSERT(*dstY1 >= dstYmin);
- ASSERT(*dstY1 <= dstYmax);
-
- ASSERT(*srcX0 >= srcXmin);
- ASSERT(*srcX0 <= srcXmax);
- ASSERT(*srcX1 >= srcXmin);
- ASSERT(*srcX1 <= srcXmax);
-
- ASSERT(*srcY0 >= srcYmin);
- ASSERT(*srcY0 <= srcYmax);
- ASSERT(*srcY1 >= srcYmin);
- ASSERT(*srcY1 <= srcYmax);
-
- return GL_TRUE;
-}
+/* + * Mesa 3-D graphics library + * Version: 7.5 + * + * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. + * Copyright (C) 2009 VMware, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +/** + * \file image.c + * Image handling. + */ + + +#include "glheader.h" +#include "colormac.h" +#include "image.h" +#include "imports.h" +#include "macros.h" +#include "mfeatures.h" +#include "mtypes.h" + + +/** + * NOTE: + * Normally, BYTE_TO_FLOAT(0) returns 0.00392 That causes problems when + * we later convert the float to a packed integer value (such as for + * GL_RGB5_A1) because we'll wind up with a non-zero value. + * + * We redefine the macros here so zero is handled correctly. + */ +#undef BYTE_TO_FLOAT +#define BYTE_TO_FLOAT(B) ((B) == 0 ? 0.0F : ((2.0F * (B) + 1.0F) * (1.0F/255.0F))) + +#undef SHORT_TO_FLOAT +#define SHORT_TO_FLOAT(S) ((S) == 0 ? 0.0F : ((2.0F * (S) + 1.0F) * (1.0F/65535.0F))) + + + +/** Compute ceiling of integer quotient of A divided by B. */ +#define CEILING( A, B ) ( (A) % (B) == 0 ? (A)/(B) : (A)/(B)+1 ) + + +/** + * \return GL_TRUE if type is packed pixel type, GL_FALSE otherwise. + */ +GLboolean +_mesa_type_is_packed(GLenum type) +{ + switch (type) { + case GL_UNSIGNED_BYTE_3_3_2: + case GL_UNSIGNED_BYTE_2_3_3_REV: + case MESA_UNSIGNED_BYTE_4_4: + case GL_UNSIGNED_SHORT_5_6_5: + case GL_UNSIGNED_SHORT_5_6_5_REV: + case GL_UNSIGNED_SHORT_4_4_4_4: + case GL_UNSIGNED_SHORT_4_4_4_4_REV: + case GL_UNSIGNED_SHORT_5_5_5_1: + case GL_UNSIGNED_SHORT_1_5_5_5_REV: + case GL_UNSIGNED_INT_8_8_8_8: + case GL_UNSIGNED_INT_8_8_8_8_REV: + case GL_UNSIGNED_INT_10_10_10_2: + case GL_UNSIGNED_INT_2_10_10_10_REV: + case GL_UNSIGNED_SHORT_8_8_MESA: + case GL_UNSIGNED_SHORT_8_8_REV_MESA: + case GL_UNSIGNED_INT_24_8_EXT: + case GL_UNSIGNED_INT_5_9_9_9_REV: + case GL_UNSIGNED_INT_10F_11F_11F_REV: + case GL_FLOAT_32_UNSIGNED_INT_24_8_REV: + return GL_TRUE; + } + + return GL_FALSE; +} + + + +/** + * Flip the order of the 2 bytes in each word in the given array. + * + * \param p array. + * \param n number of words. + */ +void +_mesa_swap2( GLushort *p, GLuint n ) +{ + GLuint i; + for (i = 0; i < n; i++) { + p[i] = (p[i] >> 8) | ((p[i] << 8) & 0xff00); + } +} + + + +/* + * Flip the order of the 4 bytes in each word in the given array. + */ +void +_mesa_swap4( GLuint *p, GLuint n ) +{ + GLuint i, a, b; + for (i = 0; i < n; i++) { + b = p[i]; + a = (b >> 24) + | ((b >> 8) & 0xff00) + | ((b << 8) & 0xff0000) + | ((b << 24) & 0xff000000); + p[i] = a; + } +} + + +/** + * Get the size of a GL data type. + * + * \param type GL data type. + * + * \return the size, in bytes, of the given data type, 0 if a GL_BITMAP, or -1 + * if an invalid type enum. + */ +GLint +_mesa_sizeof_type( GLenum type ) +{ + switch (type) { + case GL_BITMAP: + return 0; + case GL_UNSIGNED_BYTE: + return sizeof(GLubyte); + case GL_BYTE: + return sizeof(GLbyte); + case GL_UNSIGNED_SHORT: + return sizeof(GLushort); + case GL_SHORT: + return sizeof(GLshort); + case GL_UNSIGNED_INT: + return sizeof(GLuint); + case GL_INT: + return sizeof(GLint); + case GL_FLOAT: + return sizeof(GLfloat); + case GL_DOUBLE: + return sizeof(GLdouble); + case GL_HALF_FLOAT_ARB: + return sizeof(GLhalfARB); + case GL_FIXED: + return sizeof(GLfixed); + default: + return -1; + } +} + + +/** + * Same as _mesa_sizeof_type() but also accepting the packed pixel + * format data types. + */ +GLint +_mesa_sizeof_packed_type( GLenum type ) +{ + switch (type) { + case GL_BITMAP: + return 0; + case GL_UNSIGNED_BYTE: + return sizeof(GLubyte); + case GL_BYTE: + return sizeof(GLbyte); + case GL_UNSIGNED_SHORT: + return sizeof(GLushort); + case GL_SHORT: + return sizeof(GLshort); + case GL_UNSIGNED_INT: + return sizeof(GLuint); + case GL_INT: + return sizeof(GLint); + case GL_HALF_FLOAT_ARB: + return sizeof(GLhalfARB); + case GL_FLOAT: + return sizeof(GLfloat); + case GL_UNSIGNED_BYTE_3_3_2: + return sizeof(GLubyte); + case GL_UNSIGNED_BYTE_2_3_3_REV: + return sizeof(GLubyte); + case MESA_UNSIGNED_BYTE_4_4: + return sizeof(GLubyte); + case GL_UNSIGNED_SHORT_5_6_5: + return sizeof(GLushort); + case GL_UNSIGNED_SHORT_5_6_5_REV: + return sizeof(GLushort); + case GL_UNSIGNED_SHORT_4_4_4_4: + return sizeof(GLushort); + case GL_UNSIGNED_SHORT_4_4_4_4_REV: + return sizeof(GLushort); + case GL_UNSIGNED_SHORT_5_5_5_1: + return sizeof(GLushort); + case GL_UNSIGNED_SHORT_1_5_5_5_REV: + return sizeof(GLushort); + case GL_UNSIGNED_INT_8_8_8_8: + return sizeof(GLuint); + case GL_UNSIGNED_INT_8_8_8_8_REV: + return sizeof(GLuint); + case GL_UNSIGNED_INT_10_10_10_2: + return sizeof(GLuint); + case GL_UNSIGNED_INT_2_10_10_10_REV: + return sizeof(GLuint); + case GL_UNSIGNED_SHORT_8_8_MESA: + case GL_UNSIGNED_SHORT_8_8_REV_MESA: + return sizeof(GLushort); + case GL_UNSIGNED_INT_24_8_EXT: + return sizeof(GLuint); + case GL_UNSIGNED_INT_5_9_9_9_REV: + return sizeof(GLuint); + case GL_UNSIGNED_INT_10F_11F_11F_REV: + return sizeof(GLuint); + case GL_FLOAT_32_UNSIGNED_INT_24_8_REV: + return 8; + default: + return -1; + } +} + + +/** + * Get the number of components in a pixel format. + * + * \param format pixel format. + * + * \return the number of components in the given format, or -1 if a bad format. + */ +GLint +_mesa_components_in_format( GLenum format ) +{ + switch (format) { + case GL_COLOR_INDEX: + case GL_COLOR_INDEX1_EXT: + case GL_COLOR_INDEX2_EXT: + case GL_COLOR_INDEX4_EXT: + case GL_COLOR_INDEX8_EXT: + case GL_COLOR_INDEX12_EXT: + case GL_COLOR_INDEX16_EXT: + case GL_STENCIL_INDEX: + case GL_DEPTH_COMPONENT: + case GL_RED: + case GL_RED_INTEGER_EXT: + case GL_GREEN: + case GL_GREEN_INTEGER_EXT: + case GL_BLUE: + case GL_BLUE_INTEGER_EXT: + case GL_ALPHA: + case GL_ALPHA_INTEGER_EXT: + case GL_LUMINANCE: + case GL_LUMINANCE_INTEGER_EXT: + case GL_INTENSITY: + return 1; + case GL_LUMINANCE_ALPHA: + case GL_LUMINANCE_ALPHA_INTEGER_EXT: + case GL_RG: + return 2; + case GL_RGB: + case GL_RGB_INTEGER_EXT: + return 3; + case GL_RGBA: + case GL_RGBA_INTEGER_EXT: + return 4; + case GL_BGR: + return 3; + case GL_BGRA: + return 4; + case GL_ABGR_EXT: + return 4; + case GL_YCBCR_MESA: + return 2; + case GL_DEPTH_STENCIL_EXT: + return 2; + case GL_DUDV_ATI: + case GL_DU8DV8_ATI: + return 2; + default: + return -1; + } +} + + +/** + * Get the bytes per pixel of pixel format type pair. + * + * \param format pixel format. + * \param type pixel type. + * + * \return bytes per pixel, or -1 if a bad format or type was given. + */ +GLint +_mesa_bytes_per_pixel( GLenum format, GLenum type ) +{ + GLint comps = _mesa_components_in_format( format ); + if (comps < 0) + return -1; + + switch (type) { + case GL_BITMAP: + return 0; /* special case */ + case GL_BYTE: + case GL_UNSIGNED_BYTE: + return comps * sizeof(GLubyte); + case GL_SHORT: + case GL_UNSIGNED_SHORT: + return comps * sizeof(GLshort); + case GL_INT: + case GL_UNSIGNED_INT: + return comps * sizeof(GLint); + case GL_FLOAT: + return comps * sizeof(GLfloat); + case GL_HALF_FLOAT_ARB: + return comps * sizeof(GLhalfARB); + case GL_UNSIGNED_BYTE_3_3_2: + case GL_UNSIGNED_BYTE_2_3_3_REV: + if (format == GL_RGB || format == GL_BGR || + format == GL_RGB_INTEGER_EXT || format == GL_BGR_INTEGER_EXT) + return sizeof(GLubyte); + else + return -1; /* error */ + case GL_UNSIGNED_SHORT_5_6_5: + case GL_UNSIGNED_SHORT_5_6_5_REV: + if (format == GL_RGB || format == GL_BGR || + format == GL_RGB_INTEGER_EXT || format == GL_BGR_INTEGER_EXT) + return sizeof(GLushort); + else + return -1; /* error */ + case GL_UNSIGNED_SHORT_4_4_4_4: + case GL_UNSIGNED_SHORT_4_4_4_4_REV: + case GL_UNSIGNED_SHORT_5_5_5_1: + case GL_UNSIGNED_SHORT_1_5_5_5_REV: + if (format == GL_RGBA || format == GL_BGRA || format == GL_ABGR_EXT || + format == GL_RGBA_INTEGER_EXT || format == GL_BGRA_INTEGER_EXT) + return sizeof(GLushort); + else + return -1; + case GL_UNSIGNED_INT_8_8_8_8: + case GL_UNSIGNED_INT_8_8_8_8_REV: + case GL_UNSIGNED_INT_10_10_10_2: + case GL_UNSIGNED_INT_2_10_10_10_REV: + if (format == GL_RGBA || format == GL_BGRA || format == GL_ABGR_EXT || + format == GL_RGBA_INTEGER_EXT || format == GL_BGRA_INTEGER_EXT) + return sizeof(GLuint); + else + return -1; + case GL_UNSIGNED_SHORT_8_8_MESA: + case GL_UNSIGNED_SHORT_8_8_REV_MESA: + if (format == GL_YCBCR_MESA) + return sizeof(GLushort); + else + return -1; + case GL_UNSIGNED_INT_24_8_EXT: + if (format == GL_DEPTH_STENCIL_EXT) + return sizeof(GLuint); + else + return -1; + case GL_UNSIGNED_INT_5_9_9_9_REV: + if (format == GL_RGB) + return sizeof(GLuint); + else + return -1; + case GL_UNSIGNED_INT_10F_11F_11F_REV: + if (format == GL_RGB) + return sizeof(GLuint); + else + return -1; + case GL_FLOAT_32_UNSIGNED_INT_24_8_REV: + if (format == GL_DEPTH_STENCIL) + return 8; + else + return -1; + default: + return -1; + } +} + + +/** + * Test for a legal pixel format and type. + * + * \param format pixel format. + * \param type pixel type. + * + * \return GL_TRUE if the given pixel format and type are legal, or GL_FALSE + * otherwise. + */ +GLboolean +_mesa_is_legal_format_and_type(const struct gl_context *ctx, + GLenum format, GLenum type) +{ + switch (format) { + case GL_COLOR_INDEX: + case GL_STENCIL_INDEX: + switch (type) { + case GL_BITMAP: + case GL_BYTE: + case GL_UNSIGNED_BYTE: + case GL_SHORT: + case GL_UNSIGNED_SHORT: + case GL_INT: + case GL_UNSIGNED_INT: + case GL_FLOAT: + return GL_TRUE; + case GL_HALF_FLOAT_ARB: + return ctx->Extensions.ARB_half_float_pixel; + default: + return GL_FALSE; + } + case GL_RED: + case GL_GREEN: + case GL_BLUE: + case GL_ALPHA: +#if 0 /* not legal! see table 3.6 of the 1.5 spec */ + case GL_INTENSITY: +#endif + case GL_LUMINANCE: + case GL_LUMINANCE_ALPHA: + case GL_DEPTH_COMPONENT: + switch (type) { + case GL_BYTE: + case GL_UNSIGNED_BYTE: + case GL_SHORT: + case GL_UNSIGNED_SHORT: + case GL_INT: + case GL_UNSIGNED_INT: + case GL_FLOAT: + return GL_TRUE; + case GL_HALF_FLOAT_ARB: + return ctx->Extensions.ARB_half_float_pixel; + default: + return GL_FALSE; + } + case GL_RG: + if (!ctx->Extensions.ARB_texture_rg) + return GL_FALSE; + + switch (type) { + case GL_BYTE: + case GL_UNSIGNED_BYTE: + case GL_SHORT: + case GL_UNSIGNED_SHORT: + case GL_INT: + case GL_UNSIGNED_INT: + case GL_FLOAT: + return GL_TRUE; + case GL_HALF_FLOAT_ARB: + return ctx->Extensions.ARB_half_float_pixel; + default: + return GL_FALSE; + } + case GL_RGB: + switch (type) { + case GL_BYTE: + case GL_UNSIGNED_BYTE: + case GL_SHORT: + case GL_UNSIGNED_SHORT: + case GL_INT: + case GL_UNSIGNED_INT: + case GL_FLOAT: + case GL_UNSIGNED_BYTE_3_3_2: + case GL_UNSIGNED_BYTE_2_3_3_REV: + case GL_UNSIGNED_SHORT_5_6_5: + case GL_UNSIGNED_SHORT_5_6_5_REV: + return GL_TRUE; + case GL_HALF_FLOAT_ARB: + return ctx->Extensions.ARB_half_float_pixel; + case GL_UNSIGNED_INT_5_9_9_9_REV: + return ctx->Extensions.EXT_texture_shared_exponent; + case GL_UNSIGNED_INT_10F_11F_11F_REV: + return ctx->Extensions.EXT_packed_float; + default: + return GL_FALSE; + } + case GL_BGR: + switch (type) { + /* NOTE: no packed types are supported with BGR. That's + * intentional, according to the GL spec. + */ + case GL_BYTE: + case GL_UNSIGNED_BYTE: + case GL_SHORT: + case GL_UNSIGNED_SHORT: + case GL_INT: + case GL_UNSIGNED_INT: + case GL_FLOAT: + return GL_TRUE; + case GL_HALF_FLOAT_ARB: + return ctx->Extensions.ARB_half_float_pixel; + default: + return GL_FALSE; + } + case GL_RGBA: + case GL_BGRA: + case GL_ABGR_EXT: + switch (type) { + case GL_BYTE: + case GL_UNSIGNED_BYTE: + case GL_SHORT: + case GL_UNSIGNED_SHORT: + case GL_INT: + case GL_UNSIGNED_INT: + case GL_FLOAT: + case GL_UNSIGNED_SHORT_4_4_4_4: + case GL_UNSIGNED_SHORT_4_4_4_4_REV: + case GL_UNSIGNED_SHORT_5_5_5_1: + case GL_UNSIGNED_SHORT_1_5_5_5_REV: + case GL_UNSIGNED_INT_8_8_8_8: + case GL_UNSIGNED_INT_8_8_8_8_REV: + case GL_UNSIGNED_INT_10_10_10_2: + case GL_UNSIGNED_INT_2_10_10_10_REV: + return GL_TRUE; + case GL_HALF_FLOAT_ARB: + return ctx->Extensions.ARB_half_float_pixel; + default: + return GL_FALSE; + } + case GL_YCBCR_MESA: + if (type == GL_UNSIGNED_SHORT_8_8_MESA || + type == GL_UNSIGNED_SHORT_8_8_REV_MESA) + return GL_TRUE; + else + return GL_FALSE; + case GL_DEPTH_STENCIL_EXT: + if ((ctx->Extensions.EXT_packed_depth_stencil && + type == GL_UNSIGNED_INT_24_8_EXT) || + (ctx->Extensions.ARB_depth_buffer_float && + type == GL_FLOAT_32_UNSIGNED_INT_24_8_REV)) + return GL_TRUE; + else + return GL_FALSE; + case GL_DUDV_ATI: + case GL_DU8DV8_ATI: + switch (type) { + case GL_BYTE: + case GL_UNSIGNED_BYTE: + case GL_SHORT: + case GL_UNSIGNED_SHORT: + case GL_INT: + case GL_UNSIGNED_INT: + case GL_FLOAT: + return GL_TRUE; + default: + return GL_FALSE; + } + + /* integer-valued formats */ + case GL_RED_INTEGER_EXT: + case GL_GREEN_INTEGER_EXT: + case GL_BLUE_INTEGER_EXT: + case GL_ALPHA_INTEGER_EXT: + switch (type) { + case GL_BYTE: + case GL_UNSIGNED_BYTE: + case GL_SHORT: + case GL_UNSIGNED_SHORT: + case GL_INT: + case GL_UNSIGNED_INT: + return ctx->Extensions.EXT_texture_integer; + default: + return GL_FALSE; + } + + case GL_RGB_INTEGER_EXT: + switch (type) { + case GL_BYTE: + case GL_UNSIGNED_BYTE: + case GL_SHORT: + case GL_UNSIGNED_SHORT: + case GL_INT: + case GL_UNSIGNED_INT: + case GL_UNSIGNED_BYTE_3_3_2: + case GL_UNSIGNED_BYTE_2_3_3_REV: + case GL_UNSIGNED_SHORT_5_6_5: + case GL_UNSIGNED_SHORT_5_6_5_REV: + return ctx->Extensions.EXT_texture_integer; + default: + return GL_FALSE; + } + + case GL_BGR_INTEGER_EXT: + switch (type) { + case GL_BYTE: + case GL_UNSIGNED_BYTE: + case GL_SHORT: + case GL_UNSIGNED_SHORT: + case GL_INT: + case GL_UNSIGNED_INT: + /* NOTE: no packed formats w/ BGR format */ + return ctx->Extensions.EXT_texture_integer; + default: + return GL_FALSE; + } + + case GL_RGBA_INTEGER_EXT: + case GL_BGRA_INTEGER_EXT: + switch (type) { + case GL_BYTE: + case GL_UNSIGNED_BYTE: + case GL_SHORT: + case GL_UNSIGNED_SHORT: + case GL_INT: + case GL_UNSIGNED_INT: + case GL_UNSIGNED_SHORT_4_4_4_4: + case GL_UNSIGNED_SHORT_4_4_4_4_REV: + case GL_UNSIGNED_SHORT_5_5_5_1: + case GL_UNSIGNED_SHORT_1_5_5_5_REV: + case GL_UNSIGNED_INT_8_8_8_8: + case GL_UNSIGNED_INT_8_8_8_8_REV: + case GL_UNSIGNED_INT_10_10_10_2: + case GL_UNSIGNED_INT_2_10_10_10_REV: + return ctx->Extensions.EXT_texture_integer; + default: + return GL_FALSE; + } + + case GL_LUMINANCE_INTEGER_EXT: + case GL_LUMINANCE_ALPHA_INTEGER_EXT: + switch (type) { + case GL_BYTE: + case GL_UNSIGNED_BYTE: + case GL_SHORT: + case GL_UNSIGNED_SHORT: + case GL_INT: + case GL_UNSIGNED_INT: + return ctx->Extensions.EXT_texture_integer; + default: + return GL_FALSE; + } + + default: + ; /* fall-through */ + } + return GL_FALSE; +} + + +/** + * Test if the given image format is a color/RGBA format (i.e., not color + * index, depth, stencil, etc). + * \param format the image format value (may by an internal texture format) + * \return GL_TRUE if its a color/RGBA format, GL_FALSE otherwise. + */ +GLboolean +_mesa_is_color_format(GLenum format) +{ + switch (format) { + case GL_RED: + case GL_GREEN: + case GL_BLUE: + case GL_ALPHA: + case GL_ALPHA4: + case GL_ALPHA8: + case GL_ALPHA12: + case GL_ALPHA16: + case 1: + case GL_LUMINANCE: + case GL_LUMINANCE4: + case GL_LUMINANCE8: + case GL_LUMINANCE12: + case GL_LUMINANCE16: + case 2: + case GL_LUMINANCE_ALPHA: + case GL_LUMINANCE4_ALPHA4: + case GL_LUMINANCE6_ALPHA2: + case GL_LUMINANCE8_ALPHA8: + case GL_LUMINANCE12_ALPHA4: + case GL_LUMINANCE12_ALPHA12: + case GL_LUMINANCE16_ALPHA16: + case GL_INTENSITY: + case GL_INTENSITY4: + case GL_INTENSITY8: + case GL_INTENSITY12: + case GL_INTENSITY16: + case GL_R8: + case GL_R16: + case GL_RG: + case GL_RG8: + case GL_RG16: + case 3: + case GL_RGB: + case GL_BGR: + case GL_R3_G3_B2: + case GL_RGB4: + case GL_RGB5: + case GL_RGB8: + case GL_RGB10: + case GL_RGB12: + case GL_RGB16: + case 4: + case GL_ABGR_EXT: + case GL_RGBA: + case GL_BGRA: + case GL_RGBA2: + case GL_RGBA4: + case GL_RGB5_A1: + case GL_RGBA8: + case GL_RGB10_A2: + case GL_RGBA12: + case GL_RGBA16: + /* float texture formats */ + case GL_ALPHA16F_ARB: + case GL_ALPHA32F_ARB: + case GL_LUMINANCE16F_ARB: + case GL_LUMINANCE32F_ARB: + case GL_LUMINANCE_ALPHA16F_ARB: + case GL_LUMINANCE_ALPHA32F_ARB: + case GL_INTENSITY16F_ARB: + case GL_INTENSITY32F_ARB: + case GL_R16F: + case GL_R32F: + case GL_RG16F: + case GL_RG32F: + case GL_RGB16F_ARB: + case GL_RGB32F_ARB: + case GL_RGBA16F_ARB: + case GL_RGBA32F_ARB: + /* compressed formats */ + case GL_COMPRESSED_ALPHA: + case GL_COMPRESSED_LUMINANCE: + case GL_COMPRESSED_LUMINANCE_ALPHA: + case GL_COMPRESSED_INTENSITY: + case GL_COMPRESSED_RED: + case GL_COMPRESSED_RG: + case GL_COMPRESSED_RGB: + case GL_COMPRESSED_RGBA: + case GL_RGB_S3TC: + case GL_RGB4_S3TC: + case GL_RGBA_S3TC: + case GL_RGBA4_S3TC: + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: + case GL_COMPRESSED_RGB_FXT1_3DFX: + case GL_COMPRESSED_RGBA_FXT1_3DFX: +#if FEATURE_EXT_texture_sRGB + case GL_SRGB_EXT: + case GL_SRGB8_EXT: + case GL_SRGB_ALPHA_EXT: + case GL_SRGB8_ALPHA8_EXT: + case GL_SLUMINANCE_ALPHA_EXT: + case GL_SLUMINANCE8_ALPHA8_EXT: + case GL_SLUMINANCE_EXT: + case GL_SLUMINANCE8_EXT: + case GL_COMPRESSED_SRGB_EXT: + case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT: + case GL_COMPRESSED_SRGB_ALPHA_EXT: + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: + case GL_COMPRESSED_SLUMINANCE_EXT: + case GL_COMPRESSED_SLUMINANCE_ALPHA_EXT: +#endif /* FEATURE_EXT_texture_sRGB */ + case GL_COMPRESSED_RED_RGTC1: + case GL_COMPRESSED_SIGNED_RED_RGTC1: + case GL_COMPRESSED_RG_RGTC2: + case GL_COMPRESSED_SIGNED_RG_RGTC2: + case GL_COMPRESSED_LUMINANCE_LATC1_EXT: + case GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT: + case GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT: + case GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT: + case GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI: + /* generic integer formats */ + case GL_RED_INTEGER_EXT: + case GL_GREEN_INTEGER_EXT: + case GL_BLUE_INTEGER_EXT: + case GL_ALPHA_INTEGER_EXT: + case GL_RGB_INTEGER_EXT: + case GL_RGBA_INTEGER_EXT: + case GL_BGR_INTEGER_EXT: + case GL_BGRA_INTEGER_EXT: + case GL_LUMINANCE_INTEGER_EXT: + case GL_LUMINANCE_ALPHA_INTEGER_EXT: + /* sized integer formats */ + case GL_RGBA32UI_EXT: + case GL_RGB32UI_EXT: + case GL_ALPHA32UI_EXT: + case GL_INTENSITY32UI_EXT: + case GL_LUMINANCE32UI_EXT: + case GL_LUMINANCE_ALPHA32UI_EXT: + case GL_RGBA16UI_EXT: + case GL_RGB16UI_EXT: + case GL_ALPHA16UI_EXT: + case GL_INTENSITY16UI_EXT: + case GL_LUMINANCE16UI_EXT: + case GL_LUMINANCE_ALPHA16UI_EXT: + case GL_RGBA8UI_EXT: + case GL_RGB8UI_EXT: + case GL_ALPHA8UI_EXT: + case GL_INTENSITY8UI_EXT: + case GL_LUMINANCE8UI_EXT: + case GL_LUMINANCE_ALPHA8UI_EXT: + case GL_RGBA32I_EXT: + case GL_RGB32I_EXT: + case GL_ALPHA32I_EXT: + case GL_INTENSITY32I_EXT: + case GL_LUMINANCE32I_EXT: + case GL_LUMINANCE_ALPHA32I_EXT: + case GL_RGBA16I_EXT: + case GL_RGB16I_EXT: + case GL_ALPHA16I_EXT: + case GL_INTENSITY16I_EXT: + case GL_LUMINANCE16I_EXT: + case GL_LUMINANCE_ALPHA16I_EXT: + case GL_RGBA8I_EXT: + case GL_RGB8I_EXT: + case GL_ALPHA8I_EXT: + case GL_INTENSITY8I_EXT: + case GL_LUMINANCE8I_EXT: + case GL_LUMINANCE_ALPHA8I_EXT: + /* signed, normalized texture formats */ + case GL_RED_SNORM: + case GL_R8_SNORM: + case GL_R16_SNORM: + case GL_RG_SNORM: + case GL_RG8_SNORM: + case GL_RG16_SNORM: + case GL_RGB_SNORM: + case GL_RGB8_SNORM: + case GL_RGB16_SNORM: + case GL_RGBA_SNORM: + case GL_RGBA8_SNORM: + case GL_RGBA16_SNORM: + case GL_ALPHA_SNORM: + case GL_ALPHA8_SNORM: + case GL_ALPHA16_SNORM: + case GL_LUMINANCE_SNORM: + case GL_LUMINANCE8_SNORM: + case GL_LUMINANCE16_SNORM: + case GL_LUMINANCE_ALPHA_SNORM: + case GL_LUMINANCE8_ALPHA8_SNORM: + case GL_LUMINANCE16_ALPHA16_SNORM: + case GL_INTENSITY_SNORM: + case GL_INTENSITY8_SNORM: + case GL_INTENSITY16_SNORM: + case GL_RGB9_E5: + case GL_R11F_G11F_B10F: + return GL_TRUE; + case GL_YCBCR_MESA: /* not considered to be RGB */ + /* fall-through */ + default: + return GL_FALSE; + } +} + + +/** + * Test if the given image format is a color index format. + */ +GLboolean +_mesa_is_index_format(GLenum format) +{ + switch (format) { + case GL_COLOR_INDEX: + case GL_COLOR_INDEX1_EXT: + case GL_COLOR_INDEX2_EXT: + case GL_COLOR_INDEX4_EXT: + case GL_COLOR_INDEX8_EXT: + case GL_COLOR_INDEX12_EXT: + case GL_COLOR_INDEX16_EXT: + return GL_TRUE; + default: + return GL_FALSE; + } +} + + +/** + * Test if the given image format is a depth component format. + */ +GLboolean +_mesa_is_depth_format(GLenum format) +{ + switch (format) { + case GL_DEPTH_COMPONENT: + case GL_DEPTH_COMPONENT16: + case GL_DEPTH_COMPONENT24: + case GL_DEPTH_COMPONENT32: + case GL_DEPTH_COMPONENT32F: + return GL_TRUE; + default: + return GL_FALSE; + } +} + + +/** + * Test if the given image format is a stencil format. + */ +GLboolean +_mesa_is_stencil_format(GLenum format) +{ + switch (format) { + case GL_STENCIL_INDEX: + case GL_DEPTH_STENCIL: + return GL_TRUE; + default: + return GL_FALSE; + } +} + + +/** + * Test if the given image format is a YCbCr format. + */ +GLboolean +_mesa_is_ycbcr_format(GLenum format) +{ + switch (format) { + case GL_YCBCR_MESA: + return GL_TRUE; + default: + return GL_FALSE; + } +} + + +/** + * Test if the given image format is a depth+stencil format. + */ +GLboolean +_mesa_is_depthstencil_format(GLenum format) +{ + switch (format) { + case GL_DEPTH24_STENCIL8_EXT: + case GL_DEPTH_STENCIL_EXT: + case GL_DEPTH32F_STENCIL8: + return GL_TRUE; + default: + return GL_FALSE; + } +} + + +/** + * Test if the given image format is a depth or stencil format. + */ +GLboolean +_mesa_is_depth_or_stencil_format(GLenum format) +{ + switch (format) { + case GL_DEPTH_COMPONENT: + case GL_DEPTH_COMPONENT16: + case GL_DEPTH_COMPONENT24: + case GL_DEPTH_COMPONENT32: + case GL_STENCIL_INDEX: + case GL_STENCIL_INDEX1_EXT: + case GL_STENCIL_INDEX4_EXT: + case GL_STENCIL_INDEX8_EXT: + case GL_STENCIL_INDEX16_EXT: + case GL_DEPTH_STENCIL_EXT: + case GL_DEPTH24_STENCIL8_EXT: + case GL_DEPTH_COMPONENT32F: + case GL_DEPTH32F_STENCIL8: + return GL_TRUE; + default: + return GL_FALSE; + } +} + + +/** + * Test if the given image format is a dudv format. + */ +GLboolean +_mesa_is_dudv_format(GLenum format) +{ + switch (format) { + case GL_DUDV_ATI: + case GL_DU8DV8_ATI: + return GL_TRUE; + default: + return GL_FALSE; + } +} + + +/** + * Test if the given format is an integer (non-normalized) format. + */ +GLboolean +_mesa_is_integer_format(GLenum format) +{ + switch (format) { + /* generic integer formats */ + case GL_RED_INTEGER_EXT: + case GL_GREEN_INTEGER_EXT: + case GL_BLUE_INTEGER_EXT: + case GL_ALPHA_INTEGER_EXT: + case GL_RGB_INTEGER_EXT: + case GL_RGBA_INTEGER_EXT: + case GL_BGR_INTEGER_EXT: + case GL_BGRA_INTEGER_EXT: + case GL_LUMINANCE_INTEGER_EXT: + case GL_LUMINANCE_ALPHA_INTEGER_EXT: + /* specific integer formats */ + case GL_RGBA32UI_EXT: + case GL_RGB32UI_EXT: + case GL_ALPHA32UI_EXT: + case GL_INTENSITY32UI_EXT: + case GL_LUMINANCE32UI_EXT: + case GL_LUMINANCE_ALPHA32UI_EXT: + case GL_RGBA16UI_EXT: + case GL_RGB16UI_EXT: + case GL_ALPHA16UI_EXT: + case GL_INTENSITY16UI_EXT: + case GL_LUMINANCE16UI_EXT: + case GL_LUMINANCE_ALPHA16UI_EXT: + case GL_RGBA8UI_EXT: + case GL_RGB8UI_EXT: + case GL_ALPHA8UI_EXT: + case GL_INTENSITY8UI_EXT: + case GL_LUMINANCE8UI_EXT: + case GL_LUMINANCE_ALPHA8UI_EXT: + case GL_RGBA32I_EXT: + case GL_RGB32I_EXT: + case GL_ALPHA32I_EXT: + case GL_INTENSITY32I_EXT: + case GL_LUMINANCE32I_EXT: + case GL_LUMINANCE_ALPHA32I_EXT: + case GL_RGBA16I_EXT: + case GL_RGB16I_EXT: + case GL_ALPHA16I_EXT: + case GL_INTENSITY16I_EXT: + case GL_LUMINANCE16I_EXT: + case GL_LUMINANCE_ALPHA16I_EXT: + case GL_RGBA8I_EXT: + case GL_RGB8I_EXT: + case GL_ALPHA8I_EXT: + case GL_INTENSITY8I_EXT: + case GL_LUMINANCE8I_EXT: + case GL_LUMINANCE_ALPHA8I_EXT: + return GL_TRUE; + default: + return GL_FALSE; + } +} + + +/** + * Test if an image format is a supported compressed format. + * \param format the internal format token provided by the user. + * \return GL_TRUE if compressed, GL_FALSE if uncompressed + */ +GLboolean +_mesa_is_compressed_format(struct gl_context *ctx, GLenum format) +{ + switch (format) { + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: + return ctx->Extensions.EXT_texture_compression_s3tc; + case GL_RGB_S3TC: + case GL_RGB4_S3TC: + case GL_RGBA_S3TC: + case GL_RGBA4_S3TC: + return ctx->Extensions.S3_s3tc; + case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT: + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: + return ctx->Extensions.EXT_texture_sRGB + && ctx->Extensions.EXT_texture_compression_s3tc; + case GL_COMPRESSED_RGB_FXT1_3DFX: + case GL_COMPRESSED_RGBA_FXT1_3DFX: + return ctx->Extensions.TDFX_texture_compression_FXT1; + case GL_COMPRESSED_RED_RGTC1: + case GL_COMPRESSED_SIGNED_RED_RGTC1: + case GL_COMPRESSED_RG_RGTC2: + case GL_COMPRESSED_SIGNED_RG_RGTC2: + return ctx->Extensions.ARB_texture_compression_rgtc; + case GL_COMPRESSED_LUMINANCE_LATC1_EXT: + case GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT: + case GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT: + case GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT: + return ctx->Extensions.EXT_texture_compression_latc; + case GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI: + return ctx->Extensions.ATI_texture_compression_3dc; + default: + return GL_FALSE; + } +} + + +/** + * Return the address of a specific pixel in an image (1D, 2D or 3D). + * + * Pixel unpacking/packing parameters are observed according to \p packing. + * + * \param dimensions either 1, 2 or 3 to indicate dimensionality of image + * \param image starting address of image data + * \param width the image width + * \param height theimage height + * \param format the pixel format + * \param type the pixel data type + * \param packing the pixelstore attributes + * \param img which image in the volume (0 for 1D or 2D images) + * \param row row of pixel in the image (0 for 1D images) + * \param column column of pixel in the image + * + * \return address of pixel on success, or NULL on error. + * + * \sa gl_pixelstore_attrib. + */ +GLvoid * +_mesa_image_address( GLuint dimensions, + const struct gl_pixelstore_attrib *packing, + const GLvoid *image, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + GLint img, GLint row, GLint column ) +{ + GLint alignment; /* 1, 2 or 4 */ + GLint pixels_per_row; + GLint rows_per_image; + GLint skiprows; + GLint skippixels; + GLint skipimages; /* for 3-D volume images */ + GLubyte *pixel_addr; + + ASSERT(dimensions >= 1 && dimensions <= 3); + + alignment = packing->Alignment; + if (packing->RowLength > 0) { + pixels_per_row = packing->RowLength; + } + else { + pixels_per_row = width; + } + if (packing->ImageHeight > 0) { + rows_per_image = packing->ImageHeight; + } + else { + rows_per_image = height; + } + + skippixels = packing->SkipPixels; + /* Note: SKIP_ROWS _is_ used for 1D images */ + skiprows = packing->SkipRows; + /* Note: SKIP_IMAGES is only used for 3D images */ + skipimages = (dimensions == 3) ? packing->SkipImages : 0; + + if (type == GL_BITMAP) { + /* BITMAP data */ + GLint comp_per_pixel; /* components per pixel */ + GLint bytes_per_comp; /* bytes per component */ + GLint bytes_per_row; + GLint bytes_per_image; + + /* Compute bytes per component */ + bytes_per_comp = _mesa_sizeof_packed_type( type ); + if (bytes_per_comp < 0) { + return NULL; + } + + /* Compute number of components per pixel */ + comp_per_pixel = _mesa_components_in_format( format ); + if (comp_per_pixel < 0) { + return NULL; + } + + bytes_per_row = alignment + * CEILING( comp_per_pixel*pixels_per_row, 8*alignment ); + + bytes_per_image = bytes_per_row * rows_per_image; + + pixel_addr = (GLubyte *) image + + (skipimages + img) * bytes_per_image + + (skiprows + row) * bytes_per_row + + (skippixels + column) / 8; + } + else { + /* Non-BITMAP data */ + GLint bytes_per_pixel, bytes_per_row, remainder, bytes_per_image; + GLint topOfImage; + + bytes_per_pixel = _mesa_bytes_per_pixel( format, type ); + + /* The pixel type and format should have been error checked earlier */ + assert(bytes_per_pixel > 0); + + bytes_per_row = pixels_per_row * bytes_per_pixel; + remainder = bytes_per_row % alignment; + if (remainder > 0) + bytes_per_row += (alignment - remainder); + + ASSERT(bytes_per_row % alignment == 0); + + bytes_per_image = bytes_per_row * rows_per_image; + + if (packing->Invert) { + /* set pixel_addr to the last row */ + topOfImage = bytes_per_row * (height - 1); + bytes_per_row = -bytes_per_row; + } + else { + topOfImage = 0; + } + + /* compute final pixel address */ + pixel_addr = (GLubyte *) image + + (skipimages + img) * bytes_per_image + + topOfImage + + (skiprows + row) * bytes_per_row + + (skippixels + column) * bytes_per_pixel; + } + + return (GLvoid *) pixel_addr; +} + + +GLvoid * +_mesa_image_address1d( const struct gl_pixelstore_attrib *packing, + const GLvoid *image, + GLsizei width, + GLenum format, GLenum type, + GLint column ) +{ + return _mesa_image_address(1, packing, image, width, 1, + format, type, 0, 0, column); +} + + +GLvoid * +_mesa_image_address2d( const struct gl_pixelstore_attrib *packing, + const GLvoid *image, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + GLint row, GLint column ) +{ + return _mesa_image_address(2, packing, image, width, height, + format, type, 0, row, column); +} + + +GLvoid * +_mesa_image_address3d( const struct gl_pixelstore_attrib *packing, + const GLvoid *image, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + GLint img, GLint row, GLint column ) +{ + return _mesa_image_address(3, packing, image, width, height, + format, type, img, row, column); +} + + + +/** + * Compute the stride (in bytes) between image rows. + * + * \param packing the pixelstore attributes + * \param width image width. + * \param format pixel format. + * \param type pixel data type. + * + * \return the stride in bytes for the given parameters, or -1 if error + */ +GLint +_mesa_image_row_stride( const struct gl_pixelstore_attrib *packing, + GLint width, GLenum format, GLenum type ) +{ + GLint bytesPerRow, remainder; + + ASSERT(packing); + + if (type == GL_BITMAP) { + if (packing->RowLength == 0) { + bytesPerRow = (width + 7) / 8; + } + else { + bytesPerRow = (packing->RowLength + 7) / 8; + } + } + else { + /* Non-BITMAP data */ + const GLint bytesPerPixel = _mesa_bytes_per_pixel(format, type); + if (bytesPerPixel <= 0) + return -1; /* error */ + if (packing->RowLength == 0) { + bytesPerRow = bytesPerPixel * width; + } + else { + bytesPerRow = bytesPerPixel * packing->RowLength; + } + } + + remainder = bytesPerRow % packing->Alignment; + if (remainder > 0) { + bytesPerRow += (packing->Alignment - remainder); + } + + if (packing->Invert) { + /* negate the bytes per row (negative row stride) */ + bytesPerRow = -bytesPerRow; + } + + return bytesPerRow; +} + + +/* + * Compute the stride between images in a 3D texture (in bytes) for the given + * pixel packing parameters and image width, format and type. + */ +GLint +_mesa_image_image_stride( const struct gl_pixelstore_attrib *packing, + GLint width, GLint height, + GLenum format, GLenum type ) +{ + GLint bytesPerRow, bytesPerImage, remainder; + + ASSERT(packing); + + if (type == GL_BITMAP) { + if (packing->RowLength == 0) { + bytesPerRow = (width + 7) / 8; + } + else { + bytesPerRow = (packing->RowLength + 7) / 8; + } + } + else { + const GLint bytesPerPixel = _mesa_bytes_per_pixel(format, type); + + if (bytesPerPixel <= 0) + return -1; /* error */ + if (packing->RowLength == 0) { + bytesPerRow = bytesPerPixel * width; + } + else { + bytesPerRow = bytesPerPixel * packing->RowLength; + } + } + + remainder = bytesPerRow % packing->Alignment; + if (remainder > 0) + bytesPerRow += (packing->Alignment - remainder); + + if (packing->ImageHeight == 0) + bytesPerImage = bytesPerRow * height; + else + bytesPerImage = bytesPerRow * packing->ImageHeight; + + return bytesPerImage; +} + + + +/** + * "Expand" a bitmap from 1-bit per pixel to 8-bits per pixel. + * This is typically used to convert a bitmap into a GLubyte/pixel texture. + * "On" bits will set texels to \p onValue. + * "Off" bits will not modify texels. + * \param width src bitmap width in pixels + * \param height src bitmap height in pixels + * \param unpack bitmap unpacking state + * \param bitmap the src bitmap data + * \param destBuffer start of dest buffer + * \param destStride row stride in dest buffer + * \param onValue if bit is 1, set destBuffer pixel to this value + */ +void +_mesa_expand_bitmap(GLsizei width, GLsizei height, + const struct gl_pixelstore_attrib *unpack, + const GLubyte *bitmap, + GLubyte *destBuffer, GLint destStride, + GLubyte onValue) +{ + const GLubyte *srcRow = (const GLubyte *) + _mesa_image_address2d(unpack, bitmap, width, height, + GL_COLOR_INDEX, GL_BITMAP, 0, 0); + const GLint srcStride = _mesa_image_row_stride(unpack, width, + GL_COLOR_INDEX, GL_BITMAP); + GLint row, col; + +#define SET_PIXEL(COL, ROW) \ + destBuffer[(ROW) * destStride + (COL)] = onValue; + + for (row = 0; row < height; row++) { + const GLubyte *src = srcRow; + + if (unpack->LsbFirst) { + /* Lsb first */ + GLubyte mask = 1U << (unpack->SkipPixels & 0x7); + for (col = 0; col < width; col++) { + + if (*src & mask) { + SET_PIXEL(col, row); + } + + if (mask == 128U) { + src++; + mask = 1U; + } + else { + mask = mask << 1; + } + } + + /* get ready for next row */ + if (mask != 1) + src++; + } + else { + /* Msb first */ + GLubyte mask = 128U >> (unpack->SkipPixels & 0x7); + for (col = 0; col < width; col++) { + + if (*src & mask) { + SET_PIXEL(col, row); + } + + if (mask == 1U) { + src++; + mask = 128U; + } + else { + mask = mask >> 1; + } + } + + /* get ready for next row */ + if (mask != 128) + src++; + } + + srcRow += srcStride; + } /* row */ + +#undef SET_PIXEL +} + + + + +/** + * Convert an array of RGBA colors from one datatype to another. + * NOTE: src may equal dst. In that case, we use a temporary buffer. + */ +void +_mesa_convert_colors(GLenum srcType, const GLvoid *src, + GLenum dstType, GLvoid *dst, + GLuint count, const GLubyte mask[]) +{ + GLuint tempBuffer[MAX_WIDTH][4]; + const GLboolean useTemp = (src == dst); + + ASSERT(srcType != dstType); + + switch (srcType) { + case GL_UNSIGNED_BYTE: + if (dstType == GL_UNSIGNED_SHORT) { + const GLubyte (*src1)[4] = (const GLubyte (*)[4]) src; + GLushort (*dst2)[4] = (GLushort (*)[4]) (useTemp ? tempBuffer : dst); + GLuint i; + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + dst2[i][RCOMP] = UBYTE_TO_USHORT(src1[i][RCOMP]); + dst2[i][GCOMP] = UBYTE_TO_USHORT(src1[i][GCOMP]); + dst2[i][BCOMP] = UBYTE_TO_USHORT(src1[i][BCOMP]); + dst2[i][ACOMP] = UBYTE_TO_USHORT(src1[i][ACOMP]); + } + } + if (useTemp) + memcpy(dst, tempBuffer, count * 4 * sizeof(GLushort)); + } + else { + const GLubyte (*src1)[4] = (const GLubyte (*)[4]) src; + GLfloat (*dst4)[4] = (GLfloat (*)[4]) (useTemp ? tempBuffer : dst); + GLuint i; + ASSERT(dstType == GL_FLOAT); + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + dst4[i][RCOMP] = UBYTE_TO_FLOAT(src1[i][RCOMP]); + dst4[i][GCOMP] = UBYTE_TO_FLOAT(src1[i][GCOMP]); + dst4[i][BCOMP] = UBYTE_TO_FLOAT(src1[i][BCOMP]); + dst4[i][ACOMP] = UBYTE_TO_FLOAT(src1[i][ACOMP]); + } + } + if (useTemp) + memcpy(dst, tempBuffer, count * 4 * sizeof(GLfloat)); + } + break; + case GL_UNSIGNED_SHORT: + if (dstType == GL_UNSIGNED_BYTE) { + const GLushort (*src2)[4] = (const GLushort (*)[4]) src; + GLubyte (*dst1)[4] = (GLubyte (*)[4]) (useTemp ? tempBuffer : dst); + GLuint i; + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + dst1[i][RCOMP] = USHORT_TO_UBYTE(src2[i][RCOMP]); + dst1[i][GCOMP] = USHORT_TO_UBYTE(src2[i][GCOMP]); + dst1[i][BCOMP] = USHORT_TO_UBYTE(src2[i][BCOMP]); + dst1[i][ACOMP] = USHORT_TO_UBYTE(src2[i][ACOMP]); + } + } + if (useTemp) + memcpy(dst, tempBuffer, count * 4 * sizeof(GLubyte)); + } + else { + const GLushort (*src2)[4] = (const GLushort (*)[4]) src; + GLfloat (*dst4)[4] = (GLfloat (*)[4]) (useTemp ? tempBuffer : dst); + GLuint i; + ASSERT(dstType == GL_FLOAT); + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + dst4[i][RCOMP] = USHORT_TO_FLOAT(src2[i][RCOMP]); + dst4[i][GCOMP] = USHORT_TO_FLOAT(src2[i][GCOMP]); + dst4[i][BCOMP] = USHORT_TO_FLOAT(src2[i][BCOMP]); + dst4[i][ACOMP] = USHORT_TO_FLOAT(src2[i][ACOMP]); + } + } + if (useTemp) + memcpy(dst, tempBuffer, count * 4 * sizeof(GLfloat)); + } + break; + case GL_FLOAT: + if (dstType == GL_UNSIGNED_BYTE) { + const GLfloat (*src4)[4] = (const GLfloat (*)[4]) src; + GLubyte (*dst1)[4] = (GLubyte (*)[4]) (useTemp ? tempBuffer : dst); + GLuint i; + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + UNCLAMPED_FLOAT_TO_UBYTE(dst1[i][RCOMP], src4[i][RCOMP]); + UNCLAMPED_FLOAT_TO_UBYTE(dst1[i][GCOMP], src4[i][GCOMP]); + UNCLAMPED_FLOAT_TO_UBYTE(dst1[i][BCOMP], src4[i][BCOMP]); + UNCLAMPED_FLOAT_TO_UBYTE(dst1[i][ACOMP], src4[i][ACOMP]); + } + } + if (useTemp) + memcpy(dst, tempBuffer, count * 4 * sizeof(GLubyte)); + } + else { + const GLfloat (*src4)[4] = (const GLfloat (*)[4]) src; + GLushort (*dst2)[4] = (GLushort (*)[4]) (useTemp ? tempBuffer : dst); + GLuint i; + ASSERT(dstType == GL_UNSIGNED_SHORT); + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + UNCLAMPED_FLOAT_TO_USHORT(dst2[i][RCOMP], src4[i][RCOMP]); + UNCLAMPED_FLOAT_TO_USHORT(dst2[i][GCOMP], src4[i][GCOMP]); + UNCLAMPED_FLOAT_TO_USHORT(dst2[i][BCOMP], src4[i][BCOMP]); + UNCLAMPED_FLOAT_TO_USHORT(dst2[i][ACOMP], src4[i][ACOMP]); + } + } + if (useTemp) + memcpy(dst, tempBuffer, count * 4 * sizeof(GLushort)); + } + break; + default: + _mesa_problem(NULL, "Invalid datatype in _mesa_convert_colors"); + } +} + + + + +/** + * Perform basic clipping for glDrawPixels. The image's position and size + * and the unpack SkipPixels and SkipRows are adjusted so that the image + * region is entirely within the window and scissor bounds. + * NOTE: this will only work when glPixelZoom is (1, 1) or (1, -1). + * If Pixel.ZoomY is -1, *destY will be changed to be the first row which + * we'll actually write. Beforehand, *destY-1 is the first drawing row. + * + * \return GL_TRUE if image is ready for drawing or + * GL_FALSE if image was completely clipped away (draw nothing) + */ +GLboolean +_mesa_clip_drawpixels(const struct gl_context *ctx, + GLint *destX, GLint *destY, + GLsizei *width, GLsizei *height, + struct gl_pixelstore_attrib *unpack) +{ + const struct gl_framebuffer *buffer = ctx->DrawBuffer; + + if (unpack->RowLength == 0) { + unpack->RowLength = *width; + } + + ASSERT(ctx->Pixel.ZoomX == 1.0F); + ASSERT(ctx->Pixel.ZoomY == 1.0F || ctx->Pixel.ZoomY == -1.0F); + + /* left clipping */ + if (*destX < buffer->_Xmin) { + unpack->SkipPixels += (buffer->_Xmin - *destX); + *width -= (buffer->_Xmin - *destX); + *destX = buffer->_Xmin; + } + /* right clipping */ + if (*destX + *width > buffer->_Xmax) + *width -= (*destX + *width - buffer->_Xmax); + + if (*width <= 0) + return GL_FALSE; + + if (ctx->Pixel.ZoomY == 1.0F) { + /* bottom clipping */ + if (*destY < buffer->_Ymin) { + unpack->SkipRows += (buffer->_Ymin - *destY); + *height -= (buffer->_Ymin - *destY); + *destY = buffer->_Ymin; + } + /* top clipping */ + if (*destY + *height > buffer->_Ymax) + *height -= (*destY + *height - buffer->_Ymax); + } + else { /* upside down */ + /* top clipping */ + if (*destY > buffer->_Ymax) { + unpack->SkipRows += (*destY - buffer->_Ymax); + *height -= (*destY - buffer->_Ymax); + *destY = buffer->_Ymax; + } + /* bottom clipping */ + if (*destY - *height < buffer->_Ymin) + *height -= (buffer->_Ymin - (*destY - *height)); + /* adjust destY so it's the first row to write to */ + (*destY)--; + } + + if (*height <= 0) + return GL_FALSE; + + return GL_TRUE; +} + + +/** + * Perform clipping for glReadPixels. The image's window position + * and size, and the pack skipPixels, skipRows and rowLength are adjusted + * so that the image region is entirely within the window bounds. + * Note: this is different from _mesa_clip_drawpixels() in that the + * scissor box is ignored, and we use the bounds of the current readbuffer + * surface. + * + * \return GL_TRUE if region to read is in bounds + * GL_FALSE if region is completely out of bounds (nothing to read) + */ +GLboolean +_mesa_clip_readpixels(const struct gl_context *ctx, + GLint *srcX, GLint *srcY, + GLsizei *width, GLsizei *height, + struct gl_pixelstore_attrib *pack) +{ + const struct gl_framebuffer *buffer = ctx->ReadBuffer; + + if (pack->RowLength == 0) { + pack->RowLength = *width; + } + + /* left clipping */ + if (*srcX < 0) { + pack->SkipPixels += (0 - *srcX); + *width -= (0 - *srcX); + *srcX = 0; + } + /* right clipping */ + if (*srcX + *width > (GLsizei) buffer->Width) + *width -= (*srcX + *width - buffer->Width); + + if (*width <= 0) + return GL_FALSE; + + /* bottom clipping */ + if (*srcY < 0) { + pack->SkipRows += (0 - *srcY); + *height -= (0 - *srcY); + *srcY = 0; + } + /* top clipping */ + if (*srcY + *height > (GLsizei) buffer->Height) + *height -= (*srcY + *height - buffer->Height); + + if (*height <= 0) + return GL_FALSE; + + return GL_TRUE; +} + + +/** + * Do clipping for a glCopyTexSubImage call. + * The framebuffer source region might extend outside the framebuffer + * bounds. Clip the source region against the framebuffer bounds and + * adjust the texture/dest position and size accordingly. + * + * \return GL_FALSE if region is totally clipped, GL_TRUE otherwise. + */ +GLboolean +_mesa_clip_copytexsubimage(const struct gl_context *ctx, + GLint *destX, GLint *destY, + GLint *srcX, GLint *srcY, + GLsizei *width, GLsizei *height) +{ + const struct gl_framebuffer *fb = ctx->ReadBuffer; + const GLint srcX0 = *srcX, srcY0 = *srcY; + + if (_mesa_clip_to_region(0, 0, fb->Width, fb->Height, + srcX, srcY, width, height)) { + *destX = *destX + *srcX - srcX0; + *destY = *destY + *srcY - srcY0; + + return GL_TRUE; + } + else { + return GL_FALSE; + } +} + + + +/** + * Clip the rectangle defined by (x, y, width, height) against the bounds + * specified by [xmin, xmax) and [ymin, ymax). + * \return GL_FALSE if rect is totally clipped, GL_TRUE otherwise. + */ +GLboolean +_mesa_clip_to_region(GLint xmin, GLint ymin, + GLint xmax, GLint ymax, + GLint *x, GLint *y, + GLsizei *width, GLsizei *height ) +{ + /* left clipping */ + if (*x < xmin) { + *width -= (xmin - *x); + *x = xmin; + } + + /* right clipping */ + if (*x + *width > xmax) + *width -= (*x + *width - xmax); + + if (*width <= 0) + return GL_FALSE; + + /* bottom (or top) clipping */ + if (*y < ymin) { + *height -= (ymin - *y); + *y = ymin; + } + + /* top (or bottom) clipping */ + if (*y + *height > ymax) + *height -= (*y + *height - ymax); + + if (*height <= 0) + return GL_FALSE; + + return GL_TRUE; +} + + +/** + * Clip dst coords against Xmax (or Ymax). + */ +static INLINE void +clip_right_or_top(GLint *srcX0, GLint *srcX1, + GLint *dstX0, GLint *dstX1, + GLint maxValue) +{ + GLfloat t, bias; + + if (*dstX1 > maxValue) { + /* X1 outside right edge */ + ASSERT(*dstX0 < maxValue); /* X0 should be inside right edge */ + t = (GLfloat) (maxValue - *dstX0) / (GLfloat) (*dstX1 - *dstX0); + /* chop off [t, 1] part */ + ASSERT(t >= 0.0 && t <= 1.0); + *dstX1 = maxValue; + bias = (*srcX0 < *srcX1) ? 0.5F : -0.5F; + *srcX1 = *srcX0 + (GLint) (t * (*srcX1 - *srcX0) + bias); + } + else if (*dstX0 > maxValue) { + /* X0 outside right edge */ + ASSERT(*dstX1 < maxValue); /* X1 should be inside right edge */ + t = (GLfloat) (maxValue - *dstX1) / (GLfloat) (*dstX0 - *dstX1); + /* chop off [t, 1] part */ + ASSERT(t >= 0.0 && t <= 1.0); + *dstX0 = maxValue; + bias = (*srcX0 < *srcX1) ? -0.5F : 0.5F; + *srcX0 = *srcX1 + (GLint) (t * (*srcX0 - *srcX1) + bias); + } +} + + +/** + * Clip dst coords against Xmin (or Ymin). + */ +static INLINE void +clip_left_or_bottom(GLint *srcX0, GLint *srcX1, + GLint *dstX0, GLint *dstX1, + GLint minValue) +{ + GLfloat t, bias; + + if (*dstX0 < minValue) { + /* X0 outside left edge */ + ASSERT(*dstX1 > minValue); /* X1 should be inside left edge */ + t = (GLfloat) (minValue - *dstX0) / (GLfloat) (*dstX1 - *dstX0); + /* chop off [0, t] part */ + ASSERT(t >= 0.0 && t <= 1.0); + *dstX0 = minValue; + bias = (*srcX0 < *srcX1) ? 0.5F : -0.5F; /* flipped??? */ + *srcX0 = *srcX0 + (GLint) (t * (*srcX1 - *srcX0) + bias); + } + else if (*dstX1 < minValue) { + /* X1 outside left edge */ + ASSERT(*dstX0 > minValue); /* X0 should be inside left edge */ + t = (GLfloat) (minValue - *dstX1) / (GLfloat) (*dstX0 - *dstX1); + /* chop off [0, t] part */ + ASSERT(t >= 0.0 && t <= 1.0); + *dstX1 = minValue; + bias = (*srcX0 < *srcX1) ? 0.5F : -0.5F; + *srcX1 = *srcX1 + (GLint) (t * (*srcX0 - *srcX1) + bias); + } +} + + +/** + * Do clipping of blit src/dest rectangles. + * The dest rect is clipped against both the buffer bounds and scissor bounds. + * The src rect is just clipped against the buffer bounds. + * + * When either the src or dest rect is clipped, the other is also clipped + * proportionately! + * + * Note that X0 need not be less than X1 (same for Y) for either the source + * and dest rects. That makes the clipping a little trickier. + * + * \return GL_TRUE if anything is left to draw, GL_FALSE if totally clipped + */ +GLboolean +_mesa_clip_blit(struct gl_context *ctx, + GLint *srcX0, GLint *srcY0, GLint *srcX1, GLint *srcY1, + GLint *dstX0, GLint *dstY0, GLint *dstX1, GLint *dstY1) +{ + const GLint srcXmin = 0; + const GLint srcXmax = ctx->ReadBuffer->Width; + const GLint srcYmin = 0; + const GLint srcYmax = ctx->ReadBuffer->Height; + + /* these include scissor bounds */ + const GLint dstXmin = ctx->DrawBuffer->_Xmin; + const GLint dstXmax = ctx->DrawBuffer->_Xmax; + const GLint dstYmin = ctx->DrawBuffer->_Ymin; + const GLint dstYmax = ctx->DrawBuffer->_Ymax; + + /* + printf("PreClipX: src: %d .. %d dst: %d .. %d\n", + *srcX0, *srcX1, *dstX0, *dstX1); + printf("PreClipY: src: %d .. %d dst: %d .. %d\n", + *srcY0, *srcY1, *dstY0, *dstY1); + */ + + /* trivial rejection tests */ + if (*dstX0 == *dstX1) + return GL_FALSE; /* no width */ + if (*dstX0 <= dstXmin && *dstX1 <= dstXmin) + return GL_FALSE; /* totally out (left) of bounds */ + if (*dstX0 >= dstXmax && *dstX1 >= dstXmax) + return GL_FALSE; /* totally out (right) of bounds */ + + if (*dstY0 == *dstY1) + return GL_FALSE; + if (*dstY0 <= dstYmin && *dstY1 <= dstYmin) + return GL_FALSE; + if (*dstY0 >= dstYmax && *dstY1 >= dstYmax) + return GL_FALSE; + + if (*srcX0 == *srcX1) + return GL_FALSE; + if (*srcX0 <= srcXmin && *srcX1 <= srcXmin) + return GL_FALSE; + if (*srcX0 >= srcXmax && *srcX1 >= srcXmax) + return GL_FALSE; + + if (*srcY0 == *srcY1) + return GL_FALSE; + if (*srcY0 <= srcYmin && *srcY1 <= srcYmin) + return GL_FALSE; + if (*srcY0 >= srcYmax && *srcY1 >= srcYmax) + return GL_FALSE; + + /* + * dest clip + */ + clip_right_or_top(srcX0, srcX1, dstX0, dstX1, dstXmax); + clip_right_or_top(srcY0, srcY1, dstY0, dstY1, dstYmax); + clip_left_or_bottom(srcX0, srcX1, dstX0, dstX1, dstXmin); + clip_left_or_bottom(srcY0, srcY1, dstY0, dstY1, dstYmin); + + /* + * src clip (just swap src/dst values from above) + */ + clip_right_or_top(dstX0, dstX1, srcX0, srcX1, srcXmax); + clip_right_or_top(dstY0, dstY1, srcY0, srcY1, srcYmax); + clip_left_or_bottom(dstX0, dstX1, srcX0, srcX1, srcXmin); + clip_left_or_bottom(dstY0, dstY1, srcY0, srcY1, srcYmin); + + /* + printf("PostClipX: src: %d .. %d dst: %d .. %d\n", + *srcX0, *srcX1, *dstX0, *dstX1); + printf("PostClipY: src: %d .. %d dst: %d .. %d\n", + *srcY0, *srcY1, *dstY0, *dstY1); + */ + + ASSERT(*dstX0 >= dstXmin); + ASSERT(*dstX0 <= dstXmax); + ASSERT(*dstX1 >= dstXmin); + ASSERT(*dstX1 <= dstXmax); + + ASSERT(*dstY0 >= dstYmin); + ASSERT(*dstY0 <= dstYmax); + ASSERT(*dstY1 >= dstYmin); + ASSERT(*dstY1 <= dstYmax); + + ASSERT(*srcX0 >= srcXmin); + ASSERT(*srcX0 <= srcXmax); + ASSERT(*srcX1 >= srcXmin); + ASSERT(*srcX1 <= srcXmax); + + ASSERT(*srcY0 >= srcYmin); + ASSERT(*srcY0 <= srcYmax); + ASSERT(*srcY1 >= srcYmin); + ASSERT(*srcY1 <= srcYmax); + + return GL_TRUE; +} diff --git a/mesalib/src/mesa/main/mipmap.c b/mesalib/src/mesa/main/mipmap.c index f2724dbca..8a811cb72 100644 --- a/mesalib/src/mesa/main/mipmap.c +++ b/mesalib/src/mesa/main/mipmap.c @@ -706,6 +706,17 @@ do_row(GLenum datatype, GLuint comps, GLint srcWidth, } } + else if (datatype == GL_FLOAT_32_UNSIGNED_INT_24_8_REV && comps == 1) { + GLuint i, j, k; + const GLfloat *rowA = (const GLfloat *) srcRowA; + const GLfloat *rowB = (const GLfloat *) srcRowB; + GLfloat *dst = (GLfloat *) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + dst[i*2] = (rowA[j*2] + rowA[k*2] + rowB[j*2] + rowB[k*2]) * 0.25F; + } + } + else { _mesa_problem(NULL, "bad format in do_row()"); } @@ -1341,6 +1352,15 @@ do_row_3D(GLenum datatype, GLuint comps, GLint srcWidth, } } + else if (datatype == GL_FLOAT_32_UNSIGNED_INT_24_8_REV && comps == 1) { + DECLARE_ROW_POINTERS(GLfloat, 2); + + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + FILTER_F_3D(0); + } + } + else { _mesa_problem(NULL, "bad format in do_row()"); } diff --git a/mesalib/src/mesa/main/mtypes.h b/mesalib/src/mesa/main/mtypes.h index f018c75cc..b88118366 100644 --- a/mesalib/src/mesa/main/mtypes.h +++ b/mesalib/src/mesa/main/mtypes.h @@ -1856,7 +1856,7 @@ struct gl_program GLbitfield SystemValuesRead; /**< Bitmask of SYSTEM_VALUE_x inputs used */ GLbitfield InputFlags[MAX_PROGRAM_INPUTS]; /**< PROG_PARAM_BIT_x flags */ GLbitfield OutputFlags[MAX_PROGRAM_OUTPUTS]; /**< PROG_PARAM_BIT_x flags */ - GLbitfield TexturesUsed[MAX_TEXTURE_UNITS]; /**< TEXTURE_x_BIT bitmask */ + GLbitfield TexturesUsed[MAX_COMBINED_TEXTURE_IMAGE_UNITS]; /**< TEXTURE_x_BIT bitmask */ GLbitfield SamplersUsed; /**< Bitfield of which samplers are used */ GLbitfield ShadowSamplers; /**< Texture units used for shadow sampling. */ diff --git a/mesalib/src/mesa/main/pack.c b/mesalib/src/mesa/main/pack.c index a232a51c3..7de1d05b9 100644 --- a/mesalib/src/mesa/main/pack.c +++ b/mesalib/src/mesa/main/pack.c @@ -1971,7 +1971,8 @@ extract_uint_indexes(GLuint n, GLuint indexes[], srcType == GL_INT || srcType == GL_UNSIGNED_INT_24_8_EXT || srcType == GL_HALF_FLOAT_ARB || - srcType == GL_FLOAT); + srcType == GL_FLOAT || + srcType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV); switch (srcType) { case GL_BITMAP: @@ -2142,6 +2143,23 @@ extract_uint_indexes(GLuint n, GLuint indexes[], } } break; + case GL_FLOAT_32_UNSIGNED_INT_24_8_REV: + { + GLuint i; + const GLuint *s = (const GLuint *) src; + if (unpack->SwapBytes) { + for (i = 0; i < n; i++) { + GLuint value = s[i*2+1]; + SWAP4BYTE(value); + indexes[i] = value & 0xff; /* lower 8 bits */ + } + } + else { + for (i = 0; i < n; i++) + indexes[i] = s[i*2+1] & 0xff; /* lower 8 bits */ + } + } + break; default: _mesa_problem(NULL, "bad srcType in extract_uint_indexes"); @@ -4412,11 +4430,13 @@ _mesa_unpack_stencil_span( struct gl_context *ctx, GLuint n, srcType == GL_INT || srcType == GL_UNSIGNED_INT_24_8_EXT || srcType == GL_HALF_FLOAT_ARB || - srcType == GL_FLOAT); + srcType == GL_FLOAT || + srcType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV); ASSERT(dstType == GL_UNSIGNED_BYTE || dstType == GL_UNSIGNED_SHORT || - dstType == GL_UNSIGNED_INT); + dstType == GL_UNSIGNED_INT || + dstType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV); /* only shift and offset apply to stencil */ transferOps &= IMAGE_SHIFT_OFFSET_BIT; @@ -4488,6 +4508,15 @@ _mesa_unpack_stencil_span( struct gl_context *ctx, GLuint n, case GL_UNSIGNED_INT: memcpy(dest, indexes, n * sizeof(GLuint)); break; + case GL_FLOAT_32_UNSIGNED_INT_24_8_REV: + { + GLuint *dst = (GLuint *) dest; + GLuint i; + for (i = 0; i < n; i++) { + dst[i*2+1] = indexes[i] & 0xff; /* lower 8 bits */ + } + } + break; default: _mesa_problem(ctx, "bad dstType in _mesa_unpack_stencil_span"); } @@ -4798,6 +4827,20 @@ _mesa_unpack_depth_span( struct gl_context *ctx, GLuint n, } } break; + case GL_FLOAT_32_UNSIGNED_INT_24_8_REV: + { + GLuint i; + const GLfloat *src = (const GLfloat *)source; + for (i = 0; i < n; i++) { + GLfloat value = src[i * 2]; + if (srcPacking->SwapBytes) { + SWAP4BYTE(value); + } + depthValues[i] = value; + } + needClamp = GL_TRUE; + } + break; case GL_FLOAT: DEPTH_VALUES(GLfloat, 1*); needClamp = GL_TRUE; @@ -4874,9 +4917,18 @@ _mesa_unpack_depth_span( struct gl_context *ctx, GLuint n, zValues[i] = (GLushort) (depthValues[i] * (GLfloat) depthMax); } } + else if (dstType == GL_FLOAT) { + /* Nothing to do. depthValues is pointing to dest. */ + } + else if (dstType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV) { + GLfloat *zValues = (GLfloat*) dest; + GLuint i; + for (i = 0; i < n; i++) { + zValues[i*2] = depthValues[i]; + } + } else { - ASSERT(dstType == GL_FLOAT); - /*ASSERT(depthMax == 1.0F);*/ + ASSERT(0); } free(depthTemp); @@ -5004,10 +5056,11 @@ _mesa_pack_depth_span( struct gl_context *ctx, GLuint n, GLvoid *dest, /** - * Pack depth and stencil values as GL_DEPTH_STENCIL/GL_UNSIGNED_INT_24_8. + * Pack depth and stencil values as GL_DEPTH_STENCIL (GL_UNSIGNED_INT_24_8 etc) */ void -_mesa_pack_depth_stencil_span(struct gl_context *ctx, GLuint n, GLuint *dest, +_mesa_pack_depth_stencil_span(struct gl_context *ctx,GLuint n, + GLenum dstType, GLuint *dest, const GLfloat *depthVals, const GLstencil *stencilVals, const struct gl_pixelstore_attrib *dstPacking) @@ -5037,9 +5090,19 @@ _mesa_pack_depth_stencil_span(struct gl_context *ctx, GLuint n, GLuint *dest, stencilVals = stencilCopy; } - for (i = 0; i < n; i++) { - GLuint z = (GLuint) (depthVals[i] * 0xffffff); - dest[i] = (z << 8) | (stencilVals[i] & 0xff); + switch (dstType) { + case GL_UNSIGNED_INT_24_8: + for (i = 0; i < n; i++) { + GLuint z = (GLuint) (depthVals[i] * 0xffffff); + dest[i] = (z << 8) | (stencilVals[i] & 0xff); + } + break; + case GL_FLOAT_32_UNSIGNED_INT_24_8_REV: + for (i = 0; i < n; i++) { + ((GLfloat*)dest)[i*2] = depthVals[i]; + dest[i*2+1] = stencilVals[i] & 0xff; + } + break; } if (dstPacking->SwapBytes) { diff --git a/mesalib/src/mesa/main/pack.h b/mesalib/src/mesa/main/pack.h index 1f19a5a7c..00aab409e 100644 --- a/mesalib/src/mesa/main/pack.h +++ b/mesalib/src/mesa/main/pack.h @@ -1,147 +1,147 @@ -/*
- * Mesa 3-D graphics library
- *
- * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
- * Copyright (C) 1999-2010 VMware, Inc. All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-#ifndef PACK_H
-#define PACK_H
-
-
-#include "mtypes.h"
-
-
-extern void
-_mesa_unpack_polygon_stipple(const GLubyte *pattern, GLuint dest[32],
- const struct gl_pixelstore_attrib *unpacking);
-
-
-extern void
-_mesa_pack_polygon_stipple(const GLuint pattern[32], GLubyte *dest,
- const struct gl_pixelstore_attrib *packing);
-
-
-extern GLvoid *
-_mesa_unpack_bitmap(GLint width, GLint height, const GLubyte *pixels,
- const struct gl_pixelstore_attrib *packing);
-
-extern void
-_mesa_pack_bitmap(GLint width, GLint height, const GLubyte *source,
- GLubyte *dest, const struct gl_pixelstore_attrib *packing);
-
-
-extern void
-_mesa_pack_rgba_span_float(struct gl_context *ctx, GLuint n,
- GLfloat rgba[][4],
- GLenum dstFormat, GLenum dstType, GLvoid *dstAddr,
- const struct gl_pixelstore_attrib *dstPacking,
- GLbitfield transferOps);
-
-
-extern void
-_mesa_unpack_color_span_chan(struct gl_context *ctx,
- GLuint n, GLenum dstFormat, GLchan dest[],
- GLenum srcFormat, GLenum srcType,
- const GLvoid *source,
- const struct gl_pixelstore_attrib *srcPacking,
- GLbitfield transferOps);
-
-
-extern void
-_mesa_unpack_color_span_float(struct gl_context *ctx,
- GLuint n, GLenum dstFormat, GLfloat dest[],
- GLenum srcFormat, GLenum srcType,
- const GLvoid *source,
- const struct gl_pixelstore_attrib *srcPacking,
- GLbitfield transferOps);
-
-extern void
-_mesa_unpack_color_span_uint(struct gl_context *ctx,
- GLuint n, GLenum dstFormat, GLuint *dest,
- GLenum srcFormat, GLenum srcType,
- const GLvoid *source,
- const struct gl_pixelstore_attrib *srcPacking);
-
-extern void
-_mesa_unpack_dudv_span_byte(struct gl_context *ctx,
- GLuint n, GLenum dstFormat, GLbyte dest[],
- GLenum srcFormat, GLenum srcType,
- const GLvoid *source,
- const struct gl_pixelstore_attrib *srcPacking,
- GLbitfield transferOps);
-
-extern void
-_mesa_unpack_index_span(struct gl_context *ctx, GLuint n,
- GLenum dstType, GLvoid *dest,
- GLenum srcType, const GLvoid *source,
- const struct gl_pixelstore_attrib *srcPacking,
- GLbitfield transferOps);
-
-
-extern void
-_mesa_pack_index_span(struct gl_context *ctx, GLuint n,
- GLenum dstType, GLvoid *dest, const GLuint *source,
- const struct gl_pixelstore_attrib *dstPacking,
- GLbitfield transferOps);
-
-
-extern void
-_mesa_unpack_stencil_span(struct gl_context *ctx, GLuint n,
- GLenum dstType, GLvoid *dest,
- GLenum srcType, const GLvoid *source,
- const struct gl_pixelstore_attrib *srcPacking,
- GLbitfield transferOps);
-
-extern void
-_mesa_pack_stencil_span(struct gl_context *ctx, GLuint n,
- GLenum dstType, GLvoid *dest, const GLstencil *source,
- const struct gl_pixelstore_attrib *dstPacking);
-
-
-extern void
-_mesa_unpack_depth_span(struct gl_context *ctx, GLuint n,
- GLenum dstType, GLvoid *dest, GLuint depthMax,
- GLenum srcType, const GLvoid *source,
- const struct gl_pixelstore_attrib *srcPacking);
-
-extern void
-_mesa_pack_depth_span(struct gl_context *ctx, GLuint n, GLvoid *dest,
- GLenum dstType, const GLfloat *depthSpan,
- const struct gl_pixelstore_attrib *dstPacking);
-
-
-extern void
-_mesa_pack_depth_stencil_span(struct gl_context *ctx,
- GLuint n, GLuint *dest,
- const GLfloat *depthVals,
- const GLstencil *stencilVals,
- const struct gl_pixelstore_attrib *dstPacking);
-
-
-extern void *
-_mesa_unpack_image(GLuint dimensions,
- GLsizei width, GLsizei height, GLsizei depth,
- GLenum format, GLenum type, const GLvoid *pixels,
- const struct gl_pixelstore_attrib *unpack);
-
-
-#endif
+/* + * Mesa 3-D graphics library + * + * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. + * Copyright (C) 1999-2010 VMware, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef PACK_H +#define PACK_H + + +#include "mtypes.h" + + +extern void +_mesa_unpack_polygon_stipple(const GLubyte *pattern, GLuint dest[32], + const struct gl_pixelstore_attrib *unpacking); + + +extern void +_mesa_pack_polygon_stipple(const GLuint pattern[32], GLubyte *dest, + const struct gl_pixelstore_attrib *packing); + + +extern GLvoid * +_mesa_unpack_bitmap(GLint width, GLint height, const GLubyte *pixels, + const struct gl_pixelstore_attrib *packing); + +extern void +_mesa_pack_bitmap(GLint width, GLint height, const GLubyte *source, + GLubyte *dest, const struct gl_pixelstore_attrib *packing); + + +extern void +_mesa_pack_rgba_span_float(struct gl_context *ctx, GLuint n, + GLfloat rgba[][4], + GLenum dstFormat, GLenum dstType, GLvoid *dstAddr, + const struct gl_pixelstore_attrib *dstPacking, + GLbitfield transferOps); + + +extern void +_mesa_unpack_color_span_chan(struct gl_context *ctx, + GLuint n, GLenum dstFormat, GLchan dest[], + GLenum srcFormat, GLenum srcType, + const GLvoid *source, + const struct gl_pixelstore_attrib *srcPacking, + GLbitfield transferOps); + + +extern void +_mesa_unpack_color_span_float(struct gl_context *ctx, + GLuint n, GLenum dstFormat, GLfloat dest[], + GLenum srcFormat, GLenum srcType, + const GLvoid *source, + const struct gl_pixelstore_attrib *srcPacking, + GLbitfield transferOps); + +extern void +_mesa_unpack_color_span_uint(struct gl_context *ctx, + GLuint n, GLenum dstFormat, GLuint *dest, + GLenum srcFormat, GLenum srcType, + const GLvoid *source, + const struct gl_pixelstore_attrib *srcPacking); + +extern void +_mesa_unpack_dudv_span_byte(struct gl_context *ctx, + GLuint n, GLenum dstFormat, GLbyte dest[], + GLenum srcFormat, GLenum srcType, + const GLvoid *source, + const struct gl_pixelstore_attrib *srcPacking, + GLbitfield transferOps); + +extern void +_mesa_unpack_index_span(struct gl_context *ctx, GLuint n, + GLenum dstType, GLvoid *dest, + GLenum srcType, const GLvoid *source, + const struct gl_pixelstore_attrib *srcPacking, + GLbitfield transferOps); + + +extern void +_mesa_pack_index_span(struct gl_context *ctx, GLuint n, + GLenum dstType, GLvoid *dest, const GLuint *source, + const struct gl_pixelstore_attrib *dstPacking, + GLbitfield transferOps); + + +extern void +_mesa_unpack_stencil_span(struct gl_context *ctx, GLuint n, + GLenum dstType, GLvoid *dest, + GLenum srcType, const GLvoid *source, + const struct gl_pixelstore_attrib *srcPacking, + GLbitfield transferOps); + +extern void +_mesa_pack_stencil_span(struct gl_context *ctx, GLuint n, + GLenum dstType, GLvoid *dest, const GLstencil *source, + const struct gl_pixelstore_attrib *dstPacking); + + +extern void +_mesa_unpack_depth_span(struct gl_context *ctx, GLuint n, + GLenum dstType, GLvoid *dest, GLuint depthMax, + GLenum srcType, const GLvoid *source, + const struct gl_pixelstore_attrib *srcPacking); + +extern void +_mesa_pack_depth_span(struct gl_context *ctx, GLuint n, GLvoid *dest, + GLenum dstType, const GLfloat *depthSpan, + const struct gl_pixelstore_attrib *dstPacking); + + +extern void +_mesa_pack_depth_stencil_span(struct gl_context *ctx,GLuint n, + GLenum dstType, GLuint *dest, + const GLfloat *depthVals, + const GLstencil *stencilVals, + const struct gl_pixelstore_attrib *dstPacking); + + +extern void * +_mesa_unpack_image(GLuint dimensions, + GLsizei width, GLsizei height, GLsizei depth, + GLenum format, GLenum type, const GLvoid *pixels, + const struct gl_pixelstore_attrib *unpack); + + +#endif diff --git a/mesalib/src/mesa/main/readpix.c b/mesalib/src/mesa/main/readpix.c index 0331a8ca2..84c5b2228 100644 --- a/mesalib/src/mesa/main/readpix.c +++ b/mesalib/src/mesa/main/readpix.c @@ -61,6 +61,14 @@ _mesa_error_check_format_type(struct gl_context *ctx, GLenum format, return GL_TRUE; } + if (ctx->Extensions.ARB_depth_buffer_float + && type == GL_FLOAT_32_UNSIGNED_INT_24_8_REV + && format != GL_DEPTH_STENCIL_EXT) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "gl%sPixels(format is not GL_DEPTH_STENCIL_EXT)", readDraw); + return GL_TRUE; + } + /* basic combinations test */ if (!_mesa_is_legal_format_and_type(ctx, format, type)) { _mesa_error(ctx, GL_INVALID_ENUM, @@ -142,10 +150,23 @@ _mesa_error_check_format_type(struct gl_context *ctx, GLenum format, } break; case GL_DEPTH_STENCIL_EXT: - if (!ctx->Extensions.EXT_packed_depth_stencil || - type != GL_UNSIGNED_INT_24_8_EXT) { - _mesa_error(ctx, GL_INVALID_ENUM, "gl%sPixels(type)", readDraw); - return GL_TRUE; + /* Check validity of the type first. */ + switch (type) { + case GL_UNSIGNED_INT_24_8_EXT: + if (!ctx->Extensions.EXT_packed_depth_stencil) { + _mesa_error(ctx, GL_INVALID_ENUM, "gl%sPixels(type)", readDraw); + return GL_TRUE; + } + break; + case GL_FLOAT_32_UNSIGNED_INT_24_8_REV: + if (!ctx->Extensions.ARB_depth_buffer_float) { + _mesa_error(ctx, GL_INVALID_ENUM, "gl%sPixels(type)", readDraw); + return GL_TRUE; + } + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "gl%sPixels(type)", readDraw); + return GL_TRUE; } if ((drawing && !_mesa_dest_buffer_exists(ctx, format)) || (reading && !_mesa_source_buffer_exists(ctx, format))) { diff --git a/mesalib/src/mesa/main/renderbuffer.c b/mesalib/src/mesa/main/renderbuffer.c index c36175c60..f5b20020d 100644 --- a/mesalib/src/mesa/main/renderbuffer.c +++ b/mesalib/src/mesa/main/renderbuffer.c @@ -66,6 +66,9 @@ get_datatype_bytes(struct gl_renderbuffer *rb) int component_size; switch (rb->DataType) { + case GL_FLOAT_32_UNSIGNED_INT_24_8_REV: + component_size = 8; + break; case GL_FLOAT: case GL_UNSIGNED_INT: case GL_UNSIGNED_INT_24_8_EXT: diff --git a/mesalib/src/mesa/main/samplerobj.c b/mesalib/src/mesa/main/samplerobj.c index f7774fdd7..8f8d87b90 100644 --- a/mesalib/src/mesa/main/samplerobj.c +++ b/mesalib/src/mesa/main/samplerobj.c @@ -251,7 +251,7 @@ _mesa_BindSampler(GLuint unit, GLuint sampler) struct gl_sampler_object *sampObj; GET_CURRENT_CONTEXT(ctx); - if (unit >= ctx->Const.MaxTextureImageUnits) { + if (unit >= ctx->Const.MaxCombinedTextureImageUnits) { _mesa_error(ctx, GL_INVALID_VALUE, "glBindSampler(unit %u)", unit); return; } diff --git a/mesalib/src/mesa/main/shaderapi.c b/mesalib/src/mesa/main/shaderapi.c index b58e30de9..8df25c3f9 100644 --- a/mesalib/src/mesa/main/shaderapi.c +++ b/mesalib/src/mesa/main/shaderapi.c @@ -1032,7 +1032,7 @@ validate_samplers(const struct gl_program *prog, char *errMsg) "TEXTURE_2D", "TEXTURE_1D", }; - GLint targetUsed[MAX_TEXTURE_IMAGE_UNITS]; + GLint targetUsed[MAX_COMBINED_TEXTURE_IMAGE_UNITS]; GLbitfield samplersUsed = prog->SamplersUsed; GLuint i; @@ -1050,7 +1050,7 @@ validate_samplers(const struct gl_program *prog, char *errMsg) gl_texture_index target; GLint sampler = _mesa_ffs(samplersUsed) - 1; assert(sampler >= 0); - assert(sampler < MAX_TEXTURE_IMAGE_UNITS); + assert(sampler < Elements(prog->SamplerUnits)); unit = prog->SamplerUnits[sampler]; target = prog->SamplerTargets[sampler]; if (targetUsed[unit] != -1 && targetUsed[unit] != (int) target) { diff --git a/mesalib/src/mesa/main/texenv.c b/mesalib/src/mesa/main/texenv.c index 9228e354a..c0d0f3779 100644 --- a/mesalib/src/mesa/main/texenv.c +++ b/mesalib/src/mesa/main/texenv.c @@ -419,7 +419,7 @@ _mesa_TexEnvfv( GLenum target, GLenum pname, const GLfloat *param ) ASSERT_OUTSIDE_BEGIN_END(ctx); maxUnit = (target == GL_POINT_SPRITE_NV && pname == GL_COORD_REPLACE_NV) - ? ctx->Const.MaxTextureCoordUnits : ctx->Const.MaxTextureImageUnits; + ? ctx->Const.MaxTextureCoordUnits : ctx->Const.MaxCombinedTextureImageUnits; if (ctx->Texture.CurrentUnit >= maxUnit) { _mesa_error(ctx, GL_INVALID_OPERATION, "glTexEnvfv(current unit)"); return; @@ -748,7 +748,7 @@ _mesa_GetTexEnvfv( GLenum target, GLenum pname, GLfloat *params ) ASSERT_OUTSIDE_BEGIN_END(ctx); maxUnit = (target == GL_POINT_SPRITE_NV && pname == GL_COORD_REPLACE_NV) - ? ctx->Const.MaxTextureCoordUnits : ctx->Const.MaxTextureImageUnits; + ? ctx->Const.MaxTextureCoordUnits : ctx->Const.MaxCombinedTextureImageUnits; if (ctx->Texture.CurrentUnit >= maxUnit) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexEnvfv(current unit)"); return; @@ -817,7 +817,7 @@ _mesa_GetTexEnviv( GLenum target, GLenum pname, GLint *params ) ASSERT_OUTSIDE_BEGIN_END(ctx); maxUnit = (target == GL_POINT_SPRITE_NV && pname == GL_COORD_REPLACE_NV) - ? ctx->Const.MaxTextureCoordUnits : ctx->Const.MaxTextureImageUnits; + ? ctx->Const.MaxTextureCoordUnits : ctx->Const.MaxCombinedTextureImageUnits; if (ctx->Texture.CurrentUnit >= maxUnit) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexEnviv(current unit)"); return; diff --git a/mesalib/src/mesa/main/texfetch.c b/mesalib/src/mesa/main/texfetch.c index ab3abf657..72283eb68 100644 --- a/mesalib/src/mesa/main/texfetch.c +++ b/mesalib/src/mesa/main/texfetch.c @@ -1,1050 +1,1064 @@ -/*
- * Mesa 3-D graphics library
- * Version: 7.7
- *
- * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
- * Copyright (c) 2009 VMware, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-/**
- * \file texfetch.c
- *
- * Texel fetch/store functions
- *
- * \author Gareth Hughes
- */
-
-
-#include "colormac.h"
-#include "macros.h"
-#include "texcompress.h"
-#include "texcompress_fxt1.h"
-#include "texcompress_s3tc.h"
-#include "texcompress_rgtc.h"
-#include "texfetch.h"
-#include "teximage.h"
-#include "../../gallium/auxiliary/util/u_format_rgb9e5.h"
-#include "../../gallium/auxiliary/util/u_format_r11g11b10f.h"
-
-
-/**
- * Convert an 8-bit sRGB value from non-linear space to a
- * linear RGB value in [0, 1].
- * Implemented with a 256-entry lookup table.
- */
-static INLINE GLfloat
-nonlinear_to_linear(GLubyte cs8)
-{
- static GLfloat table[256];
- static GLboolean tableReady = GL_FALSE;
- if (!tableReady) {
- /* compute lookup table now */
- GLuint i;
- for (i = 0; i < 256; i++) {
- const GLfloat cs = UBYTE_TO_FLOAT(i);
- if (cs <= 0.04045) {
- table[i] = cs / 12.92f;
- }
- else {
- table[i] = (GLfloat) pow((cs + 0.055) / 1.055, 2.4);
- }
- }
- tableReady = GL_TRUE;
- }
- return table[cs8];
-}
-
-
-
-/* Texel fetch routines for all supported formats
- */
-#define DIM 1
-#include "texfetch_tmp.h"
-
-#define DIM 2
-#include "texfetch_tmp.h"
-
-#define DIM 3
-#include "texfetch_tmp.h"
-
-/**
- * Null texel fetch function.
- *
- * Have to have this so the FetchTexel function pointer is never NULL.
- */
-static void fetch_null_texelf( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- (void) texImage; (void) i; (void) j; (void) k;
- texel[RCOMP] = 0.0;
- texel[GCOMP] = 0.0;
- texel[BCOMP] = 0.0;
- texel[ACOMP] = 0.0;
- _mesa_warning(NULL, "fetch_null_texelf() called!");
-}
-
-static void store_null_texel(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- (void) texImage;
- (void) i;
- (void) j;
- (void) k;
- (void) texel;
- /* no-op */
-}
-
-
-
-/**
- * Table to map MESA_FORMAT_ to texel fetch/store funcs.
- * XXX this is somewhat temporary.
- */
-static struct {
- gl_format Name;
- FetchTexelFuncF Fetch1D;
- FetchTexelFuncF Fetch2D;
- FetchTexelFuncF Fetch3D;
- StoreTexelFunc StoreTexel;
-}
-texfetch_funcs[MESA_FORMAT_COUNT] =
-{
- {
- MESA_FORMAT_NONE,
- fetch_null_texelf,
- fetch_null_texelf,
- fetch_null_texelf,
- store_null_texel
- },
-
- {
- MESA_FORMAT_RGBA8888,
- fetch_texel_1d_f_rgba8888,
- fetch_texel_2d_f_rgba8888,
- fetch_texel_3d_f_rgba8888,
- store_texel_rgba8888
- },
- {
- MESA_FORMAT_RGBA8888_REV,
- fetch_texel_1d_f_rgba8888_rev,
- fetch_texel_2d_f_rgba8888_rev,
- fetch_texel_3d_f_rgba8888_rev,
- store_texel_rgba8888_rev
- },
- {
- MESA_FORMAT_ARGB8888,
- fetch_texel_1d_f_argb8888,
- fetch_texel_2d_f_argb8888,
- fetch_texel_3d_f_argb8888,
- store_texel_argb8888
- },
- {
- MESA_FORMAT_ARGB8888_REV,
- fetch_texel_1d_f_argb8888_rev,
- fetch_texel_2d_f_argb8888_rev,
- fetch_texel_3d_f_argb8888_rev,
- store_texel_argb8888_rev
- },
- {
- MESA_FORMAT_XRGB8888,
- fetch_texel_1d_f_xrgb8888,
- fetch_texel_2d_f_xrgb8888,
- fetch_texel_3d_f_xrgb8888,
- store_texel_xrgb8888
- },
- {
- MESA_FORMAT_XRGB8888_REV,
- fetch_texel_1d_f_xrgb8888_rev,
- fetch_texel_2d_f_xrgb8888_rev,
- fetch_texel_3d_f_xrgb8888_rev,
- store_texel_xrgb8888_rev,
- },
- {
- MESA_FORMAT_RGB888,
- fetch_texel_1d_f_rgb888,
- fetch_texel_2d_f_rgb888,
- fetch_texel_3d_f_rgb888,
- store_texel_rgb888
- },
- {
- MESA_FORMAT_BGR888,
- fetch_texel_1d_f_bgr888,
- fetch_texel_2d_f_bgr888,
- fetch_texel_3d_f_bgr888,
- store_texel_bgr888
- },
- {
- MESA_FORMAT_RGB565,
- fetch_texel_1d_f_rgb565,
- fetch_texel_2d_f_rgb565,
- fetch_texel_3d_f_rgb565,
- store_texel_rgb565
- },
- {
- MESA_FORMAT_RGB565_REV,
- fetch_texel_1d_f_rgb565_rev,
- fetch_texel_2d_f_rgb565_rev,
- fetch_texel_3d_f_rgb565_rev,
- store_texel_rgb565_rev
- },
- {
- MESA_FORMAT_ARGB4444,
- fetch_texel_1d_f_argb4444,
- fetch_texel_2d_f_argb4444,
- fetch_texel_3d_f_argb4444,
- store_texel_argb4444
- },
- {
- MESA_FORMAT_ARGB4444_REV,
- fetch_texel_1d_f_argb4444_rev,
- fetch_texel_2d_f_argb4444_rev,
- fetch_texel_3d_f_argb4444_rev,
- store_texel_argb4444_rev
- },
- {
- MESA_FORMAT_RGBA5551,
- fetch_texel_1d_f_rgba5551,
- fetch_texel_2d_f_rgba5551,
- fetch_texel_3d_f_rgba5551,
- store_texel_rgba5551
- },
- {
- MESA_FORMAT_ARGB1555,
- fetch_texel_1d_f_argb1555,
- fetch_texel_2d_f_argb1555,
- fetch_texel_3d_f_argb1555,
- store_texel_argb1555
- },
- {
- MESA_FORMAT_ARGB1555_REV,
- fetch_texel_1d_f_argb1555_rev,
- fetch_texel_2d_f_argb1555_rev,
- fetch_texel_3d_f_argb1555_rev,
- store_texel_argb1555_rev
- },
- {
- MESA_FORMAT_AL44,
- fetch_texel_1d_f_al44,
- fetch_texel_2d_f_al44,
- fetch_texel_3d_f_al44,
- store_texel_al44
- },
- {
- MESA_FORMAT_AL88,
- fetch_texel_1d_f_al88,
- fetch_texel_2d_f_al88,
- fetch_texel_3d_f_al88,
- store_texel_al88
- },
- {
- MESA_FORMAT_AL88_REV,
- fetch_texel_1d_f_al88_rev,
- fetch_texel_2d_f_al88_rev,
- fetch_texel_3d_f_al88_rev,
- store_texel_al88_rev
- },
- {
- MESA_FORMAT_AL1616,
- fetch_texel_1d_f_al1616,
- fetch_texel_2d_f_al1616,
- fetch_texel_3d_f_al1616,
- store_texel_al1616
- },
- {
- MESA_FORMAT_AL1616_REV,
- fetch_texel_1d_f_al1616_rev,
- fetch_texel_2d_f_al1616_rev,
- fetch_texel_3d_f_al1616_rev,
- store_texel_al1616_rev
- },
- {
- MESA_FORMAT_RGB332,
- fetch_texel_1d_f_rgb332,
- fetch_texel_2d_f_rgb332,
- fetch_texel_3d_f_rgb332,
- store_texel_rgb332
- },
- {
- MESA_FORMAT_A8,
- fetch_texel_1d_f_a8,
- fetch_texel_2d_f_a8,
- fetch_texel_3d_f_a8,
- store_texel_a8
- },
- {
- MESA_FORMAT_A16,
- fetch_texel_1d_f_a16,
- fetch_texel_2d_f_a16,
- fetch_texel_3d_f_a16,
- store_texel_a16
- },
- {
- MESA_FORMAT_L8,
- fetch_texel_1d_f_l8,
- fetch_texel_2d_f_l8,
- fetch_texel_3d_f_l8,
- store_texel_l8
- },
- {
- MESA_FORMAT_L16,
- fetch_texel_1d_f_l16,
- fetch_texel_2d_f_l16,
- fetch_texel_3d_f_l16,
- store_texel_l16
- },
- {
- MESA_FORMAT_I8,
- fetch_texel_1d_f_i8,
- fetch_texel_2d_f_i8,
- fetch_texel_3d_f_i8,
- store_texel_i8
- },
- {
- MESA_FORMAT_I16,
- fetch_texel_1d_f_i16,
- fetch_texel_2d_f_i16,
- fetch_texel_3d_f_i16,
- store_texel_i16
- },
- {
- MESA_FORMAT_CI8,
- fetch_texel_1d_f_ci8,
- fetch_texel_2d_f_ci8,
- fetch_texel_3d_f_ci8,
- store_texel_ci8
- },
- {
- MESA_FORMAT_YCBCR,
- fetch_texel_1d_f_ycbcr,
- fetch_texel_2d_f_ycbcr,
- fetch_texel_3d_f_ycbcr,
- store_texel_ycbcr
- },
- {
- MESA_FORMAT_YCBCR_REV,
- fetch_texel_1d_f_ycbcr_rev,
- fetch_texel_2d_f_ycbcr_rev,
- fetch_texel_3d_f_ycbcr_rev,
- store_texel_ycbcr_rev
- },
- {
- MESA_FORMAT_R8,
- fetch_texel_1d_f_r8,
- fetch_texel_2d_f_r8,
- fetch_texel_3d_f_r8,
- store_texel_r8,
- },
- {
- MESA_FORMAT_RG88,
- fetch_texel_1d_f_rg88,
- fetch_texel_2d_f_rg88,
- fetch_texel_3d_f_rg88,
- store_texel_rg88,
- },
- {
- MESA_FORMAT_RG88_REV,
- fetch_texel_1d_f_rg88_rev,
- fetch_texel_2d_f_rg88_rev,
- fetch_texel_3d_f_rg88_rev,
- store_texel_rg88_rev,
- },
- {
- MESA_FORMAT_R16,
- fetch_texel_1d_f_r16,
- fetch_texel_2d_f_r16,
- fetch_texel_3d_f_r16,
- store_texel_r16,
- },
- {
- MESA_FORMAT_RG1616,
- fetch_texel_1d_f_rg1616,
- fetch_texel_2d_f_rg1616,
- fetch_texel_3d_f_rg1616,
- store_texel_rg1616,
- },
- {
- MESA_FORMAT_RG1616_REV,
- fetch_texel_1d_f_rg1616_rev,
- fetch_texel_2d_f_rg1616_rev,
- fetch_texel_3d_f_rg1616_rev,
- store_texel_rg1616_rev,
- },
- {
- MESA_FORMAT_ARGB2101010,
- fetch_texel_1d_f_argb2101010,
- fetch_texel_2d_f_argb2101010,
- fetch_texel_3d_f_argb2101010,
- store_texel_argb2101010
- },
- {
- MESA_FORMAT_Z24_S8,
- fetch_texel_1d_f_z24_s8,
- fetch_texel_2d_f_z24_s8,
- fetch_texel_3d_f_z24_s8,
- store_texel_z24_s8
- },
- {
- MESA_FORMAT_S8_Z24,
- fetch_texel_1d_f_s8_z24,
- fetch_texel_2d_f_s8_z24,
- fetch_texel_3d_f_s8_z24,
- store_texel_s8_z24
- },
- {
- MESA_FORMAT_Z16,
- fetch_texel_1d_f_z16,
- fetch_texel_2d_f_z16,
- fetch_texel_3d_f_z16,
- store_texel_z16
- },
- {
- MESA_FORMAT_X8_Z24,
- fetch_texel_1d_f_s8_z24,
- fetch_texel_2d_f_s8_z24,
- fetch_texel_3d_f_s8_z24,
- store_texel_s8_z24
- },
- {
- MESA_FORMAT_Z24_X8,
- fetch_texel_1d_f_z24_s8,
- fetch_texel_2d_f_z24_s8,
- fetch_texel_3d_f_z24_s8,
- store_texel_z24_s8
- },
- {
- MESA_FORMAT_Z32,
- fetch_texel_1d_f_z32,
- fetch_texel_2d_f_z32,
- fetch_texel_3d_f_z32,
- store_texel_z32
- },
- {
- MESA_FORMAT_S8,
- NULL,
- NULL,
- NULL,
- NULL
- },
- {
- MESA_FORMAT_SRGB8,
- fetch_texel_1d_srgb8,
- fetch_texel_2d_srgb8,
- fetch_texel_3d_srgb8,
- store_texel_srgb8
- },
- {
- MESA_FORMAT_SRGBA8,
- fetch_texel_1d_srgba8,
- fetch_texel_2d_srgba8,
- fetch_texel_3d_srgba8,
- store_texel_srgba8
- },
- {
- MESA_FORMAT_SARGB8,
- fetch_texel_1d_sargb8,
- fetch_texel_2d_sargb8,
- fetch_texel_3d_sargb8,
- store_texel_sargb8
- },
- {
- MESA_FORMAT_SL8,
- fetch_texel_1d_sl8,
- fetch_texel_2d_sl8,
- fetch_texel_3d_sl8,
- store_texel_sl8
- },
- {
- MESA_FORMAT_SLA8,
- fetch_texel_1d_sla8,
- fetch_texel_2d_sla8,
- fetch_texel_3d_sla8,
- store_texel_sla8
- },
- {
- MESA_FORMAT_SRGB_DXT1,
- NULL,
- _mesa_fetch_texel_2d_f_srgb_dxt1,
- NULL,
- NULL
- },
- {
- MESA_FORMAT_SRGBA_DXT1,
- NULL,
- _mesa_fetch_texel_2d_f_srgba_dxt1,
- NULL,
- NULL
- },
- {
- MESA_FORMAT_SRGBA_DXT3,
- NULL,
- _mesa_fetch_texel_2d_f_srgba_dxt3,
- NULL,
- NULL
- },
- {
- MESA_FORMAT_SRGBA_DXT5,
- NULL,
- _mesa_fetch_texel_2d_f_srgba_dxt5,
- NULL,
- NULL
- },
-
- {
- MESA_FORMAT_RGB_FXT1,
- NULL,
- _mesa_fetch_texel_2d_f_rgb_fxt1,
- NULL,
- NULL
- },
- {
- MESA_FORMAT_RGBA_FXT1,
- NULL,
- _mesa_fetch_texel_2d_f_rgba_fxt1,
- NULL,
- NULL
- },
- {
- MESA_FORMAT_RGB_DXT1,
- NULL,
- _mesa_fetch_texel_2d_f_rgb_dxt1,
- NULL,
- NULL
- },
- {
- MESA_FORMAT_RGBA_DXT1,
- NULL,
- _mesa_fetch_texel_2d_f_rgba_dxt1,
- NULL,
- NULL
- },
- {
- MESA_FORMAT_RGBA_DXT3,
- NULL,
- _mesa_fetch_texel_2d_f_rgba_dxt3,
- NULL,
- NULL
- },
- {
- MESA_FORMAT_RGBA_DXT5,
- NULL,
- _mesa_fetch_texel_2d_f_rgba_dxt5,
- NULL,
- NULL
- },
- {
- MESA_FORMAT_RGBA_FLOAT32,
- fetch_texel_1d_f_rgba_f32,
- fetch_texel_2d_f_rgba_f32,
- fetch_texel_3d_f_rgba_f32,
- store_texel_rgba_f32
- },
- {
- MESA_FORMAT_RGBA_FLOAT16,
- fetch_texel_1d_f_rgba_f16,
- fetch_texel_2d_f_rgba_f16,
- fetch_texel_3d_f_rgba_f16,
- store_texel_rgba_f16
- },
- {
- MESA_FORMAT_RGB_FLOAT32,
- fetch_texel_1d_f_rgb_f32,
- fetch_texel_2d_f_rgb_f32,
- fetch_texel_3d_f_rgb_f32,
- store_texel_rgb_f32
- },
- {
- MESA_FORMAT_RGB_FLOAT16,
- fetch_texel_1d_f_rgb_f16,
- fetch_texel_2d_f_rgb_f16,
- fetch_texel_3d_f_rgb_f16,
- store_texel_rgb_f16
- },
- {
- MESA_FORMAT_ALPHA_FLOAT32,
- fetch_texel_1d_f_alpha_f32,
- fetch_texel_2d_f_alpha_f32,
- fetch_texel_3d_f_alpha_f32,
- store_texel_alpha_f32
- },
- {
- MESA_FORMAT_ALPHA_FLOAT16,
- fetch_texel_1d_f_alpha_f16,
- fetch_texel_2d_f_alpha_f16,
- fetch_texel_3d_f_alpha_f16,
- store_texel_alpha_f16
- },
- {
- MESA_FORMAT_LUMINANCE_FLOAT32,
- fetch_texel_1d_f_luminance_f32,
- fetch_texel_2d_f_luminance_f32,
- fetch_texel_3d_f_luminance_f32,
- store_texel_luminance_f32
- },
- {
- MESA_FORMAT_LUMINANCE_FLOAT16,
- fetch_texel_1d_f_luminance_f16,
- fetch_texel_2d_f_luminance_f16,
- fetch_texel_3d_f_luminance_f16,
- store_texel_luminance_f16
- },
- {
- MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32,
- fetch_texel_1d_f_luminance_alpha_f32,
- fetch_texel_2d_f_luminance_alpha_f32,
- fetch_texel_3d_f_luminance_alpha_f32,
- store_texel_luminance_alpha_f32
- },
- {
- MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16,
- fetch_texel_1d_f_luminance_alpha_f16,
- fetch_texel_2d_f_luminance_alpha_f16,
- fetch_texel_3d_f_luminance_alpha_f16,
- store_texel_luminance_alpha_f16
- },
- {
- MESA_FORMAT_INTENSITY_FLOAT32,
- fetch_texel_1d_f_intensity_f32,
- fetch_texel_2d_f_intensity_f32,
- fetch_texel_3d_f_intensity_f32,
- store_texel_intensity_f32
- },
- {
- MESA_FORMAT_INTENSITY_FLOAT16,
- fetch_texel_1d_f_intensity_f16,
- fetch_texel_2d_f_intensity_f16,
- fetch_texel_3d_f_intensity_f16,
- store_texel_intensity_f16
- },
- {
- MESA_FORMAT_R_FLOAT32,
- fetch_texel_1d_f_r_f32,
- fetch_texel_2d_f_r_f32,
- fetch_texel_3d_f_r_f32,
- store_texel_r_f32
- },
- {
- MESA_FORMAT_R_FLOAT16,
- fetch_texel_1d_f_r_f16,
- fetch_texel_2d_f_r_f16,
- fetch_texel_3d_f_r_f16,
- store_texel_r_f16
- },
- {
- MESA_FORMAT_RG_FLOAT32,
- fetch_texel_1d_f_rg_f32,
- fetch_texel_2d_f_rg_f32,
- fetch_texel_3d_f_rg_f32,
- store_texel_rg_f32
- },
- {
- MESA_FORMAT_RG_FLOAT16,
- fetch_texel_1d_f_rg_f16,
- fetch_texel_2d_f_rg_f16,
- fetch_texel_3d_f_rg_f16,
- store_texel_rg_f16
- },
-
- /* non-normalized, signed int */
- {
- MESA_FORMAT_RGBA_INT8,
- fetch_texel_1d_rgba_int8,
- fetch_texel_2d_rgba_int8,
- fetch_texel_3d_rgba_int8,
- store_texel_rgba_int8
- },
- {
- MESA_FORMAT_RGBA_INT16,
- fetch_texel_1d_rgba_int16,
- fetch_texel_2d_rgba_int16,
- fetch_texel_3d_rgba_int16,
- store_texel_rgba_int16
- },
- {
- MESA_FORMAT_RGBA_INT32,
- fetch_texel_1d_rgba_int32,
- fetch_texel_2d_rgba_int32,
- fetch_texel_3d_rgba_int32,
- store_texel_rgba_int32
- },
-
- /* non-normalized, unsigned int */
- {
- MESA_FORMAT_RGBA_UINT8,
- fetch_texel_1d_rgba_uint8,
- fetch_texel_2d_rgba_uint8,
- fetch_texel_3d_rgba_uint8,
- store_texel_rgba_uint8
- },
- {
- MESA_FORMAT_RGBA_UINT16,
- fetch_texel_1d_rgba_uint16,
- fetch_texel_2d_rgba_uint16,
- fetch_texel_3d_rgba_uint16,
- store_texel_rgba_uint16
- },
- {
- MESA_FORMAT_RGBA_UINT32,
- fetch_texel_1d_rgba_uint32,
- fetch_texel_2d_rgba_uint32,
- fetch_texel_3d_rgba_uint32,
- store_texel_rgba_uint32
- },
-
- /* dudv */
- {
- MESA_FORMAT_DUDV8,
- fetch_texel_1d_dudv8,
- fetch_texel_2d_dudv8,
- fetch_texel_3d_dudv8,
- NULL
- },
-
- /* signed, normalized */
- {
- MESA_FORMAT_SIGNED_R8,
- fetch_texel_1d_signed_r8,
- fetch_texel_2d_signed_r8,
- fetch_texel_3d_signed_r8,
- store_texel_signed_r8
- },
- {
- MESA_FORMAT_SIGNED_RG88_REV,
- fetch_texel_1d_signed_rg88_rev,
- fetch_texel_2d_signed_rg88_rev,
- fetch_texel_3d_signed_rg88_rev,
- store_texel_signed_rg88_rev
- },
- {
- MESA_FORMAT_SIGNED_RGBX8888,
- fetch_texel_1d_signed_rgbx8888,
- fetch_texel_2d_signed_rgbx8888,
- fetch_texel_3d_signed_rgbx8888,
- store_texel_signed_rgbx8888
- },
- {
- MESA_FORMAT_SIGNED_RGBA8888,
- fetch_texel_1d_signed_rgba8888,
- fetch_texel_2d_signed_rgba8888,
- fetch_texel_3d_signed_rgba8888,
- store_texel_signed_rgba8888
- },
- {
- MESA_FORMAT_SIGNED_RGBA8888_REV,
- fetch_texel_1d_signed_rgba8888_rev,
- fetch_texel_2d_signed_rgba8888_rev,
- fetch_texel_3d_signed_rgba8888_rev,
- store_texel_signed_rgba8888_rev
- },
- {
- MESA_FORMAT_SIGNED_R16,
- fetch_texel_1d_signed_r16,
- fetch_texel_2d_signed_r16,
- fetch_texel_3d_signed_r16,
- store_texel_signed_r16
- },
- {
- MESA_FORMAT_SIGNED_GR1616,
- fetch_texel_1d_signed_rg1616,
- fetch_texel_2d_signed_rg1616,
- fetch_texel_3d_signed_rg1616,
- store_texel_signed_rg1616
- },
- {
- MESA_FORMAT_SIGNED_RGB_16,
- fetch_texel_1d_signed_rgb_16,
- fetch_texel_2d_signed_rgb_16,
- fetch_texel_3d_signed_rgb_16,
- store_texel_signed_rgb_16
- },
- {
- MESA_FORMAT_SIGNED_RGBA_16,
- fetch_texel_1d_signed_rgba_16,
- fetch_texel_2d_signed_rgba_16,
- fetch_texel_3d_signed_rgba_16,
- store_texel_signed_rgba_16
- },
- {
- MESA_FORMAT_RGBA_16,
- fetch_texel_1d_rgba_16,
- fetch_texel_2d_rgba_16,
- fetch_texel_3d_rgba_16,
- store_texel_rgba_16
- },
- {
- MESA_FORMAT_RED_RGTC1,
- NULL,
- _mesa_fetch_texel_2d_f_red_rgtc1,
- NULL,
- NULL
- },
- {
- MESA_FORMAT_SIGNED_RED_RGTC1,
- NULL,
- _mesa_fetch_texel_2d_f_signed_red_rgtc1,
- NULL,
- NULL
- },
- {
- MESA_FORMAT_RG_RGTC2,
- NULL,
- _mesa_fetch_texel_2d_f_rg_rgtc2,
- NULL,
- NULL
- },
- {
- MESA_FORMAT_SIGNED_RG_RGTC2,
- NULL,
- _mesa_fetch_texel_2d_f_signed_rg_rgtc2,
- NULL,
- NULL
- },
- {
- MESA_FORMAT_L_LATC1,
- NULL,
- _mesa_fetch_texel_2d_f_l_latc1,
- NULL,
- NULL
- },
- {
- MESA_FORMAT_SIGNED_L_LATC1,
- NULL,
- _mesa_fetch_texel_2d_f_signed_l_latc1,
- NULL,
- NULL
- },
- {
- MESA_FORMAT_LA_LATC2,
- NULL,
- _mesa_fetch_texel_2d_f_la_latc2,
- NULL,
- NULL
- },
- {
- MESA_FORMAT_SIGNED_LA_LATC2,
- NULL,
- _mesa_fetch_texel_2d_f_signed_la_latc2,
- NULL,
- NULL
- },
- {
- MESA_FORMAT_SIGNED_A8,
- fetch_texel_1d_signed_a8,
- fetch_texel_2d_signed_a8,
- fetch_texel_3d_signed_a8,
- store_texel_signed_a8
- },
- {
- MESA_FORMAT_SIGNED_L8,
- fetch_texel_1d_signed_l8,
- fetch_texel_2d_signed_l8,
- fetch_texel_3d_signed_l8,
- store_texel_signed_l8
- },
- {
- MESA_FORMAT_SIGNED_AL88,
- fetch_texel_1d_signed_al88,
- fetch_texel_2d_signed_al88,
- fetch_texel_3d_signed_al88,
- store_texel_signed_al88
- },
- {
- MESA_FORMAT_SIGNED_I8,
- fetch_texel_1d_signed_i8,
- fetch_texel_2d_signed_i8,
- fetch_texel_3d_signed_i8,
- store_texel_signed_i8
- },
- {
- MESA_FORMAT_SIGNED_A16,
- fetch_texel_1d_signed_a16,
- fetch_texel_2d_signed_a16,
- fetch_texel_3d_signed_a16,
- store_texel_signed_a16
- },
- {
- MESA_FORMAT_SIGNED_L16,
- fetch_texel_1d_signed_l16,
- fetch_texel_2d_signed_l16,
- fetch_texel_3d_signed_l16,
- store_texel_signed_l16
- },
- {
- MESA_FORMAT_SIGNED_AL1616,
- fetch_texel_1d_signed_al1616,
- fetch_texel_2d_signed_al1616,
- fetch_texel_3d_signed_al1616,
- store_texel_signed_al1616
- },
- {
- MESA_FORMAT_SIGNED_I16,
- fetch_texel_1d_signed_i16,
- fetch_texel_2d_signed_i16,
- fetch_texel_3d_signed_i16,
- store_texel_signed_i16
- },
- {
- MESA_FORMAT_RGB9_E5_FLOAT,
- fetch_texel_1d_rgb9_e5,
- fetch_texel_2d_rgb9_e5,
- fetch_texel_3d_rgb9_e5,
- store_texel_rgb9_e5
- },
- {
- MESA_FORMAT_R11_G11_B10_FLOAT,
- fetch_texel_1d_r11_g11_b10f,
- fetch_texel_2d_r11_g11_b10f,
- fetch_texel_3d_r11_g11_b10f,
- store_texel_r11_g11_b10f
- }
-};
-
-
-FetchTexelFuncF
-_mesa_get_texel_fetch_func(gl_format format, GLuint dims)
-{
-#ifdef DEBUG
- /* check that the table entries are sorted by format name */
- gl_format fmt;
- for (fmt = 0; fmt < MESA_FORMAT_COUNT; fmt++) {
- assert(texfetch_funcs[fmt].Name == fmt);
- }
-#endif
-
- assert(Elements(texfetch_funcs) == MESA_FORMAT_COUNT);
- assert(format < MESA_FORMAT_COUNT);
-
- switch (dims) {
- case 1:
- return texfetch_funcs[format].Fetch1D;
- case 2:
- return texfetch_funcs[format].Fetch2D;
- case 3:
- return texfetch_funcs[format].Fetch3D;
- default:
- assert(0 && "bad dims in _mesa_get_texel_fetch_func");
- return NULL;
- }
-}
-
-
-StoreTexelFunc
-_mesa_get_texel_store_func(gl_format format)
-{
- assert(format < MESA_FORMAT_COUNT);
- return texfetch_funcs[format].StoreTexel;
-}
-
-
-/**
- * Adaptor for fetching a GLchan texel from a float-valued texture.
- */
-static void
-fetch_texel_float_to_chan(const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLchan *texelOut)
-{
- GLfloat temp[4];
- GLenum baseFormat = _mesa_get_format_base_format(texImage->TexFormat);
-
- ASSERT(texImage->FetchTexelf);
- texImage->FetchTexelf(texImage, i, j, k, temp);
- if (baseFormat == GL_DEPTH_COMPONENT ||
- baseFormat == GL_DEPTH_STENCIL_EXT) {
- /* just one channel */
- UNCLAMPED_FLOAT_TO_CHAN(texelOut[0], temp[0]);
- }
- else {
- /* four channels */
- UNCLAMPED_FLOAT_TO_CHAN(texelOut[0], temp[0]);
- UNCLAMPED_FLOAT_TO_CHAN(texelOut[1], temp[1]);
- UNCLAMPED_FLOAT_TO_CHAN(texelOut[2], temp[2]);
- UNCLAMPED_FLOAT_TO_CHAN(texelOut[3], temp[3]);
- }
-}
-
-
-#if 0
-/**
- * Adaptor for fetching a float texel from a GLchan-valued texture.
- */
-static void
-fetch_texel_chan_to_float(const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texelOut)
-{
- GLchan temp[4];
- GLenum baseFormat = _mesa_get_format_base_format(texImage->TexFormat);
-
- ASSERT(texImage->FetchTexelc);
- texImage->FetchTexelc(texImage, i, j, k, temp);
- if (baseFormat == GL_DEPTH_COMPONENT ||
- baseFormat == GL_DEPTH_STENCIL_EXT) {
- /* just one channel */
- texelOut[0] = CHAN_TO_FLOAT(temp[0]);
- }
- else {
- /* four channels */
- texelOut[0] = CHAN_TO_FLOAT(temp[0]);
- texelOut[1] = CHAN_TO_FLOAT(temp[1]);
- texelOut[2] = CHAN_TO_FLOAT(temp[2]);
- texelOut[3] = CHAN_TO_FLOAT(temp[3]);
- }
-}
-#endif
-
-
-/**
- * Initialize the texture image's FetchTexelc and FetchTexelf methods.
- */
-void
-_mesa_set_fetch_functions(struct gl_texture_image *texImage, GLuint dims)
-{
- gl_format format = texImage->TexFormat;
-
- ASSERT(dims == 1 || dims == 2 || dims == 3);
-
- if (texImage->TexObject->Sampler.sRGBDecode == GL_SKIP_DECODE_EXT &&
- _mesa_get_format_color_encoding(format) == GL_SRGB) {
- format = _mesa_get_srgb_format_linear(format);
- }
-
- texImage->FetchTexelf = _mesa_get_texel_fetch_func(format, dims);
-
- texImage->FetchTexelc = fetch_texel_float_to_chan;
-
- ASSERT(texImage->FetchTexelc);
- ASSERT(texImage->FetchTexelf);
-}
-
-void
-_mesa_update_fetch_functions(struct gl_texture_object *texObj)
-{
- GLuint face, i;
- GLuint dims;
-
- dims = _mesa_get_texture_dimensions(texObj->Target);
-
- for (face = 0; face < 6; face++) {
- for (i = 0; i < MAX_TEXTURE_LEVELS; i++) {
- if (texObj->Image[face][i]) {
- _mesa_set_fetch_functions(texObj->Image[face][i], dims);
- }
- }
- }
-}
+/* + * Mesa 3-D graphics library + * Version: 7.7 + * + * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. + * Copyright (c) 2009 VMware, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +/** + * \file texfetch.c + * + * Texel fetch/store functions + * + * \author Gareth Hughes + */ + + +#include "colormac.h" +#include "macros.h" +#include "texcompress.h" +#include "texcompress_fxt1.h" +#include "texcompress_s3tc.h" +#include "texcompress_rgtc.h" +#include "texfetch.h" +#include "teximage.h" +#include "../../gallium/auxiliary/util/u_format_rgb9e5.h" +#include "../../gallium/auxiliary/util/u_format_r11g11b10f.h" + + +/** + * Convert an 8-bit sRGB value from non-linear space to a + * linear RGB value in [0, 1]. + * Implemented with a 256-entry lookup table. + */ +static INLINE GLfloat +nonlinear_to_linear(GLubyte cs8) +{ + static GLfloat table[256]; + static GLboolean tableReady = GL_FALSE; + if (!tableReady) { + /* compute lookup table now */ + GLuint i; + for (i = 0; i < 256; i++) { + const GLfloat cs = UBYTE_TO_FLOAT(i); + if (cs <= 0.04045) { + table[i] = cs / 12.92f; + } + else { + table[i] = (GLfloat) pow((cs + 0.055) / 1.055, 2.4); + } + } + tableReady = GL_TRUE; + } + return table[cs8]; +} + + + +/* Texel fetch routines for all supported formats + */ +#define DIM 1 +#include "texfetch_tmp.h" + +#define DIM 2 +#include "texfetch_tmp.h" + +#define DIM 3 +#include "texfetch_tmp.h" + +/** + * Null texel fetch function. + * + * Have to have this so the FetchTexel function pointer is never NULL. + */ +static void fetch_null_texelf( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + (void) texImage; (void) i; (void) j; (void) k; + texel[RCOMP] = 0.0; + texel[GCOMP] = 0.0; + texel[BCOMP] = 0.0; + texel[ACOMP] = 0.0; + _mesa_warning(NULL, "fetch_null_texelf() called!"); +} + +static void store_null_texel(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + (void) texImage; + (void) i; + (void) j; + (void) k; + (void) texel; + /* no-op */ +} + + + +/** + * Table to map MESA_FORMAT_ to texel fetch/store funcs. + * XXX this is somewhat temporary. + */ +static struct { + gl_format Name; + FetchTexelFuncF Fetch1D; + FetchTexelFuncF Fetch2D; + FetchTexelFuncF Fetch3D; + StoreTexelFunc StoreTexel; +} +texfetch_funcs[MESA_FORMAT_COUNT] = +{ + { + MESA_FORMAT_NONE, + fetch_null_texelf, + fetch_null_texelf, + fetch_null_texelf, + store_null_texel + }, + + { + MESA_FORMAT_RGBA8888, + fetch_texel_1d_f_rgba8888, + fetch_texel_2d_f_rgba8888, + fetch_texel_3d_f_rgba8888, + store_texel_rgba8888 + }, + { + MESA_FORMAT_RGBA8888_REV, + fetch_texel_1d_f_rgba8888_rev, + fetch_texel_2d_f_rgba8888_rev, + fetch_texel_3d_f_rgba8888_rev, + store_texel_rgba8888_rev + }, + { + MESA_FORMAT_ARGB8888, + fetch_texel_1d_f_argb8888, + fetch_texel_2d_f_argb8888, + fetch_texel_3d_f_argb8888, + store_texel_argb8888 + }, + { + MESA_FORMAT_ARGB8888_REV, + fetch_texel_1d_f_argb8888_rev, + fetch_texel_2d_f_argb8888_rev, + fetch_texel_3d_f_argb8888_rev, + store_texel_argb8888_rev + }, + { + MESA_FORMAT_XRGB8888, + fetch_texel_1d_f_xrgb8888, + fetch_texel_2d_f_xrgb8888, + fetch_texel_3d_f_xrgb8888, + store_texel_xrgb8888 + }, + { + MESA_FORMAT_XRGB8888_REV, + fetch_texel_1d_f_xrgb8888_rev, + fetch_texel_2d_f_xrgb8888_rev, + fetch_texel_3d_f_xrgb8888_rev, + store_texel_xrgb8888_rev, + }, + { + MESA_FORMAT_RGB888, + fetch_texel_1d_f_rgb888, + fetch_texel_2d_f_rgb888, + fetch_texel_3d_f_rgb888, + store_texel_rgb888 + }, + { + MESA_FORMAT_BGR888, + fetch_texel_1d_f_bgr888, + fetch_texel_2d_f_bgr888, + fetch_texel_3d_f_bgr888, + store_texel_bgr888 + }, + { + MESA_FORMAT_RGB565, + fetch_texel_1d_f_rgb565, + fetch_texel_2d_f_rgb565, + fetch_texel_3d_f_rgb565, + store_texel_rgb565 + }, + { + MESA_FORMAT_RGB565_REV, + fetch_texel_1d_f_rgb565_rev, + fetch_texel_2d_f_rgb565_rev, + fetch_texel_3d_f_rgb565_rev, + store_texel_rgb565_rev + }, + { + MESA_FORMAT_ARGB4444, + fetch_texel_1d_f_argb4444, + fetch_texel_2d_f_argb4444, + fetch_texel_3d_f_argb4444, + store_texel_argb4444 + }, + { + MESA_FORMAT_ARGB4444_REV, + fetch_texel_1d_f_argb4444_rev, + fetch_texel_2d_f_argb4444_rev, + fetch_texel_3d_f_argb4444_rev, + store_texel_argb4444_rev + }, + { + MESA_FORMAT_RGBA5551, + fetch_texel_1d_f_rgba5551, + fetch_texel_2d_f_rgba5551, + fetch_texel_3d_f_rgba5551, + store_texel_rgba5551 + }, + { + MESA_FORMAT_ARGB1555, + fetch_texel_1d_f_argb1555, + fetch_texel_2d_f_argb1555, + fetch_texel_3d_f_argb1555, + store_texel_argb1555 + }, + { + MESA_FORMAT_ARGB1555_REV, + fetch_texel_1d_f_argb1555_rev, + fetch_texel_2d_f_argb1555_rev, + fetch_texel_3d_f_argb1555_rev, + store_texel_argb1555_rev + }, + { + MESA_FORMAT_AL44, + fetch_texel_1d_f_al44, + fetch_texel_2d_f_al44, + fetch_texel_3d_f_al44, + store_texel_al44 + }, + { + MESA_FORMAT_AL88, + fetch_texel_1d_f_al88, + fetch_texel_2d_f_al88, + fetch_texel_3d_f_al88, + store_texel_al88 + }, + { + MESA_FORMAT_AL88_REV, + fetch_texel_1d_f_al88_rev, + fetch_texel_2d_f_al88_rev, + fetch_texel_3d_f_al88_rev, + store_texel_al88_rev + }, + { + MESA_FORMAT_AL1616, + fetch_texel_1d_f_al1616, + fetch_texel_2d_f_al1616, + fetch_texel_3d_f_al1616, + store_texel_al1616 + }, + { + MESA_FORMAT_AL1616_REV, + fetch_texel_1d_f_al1616_rev, + fetch_texel_2d_f_al1616_rev, + fetch_texel_3d_f_al1616_rev, + store_texel_al1616_rev + }, + { + MESA_FORMAT_RGB332, + fetch_texel_1d_f_rgb332, + fetch_texel_2d_f_rgb332, + fetch_texel_3d_f_rgb332, + store_texel_rgb332 + }, + { + MESA_FORMAT_A8, + fetch_texel_1d_f_a8, + fetch_texel_2d_f_a8, + fetch_texel_3d_f_a8, + store_texel_a8 + }, + { + MESA_FORMAT_A16, + fetch_texel_1d_f_a16, + fetch_texel_2d_f_a16, + fetch_texel_3d_f_a16, + store_texel_a16 + }, + { + MESA_FORMAT_L8, + fetch_texel_1d_f_l8, + fetch_texel_2d_f_l8, + fetch_texel_3d_f_l8, + store_texel_l8 + }, + { + MESA_FORMAT_L16, + fetch_texel_1d_f_l16, + fetch_texel_2d_f_l16, + fetch_texel_3d_f_l16, + store_texel_l16 + }, + { + MESA_FORMAT_I8, + fetch_texel_1d_f_i8, + fetch_texel_2d_f_i8, + fetch_texel_3d_f_i8, + store_texel_i8 + }, + { + MESA_FORMAT_I16, + fetch_texel_1d_f_i16, + fetch_texel_2d_f_i16, + fetch_texel_3d_f_i16, + store_texel_i16 + }, + { + MESA_FORMAT_CI8, + fetch_texel_1d_f_ci8, + fetch_texel_2d_f_ci8, + fetch_texel_3d_f_ci8, + store_texel_ci8 + }, + { + MESA_FORMAT_YCBCR, + fetch_texel_1d_f_ycbcr, + fetch_texel_2d_f_ycbcr, + fetch_texel_3d_f_ycbcr, + store_texel_ycbcr + }, + { + MESA_FORMAT_YCBCR_REV, + fetch_texel_1d_f_ycbcr_rev, + fetch_texel_2d_f_ycbcr_rev, + fetch_texel_3d_f_ycbcr_rev, + store_texel_ycbcr_rev + }, + { + MESA_FORMAT_R8, + fetch_texel_1d_f_r8, + fetch_texel_2d_f_r8, + fetch_texel_3d_f_r8, + store_texel_r8, + }, + { + MESA_FORMAT_RG88, + fetch_texel_1d_f_rg88, + fetch_texel_2d_f_rg88, + fetch_texel_3d_f_rg88, + store_texel_rg88, + }, + { + MESA_FORMAT_RG88_REV, + fetch_texel_1d_f_rg88_rev, + fetch_texel_2d_f_rg88_rev, + fetch_texel_3d_f_rg88_rev, + store_texel_rg88_rev, + }, + { + MESA_FORMAT_R16, + fetch_texel_1d_f_r16, + fetch_texel_2d_f_r16, + fetch_texel_3d_f_r16, + store_texel_r16, + }, + { + MESA_FORMAT_RG1616, + fetch_texel_1d_f_rg1616, + fetch_texel_2d_f_rg1616, + fetch_texel_3d_f_rg1616, + store_texel_rg1616, + }, + { + MESA_FORMAT_RG1616_REV, + fetch_texel_1d_f_rg1616_rev, + fetch_texel_2d_f_rg1616_rev, + fetch_texel_3d_f_rg1616_rev, + store_texel_rg1616_rev, + }, + { + MESA_FORMAT_ARGB2101010, + fetch_texel_1d_f_argb2101010, + fetch_texel_2d_f_argb2101010, + fetch_texel_3d_f_argb2101010, + store_texel_argb2101010 + }, + { + MESA_FORMAT_Z24_S8, + fetch_texel_1d_f_z24_s8, + fetch_texel_2d_f_z24_s8, + fetch_texel_3d_f_z24_s8, + store_texel_z24_s8 + }, + { + MESA_FORMAT_S8_Z24, + fetch_texel_1d_f_s8_z24, + fetch_texel_2d_f_s8_z24, + fetch_texel_3d_f_s8_z24, + store_texel_s8_z24 + }, + { + MESA_FORMAT_Z16, + fetch_texel_1d_f_z16, + fetch_texel_2d_f_z16, + fetch_texel_3d_f_z16, + store_texel_z16 + }, + { + MESA_FORMAT_X8_Z24, + fetch_texel_1d_f_s8_z24, + fetch_texel_2d_f_s8_z24, + fetch_texel_3d_f_s8_z24, + store_texel_s8_z24 + }, + { + MESA_FORMAT_Z24_X8, + fetch_texel_1d_f_z24_s8, + fetch_texel_2d_f_z24_s8, + fetch_texel_3d_f_z24_s8, + store_texel_z24_s8 + }, + { + MESA_FORMAT_Z32, + fetch_texel_1d_f_z32, + fetch_texel_2d_f_z32, + fetch_texel_3d_f_z32, + store_texel_z32 + }, + { + MESA_FORMAT_S8, + NULL, + NULL, + NULL, + NULL + }, + { + MESA_FORMAT_SRGB8, + fetch_texel_1d_srgb8, + fetch_texel_2d_srgb8, + fetch_texel_3d_srgb8, + store_texel_srgb8 + }, + { + MESA_FORMAT_SRGBA8, + fetch_texel_1d_srgba8, + fetch_texel_2d_srgba8, + fetch_texel_3d_srgba8, + store_texel_srgba8 + }, + { + MESA_FORMAT_SARGB8, + fetch_texel_1d_sargb8, + fetch_texel_2d_sargb8, + fetch_texel_3d_sargb8, + store_texel_sargb8 + }, + { + MESA_FORMAT_SL8, + fetch_texel_1d_sl8, + fetch_texel_2d_sl8, + fetch_texel_3d_sl8, + store_texel_sl8 + }, + { + MESA_FORMAT_SLA8, + fetch_texel_1d_sla8, + fetch_texel_2d_sla8, + fetch_texel_3d_sla8, + store_texel_sla8 + }, + { + MESA_FORMAT_SRGB_DXT1, + NULL, + _mesa_fetch_texel_2d_f_srgb_dxt1, + NULL, + NULL + }, + { + MESA_FORMAT_SRGBA_DXT1, + NULL, + _mesa_fetch_texel_2d_f_srgba_dxt1, + NULL, + NULL + }, + { + MESA_FORMAT_SRGBA_DXT3, + NULL, + _mesa_fetch_texel_2d_f_srgba_dxt3, + NULL, + NULL + }, + { + MESA_FORMAT_SRGBA_DXT5, + NULL, + _mesa_fetch_texel_2d_f_srgba_dxt5, + NULL, + NULL + }, + + { + MESA_FORMAT_RGB_FXT1, + NULL, + _mesa_fetch_texel_2d_f_rgb_fxt1, + NULL, + NULL + }, + { + MESA_FORMAT_RGBA_FXT1, + NULL, + _mesa_fetch_texel_2d_f_rgba_fxt1, + NULL, + NULL + }, + { + MESA_FORMAT_RGB_DXT1, + NULL, + _mesa_fetch_texel_2d_f_rgb_dxt1, + NULL, + NULL + }, + { + MESA_FORMAT_RGBA_DXT1, + NULL, + _mesa_fetch_texel_2d_f_rgba_dxt1, + NULL, + NULL + }, + { + MESA_FORMAT_RGBA_DXT3, + NULL, + _mesa_fetch_texel_2d_f_rgba_dxt3, + NULL, + NULL + }, + { + MESA_FORMAT_RGBA_DXT5, + NULL, + _mesa_fetch_texel_2d_f_rgba_dxt5, + NULL, + NULL + }, + { + MESA_FORMAT_RGBA_FLOAT32, + fetch_texel_1d_f_rgba_f32, + fetch_texel_2d_f_rgba_f32, + fetch_texel_3d_f_rgba_f32, + store_texel_rgba_f32 + }, + { + MESA_FORMAT_RGBA_FLOAT16, + fetch_texel_1d_f_rgba_f16, + fetch_texel_2d_f_rgba_f16, + fetch_texel_3d_f_rgba_f16, + store_texel_rgba_f16 + }, + { + MESA_FORMAT_RGB_FLOAT32, + fetch_texel_1d_f_rgb_f32, + fetch_texel_2d_f_rgb_f32, + fetch_texel_3d_f_rgb_f32, + store_texel_rgb_f32 + }, + { + MESA_FORMAT_RGB_FLOAT16, + fetch_texel_1d_f_rgb_f16, + fetch_texel_2d_f_rgb_f16, + fetch_texel_3d_f_rgb_f16, + store_texel_rgb_f16 + }, + { + MESA_FORMAT_ALPHA_FLOAT32, + fetch_texel_1d_f_alpha_f32, + fetch_texel_2d_f_alpha_f32, + fetch_texel_3d_f_alpha_f32, + store_texel_alpha_f32 + }, + { + MESA_FORMAT_ALPHA_FLOAT16, + fetch_texel_1d_f_alpha_f16, + fetch_texel_2d_f_alpha_f16, + fetch_texel_3d_f_alpha_f16, + store_texel_alpha_f16 + }, + { + MESA_FORMAT_LUMINANCE_FLOAT32, + fetch_texel_1d_f_luminance_f32, + fetch_texel_2d_f_luminance_f32, + fetch_texel_3d_f_luminance_f32, + store_texel_luminance_f32 + }, + { + MESA_FORMAT_LUMINANCE_FLOAT16, + fetch_texel_1d_f_luminance_f16, + fetch_texel_2d_f_luminance_f16, + fetch_texel_3d_f_luminance_f16, + store_texel_luminance_f16 + }, + { + MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32, + fetch_texel_1d_f_luminance_alpha_f32, + fetch_texel_2d_f_luminance_alpha_f32, + fetch_texel_3d_f_luminance_alpha_f32, + store_texel_luminance_alpha_f32 + }, + { + MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16, + fetch_texel_1d_f_luminance_alpha_f16, + fetch_texel_2d_f_luminance_alpha_f16, + fetch_texel_3d_f_luminance_alpha_f16, + store_texel_luminance_alpha_f16 + }, + { + MESA_FORMAT_INTENSITY_FLOAT32, + fetch_texel_1d_f_intensity_f32, + fetch_texel_2d_f_intensity_f32, + fetch_texel_3d_f_intensity_f32, + store_texel_intensity_f32 + }, + { + MESA_FORMAT_INTENSITY_FLOAT16, + fetch_texel_1d_f_intensity_f16, + fetch_texel_2d_f_intensity_f16, + fetch_texel_3d_f_intensity_f16, + store_texel_intensity_f16 + }, + { + MESA_FORMAT_R_FLOAT32, + fetch_texel_1d_f_r_f32, + fetch_texel_2d_f_r_f32, + fetch_texel_3d_f_r_f32, + store_texel_r_f32 + }, + { + MESA_FORMAT_R_FLOAT16, + fetch_texel_1d_f_r_f16, + fetch_texel_2d_f_r_f16, + fetch_texel_3d_f_r_f16, + store_texel_r_f16 + }, + { + MESA_FORMAT_RG_FLOAT32, + fetch_texel_1d_f_rg_f32, + fetch_texel_2d_f_rg_f32, + fetch_texel_3d_f_rg_f32, + store_texel_rg_f32 + }, + { + MESA_FORMAT_RG_FLOAT16, + fetch_texel_1d_f_rg_f16, + fetch_texel_2d_f_rg_f16, + fetch_texel_3d_f_rg_f16, + store_texel_rg_f16 + }, + + /* non-normalized, signed int */ + { + MESA_FORMAT_RGBA_INT8, + fetch_texel_1d_rgba_int8, + fetch_texel_2d_rgba_int8, + fetch_texel_3d_rgba_int8, + store_texel_rgba_int8 + }, + { + MESA_FORMAT_RGBA_INT16, + fetch_texel_1d_rgba_int16, + fetch_texel_2d_rgba_int16, + fetch_texel_3d_rgba_int16, + store_texel_rgba_int16 + }, + { + MESA_FORMAT_RGBA_INT32, + fetch_texel_1d_rgba_int32, + fetch_texel_2d_rgba_int32, + fetch_texel_3d_rgba_int32, + store_texel_rgba_int32 + }, + + /* non-normalized, unsigned int */ + { + MESA_FORMAT_RGBA_UINT8, + fetch_texel_1d_rgba_uint8, + fetch_texel_2d_rgba_uint8, + fetch_texel_3d_rgba_uint8, + store_texel_rgba_uint8 + }, + { + MESA_FORMAT_RGBA_UINT16, + fetch_texel_1d_rgba_uint16, + fetch_texel_2d_rgba_uint16, + fetch_texel_3d_rgba_uint16, + store_texel_rgba_uint16 + }, + { + MESA_FORMAT_RGBA_UINT32, + fetch_texel_1d_rgba_uint32, + fetch_texel_2d_rgba_uint32, + fetch_texel_3d_rgba_uint32, + store_texel_rgba_uint32 + }, + + /* dudv */ + { + MESA_FORMAT_DUDV8, + fetch_texel_1d_dudv8, + fetch_texel_2d_dudv8, + fetch_texel_3d_dudv8, + NULL + }, + + /* signed, normalized */ + { + MESA_FORMAT_SIGNED_R8, + fetch_texel_1d_signed_r8, + fetch_texel_2d_signed_r8, + fetch_texel_3d_signed_r8, + store_texel_signed_r8 + }, + { + MESA_FORMAT_SIGNED_RG88_REV, + fetch_texel_1d_signed_rg88_rev, + fetch_texel_2d_signed_rg88_rev, + fetch_texel_3d_signed_rg88_rev, + store_texel_signed_rg88_rev + }, + { + MESA_FORMAT_SIGNED_RGBX8888, + fetch_texel_1d_signed_rgbx8888, + fetch_texel_2d_signed_rgbx8888, + fetch_texel_3d_signed_rgbx8888, + store_texel_signed_rgbx8888 + }, + { + MESA_FORMAT_SIGNED_RGBA8888, + fetch_texel_1d_signed_rgba8888, + fetch_texel_2d_signed_rgba8888, + fetch_texel_3d_signed_rgba8888, + store_texel_signed_rgba8888 + }, + { + MESA_FORMAT_SIGNED_RGBA8888_REV, + fetch_texel_1d_signed_rgba8888_rev, + fetch_texel_2d_signed_rgba8888_rev, + fetch_texel_3d_signed_rgba8888_rev, + store_texel_signed_rgba8888_rev + }, + { + MESA_FORMAT_SIGNED_R16, + fetch_texel_1d_signed_r16, + fetch_texel_2d_signed_r16, + fetch_texel_3d_signed_r16, + store_texel_signed_r16 + }, + { + MESA_FORMAT_SIGNED_GR1616, + fetch_texel_1d_signed_rg1616, + fetch_texel_2d_signed_rg1616, + fetch_texel_3d_signed_rg1616, + store_texel_signed_rg1616 + }, + { + MESA_FORMAT_SIGNED_RGB_16, + fetch_texel_1d_signed_rgb_16, + fetch_texel_2d_signed_rgb_16, + fetch_texel_3d_signed_rgb_16, + store_texel_signed_rgb_16 + }, + { + MESA_FORMAT_SIGNED_RGBA_16, + fetch_texel_1d_signed_rgba_16, + fetch_texel_2d_signed_rgba_16, + fetch_texel_3d_signed_rgba_16, + store_texel_signed_rgba_16 + }, + { + MESA_FORMAT_RGBA_16, + fetch_texel_1d_rgba_16, + fetch_texel_2d_rgba_16, + fetch_texel_3d_rgba_16, + store_texel_rgba_16 + }, + { + MESA_FORMAT_RED_RGTC1, + NULL, + _mesa_fetch_texel_2d_f_red_rgtc1, + NULL, + NULL + }, + { + MESA_FORMAT_SIGNED_RED_RGTC1, + NULL, + _mesa_fetch_texel_2d_f_signed_red_rgtc1, + NULL, + NULL + }, + { + MESA_FORMAT_RG_RGTC2, + NULL, + _mesa_fetch_texel_2d_f_rg_rgtc2, + NULL, + NULL + }, + { + MESA_FORMAT_SIGNED_RG_RGTC2, + NULL, + _mesa_fetch_texel_2d_f_signed_rg_rgtc2, + NULL, + NULL + }, + { + MESA_FORMAT_L_LATC1, + NULL, + _mesa_fetch_texel_2d_f_l_latc1, + NULL, + NULL + }, + { + MESA_FORMAT_SIGNED_L_LATC1, + NULL, + _mesa_fetch_texel_2d_f_signed_l_latc1, + NULL, + NULL + }, + { + MESA_FORMAT_LA_LATC2, + NULL, + _mesa_fetch_texel_2d_f_la_latc2, + NULL, + NULL + }, + { + MESA_FORMAT_SIGNED_LA_LATC2, + NULL, + _mesa_fetch_texel_2d_f_signed_la_latc2, + NULL, + NULL + }, + { + MESA_FORMAT_SIGNED_A8, + fetch_texel_1d_signed_a8, + fetch_texel_2d_signed_a8, + fetch_texel_3d_signed_a8, + store_texel_signed_a8 + }, + { + MESA_FORMAT_SIGNED_L8, + fetch_texel_1d_signed_l8, + fetch_texel_2d_signed_l8, + fetch_texel_3d_signed_l8, + store_texel_signed_l8 + }, + { + MESA_FORMAT_SIGNED_AL88, + fetch_texel_1d_signed_al88, + fetch_texel_2d_signed_al88, + fetch_texel_3d_signed_al88, + store_texel_signed_al88 + }, + { + MESA_FORMAT_SIGNED_I8, + fetch_texel_1d_signed_i8, + fetch_texel_2d_signed_i8, + fetch_texel_3d_signed_i8, + store_texel_signed_i8 + }, + { + MESA_FORMAT_SIGNED_A16, + fetch_texel_1d_signed_a16, + fetch_texel_2d_signed_a16, + fetch_texel_3d_signed_a16, + store_texel_signed_a16 + }, + { + MESA_FORMAT_SIGNED_L16, + fetch_texel_1d_signed_l16, + fetch_texel_2d_signed_l16, + fetch_texel_3d_signed_l16, + store_texel_signed_l16 + }, + { + MESA_FORMAT_SIGNED_AL1616, + fetch_texel_1d_signed_al1616, + fetch_texel_2d_signed_al1616, + fetch_texel_3d_signed_al1616, + store_texel_signed_al1616 + }, + { + MESA_FORMAT_SIGNED_I16, + fetch_texel_1d_signed_i16, + fetch_texel_2d_signed_i16, + fetch_texel_3d_signed_i16, + store_texel_signed_i16 + }, + { + MESA_FORMAT_RGB9_E5_FLOAT, + fetch_texel_1d_rgb9_e5, + fetch_texel_2d_rgb9_e5, + fetch_texel_3d_rgb9_e5, + store_texel_rgb9_e5 + }, + { + MESA_FORMAT_R11_G11_B10_FLOAT, + fetch_texel_1d_r11_g11_b10f, + fetch_texel_2d_r11_g11_b10f, + fetch_texel_3d_r11_g11_b10f, + store_texel_r11_g11_b10f + }, + { + MESA_FORMAT_Z32_FLOAT, + fetch_texel_1d_f_r_f32, /* Reuse the R32F functions. */ + fetch_texel_2d_f_r_f32, + fetch_texel_3d_f_r_f32, + store_texel_r_f32 + }, + { + MESA_FORMAT_Z32_FLOAT_X24S8, + fetch_texel_1d_z32f_x24s8, + fetch_texel_2d_z32f_x24s8, + fetch_texel_3d_z32f_x24s8, + store_texel_z32f_x24s8 + } +}; + + +FetchTexelFuncF +_mesa_get_texel_fetch_func(gl_format format, GLuint dims) +{ +#ifdef DEBUG + /* check that the table entries are sorted by format name */ + gl_format fmt; + for (fmt = 0; fmt < MESA_FORMAT_COUNT; fmt++) { + assert(texfetch_funcs[fmt].Name == fmt); + } +#endif + + assert(Elements(texfetch_funcs) == MESA_FORMAT_COUNT); + assert(format < MESA_FORMAT_COUNT); + + switch (dims) { + case 1: + return texfetch_funcs[format].Fetch1D; + case 2: + return texfetch_funcs[format].Fetch2D; + case 3: + return texfetch_funcs[format].Fetch3D; + default: + assert(0 && "bad dims in _mesa_get_texel_fetch_func"); + return NULL; + } +} + + +StoreTexelFunc +_mesa_get_texel_store_func(gl_format format) +{ + assert(format < MESA_FORMAT_COUNT); + return texfetch_funcs[format].StoreTexel; +} + + +/** + * Adaptor for fetching a GLchan texel from a float-valued texture. + */ +static void +fetch_texel_float_to_chan(const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texelOut) +{ + GLfloat temp[4]; + GLenum baseFormat = _mesa_get_format_base_format(texImage->TexFormat); + + ASSERT(texImage->FetchTexelf); + texImage->FetchTexelf(texImage, i, j, k, temp); + if (baseFormat == GL_DEPTH_COMPONENT || + baseFormat == GL_DEPTH_STENCIL_EXT) { + /* just one channel */ + UNCLAMPED_FLOAT_TO_CHAN(texelOut[0], temp[0]); + } + else { + /* four channels */ + UNCLAMPED_FLOAT_TO_CHAN(texelOut[0], temp[0]); + UNCLAMPED_FLOAT_TO_CHAN(texelOut[1], temp[1]); + UNCLAMPED_FLOAT_TO_CHAN(texelOut[2], temp[2]); + UNCLAMPED_FLOAT_TO_CHAN(texelOut[3], temp[3]); + } +} + + +#if 0 +/** + * Adaptor for fetching a float texel from a GLchan-valued texture. + */ +static void +fetch_texel_chan_to_float(const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texelOut) +{ + GLchan temp[4]; + GLenum baseFormat = _mesa_get_format_base_format(texImage->TexFormat); + + ASSERT(texImage->FetchTexelc); + texImage->FetchTexelc(texImage, i, j, k, temp); + if (baseFormat == GL_DEPTH_COMPONENT || + baseFormat == GL_DEPTH_STENCIL_EXT) { + /* just one channel */ + texelOut[0] = CHAN_TO_FLOAT(temp[0]); + } + else { + /* four channels */ + texelOut[0] = CHAN_TO_FLOAT(temp[0]); + texelOut[1] = CHAN_TO_FLOAT(temp[1]); + texelOut[2] = CHAN_TO_FLOAT(temp[2]); + texelOut[3] = CHAN_TO_FLOAT(temp[3]); + } +} +#endif + + +/** + * Initialize the texture image's FetchTexelc and FetchTexelf methods. + */ +void +_mesa_set_fetch_functions(struct gl_texture_image *texImage, GLuint dims) +{ + gl_format format = texImage->TexFormat; + + ASSERT(dims == 1 || dims == 2 || dims == 3); + + if (texImage->TexObject->Sampler.sRGBDecode == GL_SKIP_DECODE_EXT && + _mesa_get_format_color_encoding(format) == GL_SRGB) { + format = _mesa_get_srgb_format_linear(format); + } + + texImage->FetchTexelf = _mesa_get_texel_fetch_func(format, dims); + + texImage->FetchTexelc = fetch_texel_float_to_chan; + + ASSERT(texImage->FetchTexelc); + ASSERT(texImage->FetchTexelf); +} + +void +_mesa_update_fetch_functions(struct gl_texture_object *texObj) +{ + GLuint face, i; + GLuint dims; + + dims = _mesa_get_texture_dimensions(texObj->Target); + + for (face = 0; face < 6; face++) { + for (i = 0; i < MAX_TEXTURE_LEVELS; i++) { + if (texObj->Image[face][i]) { + _mesa_set_fetch_functions(texObj->Image[face][i], dims); + } + } + } +} diff --git a/mesalib/src/mesa/main/texfetch_tmp.h b/mesalib/src/mesa/main/texfetch_tmp.h index 278becc11..3b1eedf39 100644 --- a/mesalib/src/mesa/main/texfetch_tmp.h +++ b/mesalib/src/mesa/main/texfetch_tmp.h @@ -1,2379 +1,2402 @@ -/*
- * Mesa 3-D graphics library
- * Version: 7.7
- *
- * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
- * Copyright (c) 2008-2009 VMware, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-/**
- * \file texfetch_tmp.h
- * Texel fetch functions template.
- *
- * This template file is used by texfetch.c to generate texel fetch functions
- * for 1-D, 2-D and 3-D texture images.
- *
- * It should be expanded by defining \p DIM as the number texture dimensions
- * (1, 2 or 3). According to the value of \p DIM a series of macros is defined
- * for the texel lookup in the gl_texture_image::Data.
- *
- * \author Gareth Hughes
- * \author Brian Paul
- */
-
-
-#if DIM == 1
-
-#define TEXEL_ADDR( type, image, i, j, k, size ) \
- ((void) (j), (void) (k), ((type *)(image)->Data + (i) * (size)))
-
-#define FETCH(x) fetch_texel_1d_##x
-
-#elif DIM == 2
-
-#define TEXEL_ADDR( type, image, i, j, k, size ) \
- ((void) (k), \
- ((type *)(image)->Data + ((image)->RowStride * (j) + (i)) * (size)))
-
-#define FETCH(x) fetch_texel_2d_##x
-
-#elif DIM == 3
-
-#define TEXEL_ADDR( type, image, i, j, k, size ) \
- ((type *)(image)->Data + ((image)->ImageOffsets[k] \
- + (image)->RowStride * (j) + (i)) * (size))
-
-#define FETCH(x) fetch_texel_3d_##x
-
-#else
-#error illegal number of texture dimensions
-#endif
-
-
-/* MESA_FORMAT_Z32 ***********************************************************/
-
-/* Fetch depth texel from 1D, 2D or 3D 32-bit depth texture,
- * returning 1 GLfloat.
- * Note: no GLchan version of this function.
- */
-static void FETCH(f_z32)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLuint *src = TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
- texel[0] = src[0] * (1.0F / 0xffffffff);
-}
-
-#if DIM == 3
-static void store_texel_z32(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLuint *depth = (const GLuint *) texel;
- GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
- dst[0] = *depth;
-}
-#endif
-
-
-/* MESA_FORMAT_Z16 ***********************************************************/
-
-/* Fetch depth texel from 1D, 2D or 3D 16-bit depth texture,
- * returning 1 GLfloat.
- * Note: no GLchan version of this function.
- */
-static void FETCH(f_z16)(const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLushort *src = TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
- texel[0] = src[0] * (1.0F / 65535.0F);
-}
-
-#if DIM == 3
-static void store_texel_z16(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLushort *depth = (const GLushort *) texel;
- GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
- dst[0] = *depth;
-}
-#endif
-
-
-/* MESA_FORMAT_RGBA_F32 ******************************************************/
-
-/* Fetch texel from 1D, 2D or 3D RGBA_FLOAT32 texture, returning 4 GLfloats.
- */
-static void FETCH(f_rgba_f32)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLfloat *src = TEXEL_ADDR(GLfloat, texImage, i, j, k, 4);
- texel[RCOMP] = src[0];
- texel[GCOMP] = src[1];
- texel[BCOMP] = src[2];
- texel[ACOMP] = src[3];
-}
-
-#if DIM == 3
-static void store_texel_rgba_f32(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLfloat *depth = (const GLfloat *) texel;
- GLfloat *dst = TEXEL_ADDR(GLfloat, texImage, i, j, k, 4);
- dst[0] = depth[RCOMP];
- dst[1] = depth[GCOMP];
- dst[2] = depth[BCOMP];
- dst[3] = depth[ACOMP];
-}
-#endif
-
-
-/* MESA_FORMAT_RGBA_F16 ******************************************************/
-
-/* Fetch texel from 1D, 2D or 3D RGBA_FLOAT16 texture,
- * returning 4 GLfloats.
- */
-static void FETCH(f_rgba_f16)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLhalfARB *src = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 4);
- texel[RCOMP] = _mesa_half_to_float(src[0]);
- texel[GCOMP] = _mesa_half_to_float(src[1]);
- texel[BCOMP] = _mesa_half_to_float(src[2]);
- texel[ACOMP] = _mesa_half_to_float(src[3]);
-}
-
-#if DIM == 3
-static void store_texel_rgba_f16(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLfloat *src = (const GLfloat *) texel;
- GLhalfARB *dst = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 4);
- dst[0] = _mesa_float_to_half(src[RCOMP]);
- dst[1] = _mesa_float_to_half(src[GCOMP]);
- dst[2] = _mesa_float_to_half(src[BCOMP]);
- dst[3] = _mesa_float_to_half(src[ACOMP]);
-}
-#endif
-
-/* MESA_FORMAT_RGB_F32 *******************************************************/
-
-/* Fetch texel from 1D, 2D or 3D RGB_FLOAT32 texture,
- * returning 4 GLfloats.
- */
-static void FETCH(f_rgb_f32)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLfloat *src = TEXEL_ADDR(GLfloat, texImage, i, j, k, 3);
- texel[RCOMP] = src[0];
- texel[GCOMP] = src[1];
- texel[BCOMP] = src[2];
- texel[ACOMP] = 1.0F;
-}
-
-#if DIM == 3
-static void store_texel_rgb_f32(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLfloat *src = (const GLfloat *) texel;
- GLfloat *dst = TEXEL_ADDR(GLfloat, texImage, i, j, k, 3);
- dst[0] = src[RCOMP];
- dst[1] = src[GCOMP];
- dst[2] = src[BCOMP];
-}
-#endif
-
-
-/* MESA_FORMAT_RGB_F16 *******************************************************/
-
-/* Fetch texel from 1D, 2D or 3D RGB_FLOAT16 texture,
- * returning 4 GLfloats.
- */
-static void FETCH(f_rgb_f16)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLhalfARB *src = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 3);
- texel[RCOMP] = _mesa_half_to_float(src[0]);
- texel[GCOMP] = _mesa_half_to_float(src[1]);
- texel[BCOMP] = _mesa_half_to_float(src[2]);
- texel[ACOMP] = 1.0F;
-}
-
-#if DIM == 3
-static void store_texel_rgb_f16(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLfloat *src = (const GLfloat *) texel;
- GLhalfARB *dst = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 3);
- dst[0] = _mesa_float_to_half(src[RCOMP]);
- dst[1] = _mesa_float_to_half(src[GCOMP]);
- dst[2] = _mesa_float_to_half(src[BCOMP]);
-}
-#endif
-
-
-/* MESA_FORMAT_ALPHA_F32 *****************************************************/
-
-/* Fetch texel from 1D, 2D or 3D ALPHA_FLOAT32 texture,
- * returning 4 GLfloats.
- */
-static void FETCH(f_alpha_f32)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLfloat *src = TEXEL_ADDR(GLfloat, texImage, i, j, k, 1);
- texel[RCOMP] =
- texel[GCOMP] =
- texel[BCOMP] = 0.0F;
- texel[ACOMP] = src[0];
-}
-
-#if DIM == 3
-static void store_texel_alpha_f32(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLfloat *rgba = (const GLfloat *) texel;
- GLfloat *dst = TEXEL_ADDR(GLfloat, texImage, i, j, k, 1);
- dst[0] = rgba[ACOMP];
-}
-#endif
-
-
-/* MESA_FORMAT_ALPHA_F32 *****************************************************/
-
-/* Fetch texel from 1D, 2D or 3D ALPHA_FLOAT16 texture,
- * returning 4 GLfloats.
- */
-static void FETCH(f_alpha_f16)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLhalfARB *src = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 1);
- texel[RCOMP] =
- texel[GCOMP] =
- texel[BCOMP] = 0.0F;
- texel[ACOMP] = _mesa_half_to_float(src[0]);
-}
-
-#if DIM == 3
-static void store_texel_alpha_f16(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLfloat *rgba = (const GLfloat *) texel;
- GLhalfARB *dst = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 1);
- dst[0] = _mesa_float_to_half(rgba[ACOMP]);
-}
-#endif
-
-
-/* MESA_FORMAT_LUMINANCE_F32 *************************************************/
-
-/* Fetch texel from 1D, 2D or 3D LUMINANCE_FLOAT32 texture,
- * returning 4 GLfloats.
- */
-static void FETCH(f_luminance_f32)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLfloat *src = TEXEL_ADDR(GLfloat, texImage, i, j, k, 1);
- texel[RCOMP] =
- texel[GCOMP] =
- texel[BCOMP] = src[0];
- texel[ACOMP] = 1.0F;
-}
-
-#if DIM == 3
-static void store_texel_luminance_f32(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLfloat *rgba = (const GLfloat *) texel;
- GLfloat *dst = TEXEL_ADDR(GLfloat, texImage, i, j, k, 1);
- dst[0] = rgba[RCOMP];
-}
-#endif
-
-
-/* MESA_FORMAT_LUMINANCE_F16 *************************************************/
-
-/* Fetch texel from 1D, 2D or 3D LUMINANCE_FLOAT16 texture,
- * returning 4 GLfloats.
- */
-static void FETCH(f_luminance_f16)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLhalfARB *src = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 1);
- texel[RCOMP] =
- texel[GCOMP] =
- texel[BCOMP] = _mesa_half_to_float(src[0]);
- texel[ACOMP] = 1.0F;
-}
-
-#if DIM == 3
-static void store_texel_luminance_f16(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLfloat *rgba = (const GLfloat *) texel;
- GLhalfARB *dst = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 1);
- dst[0] = _mesa_float_to_half(rgba[RCOMP]);
-}
-#endif
-
-
-/* MESA_FORMAT_LUMINANCE_ALPHA_F32 *******************************************/
-
-/* Fetch texel from 1D, 2D or 3D LUMINANCE_ALPHA_FLOAT32 texture,
- * returning 4 GLfloats.
- */
-static void FETCH(f_luminance_alpha_f32)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLfloat *src = TEXEL_ADDR(GLfloat, texImage, i, j, k, 2);
- texel[RCOMP] =
- texel[GCOMP] =
- texel[BCOMP] = src[0];
- texel[ACOMP] = src[1];
-}
-
-#if DIM == 3
-static void store_texel_luminance_alpha_f32(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLfloat *rgba = (const GLfloat *) texel;
- GLfloat *dst = TEXEL_ADDR(GLfloat, texImage, i, j, k, 2);
- dst[0] = rgba[RCOMP];
- dst[1] = rgba[ACOMP];
-}
-#endif
-
-
-/* MESA_FORMAT_LUMINANCE_ALPHA_F16 *******************************************/
-
-/* Fetch texel from 1D, 2D or 3D LUMINANCE_ALPHA_FLOAT16 texture,
- * returning 4 GLfloats.
- */
-static void FETCH(f_luminance_alpha_f16)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLhalfARB *src = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 2);
- texel[RCOMP] =
- texel[GCOMP] =
- texel[BCOMP] = _mesa_half_to_float(src[0]);
- texel[ACOMP] = _mesa_half_to_float(src[1]);
-}
-
-#if DIM == 3
-static void store_texel_luminance_alpha_f16(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLfloat *rgba = (const GLfloat *) texel;
- GLhalfARB *dst = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 2);
- dst[0] = _mesa_float_to_half(rgba[RCOMP]);
- dst[1] = _mesa_float_to_half(rgba[ACOMP]);
-}
-#endif
-
-
-/* MESA_FORMAT_INTENSITY_F32 *************************************************/
-
-/* Fetch texel from 1D, 2D or 3D INTENSITY_FLOAT32 texture,
- * returning 4 GLfloats.
- */
-static void FETCH(f_intensity_f32)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLfloat *src = TEXEL_ADDR(GLfloat, texImage, i, j, k, 1);
- texel[RCOMP] =
- texel[GCOMP] =
- texel[BCOMP] =
- texel[ACOMP] = src[0];
-}
-
-#if DIM == 3
-static void store_texel_intensity_f32(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLfloat *rgba = (const GLfloat *) texel;
- GLfloat *dst = TEXEL_ADDR(GLfloat, texImage, i, j, k, 1);
- dst[0] = rgba[RCOMP];
-}
-#endif
-
-
-/* MESA_FORMAT_INTENSITY_F16 *************************************************/
-
-/* Fetch texel from 1D, 2D or 3D INTENSITY_FLOAT16 texture,
- * returning 4 GLfloats.
- */
-static void FETCH(f_intensity_f16)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLhalfARB *src = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 1);
- texel[RCOMP] =
- texel[GCOMP] =
- texel[BCOMP] =
- texel[ACOMP] = _mesa_half_to_float(src[0]);
-}
-
-#if DIM == 3
-static void store_texel_intensity_f16(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLfloat *rgba = (const GLfloat *) texel;
- GLhalfARB *dst = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 1);
- dst[0] = _mesa_float_to_half(rgba[RCOMP]);
-}
-#endif
-
-
-/* MESA_FORMAT_R_FLOAT32 *****************************************************/
-
-/* Fetch texel from 1D, 2D or 3D R_FLOAT32 texture,
- * returning 4 GLfloats.
- */
-static void FETCH(f_r_f32)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLfloat *src = TEXEL_ADDR(GLfloat, texImage, i, j, k, 1);
- texel[RCOMP] = src[0];
- texel[GCOMP] = 0.0F;
- texel[BCOMP] = 0.0F;
- texel[ACOMP] = 1.0F;
-}
-
-#if DIM == 3
-static void store_texel_r_f32(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLfloat *rgba = (const GLfloat *) texel;
- GLfloat *dst = TEXEL_ADDR(GLfloat, texImage, i, j, k, 1);
- dst[0] = rgba[RCOMP];
-}
-#endif
-
-
-/* MESA_FORMAT_R_FLOAT16 *****************************************************/
-
-/* Fetch texel from 1D, 2D or 3D R_FLOAT16 texture,
- * returning 4 GLfloats.
- */
-static void FETCH(f_r_f16)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLhalfARB *src = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 1);
- texel[RCOMP] = _mesa_half_to_float(src[0]);
- texel[GCOMP] = 0.0F;
- texel[BCOMP] = 0.0F;
- texel[ACOMP] = 1.0F;
-}
-
-#if DIM == 3
-static void store_texel_r_f16(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLfloat *rgba = (const GLfloat *) texel;
- GLhalfARB *dst = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 1);
- dst[0] = _mesa_float_to_half(rgba[RCOMP]);
-}
-#endif
-
-
-/* MESA_FORMAT_RG_FLOAT32 ****************************************************/
-
-/* Fetch texel from 1D, 2D or 3D RG_FLOAT32 texture,
- * returning 4 GLfloats.
- */
-static void FETCH(f_rg_f32)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLfloat *src = TEXEL_ADDR(GLfloat, texImage, i, j, k, 2);
- texel[RCOMP] = src[0];
- texel[GCOMP] = src[1];
- texel[BCOMP] = 0.0F;
- texel[ACOMP] = 1.0F;
-}
-
-#if DIM == 3
-static void store_texel_rg_f32(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLfloat *rgba = (const GLfloat *) texel;
- GLfloat *dst = TEXEL_ADDR(GLfloat, texImage, i, j, k, 2);
- dst[0] = rgba[RCOMP];
- dst[1] = rgba[GCOMP];
-}
-#endif
-
-
-/* MESA_FORMAT_RG_FLOAT16 ****************************************************/
-
-/* Fetch texel from 1D, 2D or 3D RG_FLOAT16 texture,
- * returning 4 GLfloats.
- */
-static void FETCH(f_rg_f16)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLhalfARB *src = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 2);
- texel[RCOMP] = _mesa_half_to_float(src[0]);
- texel[GCOMP] = _mesa_half_to_float(src[1]);
- texel[BCOMP] = 0.0F;
- texel[ACOMP] = 1.0F;
-}
-
-#if DIM == 3
-static void store_texel_rg_f16(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLfloat *rgba = (const GLfloat *) texel;
- GLhalfARB *dst = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 2);
- dst[0] = _mesa_float_to_half(rgba[RCOMP]);
- dst[1] = _mesa_float_to_half(rgba[GCOMP]);
-}
-#endif
-
-
-/*
- * Begin Hardware formats
- */
-
-/* MESA_FORMAT_RGBA8888 ******************************************************/
-
-/* Fetch texel from 1D, 2D or 3D rgba8888 texture, return 4 GLfloats */
-static void FETCH(f_rgba8888)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLuint s = *TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
- texel[RCOMP] = UBYTE_TO_FLOAT( (s >> 24) );
- texel[GCOMP] = UBYTE_TO_FLOAT( (s >> 16) & 0xff );
- texel[BCOMP] = UBYTE_TO_FLOAT( (s >> 8) & 0xff );
- texel[ACOMP] = UBYTE_TO_FLOAT( (s ) & 0xff );
-}
-
-
-
-#if DIM == 3
-static void store_texel_rgba8888(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLubyte *rgba = (const GLubyte *) texel;
- GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
- *dst = PACK_COLOR_8888(rgba[RCOMP], rgba[GCOMP], rgba[BCOMP], rgba[ACOMP]);
-}
-#endif
-
-
-/* MESA_FORMAT_RGBA888_REV ***************************************************/
-
-/* Fetch texel from 1D, 2D or 3D abgr8888 texture, return 4 GLchans */
-static void FETCH(f_rgba8888_rev)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLuint s = *TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
- texel[RCOMP] = UBYTE_TO_FLOAT( (s ) & 0xff );
- texel[GCOMP] = UBYTE_TO_FLOAT( (s >> 8) & 0xff );
- texel[BCOMP] = UBYTE_TO_FLOAT( (s >> 16) & 0xff );
- texel[ACOMP] = UBYTE_TO_FLOAT( (s >> 24) );
-}
-
-#if DIM == 3
-static void store_texel_rgba8888_rev(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLubyte *rgba = (const GLubyte *) texel;
- GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
- *dst = PACK_COLOR_8888_REV(rgba[RCOMP], rgba[GCOMP], rgba[BCOMP], rgba[ACOMP]);
-}
-#endif
-
-
-/* MESA_FORMAT_ARGB8888 ******************************************************/
-
-/* Fetch texel from 1D, 2D or 3D argb8888 texture, return 4 GLchans */
-static void FETCH(f_argb8888)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLuint s = *TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
- texel[RCOMP] = UBYTE_TO_FLOAT( (s >> 16) & 0xff );
- texel[GCOMP] = UBYTE_TO_FLOAT( (s >> 8) & 0xff );
- texel[BCOMP] = UBYTE_TO_FLOAT( (s ) & 0xff );
- texel[ACOMP] = UBYTE_TO_FLOAT( (s >> 24) );
-}
-
-#if DIM == 3
-static void store_texel_argb8888(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLubyte *rgba = (const GLubyte *) texel;
- GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
- *dst = PACK_COLOR_8888(rgba[ACOMP], rgba[RCOMP], rgba[GCOMP], rgba[BCOMP]);
-}
-#endif
-
-
-/* MESA_FORMAT_ARGB8888_REV **************************************************/
-
-/* Fetch texel from 1D, 2D or 3D argb8888_rev texture, return 4 GLfloats */
-static void FETCH(f_argb8888_rev)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLuint s = *TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
- texel[RCOMP] = UBYTE_TO_FLOAT( (s >> 8) & 0xff );
- texel[GCOMP] = UBYTE_TO_FLOAT( (s >> 16) & 0xff );
- texel[BCOMP] = UBYTE_TO_FLOAT( (s >> 24) );
- texel[ACOMP] = UBYTE_TO_FLOAT( (s ) & 0xff );
-}
-
-#if DIM == 3
-static void store_texel_argb8888_rev(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLubyte *rgba = (const GLubyte *) texel;
- GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
- *dst = PACK_COLOR_8888(rgba[BCOMP], rgba[GCOMP], rgba[RCOMP], rgba[ACOMP]);
-}
-#endif
-
-
-/* MESA_FORMAT_XRGB8888 ******************************************************/
-
-/* Fetch texel from 1D, 2D or 3D xrgb8888 texture, return 4 GLchans */
-static void FETCH(f_xrgb8888)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLuint s = *TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
- texel[RCOMP] = UBYTE_TO_FLOAT( (s >> 16) & 0xff );
- texel[GCOMP] = UBYTE_TO_FLOAT( (s >> 8) & 0xff );
- texel[BCOMP] = UBYTE_TO_FLOAT( (s ) & 0xff );
- texel[ACOMP] = 1.0f;
-}
-
-#if DIM == 3
-static void store_texel_xrgb8888(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLubyte *rgba = (const GLubyte *) texel;
- GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
- *dst = PACK_COLOR_8888(0xff, rgba[RCOMP], rgba[GCOMP], rgba[BCOMP]);
-}
-#endif
-
-
-/* MESA_FORMAT_XRGB8888_REV **************************************************/
-
-/* Fetch texel from 1D, 2D or 3D xrgb8888_rev texture, return 4 GLfloats */
-static void FETCH(f_xrgb8888_rev)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLuint s = *TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
- texel[RCOMP] = UBYTE_TO_FLOAT( (s >> 8) & 0xff );
- texel[GCOMP] = UBYTE_TO_FLOAT( (s >> 16) & 0xff );
- texel[BCOMP] = UBYTE_TO_FLOAT( (s >> 24) );
- texel[ACOMP] = 1.0f;
-}
-
-#if DIM == 3
-static void store_texel_xrgb8888_rev(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLubyte *rgba = (const GLubyte *) texel;
- GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
- *dst = PACK_COLOR_8888(rgba[BCOMP], rgba[GCOMP], rgba[RCOMP], 0xff);
-}
-#endif
-
-
-/* MESA_FORMAT_RGB888 ********************************************************/
-
-/* Fetch texel from 1D, 2D or 3D rgb888 texture, return 4 GLchans */
-static void FETCH(f_rgb888)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 3);
- texel[RCOMP] = UBYTE_TO_FLOAT( src[2] );
- texel[GCOMP] = UBYTE_TO_FLOAT( src[1] );
- texel[BCOMP] = UBYTE_TO_FLOAT( src[0] );
- texel[ACOMP] = 1.0F;
-}
-
-#if DIM == 3
-static void store_texel_rgb888(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLubyte *rgba = (const GLubyte *) texel;
- GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 3);
- dst[0] = rgba[BCOMP];
- dst[1] = rgba[GCOMP];
- dst[2] = rgba[RCOMP];
-}
-#endif
-
-
-/* MESA_FORMAT_BGR888 ********************************************************/
-
-/* Fetch texel from 1D, 2D or 3D bgr888 texture, return 4 GLchans */
-static void FETCH(f_bgr888)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 3);
- texel[RCOMP] = UBYTE_TO_FLOAT( src[0] );
- texel[GCOMP] = UBYTE_TO_FLOAT( src[1] );
- texel[BCOMP] = UBYTE_TO_FLOAT( src[2] );
- texel[ACOMP] = 1.0F;
-}
-
-#if DIM == 3
-static void store_texel_bgr888(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLubyte *rgba = (const GLubyte *) texel;
- GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 3);
- dst[0] = rgba[RCOMP];
- dst[1] = rgba[GCOMP];
- dst[2] = rgba[BCOMP];
-}
-#endif
-
-
-/* use color expansion like (g << 2) | (g >> 4) (does somewhat random rounding)
- instead of slow (g << 2) * 255 / 252 (always rounds down) */
-
-/* MESA_FORMAT_RGB565 ********************************************************/
-
-/* Fetch texel from 1D, 2D or 3D rgb565 texture, return 4 GLchans */
-static void FETCH(f_rgb565)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLushort *src = TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
- const GLushort s = *src;
- texel[RCOMP] = ((s >> 11) & 0x1f) * (1.0F / 31.0F);
- texel[GCOMP] = ((s >> 5 ) & 0x3f) * (1.0F / 63.0F);
- texel[BCOMP] = ((s ) & 0x1f) * (1.0F / 31.0F);
- texel[ACOMP] = 1.0F;
-}
-
-#if DIM == 3
-static void store_texel_rgb565(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLubyte *rgba = (const GLubyte *) texel;
- GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
- *dst = PACK_COLOR_565(rgba[RCOMP], rgba[GCOMP], rgba[BCOMP]);
-}
-#endif
-
-
-/* MESA_FORMAT_RGB565_REV ****************************************************/
-
-/* Fetch texel from 1D, 2D or 3D rgb565_rev texture, return 4 GLchans */
-static void FETCH(f_rgb565_rev)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLushort *src = TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
- const GLushort s = (*src >> 8) | (*src << 8); /* byte swap */
- texel[RCOMP] = UBYTE_TO_FLOAT( ((s >> 8) & 0xf8) | ((s >> 13) & 0x7) );
- texel[GCOMP] = UBYTE_TO_FLOAT( ((s >> 3) & 0xfc) | ((s >> 9) & 0x3) );
- texel[BCOMP] = UBYTE_TO_FLOAT( ((s << 3) & 0xf8) | ((s >> 2) & 0x7) );
- texel[ACOMP] = 1.0F;
-}
-
-#if DIM == 3
-static void store_texel_rgb565_rev(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLubyte *rgba = (const GLubyte *) texel;
- GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
- *dst = PACK_COLOR_565(rgba[BCOMP], rgba[GCOMP], rgba[RCOMP]);
-}
-#endif
-
-
-/* MESA_FORMAT_ARGB4444 ******************************************************/
-
-/* Fetch texel from 1D, 2D or 3D argb444 texture, return 4 GLchans */
-static void FETCH(f_argb4444)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLushort *src = TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
- const GLushort s = *src;
- texel[RCOMP] = ((s >> 8) & 0xf) * (1.0F / 15.0F);
- texel[GCOMP] = ((s >> 4) & 0xf) * (1.0F / 15.0F);
- texel[BCOMP] = ((s ) & 0xf) * (1.0F / 15.0F);
- texel[ACOMP] = ((s >> 12) & 0xf) * (1.0F / 15.0F);
-}
-
-#if DIM == 3
-static void store_texel_argb4444(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLubyte *rgba = (const GLubyte *) texel;
- GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
- *dst = PACK_COLOR_4444(rgba[ACOMP], rgba[RCOMP], rgba[GCOMP], rgba[BCOMP]);
-}
-#endif
-
-
-/* MESA_FORMAT_ARGB4444_REV **************************************************/
-
-/* Fetch texel from 1D, 2D or 3D argb4444_rev texture, return 4 GLchans */
-static void FETCH(f_argb4444_rev)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLushort s = *TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
- texel[RCOMP] = ((s ) & 0xf) * (1.0F / 15.0F);
- texel[GCOMP] = ((s >> 12) & 0xf) * (1.0F / 15.0F);
- texel[BCOMP] = ((s >> 8) & 0xf) * (1.0F / 15.0F);
- texel[ACOMP] = ((s >> 4) & 0xf) * (1.0F / 15.0F);
-}
-
-#if DIM == 3
-static void store_texel_argb4444_rev(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLubyte *rgba = (const GLubyte *) texel;
- GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
- *dst = PACK_COLOR_4444(rgba[ACOMP], rgba[BCOMP], rgba[GCOMP], rgba[RCOMP]);
-}
-#endif
-
-/* MESA_FORMAT_RGBA5551 ******************************************************/
-
-/* Fetch texel from 1D, 2D or 3D argb1555 texture, return 4 GLchans */
-static void FETCH(f_rgba5551)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLushort *src = TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
- const GLushort s = *src;
- texel[RCOMP] = ((s >> 11) & 0x1f) * (1.0F / 31.0F);
- texel[GCOMP] = ((s >> 6) & 0x1f) * (1.0F / 31.0F);
- texel[BCOMP] = ((s >> 1) & 0x1f) * (1.0F / 31.0F);
- texel[ACOMP] = ((s ) & 0x01) * 1.0F;
-}
-
-#if DIM == 3
-static void store_texel_rgba5551(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLubyte *rgba = (const GLubyte *) texel;
- GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
- *dst = PACK_COLOR_5551(rgba[RCOMP], rgba[GCOMP], rgba[BCOMP], rgba[ACOMP]);
-}
-#endif
-
-/* MESA_FORMAT_ARGB1555 ******************************************************/
-
-/* Fetch texel from 1D, 2D or 3D argb1555 texture, return 4 GLchans */
-static void FETCH(f_argb1555)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLushort *src = TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
- const GLushort s = *src;
- texel[RCOMP] = ((s >> 10) & 0x1f) * (1.0F / 31.0F);
- texel[GCOMP] = ((s >> 5) & 0x1f) * (1.0F / 31.0F);
- texel[BCOMP] = ((s >> 0) & 0x1f) * (1.0F / 31.0F);
- texel[ACOMP] = ((s >> 15) & 0x01) * 1.0F;
-}
-
-#if DIM == 3
-static void store_texel_argb1555(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLubyte *rgba = (const GLubyte *) texel;
- GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
- *dst = PACK_COLOR_1555(rgba[ACOMP], rgba[RCOMP], rgba[GCOMP], rgba[BCOMP]);
-}
-#endif
-
-
-/* MESA_FORMAT_ARGB1555_REV **************************************************/
-
-/* Fetch texel from 1D, 2D or 3D argb1555_rev texture, return 4 GLchans */
-static void FETCH(f_argb1555_rev)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLushort *src = TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
- const GLushort s = (*src << 8) | (*src >> 8); /* byteswap */
- texel[RCOMP] = UBYTE_TO_FLOAT( ((s >> 7) & 0xf8) | ((s >> 12) & 0x7) );
- texel[GCOMP] = UBYTE_TO_FLOAT( ((s >> 2) & 0xf8) | ((s >> 7) & 0x7) );
- texel[BCOMP] = UBYTE_TO_FLOAT( ((s << 3) & 0xf8) | ((s >> 2) & 0x7) );
- texel[ACOMP] = UBYTE_TO_FLOAT( ((s >> 15) & 0x01) * 255 );
-}
-
-#if DIM == 3
-static void store_texel_argb1555_rev(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLubyte *rgba = (const GLubyte *) texel;
- GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
- *dst = PACK_COLOR_1555_REV(rgba[ACOMP], rgba[RCOMP], rgba[GCOMP], rgba[BCOMP]);
-}
-#endif
-
-
-/* MESA_FORMAT_ARGB2101010 ***************************************************/
-
-/* Fetch texel from 1D, 2D or 3D argb2101010 texture, return 4 GLchans */
-static void FETCH(f_argb2101010)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLuint *src = TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
- const GLuint s = *src;
- texel[RCOMP] = ((s >> 20) & 0x3ff) * (1.0F / 1023.0F);
- texel[GCOMP] = ((s >> 10) & 0x3ff) * (1.0F / 1023.0F);
- texel[BCOMP] = ((s >> 0) & 0x3ff) * (1.0F / 1023.0F);
- texel[ACOMP] = ((s >> 30) & 0x03) * (1.0F / 3.0F);
-}
-
-#if DIM == 3
-static void store_texel_argb2101010(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLubyte *rgba = (const GLubyte *) texel;
- GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
- *dst = PACK_COLOR_2101010_UB(rgba[ACOMP], rgba[RCOMP], rgba[GCOMP], rgba[BCOMP]);
-}
-#endif
-
-
-/* MESA_FORMAT_RG88 **********************************************************/
-
-/* Fetch texel from 1D, 2D or 3D rg88 texture, return 4 GLchans */
-static void FETCH(f_rg88)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLushort s = *TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
- texel[RCOMP] = UBYTE_TO_FLOAT( s & 0xff );
- texel[GCOMP] = UBYTE_TO_FLOAT( s >> 8 );
- texel[BCOMP] = 0.0;
- texel[ACOMP] = 1.0;
-}
-
-#if DIM == 3
-static void store_texel_rg88(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLubyte *rgba = (const GLubyte *) texel;
- GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
- *dst = PACK_COLOR_88(rgba[RCOMP], rgba[GCOMP]);
-}
-#endif
-
-
-/* MESA_FORMAT_RG88_REV ******************************************************/
-
-/* Fetch texel from 1D, 2D or 3D rg88_rev texture, return 4 GLchans */
-static void FETCH(f_rg88_rev)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLushort s = *TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
- texel[RCOMP] = UBYTE_TO_FLOAT( s & 0xff );
- texel[GCOMP] = UBYTE_TO_FLOAT( s >> 8 );
- texel[BCOMP] = 0.0;
- texel[ACOMP] = 1.0;
-}
-
-#if DIM == 3
-static void store_texel_rg88_rev(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLubyte *rgba = (const GLubyte *) texel;
- GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
- *dst = PACK_COLOR_88(rgba[GCOMP], rgba[RCOMP]);
-}
-#endif
-
-
-/* MESA_FORMAT_AL44 **********************************************************/
-
-/* Fetch texel from 1D, 2D or 3D al44 texture, return 4 GLchans */
-static void FETCH(f_al44)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLubyte s = *TEXEL_ADDR(GLubyte, texImage, i, j, k, 1);
- texel[RCOMP] =
- texel[GCOMP] =
- texel[BCOMP] = (s & 0xf) * (1.0F / 15.0F);
- texel[ACOMP] = ((s >> 4) & 0xf) * (1.0F / 15.0F);
-}
-
-#if DIM == 3
-static void store_texel_al44(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLubyte *rgba = (const GLubyte *) texel;
- GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1);
- *dst = PACK_COLOR_44(rgba[ACOMP], rgba[RCOMP]);
-}
-#endif
-
-
-/* MESA_FORMAT_AL88 **********************************************************/
-
-/* Fetch texel from 1D, 2D or 3D al88 texture, return 4 GLchans */
-static void FETCH(f_al88)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLushort s = *TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
- texel[RCOMP] =
- texel[GCOMP] =
- texel[BCOMP] = UBYTE_TO_FLOAT( s & 0xff );
- texel[ACOMP] = UBYTE_TO_FLOAT( s >> 8 );
-}
-
-#if DIM == 3
-static void store_texel_al88(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLubyte *rgba = (const GLubyte *) texel;
- GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
- *dst = PACK_COLOR_88(rgba[ACOMP], rgba[RCOMP]);
-}
-#endif
-
-
-/* MESA_FORMAT_R8 ************************************************************/
-
-/* Fetch texel from 1D, 2D or 3D rg88 texture, return 4 GLchans */
-static void FETCH(f_r8)(const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel)
-{
- const GLubyte s = *TEXEL_ADDR(GLubyte, texImage, i, j, k, 1);
- texel[RCOMP] = UBYTE_TO_FLOAT(s);
- texel[GCOMP] = 0.0;
- texel[BCOMP] = 0.0;
- texel[ACOMP] = 1.0;
-}
-
-#if DIM == 3
-static void store_texel_r8(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLubyte *rgba = (const GLubyte *) texel;
- GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1);
- *dst = rgba[RCOMP];
-}
-#endif
-
-
-/* MESA_FORMAT_R16 ***********************************************************/
-
-/* Fetch texel from 1D, 2D or 3D r16 texture, return 4 GLchans */
-static void FETCH(f_r16)(const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel)
-{
- const GLushort s = *TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
- texel[RCOMP] = USHORT_TO_FLOAT(s);
- texel[GCOMP] = 0.0;
- texel[BCOMP] = 0.0;
- texel[ACOMP] = 1.0;
-}
-
-#if DIM == 3
-static void store_texel_r16(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLushort *rgba = (const GLushort *) texel;
- GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
- *dst = rgba[RCOMP];
-}
-#endif
-
-
-/* MESA_FORMAT_AL88_REV ******************************************************/
-
-/* Fetch texel from 1D, 2D or 3D al88_rev texture, return 4 GLchans */
-static void FETCH(f_al88_rev)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLushort s = *TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
- texel[RCOMP] =
- texel[GCOMP] =
- texel[BCOMP] = UBYTE_TO_FLOAT( s >> 8 );
- texel[ACOMP] = UBYTE_TO_FLOAT( s & 0xff );
-}
-
-#if DIM == 3
-static void store_texel_al88_rev(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLubyte *rgba = (const GLubyte *) texel;
- GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
- *dst = PACK_COLOR_88(rgba[RCOMP], rgba[ACOMP]);
-}
-#endif
-
-
-/* MESA_FORMAT_RG1616 ********************************************************/
-
-/* Fetch texel from 1D, 2D or 3D rg1616 texture, return 4 GLchans */
-static void FETCH(f_rg1616)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLuint s = *TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
- texel[RCOMP] = USHORT_TO_FLOAT( s & 0xffff );
- texel[GCOMP] = USHORT_TO_FLOAT( s >> 16 );
- texel[BCOMP] = 0.0;
- texel[ACOMP] = 1.0;
-}
-
-#if DIM == 3
-static void store_texel_rg1616(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLubyte *rgba = (const GLubyte *) texel;
- GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
- *dst = PACK_COLOR_1616(rgba[RCOMP], rgba[GCOMP]);
-}
-#endif
-
-
-/* MESA_FORMAT_RG1616_REV ****************************************************/
-
-/* Fetch texel from 1D, 2D or 3D rg1616_rev texture, return 4 GLchans */
-static void FETCH(f_rg1616_rev)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLuint s = *TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
- texel[RCOMP] = USHORT_TO_FLOAT( s >> 16 );
- texel[GCOMP] = USHORT_TO_FLOAT( s & 0xffff );
- texel[BCOMP] = 0.0;
- texel[ACOMP] = 1.0;
-}
-
-#if DIM == 3
-static void store_texel_rg1616_rev(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLubyte *rgba = (const GLubyte *) texel;
- GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
- *dst = PACK_COLOR_1616(rgba[GCOMP], rgba[RCOMP]);
-}
-#endif
-
-
-/* MESA_FORMAT_AL1616 ********************************************************/
-
-/* Fetch texel from 1D, 2D or 3D al1616 texture, return 4 GLchans */
-static void FETCH(f_al1616)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLuint s = *TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
- texel[RCOMP] =
- texel[GCOMP] =
- texel[BCOMP] = USHORT_TO_FLOAT( s & 0xffff );
- texel[ACOMP] = USHORT_TO_FLOAT( s >> 16 );
-}
-
-#if DIM == 3
-static void store_texel_al1616(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLushort *rgba = (const GLushort *) texel;
- GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
- *dst = PACK_COLOR_1616(rgba[ACOMP], rgba[RCOMP]);
-}
-#endif
-
-
-/* MESA_FORMAT_AL1616_REV ****************************************************/
-
-/* Fetch texel from 1D, 2D or 3D al1616_rev texture, return 4 GLchans */
-static void FETCH(f_al1616_rev)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLuint s = *TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
- texel[RCOMP] =
- texel[GCOMP] =
- texel[BCOMP] = USHORT_TO_FLOAT( s >> 16 );
- texel[ACOMP] = USHORT_TO_FLOAT( s & 0xffff );
-}
-
-#if DIM == 3
-static void store_texel_al1616_rev(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLushort *rgba = (const GLushort *) texel;
- GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
- *dst = PACK_COLOR_1616(rgba[RCOMP], rgba[ACOMP]);
-}
-#endif
-
-
-/* MESA_FORMAT_RGB332 ********************************************************/
-
-/* Fetch texel from 1D, 2D or 3D rgb332 texture, return 4 GLchans */
-static void FETCH(f_rgb332)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1);
- const GLubyte s = *src;
- texel[RCOMP] = ((s >> 5) & 0x7) * (1.0F / 7.0F);
- texel[GCOMP] = ((s >> 2) & 0x7) * (1.0F / 7.0F);
- texel[BCOMP] = ((s ) & 0x3) * (1.0F / 3.0F);
- texel[ACOMP] = 1.0F;
-}
-
-#if DIM == 3
-static void store_texel_rgb332(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLubyte *rgba = (const GLubyte *) texel;
- GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1);
- *dst = PACK_COLOR_332(rgba[RCOMP], rgba[GCOMP], rgba[BCOMP]);
-}
-#endif
-
-
-/* MESA_FORMAT_A8 ************************************************************/
-
-/* Fetch texel from 1D, 2D or 3D a8 texture, return 4 GLchans */
-static void FETCH(f_a8)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1);
- texel[RCOMP] =
- texel[GCOMP] =
- texel[BCOMP] = 0.0F;
- texel[ACOMP] = UBYTE_TO_FLOAT( src[0] );
-}
-
-#if DIM == 3
-static void store_texel_a8(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLubyte *rgba = (const GLubyte *) texel;
- GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1);
- *dst = rgba[ACOMP];
-}
-#endif
-
-
-/* MESA_FORMAT_A16 ************************************************************/
-
-/* Fetch texel from 1D, 2D or 3D a8 texture, return 4 GLchans */
-static void FETCH(f_a16)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLushort *src = TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
- texel[RCOMP] =
- texel[GCOMP] =
- texel[BCOMP] = 0.0F;
- texel[ACOMP] = USHORT_TO_FLOAT( src[0] );
-}
-
-#if DIM == 3
-static void store_texel_a16(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLushort *rgba = (const GLushort *) texel;
- GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
- *dst = rgba[ACOMP];
-}
-#endif
-
-
-/* MESA_FORMAT_L8 ************************************************************/
-
-/* Fetch texel from 1D, 2D or 3D l8 texture, return 4 GLchans */
-static void FETCH(f_l8)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1);
- texel[RCOMP] =
- texel[GCOMP] =
- texel[BCOMP] = UBYTE_TO_FLOAT( src[0] );
- texel[ACOMP] = 1.0F;
-}
-
-#if DIM == 3
-static void store_texel_l8(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLubyte *rgba = (const GLubyte *) texel;
- GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1);
- *dst = rgba[RCOMP];
-}
-#endif
-
-
-/* MESA_FORMAT_L16 ***********************************************************/
-
-/* Fetch texel from 1D, 2D or 3D l16 texture, return 4 GLchans */
-static void FETCH(f_l16)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLushort *src = TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
- texel[RCOMP] =
- texel[GCOMP] =
- texel[BCOMP] = USHORT_TO_FLOAT( src[0] );
- texel[ACOMP] = 1.0F;
-}
-
-#if DIM == 3
-static void store_texel_l16(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLushort *rgba = (const GLushort *) texel;
- GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
- *dst = rgba[RCOMP];
-}
-#endif
-
-
-/* MESA_FORMAT_I8 ************************************************************/
-
-/* Fetch texel from 1D, 2D or 3D i8 texture, return 4 GLchans */
-static void FETCH(f_i8)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1);
- texel[RCOMP] =
- texel[GCOMP] =
- texel[BCOMP] =
- texel[ACOMP] = UBYTE_TO_FLOAT( src[0] );
-}
-
-#if DIM == 3
-static void store_texel_i8(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLubyte *rgba = (const GLubyte *) texel;
- GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1);
- *dst = rgba[RCOMP];
-}
-#endif
-
-
-/* MESA_FORMAT_I16 ***********************************************************/
-
-/* Fetch texel from 1D, 2D or 3D i16 texture, return 4 GLchans */
-static void FETCH(f_i16)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLushort *src = TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
- texel[RCOMP] =
- texel[GCOMP] =
- texel[BCOMP] =
- texel[ACOMP] = USHORT_TO_FLOAT( src[0] );
-}
-
-#if DIM == 3
-static void store_texel_i16(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLushort *rgba = (const GLushort *) texel;
- GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
- *dst = rgba[RCOMP];
-}
-#endif
-
-
-/* MESA_FORMAT_CI8 ***********************************************************/
-
-/* Fetch CI texel from 1D, 2D or 3D ci8 texture, lookup the index in a
- * color table, and return 4 GLchans.
- */
-static void FETCH(f_ci8)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1);
- const struct gl_color_table *palette;
- GLuint index;
- GET_CURRENT_CONTEXT(ctx);
-
- if (ctx->Texture.SharedPalette) {
- palette = &ctx->Texture.Palette;
- }
- else {
- palette = &texImage->TexObject->Palette;
- }
- if (palette->Size == 0)
- return; /* undefined results */
-
- /* Mask the index against size of palette to avoid going out of bounds */
- index = (*src) & (palette->Size - 1);
-
- {
- const GLfloat *table = palette->TableF;
- switch (palette->_BaseFormat) {
- case GL_ALPHA:
- texel[RCOMP] =
- texel[GCOMP] =
- texel[BCOMP] = 0.0F;
- texel[ACOMP] = table[index];
- break;
- case GL_LUMINANCE:
- texel[RCOMP] =
- texel[GCOMP] =
- texel[BCOMP] = table[index];
- texel[ACOMP] = 1.0F;
- break;
- case GL_INTENSITY:
- texel[RCOMP] =
- texel[GCOMP] =
- texel[BCOMP] =
- texel[ACOMP] = table[index];
- break;
- case GL_LUMINANCE_ALPHA:
- texel[RCOMP] =
- texel[GCOMP] =
- texel[BCOMP] = table[index * 2 + 0];
- texel[ACOMP] = table[index * 2 + 1];
- break;
- case GL_RGB:
- texel[RCOMP] = table[index * 3 + 0];
- texel[GCOMP] = table[index * 3 + 1];
- texel[BCOMP] = table[index * 3 + 2];
- texel[ACOMP] = 1.0F;
- break;
- case GL_RGBA:
- texel[RCOMP] = table[index * 4 + 0];
- texel[GCOMP] = table[index * 4 + 1];
- texel[BCOMP] = table[index * 4 + 2];
- texel[ACOMP] = table[index * 4 + 3];
- break;
- default:
- _mesa_problem(ctx, "Bad palette format in fetch_texel_ci8");
- return;
- }
- }
-}
-
-#if DIM == 3
-static void store_texel_ci8(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLubyte *index = (const GLubyte *) texel;
- GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1);
- *dst = *index;
-}
-#endif
-
-
-/* Fetch texel from 1D, 2D or 3D srgb8 texture, return 4 GLfloats */
-/* Note: component order is same as for MESA_FORMAT_RGB888 */
-static void FETCH(srgb8)(const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 3);
- texel[RCOMP] = nonlinear_to_linear(src[2]);
- texel[GCOMP] = nonlinear_to_linear(src[1]);
- texel[BCOMP] = nonlinear_to_linear(src[0]);
- texel[ACOMP] = 1.0F;
-}
-
-#if DIM == 3
-static void store_texel_srgb8(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLubyte *rgba = (const GLubyte *) texel;
- GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 3);
- dst[0] = rgba[BCOMP]; /* no conversion */
- dst[1] = rgba[GCOMP];
- dst[2] = rgba[RCOMP];
-}
-#endif
-
-/* Fetch texel from 1D, 2D or 3D srgba8 texture, return 4 GLfloats */
-static void FETCH(srgba8)(const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLuint s = *TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
- texel[RCOMP] = nonlinear_to_linear( (s >> 24) );
- texel[GCOMP] = nonlinear_to_linear( (s >> 16) & 0xff );
- texel[BCOMP] = nonlinear_to_linear( (s >> 8) & 0xff );
- texel[ACOMP] = UBYTE_TO_FLOAT( (s ) & 0xff ); /* linear! */
-}
-
-#if DIM == 3
-static void store_texel_srgba8(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLubyte *rgba = (const GLubyte *) texel;
- GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
- *dst = PACK_COLOR_8888(rgba[RCOMP], rgba[GCOMP], rgba[BCOMP], rgba[ACOMP]);
-}
-#endif
-
-/* Fetch texel from 1D, 2D or 3D sargb8 texture, return 4 GLfloats */
-static void FETCH(sargb8)(const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLuint s = *TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
- texel[RCOMP] = nonlinear_to_linear( (s >> 16) & 0xff );
- texel[GCOMP] = nonlinear_to_linear( (s >> 8) & 0xff );
- texel[BCOMP] = nonlinear_to_linear( (s ) & 0xff );
- texel[ACOMP] = UBYTE_TO_FLOAT( (s >> 24) ); /* linear! */
-}
-
-#if DIM == 3
-static void store_texel_sargb8(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLubyte *rgba = (const GLubyte *) texel;
- GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
- *dst = PACK_COLOR_8888(rgba[ACOMP], rgba[RCOMP], rgba[GCOMP], rgba[BCOMP]);
-}
-#endif
-
-/* Fetch texel from 1D, 2D or 3D sl8 texture, return 4 GLfloats */
-static void FETCH(sl8)(const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1);
- texel[RCOMP] =
- texel[GCOMP] =
- texel[BCOMP] = nonlinear_to_linear(src[0]);
- texel[ACOMP] = 1.0F;
-}
-
-#if DIM == 3
-static void store_texel_sl8(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLubyte *rgba = (const GLubyte *) texel;
- GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1);
- dst[0] = rgba[RCOMP];
-}
-#endif
-
-/* Fetch texel from 1D, 2D or 3D sla8 texture, return 4 GLfloats */
-static void FETCH(sla8)(const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 2);
- texel[RCOMP] =
- texel[GCOMP] =
- texel[BCOMP] = nonlinear_to_linear(src[0]);
- texel[ACOMP] = UBYTE_TO_FLOAT(src[1]); /* linear */
-}
-
-#if DIM == 3
-static void store_texel_sla8(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLubyte *rgba = (const GLubyte *) texel;
- GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 2);
- dst[0] = rgba[RCOMP];
- dst[1] = rgba[ACOMP];
-}
-#endif
-
-
-/* MESA_FORMAT_RGBA_INT8 **************************************************/
-
-static void
-FETCH(rgba_int8)(const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLbyte *src = TEXEL_ADDR(GLbyte, texImage, i, j, k, 4);
- texel[RCOMP] = (GLfloat) src[0];
- texel[GCOMP] = (GLfloat) src[1];
- texel[BCOMP] = (GLfloat) src[2];
- texel[ACOMP] = (GLfloat) src[3];
-}
-
-#if DIM == 3
-static void
-store_texel_rgba_int8(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLbyte *rgba = (const GLbyte *) texel;
- GLbyte *dst = TEXEL_ADDR(GLbyte, texImage, i, j, k, 4);
- dst[0] = rgba[RCOMP];
- dst[1] = rgba[GCOMP];
- dst[2] = rgba[BCOMP];
- dst[3] = rgba[ACOMP];
-}
-#endif
-
-
-/* MESA_FORMAT_RGBA_INT16 **************************************************/
-
-static void
-FETCH(rgba_int16)(const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLshort *src = TEXEL_ADDR(GLshort, texImage, i, j, k, 4);
- texel[RCOMP] = (GLfloat) src[0];
- texel[GCOMP] = (GLfloat) src[1];
- texel[BCOMP] = (GLfloat) src[2];
- texel[ACOMP] = (GLfloat) src[3];
-}
-
-#if DIM == 3
-static void
-store_texel_rgba_int16(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLshort *rgba = (const GLshort *) texel;
- GLshort *dst = TEXEL_ADDR(GLshort, texImage, i, j, k, 4);
- dst[0] = rgba[RCOMP];
- dst[1] = rgba[GCOMP];
- dst[2] = rgba[BCOMP];
- dst[3] = rgba[ACOMP];
-}
-#endif
-
-
-/* MESA_FORMAT_RGBA_INT32 **************************************************/
-
-static void
-FETCH(rgba_int32)(const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLint *src = TEXEL_ADDR(GLint, texImage, i, j, k, 4);
- texel[RCOMP] = (GLfloat) src[0];
- texel[GCOMP] = (GLfloat) src[1];
- texel[BCOMP] = (GLfloat) src[2];
- texel[ACOMP] = (GLfloat) src[3];
-}
-
-#if DIM == 3
-static void
-store_texel_rgba_int32(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLint *rgba = (const GLint *) texel;
- GLint *dst = TEXEL_ADDR(GLint, texImage, i, j, k, 4);
- dst[0] = rgba[RCOMP];
- dst[1] = rgba[GCOMP];
- dst[2] = rgba[BCOMP];
- dst[3] = rgba[ACOMP];
-}
-#endif
-
-
-/* MESA_FORMAT_RGBA_UINT8 **************************************************/
-
-static void
-FETCH(rgba_uint8)(const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 4);
- texel[RCOMP] = (GLfloat) src[0];
- texel[GCOMP] = (GLfloat) src[1];
- texel[BCOMP] = (GLfloat) src[2];
- texel[ACOMP] = (GLfloat) src[3];
-}
-
-#if DIM == 3
-static void
-store_texel_rgba_uint8(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLubyte *rgba = (const GLubyte *) texel;
- GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 4);
- dst[0] = rgba[RCOMP];
- dst[1] = rgba[GCOMP];
- dst[2] = rgba[BCOMP];
- dst[3] = rgba[ACOMP];
-}
-#endif
-
-
-/* MESA_FORMAT_RGBA_UINT16 **************************************************/
-
-static void
-FETCH(rgba_uint16)(const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLushort *src = TEXEL_ADDR(GLushort, texImage, i, j, k, 4);
- texel[RCOMP] = (GLfloat) src[0];
- texel[GCOMP] = (GLfloat) src[1];
- texel[BCOMP] = (GLfloat) src[2];
- texel[ACOMP] = (GLfloat) src[3];
-}
-
-#if DIM == 3
-static void
-store_texel_rgba_uint16(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLushort *rgba = (const GLushort *) texel;
- GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 4);
- dst[0] = rgba[RCOMP];
- dst[1] = rgba[GCOMP];
- dst[2] = rgba[BCOMP];
- dst[3] = rgba[ACOMP];
-}
-#endif
-
-
-/* MESA_FORMAT_RGBA_UINT32 **************************************************/
-
-static void
-FETCH(rgba_uint32)(const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLuint *src = TEXEL_ADDR(GLuint, texImage, i, j, k, 4);
- texel[RCOMP] = (GLfloat) src[0];
- texel[GCOMP] = (GLfloat) src[1];
- texel[BCOMP] = (GLfloat) src[2];
- texel[ACOMP] = (GLfloat) src[3];
-}
-
-#if DIM == 3
-static void
-store_texel_rgba_uint32(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLuint *rgba = (const GLuint *) texel;
- GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 4);
- dst[0] = rgba[RCOMP];
- dst[1] = rgba[GCOMP];
- dst[2] = rgba[BCOMP];
- dst[3] = rgba[ACOMP];
-}
-#endif
-
-
-/* MESA_FORMAT_DUDV8 ********************************************************/
-
-/* this format by definition produces 0,0,0,1 as rgba values,
- however we'll return the dudv values as rg and fix up elsewhere */
-static void FETCH(dudv8)(const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLbyte *src = TEXEL_ADDR(GLbyte, texImage, i, j, k, 2);
- texel[RCOMP] = BYTE_TO_FLOAT(src[0]);
- texel[GCOMP] = BYTE_TO_FLOAT(src[1]);
- texel[BCOMP] = 0;
- texel[ACOMP] = 0;
-}
-
-
-/* MESA_FORMAT_SIGNED_R8 ***********************************************/
-
-static void FETCH(signed_r8)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLbyte s = *TEXEL_ADDR(GLbyte, texImage, i, j, k, 1);
- texel[RCOMP] = BYTE_TO_FLOAT_TEX( s );
- texel[GCOMP] = 0.0F;
- texel[BCOMP] = 0.0F;
- texel[ACOMP] = 1.0F;
-}
-
-#if DIM == 3
-static void store_texel_signed_r8(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLbyte *rgba = (const GLbyte *) texel;
- GLbyte *dst = TEXEL_ADDR(GLbyte, texImage, i, j, k, 1);
- *dst = rgba[RCOMP];
-}
-#endif
-
-
-/* MESA_FORMAT_SIGNED_A8 ***********************************************/
-
-static void FETCH(signed_a8)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLbyte s = *TEXEL_ADDR(GLbyte, texImage, i, j, k, 1);
- texel[RCOMP] = 0.0F;
- texel[GCOMP] = 0.0F;
- texel[BCOMP] = 0.0F;
- texel[ACOMP] = BYTE_TO_FLOAT_TEX( s );
-}
-
-#if DIM == 3
-static void store_texel_signed_a8(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLbyte *rgba = (const GLbyte *) texel;
- GLbyte *dst = TEXEL_ADDR(GLbyte, texImage, i, j, k, 1);
- *dst = rgba[ACOMP];
-}
-#endif
-
-
-/* MESA_FORMAT_SIGNED_L8 ***********************************************/
-
-static void FETCH(signed_l8)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLbyte s = *TEXEL_ADDR(GLbyte, texImage, i, j, k, 1);
- texel[RCOMP] =
- texel[GCOMP] =
- texel[BCOMP] = BYTE_TO_FLOAT_TEX( s );
- texel[ACOMP] = 1.0F;
-}
-
-#if DIM == 3
-static void store_texel_signed_l8(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLbyte *rgba = (const GLbyte *) texel;
- GLbyte *dst = TEXEL_ADDR(GLbyte, texImage, i, j, k, 1);
- *dst = rgba[RCOMP];
-}
-#endif
-
-
-/* MESA_FORMAT_SIGNED_I8 ***********************************************/
-
-static void FETCH(signed_i8)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLbyte s = *TEXEL_ADDR(GLbyte, texImage, i, j, k, 1);
- texel[RCOMP] =
- texel[GCOMP] =
- texel[BCOMP] =
- texel[ACOMP] = BYTE_TO_FLOAT_TEX( s );
-}
-
-#if DIM == 3
-static void store_texel_signed_i8(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLbyte *rgba = (const GLbyte *) texel;
- GLbyte *dst = TEXEL_ADDR(GLbyte, texImage, i, j, k, 1);
- *dst = rgba[RCOMP];
-}
-#endif
-
-
-/* MESA_FORMAT_SIGNED_RG88_REV ***********************************************/
-
-static void FETCH(signed_rg88_rev)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLushort s = *TEXEL_ADDR(GLshort, texImage, i, j, k, 1);
- texel[RCOMP] = BYTE_TO_FLOAT_TEX( (GLbyte) (s & 0xff) );
- texel[GCOMP] = BYTE_TO_FLOAT_TEX( (GLbyte) (s >> 8) );
- texel[BCOMP] = 0.0F;
- texel[ACOMP] = 1.0F;
-}
-
-#if DIM == 3
-static void store_texel_signed_rg88_rev(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLbyte *rg = (const GLbyte *) texel;
- GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
- dst[0] = PACK_COLOR_88(rg[GCOMP], rg[RCOMP]);
-}
-#endif
-
-
-/* MESA_FORMAT_SIGNED_AL88 ***********************************************/
-
-static void FETCH(signed_al88)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLushort s = *TEXEL_ADDR(GLshort, texImage, i, j, k, 1);
- texel[RCOMP] =
- texel[GCOMP] =
- texel[BCOMP] = BYTE_TO_FLOAT_TEX( (GLbyte) (s & 0xff) );
- texel[ACOMP] = BYTE_TO_FLOAT_TEX( (GLbyte) (s >> 8) );
-}
-
-#if DIM == 3
-static void store_texel_signed_al88(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLbyte *rg = (const GLbyte *) texel;
- GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
- dst[0] = PACK_COLOR_88(rg[ACOMP], rg[RCOMP]);
-}
-#endif
-
-
-/* MESA_FORMAT_SIGNED_RGBX8888 ***********************************************/
-
-static void FETCH(signed_rgbx8888)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLuint s = *TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
- texel[RCOMP] = BYTE_TO_FLOAT_TEX( (GLbyte) (s >> 24) );
- texel[GCOMP] = BYTE_TO_FLOAT_TEX( (GLbyte) (s >> 16) );
- texel[BCOMP] = BYTE_TO_FLOAT_TEX( (GLbyte) (s >> 8) );
- texel[ACOMP] = 1.0f;
-}
-
-#if DIM == 3
-static void store_texel_signed_rgbx8888(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLbyte *rgba = (const GLbyte *) texel;
- GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
- *dst = PACK_COLOR_8888(rgba[RCOMP], rgba[GCOMP], rgba[BCOMP], 255);
-}
-#endif
-
-
-/* MESA_FORMAT_SIGNED_RGBA8888 ***********************************************/
-
-static void FETCH(signed_rgba8888)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLuint s = *TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
- texel[RCOMP] = BYTE_TO_FLOAT_TEX( (GLbyte) (s >> 24) );
- texel[GCOMP] = BYTE_TO_FLOAT_TEX( (GLbyte) (s >> 16) );
- texel[BCOMP] = BYTE_TO_FLOAT_TEX( (GLbyte) (s >> 8) );
- texel[ACOMP] = BYTE_TO_FLOAT_TEX( (GLbyte) (s ) );
-}
-
-#if DIM == 3
-static void store_texel_signed_rgba8888(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLbyte *rgba = (const GLbyte *) texel;
- GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
- *dst = PACK_COLOR_8888(rgba[RCOMP], rgba[GCOMP], rgba[BCOMP], rgba[ACOMP]);
-}
-#endif
-
-static void FETCH(signed_rgba8888_rev)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLuint s = *TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
- texel[RCOMP] = BYTE_TO_FLOAT_TEX( (GLbyte) (s ) );
- texel[GCOMP] = BYTE_TO_FLOAT_TEX( (GLbyte) (s >> 8) );
- texel[BCOMP] = BYTE_TO_FLOAT_TEX( (GLbyte) (s >> 16) );
- texel[ACOMP] = BYTE_TO_FLOAT_TEX( (GLbyte) (s >> 24) );
-}
-
-#if DIM == 3
-static void store_texel_signed_rgba8888_rev(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLubyte *rgba = (const GLubyte *) texel;
- GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
- *dst = PACK_COLOR_8888_REV(rgba[RCOMP], rgba[GCOMP], rgba[BCOMP], rgba[ACOMP]);
-}
-#endif
-
-
-
-/* MESA_FORMAT_SIGNED_R16 ***********************************************/
-
-static void
-FETCH(signed_r16)(const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel)
-{
- const GLshort s = *TEXEL_ADDR(GLshort, texImage, i, j, k, 1);
- texel[RCOMP] = SHORT_TO_FLOAT_TEX( s );
- texel[GCOMP] = 0.0F;
- texel[BCOMP] = 0.0F;
- texel[ACOMP] = 1.0F;
-}
-
-#if DIM == 3
-static void
-store_texel_signed_r16(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLshort *rgba = (const GLshort *) texel;
- GLshort *dst = TEXEL_ADDR(GLshort, texImage, i, j, k, 1);
- *dst = rgba[0];
-}
-#endif
-
-
-/* MESA_FORMAT_SIGNED_A16 ***********************************************/
-
-static void
-FETCH(signed_a16)(const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel)
-{
- const GLshort s = *TEXEL_ADDR(GLshort, texImage, i, j, k, 1);
- texel[RCOMP] = 0.0F;
- texel[GCOMP] = 0.0F;
- texel[BCOMP] = 0.0F;
- texel[ACOMP] = SHORT_TO_FLOAT_TEX( s );
-}
-
-#if DIM == 3
-static void
-store_texel_signed_a16(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLshort *rgba = (const GLshort *) texel;
- GLshort *dst = TEXEL_ADDR(GLshort, texImage, i, j, k, 1);
- *dst = rgba[ACOMP];
-}
-#endif
-
-
-/* MESA_FORMAT_SIGNED_L16 ***********************************************/
-
-static void
-FETCH(signed_l16)(const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel)
-{
- const GLshort s = *TEXEL_ADDR(GLshort, texImage, i, j, k, 1);
- texel[RCOMP] =
- texel[GCOMP] =
- texel[BCOMP] = SHORT_TO_FLOAT_TEX( s );
- texel[ACOMP] = 1.0F;
-}
-
-#if DIM == 3
-static void
-store_texel_signed_l16(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLshort *rgba = (const GLshort *) texel;
- GLshort *dst = TEXEL_ADDR(GLshort, texImage, i, j, k, 1);
- *dst = rgba[RCOMP];
-}
-#endif
-
-
-/* MESA_FORMAT_SIGNED_I16 ***********************************************/
-
-static void
-FETCH(signed_i16)(const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel)
-{
- const GLshort s = *TEXEL_ADDR(GLshort, texImage, i, j, k, 1);
- texel[RCOMP] =
- texel[GCOMP] =
- texel[BCOMP] =
- texel[ACOMP] = SHORT_TO_FLOAT_TEX( s );
-}
-
-#if DIM == 3
-static void
-store_texel_signed_i16(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLshort *rgba = (const GLshort *) texel;
- GLshort *dst = TEXEL_ADDR(GLshort, texImage, i, j, k, 1);
- *dst = rgba[RCOMP];
-}
-#endif
-
-
-/* MESA_FORMAT_SIGNED_RG1616 ***********************************************/
-
-static void
-FETCH(signed_rg1616)(const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel)
-{
- const GLshort *s = TEXEL_ADDR(GLshort, texImage, i, j, k, 2);
- texel[RCOMP] = SHORT_TO_FLOAT_TEX( s[0] );
- texel[GCOMP] = SHORT_TO_FLOAT_TEX( s[1] );
- texel[BCOMP] = 0.0F;
- texel[ACOMP] = 1.0F;
-}
-
-#if DIM == 3
-static void
-store_texel_signed_rg1616(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLshort *rgba = (const GLshort *) texel;
- GLshort *dst = TEXEL_ADDR(GLshort, texImage, i, j, k, 2);
- dst[0] = rgba[RCOMP];
- dst[1] = rgba[GCOMP];
-}
-#endif
-
-
-/* MESA_FORMAT_SIGNED_AL1616 ***********************************************/
-
-static void
-FETCH(signed_al1616)(const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel)
-{
- const GLshort *s = TEXEL_ADDR(GLshort, texImage, i, j, k, 2);
- texel[RCOMP] =
- texel[GCOMP] =
- texel[BCOMP] = SHORT_TO_FLOAT_TEX( s[0] );
- texel[ACOMP] = SHORT_TO_FLOAT_TEX( s[1] );
-}
-
-#if DIM == 3
-static void
-store_texel_signed_al1616(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLshort *rgba = (const GLshort *) texel;
- GLshort *dst = TEXEL_ADDR(GLshort, texImage, i, j, k, 2);
- dst[0] = rgba[RCOMP];
- dst[1] = rgba[ACOMP];
-}
-#endif
-
-
-/* MESA_FORMAT_SIGNED_RGB_16 ***********************************************/
-
-static void
-FETCH(signed_rgb_16)(const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel)
-{
- const GLshort *s = TEXEL_ADDR(GLshort, texImage, i, j, k, 3);
- texel[RCOMP] = SHORT_TO_FLOAT_TEX( s[0] );
- texel[GCOMP] = SHORT_TO_FLOAT_TEX( s[1] );
- texel[BCOMP] = SHORT_TO_FLOAT_TEX( s[2] );
- texel[ACOMP] = 1.0F;
-}
-
-#if DIM == 3
-static void
-store_texel_signed_rgb_16(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLshort *rgba = (const GLshort *) texel;
- GLshort *dst = TEXEL_ADDR(GLshort, texImage, i, j, k, 3);
- dst[0] = rgba[RCOMP];
- dst[1] = rgba[GCOMP];
- dst[2] = rgba[BCOMP];
-}
-#endif
-
-
-/* MESA_FORMAT_SIGNED_RGBA_16 ***********************************************/
-
-static void
-FETCH(signed_rgba_16)(const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel)
-{
- const GLshort *s = TEXEL_ADDR(GLshort, texImage, i, j, k, 4);
- texel[RCOMP] = SHORT_TO_FLOAT_TEX( s[0] );
- texel[GCOMP] = SHORT_TO_FLOAT_TEX( s[1] );
- texel[BCOMP] = SHORT_TO_FLOAT_TEX( s[2] );
- texel[ACOMP] = SHORT_TO_FLOAT_TEX( s[3] );
-}
-
-#if DIM == 3
-static void
-store_texel_signed_rgba_16(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLshort *rgba = (const GLshort *) texel;
- GLshort *dst = TEXEL_ADDR(GLshort, texImage, i, j, k, 4);
- dst[0] = rgba[RCOMP];
- dst[1] = rgba[GCOMP];
- dst[2] = rgba[BCOMP];
- dst[3] = rgba[ACOMP];
-}
-#endif
-
-
-
-/* MESA_FORMAT_RGBA_16 ***********************************************/
-
-static void
-FETCH(rgba_16)(const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel)
-{
- const GLushort *s = TEXEL_ADDR(GLushort, texImage, i, j, k, 4);
- texel[RCOMP] = USHORT_TO_FLOAT( s[0] );
- texel[GCOMP] = USHORT_TO_FLOAT( s[1] );
- texel[BCOMP] = USHORT_TO_FLOAT( s[2] );
- texel[ACOMP] = USHORT_TO_FLOAT( s[3] );
-}
-
-#if DIM == 3
-static void
-store_texel_rgba_16(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLushort *rgba = (const GLushort *) texel;
- GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 4);
- dst[0] = rgba[RCOMP];
- dst[1] = rgba[GCOMP];
- dst[2] = rgba[BCOMP];
- dst[3] = rgba[ACOMP];
-}
-#endif
-
-
-
-/* MESA_FORMAT_YCBCR *********************************************************/
-
-/* Fetch texel from 1D, 2D or 3D ycbcr texture, return 4 GLfloats.
- * We convert YCbCr to RGB here.
- */
-static void FETCH(f_ycbcr)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLushort *src0 = TEXEL_ADDR(GLushort, texImage, (i & ~1), j, k, 1); /* even */
- const GLushort *src1 = src0 + 1; /* odd */
- const GLubyte y0 = (*src0 >> 8) & 0xff; /* luminance */
- const GLubyte cb = *src0 & 0xff; /* chroma U */
- const GLubyte y1 = (*src1 >> 8) & 0xff; /* luminance */
- const GLubyte cr = *src1 & 0xff; /* chroma V */
- const GLubyte y = (i & 1) ? y1 : y0; /* choose even/odd luminance */
- GLfloat r = 1.164F * (y - 16) + 1.596F * (cr - 128);
- GLfloat g = 1.164F * (y - 16) - 0.813F * (cr - 128) - 0.391F * (cb - 128);
- GLfloat b = 1.164F * (y - 16) + 2.018F * (cb - 128);
- r *= (1.0F / 255.0F);
- g *= (1.0F / 255.0F);
- b *= (1.0F / 255.0F);
- texel[RCOMP] = CLAMP(r, 0.0F, 1.0F);
- texel[GCOMP] = CLAMP(g, 0.0F, 1.0F);
- texel[BCOMP] = CLAMP(b, 0.0F, 1.0F);
- texel[ACOMP] = 1.0F;
-}
-
-#if DIM == 3
-static void store_texel_ycbcr(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- (void) texImage;
- (void) i;
- (void) j;
- (void) k;
- (void) texel;
- /* XXX to do */
-}
-#endif
-
-
-/* MESA_FORMAT_YCBCR_REV *****************************************************/
-
-/* Fetch texel from 1D, 2D or 3D ycbcr_rev texture, return 4 GLfloats.
- * We convert YCbCr to RGB here.
- */
-static void FETCH(f_ycbcr_rev)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLushort *src0 = TEXEL_ADDR(GLushort, texImage, (i & ~1), j, k, 1); /* even */
- const GLushort *src1 = src0 + 1; /* odd */
- const GLubyte y0 = *src0 & 0xff; /* luminance */
- const GLubyte cr = (*src0 >> 8) & 0xff; /* chroma V */
- const GLubyte y1 = *src1 & 0xff; /* luminance */
- const GLubyte cb = (*src1 >> 8) & 0xff; /* chroma U */
- const GLubyte y = (i & 1) ? y1 : y0; /* choose even/odd luminance */
- GLfloat r = 1.164F * (y - 16) + 1.596F * (cr - 128);
- GLfloat g = 1.164F * (y - 16) - 0.813F * (cr - 128) - 0.391F * (cb - 128);
- GLfloat b = 1.164F * (y - 16) + 2.018F * (cb - 128);
- r *= (1.0F / 255.0F);
- g *= (1.0F / 255.0F);
- b *= (1.0F / 255.0F);
- texel[RCOMP] = CLAMP(r, 0.0F, 1.0F);
- texel[GCOMP] = CLAMP(g, 0.0F, 1.0F);
- texel[BCOMP] = CLAMP(b, 0.0F, 1.0F);
- texel[ACOMP] = 1.0F;
-}
-
-#if DIM == 3
-static void store_texel_ycbcr_rev(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- (void) texImage;
- (void) i;
- (void) j;
- (void) k;
- (void) texel;
- /* XXX to do */
-}
-#endif
-
-
-/* MESA_TEXFORMAT_Z24_S8 ***************************************************/
-
-static void FETCH(f_z24_s8)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- /* only return Z, not stencil data */
- const GLuint *src = TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
- const GLfloat scale = 1.0F / (GLfloat) 0xffffff;
- texel[0] = ((*src) >> 8) * scale;
- ASSERT(texImage->TexFormat == MESA_FORMAT_Z24_S8);
- ASSERT(texel[0] >= 0.0F);
- ASSERT(texel[0] <= 1.0F);
-}
-
-#if DIM == 3
-static void store_texel_z24_s8(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- /* only store Z, not stencil */
- GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
- GLfloat depth = *((GLfloat *) texel);
- GLuint zi = ((GLuint) (depth * 0xffffff)) << 8;
- *dst = zi | (*dst & 0xff);
-}
-#endif
-
-
-/* MESA_TEXFORMAT_S8_Z24 ***************************************************/
-
-static void FETCH(f_s8_z24)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- /* only return Z, not stencil data */
- const GLuint *src = TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
- const GLfloat scale = 1.0F / (GLfloat) 0xffffff;
- texel[0] = ((*src) & 0x00ffffff) * scale;
- ASSERT(texImage->TexFormat == MESA_FORMAT_S8_Z24);
- ASSERT(texel[0] >= 0.0F);
- ASSERT(texel[0] <= 1.0F);
-}
-
-#if DIM == 3
-static void store_texel_s8_z24(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- /* only store Z, not stencil */
- GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
- GLfloat depth = *((GLfloat *) texel);
- GLuint zi = (GLuint) (depth * 0xffffff);
- *dst = zi | (*dst & 0xff000000);
-}
-#endif
-
-
-/* MESA_FORMAT_RGB9_E5 ******************************************************/
-
-static void FETCH(rgb9_e5)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLuint *src = TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
- rgb9e5_to_float3(*src, texel);
- texel[ACOMP] = 1.0F;
-}
-
-#if DIM == 3
-static void store_texel_rgb9_e5(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLfloat *src = (const GLfloat *) texel;
- GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
- *dst = float3_to_rgb9e5(src);
-}
-#endif
-
-
-/* MESA_FORMAT_R11_G11_B10_FLOAT *********************************************/
-
-static void FETCH(r11_g11_b10f)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
-{
- const GLuint *src = TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
- r11g11b10f_to_float3(*src, texel);
- texel[ACOMP] = 1.0F;
-}
-
-#if DIM == 3
-static void store_texel_r11_g11_b10f(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
-{
- const GLfloat *src = (const GLfloat *) texel;
- GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
- *dst = float3_to_r11g11b10f(src);
-}
-#endif
-
-
-#undef TEXEL_ADDR
-#undef DIM
-#undef FETCH
+/* + * Mesa 3-D graphics library + * Version: 7.7 + * + * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. + * Copyright (c) 2008-2009 VMware, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +/** + * \file texfetch_tmp.h + * Texel fetch functions template. + * + * This template file is used by texfetch.c to generate texel fetch functions + * for 1-D, 2-D and 3-D texture images. + * + * It should be expanded by defining \p DIM as the number texture dimensions + * (1, 2 or 3). According to the value of \p DIM a series of macros is defined + * for the texel lookup in the gl_texture_image::Data. + * + * \author Gareth Hughes + * \author Brian Paul + */ + + +#if DIM == 1 + +#define TEXEL_ADDR( type, image, i, j, k, size ) \ + ((void) (j), (void) (k), ((type *)(image)->Data + (i) * (size))) + +#define FETCH(x) fetch_texel_1d_##x + +#elif DIM == 2 + +#define TEXEL_ADDR( type, image, i, j, k, size ) \ + ((void) (k), \ + ((type *)(image)->Data + ((image)->RowStride * (j) + (i)) * (size))) + +#define FETCH(x) fetch_texel_2d_##x + +#elif DIM == 3 + +#define TEXEL_ADDR( type, image, i, j, k, size ) \ + ((type *)(image)->Data + ((image)->ImageOffsets[k] \ + + (image)->RowStride * (j) + (i)) * (size)) + +#define FETCH(x) fetch_texel_3d_##x + +#else +#error illegal number of texture dimensions +#endif + + +/* MESA_FORMAT_Z32 ***********************************************************/ + +/* Fetch depth texel from 1D, 2D or 3D 32-bit depth texture, + * returning 1 GLfloat. + * Note: no GLchan version of this function. + */ +static void FETCH(f_z32)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLuint *src = TEXEL_ADDR(GLuint, texImage, i, j, k, 1); + texel[0] = src[0] * (1.0F / 0xffffffff); +} + +#if DIM == 3 +static void store_texel_z32(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLuint *depth = (const GLuint *) texel; + GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1); + dst[0] = *depth; +} +#endif + + +/* MESA_FORMAT_Z16 ***********************************************************/ + +/* Fetch depth texel from 1D, 2D or 3D 16-bit depth texture, + * returning 1 GLfloat. + * Note: no GLchan version of this function. + */ +static void FETCH(f_z16)(const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort *src = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + texel[0] = src[0] * (1.0F / 65535.0F); +} + +#if DIM == 3 +static void store_texel_z16(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLushort *depth = (const GLushort *) texel; + GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + dst[0] = *depth; +} +#endif + + +/* MESA_FORMAT_RGBA_F32 ******************************************************/ + +/* Fetch texel from 1D, 2D or 3D RGBA_FLOAT32 texture, returning 4 GLfloats. + */ +static void FETCH(f_rgba_f32)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLfloat *src = TEXEL_ADDR(GLfloat, texImage, i, j, k, 4); + texel[RCOMP] = src[0]; + texel[GCOMP] = src[1]; + texel[BCOMP] = src[2]; + texel[ACOMP] = src[3]; +} + +#if DIM == 3 +static void store_texel_rgba_f32(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLfloat *depth = (const GLfloat *) texel; + GLfloat *dst = TEXEL_ADDR(GLfloat, texImage, i, j, k, 4); + dst[0] = depth[RCOMP]; + dst[1] = depth[GCOMP]; + dst[2] = depth[BCOMP]; + dst[3] = depth[ACOMP]; +} +#endif + + +/* MESA_FORMAT_RGBA_F16 ******************************************************/ + +/* Fetch texel from 1D, 2D or 3D RGBA_FLOAT16 texture, + * returning 4 GLfloats. + */ +static void FETCH(f_rgba_f16)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLhalfARB *src = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 4); + texel[RCOMP] = _mesa_half_to_float(src[0]); + texel[GCOMP] = _mesa_half_to_float(src[1]); + texel[BCOMP] = _mesa_half_to_float(src[2]); + texel[ACOMP] = _mesa_half_to_float(src[3]); +} + +#if DIM == 3 +static void store_texel_rgba_f16(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLfloat *src = (const GLfloat *) texel; + GLhalfARB *dst = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 4); + dst[0] = _mesa_float_to_half(src[RCOMP]); + dst[1] = _mesa_float_to_half(src[GCOMP]); + dst[2] = _mesa_float_to_half(src[BCOMP]); + dst[3] = _mesa_float_to_half(src[ACOMP]); +} +#endif + +/* MESA_FORMAT_RGB_F32 *******************************************************/ + +/* Fetch texel from 1D, 2D or 3D RGB_FLOAT32 texture, + * returning 4 GLfloats. + */ +static void FETCH(f_rgb_f32)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLfloat *src = TEXEL_ADDR(GLfloat, texImage, i, j, k, 3); + texel[RCOMP] = src[0]; + texel[GCOMP] = src[1]; + texel[BCOMP] = src[2]; + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_rgb_f32(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLfloat *src = (const GLfloat *) texel; + GLfloat *dst = TEXEL_ADDR(GLfloat, texImage, i, j, k, 3); + dst[0] = src[RCOMP]; + dst[1] = src[GCOMP]; + dst[2] = src[BCOMP]; +} +#endif + + +/* MESA_FORMAT_RGB_F16 *******************************************************/ + +/* Fetch texel from 1D, 2D or 3D RGB_FLOAT16 texture, + * returning 4 GLfloats. + */ +static void FETCH(f_rgb_f16)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLhalfARB *src = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 3); + texel[RCOMP] = _mesa_half_to_float(src[0]); + texel[GCOMP] = _mesa_half_to_float(src[1]); + texel[BCOMP] = _mesa_half_to_float(src[2]); + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_rgb_f16(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLfloat *src = (const GLfloat *) texel; + GLhalfARB *dst = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 3); + dst[0] = _mesa_float_to_half(src[RCOMP]); + dst[1] = _mesa_float_to_half(src[GCOMP]); + dst[2] = _mesa_float_to_half(src[BCOMP]); +} +#endif + + +/* MESA_FORMAT_ALPHA_F32 *****************************************************/ + +/* Fetch texel from 1D, 2D or 3D ALPHA_FLOAT32 texture, + * returning 4 GLfloats. + */ +static void FETCH(f_alpha_f32)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLfloat *src = TEXEL_ADDR(GLfloat, texImage, i, j, k, 1); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = 0.0F; + texel[ACOMP] = src[0]; +} + +#if DIM == 3 +static void store_texel_alpha_f32(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLfloat *rgba = (const GLfloat *) texel; + GLfloat *dst = TEXEL_ADDR(GLfloat, texImage, i, j, k, 1); + dst[0] = rgba[ACOMP]; +} +#endif + + +/* MESA_FORMAT_ALPHA_F32 *****************************************************/ + +/* Fetch texel from 1D, 2D or 3D ALPHA_FLOAT16 texture, + * returning 4 GLfloats. + */ +static void FETCH(f_alpha_f16)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLhalfARB *src = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 1); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = 0.0F; + texel[ACOMP] = _mesa_half_to_float(src[0]); +} + +#if DIM == 3 +static void store_texel_alpha_f16(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLfloat *rgba = (const GLfloat *) texel; + GLhalfARB *dst = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 1); + dst[0] = _mesa_float_to_half(rgba[ACOMP]); +} +#endif + + +/* MESA_FORMAT_LUMINANCE_F32 *************************************************/ + +/* Fetch texel from 1D, 2D or 3D LUMINANCE_FLOAT32 texture, + * returning 4 GLfloats. + */ +static void FETCH(f_luminance_f32)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLfloat *src = TEXEL_ADDR(GLfloat, texImage, i, j, k, 1); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = src[0]; + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_luminance_f32(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLfloat *rgba = (const GLfloat *) texel; + GLfloat *dst = TEXEL_ADDR(GLfloat, texImage, i, j, k, 1); + dst[0] = rgba[RCOMP]; +} +#endif + + +/* MESA_FORMAT_LUMINANCE_F16 *************************************************/ + +/* Fetch texel from 1D, 2D or 3D LUMINANCE_FLOAT16 texture, + * returning 4 GLfloats. + */ +static void FETCH(f_luminance_f16)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLhalfARB *src = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 1); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = _mesa_half_to_float(src[0]); + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_luminance_f16(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLfloat *rgba = (const GLfloat *) texel; + GLhalfARB *dst = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 1); + dst[0] = _mesa_float_to_half(rgba[RCOMP]); +} +#endif + + +/* MESA_FORMAT_LUMINANCE_ALPHA_F32 *******************************************/ + +/* Fetch texel from 1D, 2D or 3D LUMINANCE_ALPHA_FLOAT32 texture, + * returning 4 GLfloats. + */ +static void FETCH(f_luminance_alpha_f32)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLfloat *src = TEXEL_ADDR(GLfloat, texImage, i, j, k, 2); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = src[0]; + texel[ACOMP] = src[1]; +} + +#if DIM == 3 +static void store_texel_luminance_alpha_f32(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLfloat *rgba = (const GLfloat *) texel; + GLfloat *dst = TEXEL_ADDR(GLfloat, texImage, i, j, k, 2); + dst[0] = rgba[RCOMP]; + dst[1] = rgba[ACOMP]; +} +#endif + + +/* MESA_FORMAT_LUMINANCE_ALPHA_F16 *******************************************/ + +/* Fetch texel from 1D, 2D or 3D LUMINANCE_ALPHA_FLOAT16 texture, + * returning 4 GLfloats. + */ +static void FETCH(f_luminance_alpha_f16)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLhalfARB *src = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 2); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = _mesa_half_to_float(src[0]); + texel[ACOMP] = _mesa_half_to_float(src[1]); +} + +#if DIM == 3 +static void store_texel_luminance_alpha_f16(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLfloat *rgba = (const GLfloat *) texel; + GLhalfARB *dst = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 2); + dst[0] = _mesa_float_to_half(rgba[RCOMP]); + dst[1] = _mesa_float_to_half(rgba[ACOMP]); +} +#endif + + +/* MESA_FORMAT_INTENSITY_F32 *************************************************/ + +/* Fetch texel from 1D, 2D or 3D INTENSITY_FLOAT32 texture, + * returning 4 GLfloats. + */ +static void FETCH(f_intensity_f32)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLfloat *src = TEXEL_ADDR(GLfloat, texImage, i, j, k, 1); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = + texel[ACOMP] = src[0]; +} + +#if DIM == 3 +static void store_texel_intensity_f32(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLfloat *rgba = (const GLfloat *) texel; + GLfloat *dst = TEXEL_ADDR(GLfloat, texImage, i, j, k, 1); + dst[0] = rgba[RCOMP]; +} +#endif + + +/* MESA_FORMAT_INTENSITY_F16 *************************************************/ + +/* Fetch texel from 1D, 2D or 3D INTENSITY_FLOAT16 texture, + * returning 4 GLfloats. + */ +static void FETCH(f_intensity_f16)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLhalfARB *src = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 1); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = + texel[ACOMP] = _mesa_half_to_float(src[0]); +} + +#if DIM == 3 +static void store_texel_intensity_f16(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLfloat *rgba = (const GLfloat *) texel; + GLhalfARB *dst = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 1); + dst[0] = _mesa_float_to_half(rgba[RCOMP]); +} +#endif + + +/* MESA_FORMAT_R_FLOAT32 *****************************************************/ + +/* Fetch texel from 1D, 2D or 3D R_FLOAT32 texture, + * returning 4 GLfloats. + */ +static void FETCH(f_r_f32)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLfloat *src = TEXEL_ADDR(GLfloat, texImage, i, j, k, 1); + texel[RCOMP] = src[0]; + texel[GCOMP] = 0.0F; + texel[BCOMP] = 0.0F; + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_r_f32(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLfloat *rgba = (const GLfloat *) texel; + GLfloat *dst = TEXEL_ADDR(GLfloat, texImage, i, j, k, 1); + dst[0] = rgba[RCOMP]; +} +#endif + + +/* MESA_FORMAT_R_FLOAT16 *****************************************************/ + +/* Fetch texel from 1D, 2D or 3D R_FLOAT16 texture, + * returning 4 GLfloats. + */ +static void FETCH(f_r_f16)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLhalfARB *src = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 1); + texel[RCOMP] = _mesa_half_to_float(src[0]); + texel[GCOMP] = 0.0F; + texel[BCOMP] = 0.0F; + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_r_f16(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLfloat *rgba = (const GLfloat *) texel; + GLhalfARB *dst = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 1); + dst[0] = _mesa_float_to_half(rgba[RCOMP]); +} +#endif + + +/* MESA_FORMAT_RG_FLOAT32 ****************************************************/ + +/* Fetch texel from 1D, 2D or 3D RG_FLOAT32 texture, + * returning 4 GLfloats. + */ +static void FETCH(f_rg_f32)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLfloat *src = TEXEL_ADDR(GLfloat, texImage, i, j, k, 2); + texel[RCOMP] = src[0]; + texel[GCOMP] = src[1]; + texel[BCOMP] = 0.0F; + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_rg_f32(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLfloat *rgba = (const GLfloat *) texel; + GLfloat *dst = TEXEL_ADDR(GLfloat, texImage, i, j, k, 2); + dst[0] = rgba[RCOMP]; + dst[1] = rgba[GCOMP]; +} +#endif + + +/* MESA_FORMAT_RG_FLOAT16 ****************************************************/ + +/* Fetch texel from 1D, 2D or 3D RG_FLOAT16 texture, + * returning 4 GLfloats. + */ +static void FETCH(f_rg_f16)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLhalfARB *src = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 2); + texel[RCOMP] = _mesa_half_to_float(src[0]); + texel[GCOMP] = _mesa_half_to_float(src[1]); + texel[BCOMP] = 0.0F; + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_rg_f16(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLfloat *rgba = (const GLfloat *) texel; + GLhalfARB *dst = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 2); + dst[0] = _mesa_float_to_half(rgba[RCOMP]); + dst[1] = _mesa_float_to_half(rgba[GCOMP]); +} +#endif + + +/* + * Begin Hardware formats + */ + +/* MESA_FORMAT_RGBA8888 ******************************************************/ + +/* Fetch texel from 1D, 2D or 3D rgba8888 texture, return 4 GLfloats */ +static void FETCH(f_rgba8888)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLuint s = *TEXEL_ADDR(GLuint, texImage, i, j, k, 1); + texel[RCOMP] = UBYTE_TO_FLOAT( (s >> 24) ); + texel[GCOMP] = UBYTE_TO_FLOAT( (s >> 16) & 0xff ); + texel[BCOMP] = UBYTE_TO_FLOAT( (s >> 8) & 0xff ); + texel[ACOMP] = UBYTE_TO_FLOAT( (s ) & 0xff ); +} + + + +#if DIM == 3 +static void store_texel_rgba8888(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1); + *dst = PACK_COLOR_8888(rgba[RCOMP], rgba[GCOMP], rgba[BCOMP], rgba[ACOMP]); +} +#endif + + +/* MESA_FORMAT_RGBA888_REV ***************************************************/ + +/* Fetch texel from 1D, 2D or 3D abgr8888 texture, return 4 GLchans */ +static void FETCH(f_rgba8888_rev)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLuint s = *TEXEL_ADDR(GLuint, texImage, i, j, k, 1); + texel[RCOMP] = UBYTE_TO_FLOAT( (s ) & 0xff ); + texel[GCOMP] = UBYTE_TO_FLOAT( (s >> 8) & 0xff ); + texel[BCOMP] = UBYTE_TO_FLOAT( (s >> 16) & 0xff ); + texel[ACOMP] = UBYTE_TO_FLOAT( (s >> 24) ); +} + +#if DIM == 3 +static void store_texel_rgba8888_rev(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1); + *dst = PACK_COLOR_8888_REV(rgba[RCOMP], rgba[GCOMP], rgba[BCOMP], rgba[ACOMP]); +} +#endif + + +/* MESA_FORMAT_ARGB8888 ******************************************************/ + +/* Fetch texel from 1D, 2D or 3D argb8888 texture, return 4 GLchans */ +static void FETCH(f_argb8888)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLuint s = *TEXEL_ADDR(GLuint, texImage, i, j, k, 1); + texel[RCOMP] = UBYTE_TO_FLOAT( (s >> 16) & 0xff ); + texel[GCOMP] = UBYTE_TO_FLOAT( (s >> 8) & 0xff ); + texel[BCOMP] = UBYTE_TO_FLOAT( (s ) & 0xff ); + texel[ACOMP] = UBYTE_TO_FLOAT( (s >> 24) ); +} + +#if DIM == 3 +static void store_texel_argb8888(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1); + *dst = PACK_COLOR_8888(rgba[ACOMP], rgba[RCOMP], rgba[GCOMP], rgba[BCOMP]); +} +#endif + + +/* MESA_FORMAT_ARGB8888_REV **************************************************/ + +/* Fetch texel from 1D, 2D or 3D argb8888_rev texture, return 4 GLfloats */ +static void FETCH(f_argb8888_rev)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLuint s = *TEXEL_ADDR(GLuint, texImage, i, j, k, 1); + texel[RCOMP] = UBYTE_TO_FLOAT( (s >> 8) & 0xff ); + texel[GCOMP] = UBYTE_TO_FLOAT( (s >> 16) & 0xff ); + texel[BCOMP] = UBYTE_TO_FLOAT( (s >> 24) ); + texel[ACOMP] = UBYTE_TO_FLOAT( (s ) & 0xff ); +} + +#if DIM == 3 +static void store_texel_argb8888_rev(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1); + *dst = PACK_COLOR_8888(rgba[BCOMP], rgba[GCOMP], rgba[RCOMP], rgba[ACOMP]); +} +#endif + + +/* MESA_FORMAT_XRGB8888 ******************************************************/ + +/* Fetch texel from 1D, 2D or 3D xrgb8888 texture, return 4 GLchans */ +static void FETCH(f_xrgb8888)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLuint s = *TEXEL_ADDR(GLuint, texImage, i, j, k, 1); + texel[RCOMP] = UBYTE_TO_FLOAT( (s >> 16) & 0xff ); + texel[GCOMP] = UBYTE_TO_FLOAT( (s >> 8) & 0xff ); + texel[BCOMP] = UBYTE_TO_FLOAT( (s ) & 0xff ); + texel[ACOMP] = 1.0f; +} + +#if DIM == 3 +static void store_texel_xrgb8888(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1); + *dst = PACK_COLOR_8888(0xff, rgba[RCOMP], rgba[GCOMP], rgba[BCOMP]); +} +#endif + + +/* MESA_FORMAT_XRGB8888_REV **************************************************/ + +/* Fetch texel from 1D, 2D or 3D xrgb8888_rev texture, return 4 GLfloats */ +static void FETCH(f_xrgb8888_rev)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLuint s = *TEXEL_ADDR(GLuint, texImage, i, j, k, 1); + texel[RCOMP] = UBYTE_TO_FLOAT( (s >> 8) & 0xff ); + texel[GCOMP] = UBYTE_TO_FLOAT( (s >> 16) & 0xff ); + texel[BCOMP] = UBYTE_TO_FLOAT( (s >> 24) ); + texel[ACOMP] = 1.0f; +} + +#if DIM == 3 +static void store_texel_xrgb8888_rev(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1); + *dst = PACK_COLOR_8888(rgba[BCOMP], rgba[GCOMP], rgba[RCOMP], 0xff); +} +#endif + + +/* MESA_FORMAT_RGB888 ********************************************************/ + +/* Fetch texel from 1D, 2D or 3D rgb888 texture, return 4 GLchans */ +static void FETCH(f_rgb888)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 3); + texel[RCOMP] = UBYTE_TO_FLOAT( src[2] ); + texel[GCOMP] = UBYTE_TO_FLOAT( src[1] ); + texel[BCOMP] = UBYTE_TO_FLOAT( src[0] ); + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_rgb888(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 3); + dst[0] = rgba[BCOMP]; + dst[1] = rgba[GCOMP]; + dst[2] = rgba[RCOMP]; +} +#endif + + +/* MESA_FORMAT_BGR888 ********************************************************/ + +/* Fetch texel from 1D, 2D or 3D bgr888 texture, return 4 GLchans */ +static void FETCH(f_bgr888)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 3); + texel[RCOMP] = UBYTE_TO_FLOAT( src[0] ); + texel[GCOMP] = UBYTE_TO_FLOAT( src[1] ); + texel[BCOMP] = UBYTE_TO_FLOAT( src[2] ); + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_bgr888(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 3); + dst[0] = rgba[RCOMP]; + dst[1] = rgba[GCOMP]; + dst[2] = rgba[BCOMP]; +} +#endif + + +/* use color expansion like (g << 2) | (g >> 4) (does somewhat random rounding) + instead of slow (g << 2) * 255 / 252 (always rounds down) */ + +/* MESA_FORMAT_RGB565 ********************************************************/ + +/* Fetch texel from 1D, 2D or 3D rgb565 texture, return 4 GLchans */ +static void FETCH(f_rgb565)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort *src = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + const GLushort s = *src; + texel[RCOMP] = ((s >> 11) & 0x1f) * (1.0F / 31.0F); + texel[GCOMP] = ((s >> 5 ) & 0x3f) * (1.0F / 63.0F); + texel[BCOMP] = ((s ) & 0x1f) * (1.0F / 31.0F); + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_rgb565(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + *dst = PACK_COLOR_565(rgba[RCOMP], rgba[GCOMP], rgba[BCOMP]); +} +#endif + + +/* MESA_FORMAT_RGB565_REV ****************************************************/ + +/* Fetch texel from 1D, 2D or 3D rgb565_rev texture, return 4 GLchans */ +static void FETCH(f_rgb565_rev)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort *src = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + const GLushort s = (*src >> 8) | (*src << 8); /* byte swap */ + texel[RCOMP] = UBYTE_TO_FLOAT( ((s >> 8) & 0xf8) | ((s >> 13) & 0x7) ); + texel[GCOMP] = UBYTE_TO_FLOAT( ((s >> 3) & 0xfc) | ((s >> 9) & 0x3) ); + texel[BCOMP] = UBYTE_TO_FLOAT( ((s << 3) & 0xf8) | ((s >> 2) & 0x7) ); + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_rgb565_rev(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + *dst = PACK_COLOR_565(rgba[BCOMP], rgba[GCOMP], rgba[RCOMP]); +} +#endif + + +/* MESA_FORMAT_ARGB4444 ******************************************************/ + +/* Fetch texel from 1D, 2D or 3D argb444 texture, return 4 GLchans */ +static void FETCH(f_argb4444)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort *src = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + const GLushort s = *src; + texel[RCOMP] = ((s >> 8) & 0xf) * (1.0F / 15.0F); + texel[GCOMP] = ((s >> 4) & 0xf) * (1.0F / 15.0F); + texel[BCOMP] = ((s ) & 0xf) * (1.0F / 15.0F); + texel[ACOMP] = ((s >> 12) & 0xf) * (1.0F / 15.0F); +} + +#if DIM == 3 +static void store_texel_argb4444(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + *dst = PACK_COLOR_4444(rgba[ACOMP], rgba[RCOMP], rgba[GCOMP], rgba[BCOMP]); +} +#endif + + +/* MESA_FORMAT_ARGB4444_REV **************************************************/ + +/* Fetch texel from 1D, 2D or 3D argb4444_rev texture, return 4 GLchans */ +static void FETCH(f_argb4444_rev)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort s = *TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + texel[RCOMP] = ((s ) & 0xf) * (1.0F / 15.0F); + texel[GCOMP] = ((s >> 12) & 0xf) * (1.0F / 15.0F); + texel[BCOMP] = ((s >> 8) & 0xf) * (1.0F / 15.0F); + texel[ACOMP] = ((s >> 4) & 0xf) * (1.0F / 15.0F); +} + +#if DIM == 3 +static void store_texel_argb4444_rev(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + *dst = PACK_COLOR_4444(rgba[ACOMP], rgba[BCOMP], rgba[GCOMP], rgba[RCOMP]); +} +#endif + +/* MESA_FORMAT_RGBA5551 ******************************************************/ + +/* Fetch texel from 1D, 2D or 3D argb1555 texture, return 4 GLchans */ +static void FETCH(f_rgba5551)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort *src = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + const GLushort s = *src; + texel[RCOMP] = ((s >> 11) & 0x1f) * (1.0F / 31.0F); + texel[GCOMP] = ((s >> 6) & 0x1f) * (1.0F / 31.0F); + texel[BCOMP] = ((s >> 1) & 0x1f) * (1.0F / 31.0F); + texel[ACOMP] = ((s ) & 0x01) * 1.0F; +} + +#if DIM == 3 +static void store_texel_rgba5551(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + *dst = PACK_COLOR_5551(rgba[RCOMP], rgba[GCOMP], rgba[BCOMP], rgba[ACOMP]); +} +#endif + +/* MESA_FORMAT_ARGB1555 ******************************************************/ + +/* Fetch texel from 1D, 2D or 3D argb1555 texture, return 4 GLchans */ +static void FETCH(f_argb1555)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort *src = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + const GLushort s = *src; + texel[RCOMP] = ((s >> 10) & 0x1f) * (1.0F / 31.0F); + texel[GCOMP] = ((s >> 5) & 0x1f) * (1.0F / 31.0F); + texel[BCOMP] = ((s >> 0) & 0x1f) * (1.0F / 31.0F); + texel[ACOMP] = ((s >> 15) & 0x01) * 1.0F; +} + +#if DIM == 3 +static void store_texel_argb1555(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + *dst = PACK_COLOR_1555(rgba[ACOMP], rgba[RCOMP], rgba[GCOMP], rgba[BCOMP]); +} +#endif + + +/* MESA_FORMAT_ARGB1555_REV **************************************************/ + +/* Fetch texel from 1D, 2D or 3D argb1555_rev texture, return 4 GLchans */ +static void FETCH(f_argb1555_rev)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort *src = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + const GLushort s = (*src << 8) | (*src >> 8); /* byteswap */ + texel[RCOMP] = UBYTE_TO_FLOAT( ((s >> 7) & 0xf8) | ((s >> 12) & 0x7) ); + texel[GCOMP] = UBYTE_TO_FLOAT( ((s >> 2) & 0xf8) | ((s >> 7) & 0x7) ); + texel[BCOMP] = UBYTE_TO_FLOAT( ((s << 3) & 0xf8) | ((s >> 2) & 0x7) ); + texel[ACOMP] = UBYTE_TO_FLOAT( ((s >> 15) & 0x01) * 255 ); +} + +#if DIM == 3 +static void store_texel_argb1555_rev(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + *dst = PACK_COLOR_1555_REV(rgba[ACOMP], rgba[RCOMP], rgba[GCOMP], rgba[BCOMP]); +} +#endif + + +/* MESA_FORMAT_ARGB2101010 ***************************************************/ + +/* Fetch texel from 1D, 2D or 3D argb2101010 texture, return 4 GLchans */ +static void FETCH(f_argb2101010)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLuint *src = TEXEL_ADDR(GLuint, texImage, i, j, k, 1); + const GLuint s = *src; + texel[RCOMP] = ((s >> 20) & 0x3ff) * (1.0F / 1023.0F); + texel[GCOMP] = ((s >> 10) & 0x3ff) * (1.0F / 1023.0F); + texel[BCOMP] = ((s >> 0) & 0x3ff) * (1.0F / 1023.0F); + texel[ACOMP] = ((s >> 30) & 0x03) * (1.0F / 3.0F); +} + +#if DIM == 3 +static void store_texel_argb2101010(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1); + *dst = PACK_COLOR_2101010_UB(rgba[ACOMP], rgba[RCOMP], rgba[GCOMP], rgba[BCOMP]); +} +#endif + + +/* MESA_FORMAT_RG88 **********************************************************/ + +/* Fetch texel from 1D, 2D or 3D rg88 texture, return 4 GLchans */ +static void FETCH(f_rg88)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort s = *TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + texel[RCOMP] = UBYTE_TO_FLOAT( s & 0xff ); + texel[GCOMP] = UBYTE_TO_FLOAT( s >> 8 ); + texel[BCOMP] = 0.0; + texel[ACOMP] = 1.0; +} + +#if DIM == 3 +static void store_texel_rg88(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + *dst = PACK_COLOR_88(rgba[RCOMP], rgba[GCOMP]); +} +#endif + + +/* MESA_FORMAT_RG88_REV ******************************************************/ + +/* Fetch texel from 1D, 2D or 3D rg88_rev texture, return 4 GLchans */ +static void FETCH(f_rg88_rev)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort s = *TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + texel[RCOMP] = UBYTE_TO_FLOAT( s & 0xff ); + texel[GCOMP] = UBYTE_TO_FLOAT( s >> 8 ); + texel[BCOMP] = 0.0; + texel[ACOMP] = 1.0; +} + +#if DIM == 3 +static void store_texel_rg88_rev(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + *dst = PACK_COLOR_88(rgba[GCOMP], rgba[RCOMP]); +} +#endif + + +/* MESA_FORMAT_AL44 **********************************************************/ + +/* Fetch texel from 1D, 2D or 3D al44 texture, return 4 GLchans */ +static void FETCH(f_al44)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLubyte s = *TEXEL_ADDR(GLubyte, texImage, i, j, k, 1); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = (s & 0xf) * (1.0F / 15.0F); + texel[ACOMP] = ((s >> 4) & 0xf) * (1.0F / 15.0F); +} + +#if DIM == 3 +static void store_texel_al44(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1); + *dst = PACK_COLOR_44(rgba[ACOMP], rgba[RCOMP]); +} +#endif + + +/* MESA_FORMAT_AL88 **********************************************************/ + +/* Fetch texel from 1D, 2D or 3D al88 texture, return 4 GLchans */ +static void FETCH(f_al88)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort s = *TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = UBYTE_TO_FLOAT( s & 0xff ); + texel[ACOMP] = UBYTE_TO_FLOAT( s >> 8 ); +} + +#if DIM == 3 +static void store_texel_al88(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + *dst = PACK_COLOR_88(rgba[ACOMP], rgba[RCOMP]); +} +#endif + + +/* MESA_FORMAT_R8 ************************************************************/ + +/* Fetch texel from 1D, 2D or 3D rg88 texture, return 4 GLchans */ +static void FETCH(f_r8)(const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel) +{ + const GLubyte s = *TEXEL_ADDR(GLubyte, texImage, i, j, k, 1); + texel[RCOMP] = UBYTE_TO_FLOAT(s); + texel[GCOMP] = 0.0; + texel[BCOMP] = 0.0; + texel[ACOMP] = 1.0; +} + +#if DIM == 3 +static void store_texel_r8(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1); + *dst = rgba[RCOMP]; +} +#endif + + +/* MESA_FORMAT_R16 ***********************************************************/ + +/* Fetch texel from 1D, 2D or 3D r16 texture, return 4 GLchans */ +static void FETCH(f_r16)(const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel) +{ + const GLushort s = *TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + texel[RCOMP] = USHORT_TO_FLOAT(s); + texel[GCOMP] = 0.0; + texel[BCOMP] = 0.0; + texel[ACOMP] = 1.0; +} + +#if DIM == 3 +static void store_texel_r16(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLushort *rgba = (const GLushort *) texel; + GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + *dst = rgba[RCOMP]; +} +#endif + + +/* MESA_FORMAT_AL88_REV ******************************************************/ + +/* Fetch texel from 1D, 2D or 3D al88_rev texture, return 4 GLchans */ +static void FETCH(f_al88_rev)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort s = *TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = UBYTE_TO_FLOAT( s >> 8 ); + texel[ACOMP] = UBYTE_TO_FLOAT( s & 0xff ); +} + +#if DIM == 3 +static void store_texel_al88_rev(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + *dst = PACK_COLOR_88(rgba[RCOMP], rgba[ACOMP]); +} +#endif + + +/* MESA_FORMAT_RG1616 ********************************************************/ + +/* Fetch texel from 1D, 2D or 3D rg1616 texture, return 4 GLchans */ +static void FETCH(f_rg1616)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLuint s = *TEXEL_ADDR(GLuint, texImage, i, j, k, 1); + texel[RCOMP] = USHORT_TO_FLOAT( s & 0xffff ); + texel[GCOMP] = USHORT_TO_FLOAT( s >> 16 ); + texel[BCOMP] = 0.0; + texel[ACOMP] = 1.0; +} + +#if DIM == 3 +static void store_texel_rg1616(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + *dst = PACK_COLOR_1616(rgba[RCOMP], rgba[GCOMP]); +} +#endif + + +/* MESA_FORMAT_RG1616_REV ****************************************************/ + +/* Fetch texel from 1D, 2D or 3D rg1616_rev texture, return 4 GLchans */ +static void FETCH(f_rg1616_rev)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLuint s = *TEXEL_ADDR(GLuint, texImage, i, j, k, 1); + texel[RCOMP] = USHORT_TO_FLOAT( s >> 16 ); + texel[GCOMP] = USHORT_TO_FLOAT( s & 0xffff ); + texel[BCOMP] = 0.0; + texel[ACOMP] = 1.0; +} + +#if DIM == 3 +static void store_texel_rg1616_rev(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + *dst = PACK_COLOR_1616(rgba[GCOMP], rgba[RCOMP]); +} +#endif + + +/* MESA_FORMAT_AL1616 ********************************************************/ + +/* Fetch texel from 1D, 2D or 3D al1616 texture, return 4 GLchans */ +static void FETCH(f_al1616)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLuint s = *TEXEL_ADDR(GLuint, texImage, i, j, k, 1); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = USHORT_TO_FLOAT( s & 0xffff ); + texel[ACOMP] = USHORT_TO_FLOAT( s >> 16 ); +} + +#if DIM == 3 +static void store_texel_al1616(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLushort *rgba = (const GLushort *) texel; + GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1); + *dst = PACK_COLOR_1616(rgba[ACOMP], rgba[RCOMP]); +} +#endif + + +/* MESA_FORMAT_AL1616_REV ****************************************************/ + +/* Fetch texel from 1D, 2D or 3D al1616_rev texture, return 4 GLchans */ +static void FETCH(f_al1616_rev)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLuint s = *TEXEL_ADDR(GLuint, texImage, i, j, k, 1); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = USHORT_TO_FLOAT( s >> 16 ); + texel[ACOMP] = USHORT_TO_FLOAT( s & 0xffff ); +} + +#if DIM == 3 +static void store_texel_al1616_rev(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLushort *rgba = (const GLushort *) texel; + GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1); + *dst = PACK_COLOR_1616(rgba[RCOMP], rgba[ACOMP]); +} +#endif + + +/* MESA_FORMAT_RGB332 ********************************************************/ + +/* Fetch texel from 1D, 2D or 3D rgb332 texture, return 4 GLchans */ +static void FETCH(f_rgb332)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1); + const GLubyte s = *src; + texel[RCOMP] = ((s >> 5) & 0x7) * (1.0F / 7.0F); + texel[GCOMP] = ((s >> 2) & 0x7) * (1.0F / 7.0F); + texel[BCOMP] = ((s ) & 0x3) * (1.0F / 3.0F); + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_rgb332(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1); + *dst = PACK_COLOR_332(rgba[RCOMP], rgba[GCOMP], rgba[BCOMP]); +} +#endif + + +/* MESA_FORMAT_A8 ************************************************************/ + +/* Fetch texel from 1D, 2D or 3D a8 texture, return 4 GLchans */ +static void FETCH(f_a8)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = 0.0F; + texel[ACOMP] = UBYTE_TO_FLOAT( src[0] ); +} + +#if DIM == 3 +static void store_texel_a8(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1); + *dst = rgba[ACOMP]; +} +#endif + + +/* MESA_FORMAT_A16 ************************************************************/ + +/* Fetch texel from 1D, 2D or 3D a8 texture, return 4 GLchans */ +static void FETCH(f_a16)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort *src = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = 0.0F; + texel[ACOMP] = USHORT_TO_FLOAT( src[0] ); +} + +#if DIM == 3 +static void store_texel_a16(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLushort *rgba = (const GLushort *) texel; + GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + *dst = rgba[ACOMP]; +} +#endif + + +/* MESA_FORMAT_L8 ************************************************************/ + +/* Fetch texel from 1D, 2D or 3D l8 texture, return 4 GLchans */ +static void FETCH(f_l8)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = UBYTE_TO_FLOAT( src[0] ); + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_l8(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1); + *dst = rgba[RCOMP]; +} +#endif + + +/* MESA_FORMAT_L16 ***********************************************************/ + +/* Fetch texel from 1D, 2D or 3D l16 texture, return 4 GLchans */ +static void FETCH(f_l16)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort *src = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = USHORT_TO_FLOAT( src[0] ); + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_l16(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLushort *rgba = (const GLushort *) texel; + GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + *dst = rgba[RCOMP]; +} +#endif + + +/* MESA_FORMAT_I8 ************************************************************/ + +/* Fetch texel from 1D, 2D or 3D i8 texture, return 4 GLchans */ +static void FETCH(f_i8)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = + texel[ACOMP] = UBYTE_TO_FLOAT( src[0] ); +} + +#if DIM == 3 +static void store_texel_i8(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1); + *dst = rgba[RCOMP]; +} +#endif + + +/* MESA_FORMAT_I16 ***********************************************************/ + +/* Fetch texel from 1D, 2D or 3D i16 texture, return 4 GLchans */ +static void FETCH(f_i16)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort *src = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = + texel[ACOMP] = USHORT_TO_FLOAT( src[0] ); +} + +#if DIM == 3 +static void store_texel_i16(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLushort *rgba = (const GLushort *) texel; + GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + *dst = rgba[RCOMP]; +} +#endif + + +/* MESA_FORMAT_CI8 ***********************************************************/ + +/* Fetch CI texel from 1D, 2D or 3D ci8 texture, lookup the index in a + * color table, and return 4 GLchans. + */ +static void FETCH(f_ci8)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1); + const struct gl_color_table *palette; + GLuint index; + GET_CURRENT_CONTEXT(ctx); + + if (ctx->Texture.SharedPalette) { + palette = &ctx->Texture.Palette; + } + else { + palette = &texImage->TexObject->Palette; + } + if (palette->Size == 0) + return; /* undefined results */ + + /* Mask the index against size of palette to avoid going out of bounds */ + index = (*src) & (palette->Size - 1); + + { + const GLfloat *table = palette->TableF; + switch (palette->_BaseFormat) { + case GL_ALPHA: + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = 0.0F; + texel[ACOMP] = table[index]; + break; + case GL_LUMINANCE: + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = table[index]; + texel[ACOMP] = 1.0F; + break; + case GL_INTENSITY: + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = + texel[ACOMP] = table[index]; + break; + case GL_LUMINANCE_ALPHA: + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = table[index * 2 + 0]; + texel[ACOMP] = table[index * 2 + 1]; + break; + case GL_RGB: + texel[RCOMP] = table[index * 3 + 0]; + texel[GCOMP] = table[index * 3 + 1]; + texel[BCOMP] = table[index * 3 + 2]; + texel[ACOMP] = 1.0F; + break; + case GL_RGBA: + texel[RCOMP] = table[index * 4 + 0]; + texel[GCOMP] = table[index * 4 + 1]; + texel[BCOMP] = table[index * 4 + 2]; + texel[ACOMP] = table[index * 4 + 3]; + break; + default: + _mesa_problem(ctx, "Bad palette format in fetch_texel_ci8"); + return; + } + } +} + +#if DIM == 3 +static void store_texel_ci8(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *index = (const GLubyte *) texel; + GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1); + *dst = *index; +} +#endif + + +/* Fetch texel from 1D, 2D or 3D srgb8 texture, return 4 GLfloats */ +/* Note: component order is same as for MESA_FORMAT_RGB888 */ +static void FETCH(srgb8)(const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 3); + texel[RCOMP] = nonlinear_to_linear(src[2]); + texel[GCOMP] = nonlinear_to_linear(src[1]); + texel[BCOMP] = nonlinear_to_linear(src[0]); + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_srgb8(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 3); + dst[0] = rgba[BCOMP]; /* no conversion */ + dst[1] = rgba[GCOMP]; + dst[2] = rgba[RCOMP]; +} +#endif + +/* Fetch texel from 1D, 2D or 3D srgba8 texture, return 4 GLfloats */ +static void FETCH(srgba8)(const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLuint s = *TEXEL_ADDR(GLuint, texImage, i, j, k, 1); + texel[RCOMP] = nonlinear_to_linear( (s >> 24) ); + texel[GCOMP] = nonlinear_to_linear( (s >> 16) & 0xff ); + texel[BCOMP] = nonlinear_to_linear( (s >> 8) & 0xff ); + texel[ACOMP] = UBYTE_TO_FLOAT( (s ) & 0xff ); /* linear! */ +} + +#if DIM == 3 +static void store_texel_srgba8(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1); + *dst = PACK_COLOR_8888(rgba[RCOMP], rgba[GCOMP], rgba[BCOMP], rgba[ACOMP]); +} +#endif + +/* Fetch texel from 1D, 2D or 3D sargb8 texture, return 4 GLfloats */ +static void FETCH(sargb8)(const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLuint s = *TEXEL_ADDR(GLuint, texImage, i, j, k, 1); + texel[RCOMP] = nonlinear_to_linear( (s >> 16) & 0xff ); + texel[GCOMP] = nonlinear_to_linear( (s >> 8) & 0xff ); + texel[BCOMP] = nonlinear_to_linear( (s ) & 0xff ); + texel[ACOMP] = UBYTE_TO_FLOAT( (s >> 24) ); /* linear! */ +} + +#if DIM == 3 +static void store_texel_sargb8(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1); + *dst = PACK_COLOR_8888(rgba[ACOMP], rgba[RCOMP], rgba[GCOMP], rgba[BCOMP]); +} +#endif + +/* Fetch texel from 1D, 2D or 3D sl8 texture, return 4 GLfloats */ +static void FETCH(sl8)(const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = nonlinear_to_linear(src[0]); + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_sl8(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1); + dst[0] = rgba[RCOMP]; +} +#endif + +/* Fetch texel from 1D, 2D or 3D sla8 texture, return 4 GLfloats */ +static void FETCH(sla8)(const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 2); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = nonlinear_to_linear(src[0]); + texel[ACOMP] = UBYTE_TO_FLOAT(src[1]); /* linear */ +} + +#if DIM == 3 +static void store_texel_sla8(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 2); + dst[0] = rgba[RCOMP]; + dst[1] = rgba[ACOMP]; +} +#endif + + +/* MESA_FORMAT_RGBA_INT8 **************************************************/ + +static void +FETCH(rgba_int8)(const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLbyte *src = TEXEL_ADDR(GLbyte, texImage, i, j, k, 4); + texel[RCOMP] = (GLfloat) src[0]; + texel[GCOMP] = (GLfloat) src[1]; + texel[BCOMP] = (GLfloat) src[2]; + texel[ACOMP] = (GLfloat) src[3]; +} + +#if DIM == 3 +static void +store_texel_rgba_int8(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLbyte *rgba = (const GLbyte *) texel; + GLbyte *dst = TEXEL_ADDR(GLbyte, texImage, i, j, k, 4); + dst[0] = rgba[RCOMP]; + dst[1] = rgba[GCOMP]; + dst[2] = rgba[BCOMP]; + dst[3] = rgba[ACOMP]; +} +#endif + + +/* MESA_FORMAT_RGBA_INT16 **************************************************/ + +static void +FETCH(rgba_int16)(const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLshort *src = TEXEL_ADDR(GLshort, texImage, i, j, k, 4); + texel[RCOMP] = (GLfloat) src[0]; + texel[GCOMP] = (GLfloat) src[1]; + texel[BCOMP] = (GLfloat) src[2]; + texel[ACOMP] = (GLfloat) src[3]; +} + +#if DIM == 3 +static void +store_texel_rgba_int16(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLshort *rgba = (const GLshort *) texel; + GLshort *dst = TEXEL_ADDR(GLshort, texImage, i, j, k, 4); + dst[0] = rgba[RCOMP]; + dst[1] = rgba[GCOMP]; + dst[2] = rgba[BCOMP]; + dst[3] = rgba[ACOMP]; +} +#endif + + +/* MESA_FORMAT_RGBA_INT32 **************************************************/ + +static void +FETCH(rgba_int32)(const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLint *src = TEXEL_ADDR(GLint, texImage, i, j, k, 4); + texel[RCOMP] = (GLfloat) src[0]; + texel[GCOMP] = (GLfloat) src[1]; + texel[BCOMP] = (GLfloat) src[2]; + texel[ACOMP] = (GLfloat) src[3]; +} + +#if DIM == 3 +static void +store_texel_rgba_int32(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLint *rgba = (const GLint *) texel; + GLint *dst = TEXEL_ADDR(GLint, texImage, i, j, k, 4); + dst[0] = rgba[RCOMP]; + dst[1] = rgba[GCOMP]; + dst[2] = rgba[BCOMP]; + dst[3] = rgba[ACOMP]; +} +#endif + + +/* MESA_FORMAT_RGBA_UINT8 **************************************************/ + +static void +FETCH(rgba_uint8)(const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 4); + texel[RCOMP] = (GLfloat) src[0]; + texel[GCOMP] = (GLfloat) src[1]; + texel[BCOMP] = (GLfloat) src[2]; + texel[ACOMP] = (GLfloat) src[3]; +} + +#if DIM == 3 +static void +store_texel_rgba_uint8(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 4); + dst[0] = rgba[RCOMP]; + dst[1] = rgba[GCOMP]; + dst[2] = rgba[BCOMP]; + dst[3] = rgba[ACOMP]; +} +#endif + + +/* MESA_FORMAT_RGBA_UINT16 **************************************************/ + +static void +FETCH(rgba_uint16)(const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort *src = TEXEL_ADDR(GLushort, texImage, i, j, k, 4); + texel[RCOMP] = (GLfloat) src[0]; + texel[GCOMP] = (GLfloat) src[1]; + texel[BCOMP] = (GLfloat) src[2]; + texel[ACOMP] = (GLfloat) src[3]; +} + +#if DIM == 3 +static void +store_texel_rgba_uint16(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLushort *rgba = (const GLushort *) texel; + GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 4); + dst[0] = rgba[RCOMP]; + dst[1] = rgba[GCOMP]; + dst[2] = rgba[BCOMP]; + dst[3] = rgba[ACOMP]; +} +#endif + + +/* MESA_FORMAT_RGBA_UINT32 **************************************************/ + +static void +FETCH(rgba_uint32)(const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLuint *src = TEXEL_ADDR(GLuint, texImage, i, j, k, 4); + texel[RCOMP] = (GLfloat) src[0]; + texel[GCOMP] = (GLfloat) src[1]; + texel[BCOMP] = (GLfloat) src[2]; + texel[ACOMP] = (GLfloat) src[3]; +} + +#if DIM == 3 +static void +store_texel_rgba_uint32(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLuint *rgba = (const GLuint *) texel; + GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 4); + dst[0] = rgba[RCOMP]; + dst[1] = rgba[GCOMP]; + dst[2] = rgba[BCOMP]; + dst[3] = rgba[ACOMP]; +} +#endif + + +/* MESA_FORMAT_DUDV8 ********************************************************/ + +/* this format by definition produces 0,0,0,1 as rgba values, + however we'll return the dudv values as rg and fix up elsewhere */ +static void FETCH(dudv8)(const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLbyte *src = TEXEL_ADDR(GLbyte, texImage, i, j, k, 2); + texel[RCOMP] = BYTE_TO_FLOAT(src[0]); + texel[GCOMP] = BYTE_TO_FLOAT(src[1]); + texel[BCOMP] = 0; + texel[ACOMP] = 0; +} + + +/* MESA_FORMAT_SIGNED_R8 ***********************************************/ + +static void FETCH(signed_r8)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLbyte s = *TEXEL_ADDR(GLbyte, texImage, i, j, k, 1); + texel[RCOMP] = BYTE_TO_FLOAT_TEX( s ); + texel[GCOMP] = 0.0F; + texel[BCOMP] = 0.0F; + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_signed_r8(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLbyte *rgba = (const GLbyte *) texel; + GLbyte *dst = TEXEL_ADDR(GLbyte, texImage, i, j, k, 1); + *dst = rgba[RCOMP]; +} +#endif + + +/* MESA_FORMAT_SIGNED_A8 ***********************************************/ + +static void FETCH(signed_a8)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLbyte s = *TEXEL_ADDR(GLbyte, texImage, i, j, k, 1); + texel[RCOMP] = 0.0F; + texel[GCOMP] = 0.0F; + texel[BCOMP] = 0.0F; + texel[ACOMP] = BYTE_TO_FLOAT_TEX( s ); +} + +#if DIM == 3 +static void store_texel_signed_a8(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLbyte *rgba = (const GLbyte *) texel; + GLbyte *dst = TEXEL_ADDR(GLbyte, texImage, i, j, k, 1); + *dst = rgba[ACOMP]; +} +#endif + + +/* MESA_FORMAT_SIGNED_L8 ***********************************************/ + +static void FETCH(signed_l8)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLbyte s = *TEXEL_ADDR(GLbyte, texImage, i, j, k, 1); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = BYTE_TO_FLOAT_TEX( s ); + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_signed_l8(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLbyte *rgba = (const GLbyte *) texel; + GLbyte *dst = TEXEL_ADDR(GLbyte, texImage, i, j, k, 1); + *dst = rgba[RCOMP]; +} +#endif + + +/* MESA_FORMAT_SIGNED_I8 ***********************************************/ + +static void FETCH(signed_i8)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLbyte s = *TEXEL_ADDR(GLbyte, texImage, i, j, k, 1); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = + texel[ACOMP] = BYTE_TO_FLOAT_TEX( s ); +} + +#if DIM == 3 +static void store_texel_signed_i8(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLbyte *rgba = (const GLbyte *) texel; + GLbyte *dst = TEXEL_ADDR(GLbyte, texImage, i, j, k, 1); + *dst = rgba[RCOMP]; +} +#endif + + +/* MESA_FORMAT_SIGNED_RG88_REV ***********************************************/ + +static void FETCH(signed_rg88_rev)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort s = *TEXEL_ADDR(GLshort, texImage, i, j, k, 1); + texel[RCOMP] = BYTE_TO_FLOAT_TEX( (GLbyte) (s & 0xff) ); + texel[GCOMP] = BYTE_TO_FLOAT_TEX( (GLbyte) (s >> 8) ); + texel[BCOMP] = 0.0F; + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_signed_rg88_rev(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLbyte *rg = (const GLbyte *) texel; + GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + dst[0] = PACK_COLOR_88(rg[GCOMP], rg[RCOMP]); +} +#endif + + +/* MESA_FORMAT_SIGNED_AL88 ***********************************************/ + +static void FETCH(signed_al88)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort s = *TEXEL_ADDR(GLshort, texImage, i, j, k, 1); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = BYTE_TO_FLOAT_TEX( (GLbyte) (s & 0xff) ); + texel[ACOMP] = BYTE_TO_FLOAT_TEX( (GLbyte) (s >> 8) ); +} + +#if DIM == 3 +static void store_texel_signed_al88(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLbyte *rg = (const GLbyte *) texel; + GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + dst[0] = PACK_COLOR_88(rg[ACOMP], rg[RCOMP]); +} +#endif + + +/* MESA_FORMAT_SIGNED_RGBX8888 ***********************************************/ + +static void FETCH(signed_rgbx8888)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLuint s = *TEXEL_ADDR(GLuint, texImage, i, j, k, 1); + texel[RCOMP] = BYTE_TO_FLOAT_TEX( (GLbyte) (s >> 24) ); + texel[GCOMP] = BYTE_TO_FLOAT_TEX( (GLbyte) (s >> 16) ); + texel[BCOMP] = BYTE_TO_FLOAT_TEX( (GLbyte) (s >> 8) ); + texel[ACOMP] = 1.0f; +} + +#if DIM == 3 +static void store_texel_signed_rgbx8888(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLbyte *rgba = (const GLbyte *) texel; + GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1); + *dst = PACK_COLOR_8888(rgba[RCOMP], rgba[GCOMP], rgba[BCOMP], 255); +} +#endif + + +/* MESA_FORMAT_SIGNED_RGBA8888 ***********************************************/ + +static void FETCH(signed_rgba8888)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLuint s = *TEXEL_ADDR(GLuint, texImage, i, j, k, 1); + texel[RCOMP] = BYTE_TO_FLOAT_TEX( (GLbyte) (s >> 24) ); + texel[GCOMP] = BYTE_TO_FLOAT_TEX( (GLbyte) (s >> 16) ); + texel[BCOMP] = BYTE_TO_FLOAT_TEX( (GLbyte) (s >> 8) ); + texel[ACOMP] = BYTE_TO_FLOAT_TEX( (GLbyte) (s ) ); +} + +#if DIM == 3 +static void store_texel_signed_rgba8888(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLbyte *rgba = (const GLbyte *) texel; + GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1); + *dst = PACK_COLOR_8888(rgba[RCOMP], rgba[GCOMP], rgba[BCOMP], rgba[ACOMP]); +} +#endif + +static void FETCH(signed_rgba8888_rev)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLuint s = *TEXEL_ADDR(GLuint, texImage, i, j, k, 1); + texel[RCOMP] = BYTE_TO_FLOAT_TEX( (GLbyte) (s ) ); + texel[GCOMP] = BYTE_TO_FLOAT_TEX( (GLbyte) (s >> 8) ); + texel[BCOMP] = BYTE_TO_FLOAT_TEX( (GLbyte) (s >> 16) ); + texel[ACOMP] = BYTE_TO_FLOAT_TEX( (GLbyte) (s >> 24) ); +} + +#if DIM == 3 +static void store_texel_signed_rgba8888_rev(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1); + *dst = PACK_COLOR_8888_REV(rgba[RCOMP], rgba[GCOMP], rgba[BCOMP], rgba[ACOMP]); +} +#endif + + + +/* MESA_FORMAT_SIGNED_R16 ***********************************************/ + +static void +FETCH(signed_r16)(const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel) +{ + const GLshort s = *TEXEL_ADDR(GLshort, texImage, i, j, k, 1); + texel[RCOMP] = SHORT_TO_FLOAT_TEX( s ); + texel[GCOMP] = 0.0F; + texel[BCOMP] = 0.0F; + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void +store_texel_signed_r16(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLshort *rgba = (const GLshort *) texel; + GLshort *dst = TEXEL_ADDR(GLshort, texImage, i, j, k, 1); + *dst = rgba[0]; +} +#endif + + +/* MESA_FORMAT_SIGNED_A16 ***********************************************/ + +static void +FETCH(signed_a16)(const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel) +{ + const GLshort s = *TEXEL_ADDR(GLshort, texImage, i, j, k, 1); + texel[RCOMP] = 0.0F; + texel[GCOMP] = 0.0F; + texel[BCOMP] = 0.0F; + texel[ACOMP] = SHORT_TO_FLOAT_TEX( s ); +} + +#if DIM == 3 +static void +store_texel_signed_a16(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLshort *rgba = (const GLshort *) texel; + GLshort *dst = TEXEL_ADDR(GLshort, texImage, i, j, k, 1); + *dst = rgba[ACOMP]; +} +#endif + + +/* MESA_FORMAT_SIGNED_L16 ***********************************************/ + +static void +FETCH(signed_l16)(const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel) +{ + const GLshort s = *TEXEL_ADDR(GLshort, texImage, i, j, k, 1); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = SHORT_TO_FLOAT_TEX( s ); + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void +store_texel_signed_l16(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLshort *rgba = (const GLshort *) texel; + GLshort *dst = TEXEL_ADDR(GLshort, texImage, i, j, k, 1); + *dst = rgba[RCOMP]; +} +#endif + + +/* MESA_FORMAT_SIGNED_I16 ***********************************************/ + +static void +FETCH(signed_i16)(const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel) +{ + const GLshort s = *TEXEL_ADDR(GLshort, texImage, i, j, k, 1); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = + texel[ACOMP] = SHORT_TO_FLOAT_TEX( s ); +} + +#if DIM == 3 +static void +store_texel_signed_i16(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLshort *rgba = (const GLshort *) texel; + GLshort *dst = TEXEL_ADDR(GLshort, texImage, i, j, k, 1); + *dst = rgba[RCOMP]; +} +#endif + + +/* MESA_FORMAT_SIGNED_RG1616 ***********************************************/ + +static void +FETCH(signed_rg1616)(const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel) +{ + const GLshort *s = TEXEL_ADDR(GLshort, texImage, i, j, k, 2); + texel[RCOMP] = SHORT_TO_FLOAT_TEX( s[0] ); + texel[GCOMP] = SHORT_TO_FLOAT_TEX( s[1] ); + texel[BCOMP] = 0.0F; + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void +store_texel_signed_rg1616(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLshort *rgba = (const GLshort *) texel; + GLshort *dst = TEXEL_ADDR(GLshort, texImage, i, j, k, 2); + dst[0] = rgba[RCOMP]; + dst[1] = rgba[GCOMP]; +} +#endif + + +/* MESA_FORMAT_SIGNED_AL1616 ***********************************************/ + +static void +FETCH(signed_al1616)(const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel) +{ + const GLshort *s = TEXEL_ADDR(GLshort, texImage, i, j, k, 2); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = SHORT_TO_FLOAT_TEX( s[0] ); + texel[ACOMP] = SHORT_TO_FLOAT_TEX( s[1] ); +} + +#if DIM == 3 +static void +store_texel_signed_al1616(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLshort *rgba = (const GLshort *) texel; + GLshort *dst = TEXEL_ADDR(GLshort, texImage, i, j, k, 2); + dst[0] = rgba[RCOMP]; + dst[1] = rgba[ACOMP]; +} +#endif + + +/* MESA_FORMAT_SIGNED_RGB_16 ***********************************************/ + +static void +FETCH(signed_rgb_16)(const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel) +{ + const GLshort *s = TEXEL_ADDR(GLshort, texImage, i, j, k, 3); + texel[RCOMP] = SHORT_TO_FLOAT_TEX( s[0] ); + texel[GCOMP] = SHORT_TO_FLOAT_TEX( s[1] ); + texel[BCOMP] = SHORT_TO_FLOAT_TEX( s[2] ); + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void +store_texel_signed_rgb_16(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLshort *rgba = (const GLshort *) texel; + GLshort *dst = TEXEL_ADDR(GLshort, texImage, i, j, k, 3); + dst[0] = rgba[RCOMP]; + dst[1] = rgba[GCOMP]; + dst[2] = rgba[BCOMP]; +} +#endif + + +/* MESA_FORMAT_SIGNED_RGBA_16 ***********************************************/ + +static void +FETCH(signed_rgba_16)(const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel) +{ + const GLshort *s = TEXEL_ADDR(GLshort, texImage, i, j, k, 4); + texel[RCOMP] = SHORT_TO_FLOAT_TEX( s[0] ); + texel[GCOMP] = SHORT_TO_FLOAT_TEX( s[1] ); + texel[BCOMP] = SHORT_TO_FLOAT_TEX( s[2] ); + texel[ACOMP] = SHORT_TO_FLOAT_TEX( s[3] ); +} + +#if DIM == 3 +static void +store_texel_signed_rgba_16(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLshort *rgba = (const GLshort *) texel; + GLshort *dst = TEXEL_ADDR(GLshort, texImage, i, j, k, 4); + dst[0] = rgba[RCOMP]; + dst[1] = rgba[GCOMP]; + dst[2] = rgba[BCOMP]; + dst[3] = rgba[ACOMP]; +} +#endif + + + +/* MESA_FORMAT_RGBA_16 ***********************************************/ + +static void +FETCH(rgba_16)(const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel) +{ + const GLushort *s = TEXEL_ADDR(GLushort, texImage, i, j, k, 4); + texel[RCOMP] = USHORT_TO_FLOAT( s[0] ); + texel[GCOMP] = USHORT_TO_FLOAT( s[1] ); + texel[BCOMP] = USHORT_TO_FLOAT( s[2] ); + texel[ACOMP] = USHORT_TO_FLOAT( s[3] ); +} + +#if DIM == 3 +static void +store_texel_rgba_16(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLushort *rgba = (const GLushort *) texel; + GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 4); + dst[0] = rgba[RCOMP]; + dst[1] = rgba[GCOMP]; + dst[2] = rgba[BCOMP]; + dst[3] = rgba[ACOMP]; +} +#endif + + + +/* MESA_FORMAT_YCBCR *********************************************************/ + +/* Fetch texel from 1D, 2D or 3D ycbcr texture, return 4 GLfloats. + * We convert YCbCr to RGB here. + */ +static void FETCH(f_ycbcr)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort *src0 = TEXEL_ADDR(GLushort, texImage, (i & ~1), j, k, 1); /* even */ + const GLushort *src1 = src0 + 1; /* odd */ + const GLubyte y0 = (*src0 >> 8) & 0xff; /* luminance */ + const GLubyte cb = *src0 & 0xff; /* chroma U */ + const GLubyte y1 = (*src1 >> 8) & 0xff; /* luminance */ + const GLubyte cr = *src1 & 0xff; /* chroma V */ + const GLubyte y = (i & 1) ? y1 : y0; /* choose even/odd luminance */ + GLfloat r = 1.164F * (y - 16) + 1.596F * (cr - 128); + GLfloat g = 1.164F * (y - 16) - 0.813F * (cr - 128) - 0.391F * (cb - 128); + GLfloat b = 1.164F * (y - 16) + 2.018F * (cb - 128); + r *= (1.0F / 255.0F); + g *= (1.0F / 255.0F); + b *= (1.0F / 255.0F); + texel[RCOMP] = CLAMP(r, 0.0F, 1.0F); + texel[GCOMP] = CLAMP(g, 0.0F, 1.0F); + texel[BCOMP] = CLAMP(b, 0.0F, 1.0F); + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_ycbcr(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + (void) texImage; + (void) i; + (void) j; + (void) k; + (void) texel; + /* XXX to do */ +} +#endif + + +/* MESA_FORMAT_YCBCR_REV *****************************************************/ + +/* Fetch texel from 1D, 2D or 3D ycbcr_rev texture, return 4 GLfloats. + * We convert YCbCr to RGB here. + */ +static void FETCH(f_ycbcr_rev)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort *src0 = TEXEL_ADDR(GLushort, texImage, (i & ~1), j, k, 1); /* even */ + const GLushort *src1 = src0 + 1; /* odd */ + const GLubyte y0 = *src0 & 0xff; /* luminance */ + const GLubyte cr = (*src0 >> 8) & 0xff; /* chroma V */ + const GLubyte y1 = *src1 & 0xff; /* luminance */ + const GLubyte cb = (*src1 >> 8) & 0xff; /* chroma U */ + const GLubyte y = (i & 1) ? y1 : y0; /* choose even/odd luminance */ + GLfloat r = 1.164F * (y - 16) + 1.596F * (cr - 128); + GLfloat g = 1.164F * (y - 16) - 0.813F * (cr - 128) - 0.391F * (cb - 128); + GLfloat b = 1.164F * (y - 16) + 2.018F * (cb - 128); + r *= (1.0F / 255.0F); + g *= (1.0F / 255.0F); + b *= (1.0F / 255.0F); + texel[RCOMP] = CLAMP(r, 0.0F, 1.0F); + texel[GCOMP] = CLAMP(g, 0.0F, 1.0F); + texel[BCOMP] = CLAMP(b, 0.0F, 1.0F); + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_ycbcr_rev(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + (void) texImage; + (void) i; + (void) j; + (void) k; + (void) texel; + /* XXX to do */ +} +#endif + + +/* MESA_TEXFORMAT_Z24_S8 ***************************************************/ + +static void FETCH(f_z24_s8)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + /* only return Z, not stencil data */ + const GLuint *src = TEXEL_ADDR(GLuint, texImage, i, j, k, 1); + const GLfloat scale = 1.0F / (GLfloat) 0xffffff; + texel[0] = ((*src) >> 8) * scale; + ASSERT(texImage->TexFormat == MESA_FORMAT_Z24_S8); + ASSERT(texel[0] >= 0.0F); + ASSERT(texel[0] <= 1.0F); +} + +#if DIM == 3 +static void store_texel_z24_s8(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + /* only store Z, not stencil */ + GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1); + GLfloat depth = *((GLfloat *) texel); + GLuint zi = ((GLuint) (depth * 0xffffff)) << 8; + *dst = zi | (*dst & 0xff); +} +#endif + + +/* MESA_TEXFORMAT_S8_Z24 ***************************************************/ + +static void FETCH(f_s8_z24)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + /* only return Z, not stencil data */ + const GLuint *src = TEXEL_ADDR(GLuint, texImage, i, j, k, 1); + const GLfloat scale = 1.0F / (GLfloat) 0xffffff; + texel[0] = ((*src) & 0x00ffffff) * scale; + ASSERT(texImage->TexFormat == MESA_FORMAT_S8_Z24); + ASSERT(texel[0] >= 0.0F); + ASSERT(texel[0] <= 1.0F); +} + +#if DIM == 3 +static void store_texel_s8_z24(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + /* only store Z, not stencil */ + GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1); + GLfloat depth = *((GLfloat *) texel); + GLuint zi = (GLuint) (depth * 0xffffff); + *dst = zi | (*dst & 0xff000000); +} +#endif + + +/* MESA_FORMAT_RGB9_E5 ******************************************************/ + +static void FETCH(rgb9_e5)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLuint *src = TEXEL_ADDR(GLuint, texImage, i, j, k, 1); + rgb9e5_to_float3(*src, texel); + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_rgb9_e5(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLfloat *src = (const GLfloat *) texel; + GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1); + *dst = float3_to_rgb9e5(src); +} +#endif + + +/* MESA_FORMAT_R11_G11_B10_FLOAT *********************************************/ + +static void FETCH(r11_g11_b10f)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLuint *src = TEXEL_ADDR(GLuint, texImage, i, j, k, 1); + r11g11b10f_to_float3(*src, texel); + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_r11_g11_b10f(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLfloat *src = (const GLfloat *) texel; + GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1); + *dst = float3_to_r11g11b10f(src); +} +#endif + + +/* MESA_FORMAT_Z32_FLOAT_X24S8 ***********************************************/ + +static void FETCH(z32f_x24s8)(const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel) +{ + const GLfloat *src = TEXEL_ADDR(GLfloat, texImage, i, j, k, 2); + texel[RCOMP] = src[0]; + texel[GCOMP] = 0.0F; + texel[BCOMP] = 0.0F; + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_z32f_x24s8(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLfloat *src = (const GLfloat *) texel; + GLfloat *dst = TEXEL_ADDR(GLfloat, texImage, i, j, k, 2); + dst[0] = src[0]; +} +#endif + + +#undef TEXEL_ADDR +#undef DIM +#undef FETCH diff --git a/mesalib/src/mesa/main/texformat.c b/mesalib/src/mesa/main/texformat.c index 8cbb021d8..c919a74e0 100644 --- a/mesalib/src/mesa/main/texformat.c +++ b/mesalib/src/mesa/main/texformat.c @@ -416,6 +416,19 @@ _mesa_choose_tex_format( struct gl_context *ctx, GLint internalFormat, } } + if (ctx->Extensions.ARB_depth_buffer_float) { + switch (internalFormat) { + case GL_DEPTH_COMPONENT32F: + ASSERT(ctx->TextureFormatSupported[MESA_FORMAT_Z32_FLOAT]); + return MESA_FORMAT_Z32_FLOAT; + case GL_DEPTH32F_STENCIL8: + ASSERT(ctx->TextureFormatSupported[MESA_FORMAT_Z32_FLOAT_X24S8]); + return MESA_FORMAT_Z32_FLOAT_X24S8; + default: + ; /* fallthrough */ + } + } + if (ctx->Extensions.ATI_envmap_bumpmap) { switch (internalFormat) { case GL_DUDV_ATI: diff --git a/mesalib/src/mesa/main/texobj.c b/mesalib/src/mesa/main/texobj.c index 565a3a2d8..0e84b8744 100644 --- a/mesalib/src/mesa/main/texobj.c +++ b/mesalib/src/mesa/main/texobj.c @@ -899,7 +899,7 @@ unbind_texobj_from_texunits(struct gl_context *ctx, { GLuint u, tex; - for (u = 0; u < MAX_TEXTURE_IMAGE_UNITS; u++) { + for (u = 0; u < Elements(ctx->Texture.Unit); u++) { struct gl_texture_unit *unit = &ctx->Texture.Unit[u]; for (tex = 0; tex < NUM_TEXTURE_TARGETS; tex++) { if (texObj == unit->CurrentTex[tex]) { diff --git a/mesalib/src/mesa/main/texstore.c b/mesalib/src/mesa/main/texstore.c index e527981ff..6e1e63bdf 100644 --- a/mesalib/src/mesa/main/texstore.c +++ b/mesalib/src/mesa/main/texstore.c @@ -1002,15 +1002,17 @@ memcpy_texture(struct gl_context *ctx, /** - * Store a 32-bit integer depth component texture image. + * Store a 32-bit integer or float depth component texture image. */ static GLboolean _mesa_texstore_z32(TEXSTORE_PARAMS) { const GLuint depthScale = 0xffffffff; const GLuint texelBytes = _mesa_get_format_bytes(dstFormat); + const GLenum dstType = _mesa_get_format_datatype(dstFormat); (void) dims; - ASSERT(dstFormat == MESA_FORMAT_Z32); + ASSERT(dstFormat == MESA_FORMAT_Z32 || + dstFormat == MESA_FORMAT_Z32_FLOAT); ASSERT(texelBytes == sizeof(GLuint)); if (ctx->Pixel.DepthScale == 1.0f && @@ -1018,7 +1020,7 @@ _mesa_texstore_z32(TEXSTORE_PARAMS) !srcPacking->SwapBytes && baseInternalFormat == GL_DEPTH_COMPONENT && srcFormat == GL_DEPTH_COMPONENT && - srcType == GL_UNSIGNED_INT) { + srcType == dstType) { /* simple memcpy path */ memcpy_texture(ctx, dims, dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, @@ -1039,7 +1041,7 @@ _mesa_texstore_z32(TEXSTORE_PARAMS) const GLvoid *src = _mesa_image_address(dims, srcPacking, srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0); _mesa_unpack_depth_span(ctx, srcWidth, - GL_UNSIGNED_INT, (GLuint *) dstRow, + dstType, dstRow, depthScale, srcType, src, srcPacking); dstRow += dstRowStride; } @@ -4285,6 +4287,72 @@ _mesa_texstore_r11_g11_b10f(TEXSTORE_PARAMS) } +static GLboolean +_mesa_texstore_z32f_x24s8(TEXSTORE_PARAMS) +{ + ASSERT(dstFormat == MESA_FORMAT_Z32_FLOAT_X24S8); + ASSERT(srcFormat == GL_DEPTH_STENCIL || + srcFormat == GL_DEPTH_COMPONENT || + srcFormat == GL_STENCIL_INDEX); + ASSERT(srcFormat != GL_DEPTH_STENCIL || + srcType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV); + + if (srcFormat == GL_DEPTH_STENCIL && + ctx->Pixel.DepthScale == 1.0f && + ctx->Pixel.DepthBias == 0.0f && + !srcPacking->SwapBytes) { + /* simple path */ + memcpy_texture(ctx, dims, + dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, + dstRowStride, + dstImageOffsets, + srcWidth, srcHeight, srcDepth, srcFormat, srcType, + srcAddr, srcPacking); + } + else if (srcFormat == GL_DEPTH_COMPONENT || + srcFormat == GL_STENCIL_INDEX) { + GLint img, row; + const GLint srcRowStride + = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType) + / sizeof(uint64_t); + + /* In case we only upload depth we need to preserve the stencil */ + for (img = 0; img < srcDepth; img++) { + uint64_t *dstRow = (uint64_t *) dstAddr + + dstImageOffsets[dstZoffset + img] + + dstYoffset * dstRowStride / sizeof(uint64_t) + + dstXoffset; + const uint64_t *src + = (const uint64_t *) _mesa_image_address(dims, srcPacking, srcAddr, + srcWidth, srcHeight, + srcFormat, srcType, + img, 0, 0); + for (row = 0; row < srcHeight; row++) { + /* The unpack functions with: + * dstType = GL_FLOAT_32_UNSIGNED_INT_24_8_REV + * only write their own dword, so the other dword (stencil + * or depth) is preserved. */ + if (srcFormat != GL_STENCIL_INDEX) + _mesa_unpack_depth_span(ctx, srcWidth, + GL_FLOAT_32_UNSIGNED_INT_24_8_REV, /* dst type */ + dstRow, /* dst addr */ + 1.0f, srcType, src, srcPacking); + + if (srcFormat != GL_DEPTH_COMPONENT) + _mesa_unpack_stencil_span(ctx, srcWidth, + GL_FLOAT_32_UNSIGNED_INT_24_8_REV, /* dst type */ + dstRow, /* dst addr */ + srcType, src, srcPacking, + ctx->_ImageTransferState); + + src += srcRowStride; + dstRow += dstRowStride / sizeof(uint64_t); + } + } + } + return GL_TRUE; +} + /** * Table mapping MESA_FORMAT_* to _mesa_texstore_*() @@ -4419,6 +4487,9 @@ texstore_funcs[MESA_FORMAT_COUNT] = { MESA_FORMAT_RGB9_E5_FLOAT, _mesa_texstore_rgb9_e5 }, { MESA_FORMAT_R11_G11_B10_FLOAT, _mesa_texstore_r11_g11_b10f }, + + { MESA_FORMAT_Z32_FLOAT, _mesa_texstore_z32 }, + { MESA_FORMAT_Z32_FLOAT_X24S8, _mesa_texstore_z32f_x24s8 }, }; diff --git a/mesalib/src/mesa/main/uniforms.c b/mesalib/src/mesa/main/uniforms.c index 1c4fd82ba..dd069a3a4 100644 --- a/mesalib/src/mesa/main/uniforms.c +++ b/mesalib/src/mesa/main/uniforms.c @@ -580,7 +580,7 @@ _mesa_update_shader_textures_used(struct gl_program *prog) if (prog->SamplersUsed & (1 << s)) { GLuint unit = prog->SamplerUnits[s]; GLuint tgt = prog->SamplerTargets[s]; - assert(unit < MAX_TEXTURE_IMAGE_UNITS); + assert(unit < Elements(prog->TexturesUsed)); assert(tgt < NUM_TEXTURE_TARGETS); prog->TexturesUsed[unit] |= (1 << tgt); } @@ -674,7 +674,7 @@ set_program_uniform(struct gl_context *ctx, struct gl_program *program, GLuint texUnit = ((GLuint *) values)[i]; /* check that the sampler (tex unit index) is legal */ - if (texUnit >= ctx->Const.MaxTextureImageUnits) { + if (texUnit >= ctx->Const.MaxCombinedTextureImageUnits) { _mesa_error(ctx, GL_INVALID_VALUE, "glUniform1(invalid sampler/tex unit index for '%s')", param->Name); diff --git a/mesalib/src/mesa/state_tracker/st_cb_clear.c b/mesalib/src/mesa/state_tracker/st_cb_clear.c index 181fedd2b..117000ba7 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_clear.c +++ b/mesalib/src/mesa/state_tracker/st_cb_clear.c @@ -381,7 +381,8 @@ check_clear_depth_stencil_with_quad(struct gl_context *ctx, struct gl_renderbuff assert(rb->Format == MESA_FORMAT_S8 || rb->Format == MESA_FORMAT_Z24_S8 || - rb->Format == MESA_FORMAT_S8_Z24); + rb->Format == MESA_FORMAT_S8_Z24 || + rb->Format == MESA_FORMAT_Z32_FLOAT_X24S8); if (ctx->Scissor.Enabled && (ctx->Scissor.X != 0 || @@ -436,7 +437,8 @@ check_clear_stencil_with_quad(struct gl_context *ctx, struct gl_renderbuffer *rb assert(rb->Format == MESA_FORMAT_S8 || rb->Format == MESA_FORMAT_Z24_S8 || - rb->Format == MESA_FORMAT_S8_Z24); + rb->Format == MESA_FORMAT_S8_Z24 || + rb->Format == MESA_FORMAT_Z32_FLOAT_X24S8); if (maskStencil) return GL_TRUE; diff --git a/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c b/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c index d61d7ac22..dca332464 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c +++ b/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c @@ -812,6 +812,7 @@ draw_stencil_pixels(struct gl_context *ctx, GLint x, GLint y, for (row = 0; row < height; row++) { GLubyte sValues[MAX_WIDTH]; GLuint zValues[MAX_WIDTH]; + GLfloat *zValuesFloat = (GLfloat*)zValues; GLenum destType = GL_UNSIGNED_BYTE; const GLvoid *source = _mesa_image_address2d(&clippedUnpack, pixels, width, height, @@ -822,7 +823,11 @@ draw_stencil_pixels(struct gl_context *ctx, GLint x, GLint y, ctx->_ImageTransferState); if (format == GL_DEPTH_STENCIL) { - _mesa_unpack_depth_span(ctx, spanWidth, GL_UNSIGNED_INT, zValues, + GLenum ztype = + pt->resource->format == PIPE_FORMAT_Z32_FLOAT_S8X24_USCALED ? + GL_FLOAT : GL_UNSIGNED_INT; + + _mesa_unpack_depth_span(ctx, spanWidth, ztype, zValues, (1 << 24) - 1, type, source, &clippedUnpack); } @@ -887,6 +892,26 @@ draw_stencil_pixels(struct gl_context *ctx, GLint x, GLint y, } } break; + case PIPE_FORMAT_Z32_FLOAT_S8X24_USCALED: + if (format == GL_DEPTH_STENCIL) { + uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4); + GLfloat *destf = (GLfloat*)dest; + GLint k; + assert(usage == PIPE_TRANSFER_WRITE); + for (k = 0; k < spanWidth; k++) { + destf[k*2] = zValuesFloat[k]; + dest[k*2+1] = sValues[k] & 0xff; + } + } + else { + uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4); + GLint k; + assert(usage == PIPE_TRANSFER_READ_WRITE); + for (k = 0; k < spanWidth; k++) { + dest[k*2+1] = sValues[k] & 0xff; + } + } + break; default: assert(0); } @@ -994,14 +1019,23 @@ st_DrawPixels(struct gl_context *ctx, GLint x, GLint y, GL_NONE, GL_NONE, PIPE_TEXTURE_2D, 0, PIPE_BIND_SAMPLER_VIEW); - if (tex_format == PIPE_FORMAT_Z24_UNORM_S8_USCALED) - stencil_format = PIPE_FORMAT_X24S8_USCALED; - else if (tex_format == PIPE_FORMAT_S8_USCALED_Z24_UNORM) - stencil_format = PIPE_FORMAT_S8X24_USCALED; - else - stencil_format = PIPE_FORMAT_S8_USCALED; - if (stencil_format == PIPE_FORMAT_NONE) - goto stencil_fallback; + + switch (tex_format) { + case PIPE_FORMAT_Z24_UNORM_S8_USCALED: + stencil_format = PIPE_FORMAT_X24S8_USCALED; + break; + case PIPE_FORMAT_S8_USCALED_Z24_UNORM: + stencil_format = PIPE_FORMAT_S8X24_USCALED; + break; + case PIPE_FORMAT_Z32_FLOAT_S8X24_USCALED: + stencil_format = PIPE_FORMAT_X32_S8X24_USCALED; + break; + case PIPE_FORMAT_S8_USCALED: + stencil_format = PIPE_FORMAT_S8_USCALED; + break; + default: + goto stencil_fallback; + } } /* Mesa state should be up to date by now */ @@ -1188,6 +1222,18 @@ copy_stencil_pixels(struct gl_context *ctx, GLint srcx, GLint srcy, assert(usage == PIPE_TRANSFER_WRITE); memcpy(dst, src, width); break; + case PIPE_FORMAT_Z32_FLOAT_S8X24_USCALED: + { + uint *dst4 = (uint *) dst; + int j; + dst4++; + assert(usage == PIPE_TRANSFER_READ_WRITE); + for (j = 0; j < width; j++) { + *dst4 = src[j] & 0xff; + dst4 += 2; + } + } + break; default: assert(0); } diff --git a/mesalib/src/mesa/state_tracker/st_cb_readpixels.c b/mesalib/src/mesa/state_tracker/st_cb_readpixels.c index 67926e392..e2b29fe30 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_readpixels.c +++ b/mesalib/src/mesa/state_tracker/st_cb_readpixels.c @@ -151,6 +151,24 @@ st_read_stencil_pixels(struct gl_context *ctx, GLint x, GLint y, } } break; + case PIPE_FORMAT_Z32_FLOAT_S8X24_USCALED: + if (format == GL_DEPTH_STENCIL) { + const uint *src = (uint *) (stmap + srcY * pt->stride); + const GLfloat *srcf = (const GLfloat*)src; + GLint k; + for (k = 0; k < width; k++) { + zValues[k] = srcf[k*2]; + sValues[k] = src[k*2+1] & 0xff; + } + } + else { + const uint *src = (uint *) (stmap + srcY * pt->stride); + GLint k; + for (k = 0; k < width; k++) { + sValues[k] = src[k*2+1] & 0xff; + } + } + break; default: assert(0); } @@ -159,7 +177,7 @@ st_read_stencil_pixels(struct gl_context *ctx, GLint x, GLint y, dest = _mesa_image_address2d(packing, pixels, width, height, format, type, j, 0); if (format == GL_DEPTH_STENCIL) { - _mesa_pack_depth_stencil_span(ctx, width, dest, + _mesa_pack_depth_stencil_span(ctx, width, type, dest, zValues, sValues, packing); } else { @@ -568,6 +586,31 @@ st_readpixels(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei h dst += dstStride; } } + else if (pformat == PIPE_FORMAT_Z32_FLOAT) { + for (i = 0; i < height; i++) { + GLfloat zfloat[MAX_WIDTH]; + pipe_get_tile_raw(pipe, trans, 0, y, width, 1, zfloat, 0); + y += yStep; + _mesa_pack_depth_span(ctx, width, dst, type, + zfloat, &clippedPacking); + dst += dstStride; + } + } + else if (pformat == PIPE_FORMAT_Z32_FLOAT_S8X24_USCALED) { + assert(format == GL_DEPTH_COMPONENT); + for (i = 0; i < height; i++) { + GLfloat zfloat[MAX_WIDTH]; /* Z32 */ + GLfloat zfloat2[MAX_WIDTH*2]; /* Z32X32 */ + pipe_get_tile_raw(pipe, trans, 0, y, width, 1, zfloat2, 0); + y += yStep; + for (j = 0; j < width; j++) { + zfloat[j] = zfloat2[j*2]; + } + _mesa_pack_depth_span(ctx, width, dst, type, + zfloat, &clippedPacking); + dst += dstStride; + } + } else { /* RGBA format */ /* Do a row at a time to flip image data vertically */ diff --git a/mesalib/src/mesa/state_tracker/st_extensions.c b/mesalib/src/mesa/state_tracker/st_extensions.c index d3aebe526..99b231d97 100644 --- a/mesalib/src/mesa/state_tracker/st_extensions.c +++ b/mesalib/src/mesa/state_tracker/st_extensions.c @@ -607,4 +607,15 @@ void st_init_extensions(struct st_context *st) if (screen->get_param(screen, PIPE_CAP_SM3)) { ctx->Extensions.ARB_shader_texture_lod = GL_TRUE; } + + if (screen->is_format_supported(screen, PIPE_FORMAT_Z32_FLOAT, + PIPE_TEXTURE_2D, 0, + PIPE_BIND_DEPTH_STENCIL | + PIPE_BIND_SAMPLER_VIEW) && + screen->is_format_supported(screen, PIPE_FORMAT_Z32_FLOAT_S8X24_USCALED, + PIPE_TEXTURE_2D, 0, + PIPE_BIND_DEPTH_STENCIL | + PIPE_BIND_SAMPLER_VIEW)) { + ctx->Extensions.ARB_depth_buffer_float = GL_TRUE; + } } diff --git a/mesalib/src/mesa/state_tracker/st_format.c b/mesalib/src/mesa/state_tracker/st_format.c index fa5d8f505..bd4f0860c 100644 --- a/mesalib/src/mesa/state_tracker/st_format.c +++ b/mesalib/src/mesa/state_tracker/st_format.c @@ -68,42 +68,70 @@ GLenum st_format_datatype(enum pipe_format format) { const struct util_format_description *desc; + int i; desc = util_format_description(format); assert(desc); + /* Find the first non-VOID channel. */ + for (i = 0; i < 4; i++) { + if (desc->channel[i].type != UTIL_FORMAT_TYPE_VOID) { + break; + } + } + if (desc->layout == UTIL_FORMAT_LAYOUT_PLAIN) { if (format == PIPE_FORMAT_B5G5R5A1_UNORM || format == PIPE_FORMAT_B5G6R5_UNORM) { return GL_UNSIGNED_SHORT; } + else if (format == PIPE_FORMAT_R11G11B10_FLOAT || + format == PIPE_FORMAT_R9G9B9E5_FLOAT) { + return GL_FLOAT; + } else if (format == PIPE_FORMAT_Z24_UNORM_S8_USCALED || format == PIPE_FORMAT_S8_USCALED_Z24_UNORM || format == PIPE_FORMAT_Z24X8_UNORM || format == PIPE_FORMAT_X8Z24_UNORM) { return GL_UNSIGNED_INT_24_8; } + else if (format == PIPE_FORMAT_Z32_FLOAT_S8X24_USCALED) { + return GL_FLOAT_32_UNSIGNED_INT_24_8_REV; + } else { const GLuint size = format_max_bits(format); + + assert(i < 4); + if (i == 4) + return GL_NONE; + if (size == 8) { - if (desc->channel[0].type == UTIL_FORMAT_TYPE_UNSIGNED) + if (desc->channel[i].type == UTIL_FORMAT_TYPE_UNSIGNED) return GL_UNSIGNED_BYTE; else return GL_BYTE; } else if (size == 16) { - if (desc->channel[0].type == UTIL_FORMAT_TYPE_UNSIGNED) + if (desc->channel[i].type == UTIL_FORMAT_TYPE_FLOAT) + return GL_HALF_FLOAT; + if (desc->channel[i].type == UTIL_FORMAT_TYPE_UNSIGNED) return GL_UNSIGNED_SHORT; else return GL_SHORT; } - else { - assert( size <= 32 ); - if (desc->channel[0].type == UTIL_FORMAT_TYPE_UNSIGNED) + else if (size <= 32) { + if (desc->channel[i].type == UTIL_FORMAT_TYPE_FLOAT) + return GL_FLOAT; + if (desc->channel[i].type == UTIL_FORMAT_TYPE_UNSIGNED) return GL_UNSIGNED_INT; else return GL_INT; } + else { + assert(size == 64); + assert(desc->channel[i].type == UTIL_FORMAT_TYPE_FLOAT); + return GL_DOUBLE; + } } } else if (format == PIPE_FORMAT_UYVY) { @@ -180,6 +208,10 @@ st_mesa_format_to_pipe_format(gl_format mesaFormat) return PIPE_FORMAT_Z24X8_UNORM; case MESA_FORMAT_S8: return PIPE_FORMAT_S8_USCALED; + case MESA_FORMAT_Z32_FLOAT: + return PIPE_FORMAT_Z32_FLOAT; + case MESA_FORMAT_Z32_FLOAT_X24S8: + return PIPE_FORMAT_Z32_FLOAT_S8X24_USCALED; case MESA_FORMAT_YCBCR: return PIPE_FORMAT_UYVY; #if FEATURE_texture_s3tc @@ -402,6 +434,10 @@ st_pipe_format_to_mesa_format(enum pipe_format format) return MESA_FORMAT_X8_Z24; case PIPE_FORMAT_Z24_UNORM_S8_USCALED: return MESA_FORMAT_S8_Z24; + case PIPE_FORMAT_Z32_FLOAT: + return MESA_FORMAT_Z32_FLOAT; + case PIPE_FORMAT_Z32_FLOAT_S8X24_USCALED: + return MESA_FORMAT_Z32_FLOAT_X24S8; case PIPE_FORMAT_UYVY: return MESA_FORMAT_YCBCR; @@ -759,6 +795,10 @@ static const struct format_mapping format_map[] = { { GL_DEPTH_COMPONENT, 0 }, { DEFAULT_DEPTH_FORMATS } }, + { + { GL_DEPTH_COMPONENT32F, 0 }, + { PIPE_FORMAT_Z32_FLOAT, 0 } + }, /* stencil formats */ { @@ -775,6 +815,10 @@ static const struct format_mapping format_map[] = { { GL_DEPTH_STENCIL_EXT, GL_DEPTH24_STENCIL8_EXT, 0 }, { PIPE_FORMAT_Z24_UNORM_S8_USCALED, PIPE_FORMAT_S8_USCALED_Z24_UNORM, 0 } }, + { + { GL_DEPTH32F_STENCIL8, 0 }, + { PIPE_FORMAT_Z32_FLOAT_S8X24_USCALED, 0 } + }, /* sRGB formats */ { diff --git a/mesalib/src/mesa/state_tracker/st_manager.c b/mesalib/src/mesa/state_tracker/st_manager.c index a8c4b5c3f..7bd82aae2 100644 --- a/mesalib/src/mesa/state_tracker/st_manager.c +++ b/mesalib/src/mesa/state_tracker/st_manager.c @@ -918,6 +918,15 @@ st_manager_add_color_renderbuffer(struct st_context *st, return FALSE; st_framebuffer_update_attachments(stfb); + + /* + * Force a call to the state tracker manager to validate the + * new renderbuffer. It might be that there is a window system + * renderbuffer available. + */ + if(stfb->iface) + stfb->iface_stamp = p_atomic_read(&stfb->iface->stamp) - 1; + st_invalidate_state(st->ctx, _NEW_BUFFERS); return TRUE; diff --git a/mesalib/src/mesa/swrast/s_blit.c b/mesalib/src/mesa/swrast/s_blit.c index 3516a41bf..7f53f19eb 100644 --- a/mesalib/src/mesa/swrast/s_blit.c +++ b/mesalib/src/mesa/swrast/s_blit.c @@ -568,9 +568,6 @@ _swrast_BlitFramebuffer(struct gl_context *ctx, }; GLint i; - if (!ctx->DrawBuffer->_NumColorDrawBuffers) - return; - if (!_mesa_clip_blit(ctx, &srcX0, &srcY0, &srcX1, &srcY1, &dstX0, &dstY0, &dstX1, &dstY1)) { return; diff --git a/mesalib/src/mesa/swrast/s_readpix.c b/mesalib/src/mesa/swrast/s_readpix.c index 214f2ea1a..66ca39293 100644 --- a/mesalib/src/mesa/swrast/s_readpix.c +++ b/mesalib/src/mesa/swrast/s_readpix.c @@ -446,7 +446,7 @@ read_depth_stencil_pixels(struct gl_context *ctx, GLfloat depthVals[MAX_WIDTH]; _swrast_read_depth_span_float(ctx, depthRb, width, x, y + i, depthVals); - _mesa_pack_depth_stencil_span(ctx, width, depthStencilDst, + _mesa_pack_depth_stencil_span(ctx, width, type, depthStencilDst, depthVals, stencilVals, packing); } } |