2 * Mesa 3-D graphics library
4 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
5 * Copyright (C) 2009-2010 VMware, Inc. All Rights Reserved.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 * OTHER DEALINGS IN THE SOFTWARE.
28 * \file pixeltransfer.c
29 * Pixel transfer operations (scale, bias, table lookups, etc)
35 #include "pixeltransfer.h"
36 #include "util/imports.h"
38 #include "util/rounding.h"
42 * Apply scale and bias factors to an array of RGBA pixels.
45 _mesa_scale_and_bias_rgba(GLuint n
, GLfloat rgba
[][4],
46 GLfloat rScale
, GLfloat gScale
,
47 GLfloat bScale
, GLfloat aScale
,
48 GLfloat rBias
, GLfloat gBias
,
49 GLfloat bBias
, GLfloat aBias
)
51 if (rScale
!= 1.0F
|| rBias
!= 0.0F
) {
53 for (i
= 0; i
< n
; i
++) {
54 rgba
[i
][RCOMP
] = rgba
[i
][RCOMP
] * rScale
+ rBias
;
57 if (gScale
!= 1.0F
|| gBias
!= 0.0F
) {
59 for (i
= 0; i
< n
; i
++) {
60 rgba
[i
][GCOMP
] = rgba
[i
][GCOMP
] * gScale
+ gBias
;
63 if (bScale
!= 1.0F
|| bBias
!= 0.0F
) {
65 for (i
= 0; i
< n
; i
++) {
66 rgba
[i
][BCOMP
] = rgba
[i
][BCOMP
] * bScale
+ bBias
;
69 if (aScale
!= 1.0F
|| aBias
!= 0.0F
) {
71 for (i
= 0; i
< n
; i
++) {
72 rgba
[i
][ACOMP
] = rgba
[i
][ACOMP
] * aScale
+ aBias
;
79 * Apply pixel mapping to an array of floating point RGBA pixels.
82 _mesa_map_rgba( const struct gl_context
*ctx
, GLuint n
, GLfloat rgba
[][4] )
84 const GLfloat rscale
= (GLfloat
) (ctx
->PixelMaps
.RtoR
.Size
- 1);
85 const GLfloat gscale
= (GLfloat
) (ctx
->PixelMaps
.GtoG
.Size
- 1);
86 const GLfloat bscale
= (GLfloat
) (ctx
->PixelMaps
.BtoB
.Size
- 1);
87 const GLfloat ascale
= (GLfloat
) (ctx
->PixelMaps
.AtoA
.Size
- 1);
88 const GLfloat
*rMap
= ctx
->PixelMaps
.RtoR
.Map
;
89 const GLfloat
*gMap
= ctx
->PixelMaps
.GtoG
.Map
;
90 const GLfloat
*bMap
= ctx
->PixelMaps
.BtoB
.Map
;
91 const GLfloat
*aMap
= ctx
->PixelMaps
.AtoA
.Map
;
94 GLfloat r
= CLAMP(rgba
[i
][RCOMP
], 0.0F
, 1.0F
);
95 GLfloat g
= CLAMP(rgba
[i
][GCOMP
], 0.0F
, 1.0F
);
96 GLfloat b
= CLAMP(rgba
[i
][BCOMP
], 0.0F
, 1.0F
);
97 GLfloat a
= CLAMP(rgba
[i
][ACOMP
], 0.0F
, 1.0F
);
98 rgba
[i
][RCOMP
] = rMap
[(int)_mesa_lroundevenf(r
* rscale
)];
99 rgba
[i
][GCOMP
] = gMap
[(int)_mesa_lroundevenf(g
* gscale
)];
100 rgba
[i
][BCOMP
] = bMap
[(int)_mesa_lroundevenf(b
* bscale
)];
101 rgba
[i
][ACOMP
] = aMap
[(int)_mesa_lroundevenf(a
* ascale
)];
106 * Map color indexes to float rgba values.
109 _mesa_map_ci_to_rgba( const struct gl_context
*ctx
, GLuint n
,
110 const GLuint index
[], GLfloat rgba
[][4] )
112 GLuint rmask
= ctx
->PixelMaps
.ItoR
.Size
- 1;
113 GLuint gmask
= ctx
->PixelMaps
.ItoG
.Size
- 1;
114 GLuint bmask
= ctx
->PixelMaps
.ItoB
.Size
- 1;
115 GLuint amask
= ctx
->PixelMaps
.ItoA
.Size
- 1;
116 const GLfloat
*rMap
= ctx
->PixelMaps
.ItoR
.Map
;
117 const GLfloat
*gMap
= ctx
->PixelMaps
.ItoG
.Map
;
118 const GLfloat
*bMap
= ctx
->PixelMaps
.ItoB
.Map
;
119 const GLfloat
*aMap
= ctx
->PixelMaps
.ItoA
.Map
;
122 rgba
[i
][RCOMP
] = rMap
[index
[i
] & rmask
];
123 rgba
[i
][GCOMP
] = gMap
[index
[i
] & gmask
];
124 rgba
[i
][BCOMP
] = bMap
[index
[i
] & bmask
];
125 rgba
[i
][ACOMP
] = aMap
[index
[i
] & amask
];
131 _mesa_scale_and_bias_depth(const struct gl_context
*ctx
, GLuint n
,
132 GLfloat depthValues
[])
134 const GLfloat scale
= ctx
->Pixel
.DepthScale
;
135 const GLfloat bias
= ctx
->Pixel
.DepthBias
;
137 for (i
= 0; i
< n
; i
++) {
138 GLfloat d
= depthValues
[i
] * scale
+ bias
;
139 depthValues
[i
] = CLAMP(d
, 0.0F
, 1.0F
);
145 _mesa_scale_and_bias_depth_uint(const struct gl_context
*ctx
, GLuint n
,
146 GLuint depthValues
[])
148 const GLdouble max
= (double) 0xffffffff;
149 const GLdouble scale
= ctx
->Pixel
.DepthScale
;
150 const GLdouble bias
= ctx
->Pixel
.DepthBias
* max
;
152 for (i
= 0; i
< n
; i
++) {
153 GLdouble d
= (GLdouble
) depthValues
[i
] * scale
+ bias
;
154 d
= CLAMP(d
, 0.0, max
);
155 depthValues
[i
] = (GLuint
) d
;
160 * Apply various pixel transfer operations to an array of RGBA pixels
161 * as indicated by the transferOps bitmask
164 _mesa_apply_rgba_transfer_ops(struct gl_context
*ctx
, GLbitfield transferOps
,
165 GLuint n
, GLfloat rgba
[][4])
168 if (transferOps
& IMAGE_SCALE_BIAS_BIT
) {
169 _mesa_scale_and_bias_rgba(n
, rgba
,
170 ctx
->Pixel
.RedScale
, ctx
->Pixel
.GreenScale
,
171 ctx
->Pixel
.BlueScale
, ctx
->Pixel
.AlphaScale
,
172 ctx
->Pixel
.RedBias
, ctx
->Pixel
.GreenBias
,
173 ctx
->Pixel
.BlueBias
, ctx
->Pixel
.AlphaBias
);
175 /* color map lookup */
176 if (transferOps
& IMAGE_MAP_COLOR_BIT
) {
177 _mesa_map_rgba( ctx
, n
, rgba
);
180 /* clamping to [0,1] */
181 if (transferOps
& IMAGE_CLAMP_BIT
) {
183 for (i
= 0; i
< n
; i
++) {
184 rgba
[i
][RCOMP
] = CLAMP(rgba
[i
][RCOMP
], 0.0F
, 1.0F
);
185 rgba
[i
][GCOMP
] = CLAMP(rgba
[i
][GCOMP
], 0.0F
, 1.0F
);
186 rgba
[i
][BCOMP
] = CLAMP(rgba
[i
][BCOMP
], 0.0F
, 1.0F
);
187 rgba
[i
][ACOMP
] = CLAMP(rgba
[i
][ACOMP
], 0.0F
, 1.0F
);
194 * Apply color index shift and offset to an array of pixels.
197 _mesa_shift_and_offset_ci(const struct gl_context
*ctx
,
198 GLuint n
, GLuint indexes
[])
200 GLint shift
= ctx
->Pixel
.IndexShift
;
201 GLint offset
= ctx
->Pixel
.IndexOffset
;
205 indexes
[i
] = (indexes
[i
] << shift
) + offset
;
208 else if (shift
< 0) {
211 indexes
[i
] = (indexes
[i
] >> shift
) + offset
;
216 indexes
[i
] = indexes
[i
] + offset
;
224 * Apply color index shift, offset and table lookup to an array
228 _mesa_apply_ci_transfer_ops(const struct gl_context
*ctx
,
229 GLbitfield transferOps
,
230 GLuint n
, GLuint indexes
[])
232 if (transferOps
& IMAGE_SHIFT_OFFSET_BIT
) {
233 _mesa_shift_and_offset_ci(ctx
, n
, indexes
);
235 if (transferOps
& IMAGE_MAP_COLOR_BIT
) {
236 const GLuint mask
= ctx
->PixelMaps
.ItoI
.Size
- 1;
238 for (i
= 0; i
< n
; i
++) {
239 const GLuint j
= indexes
[i
] & mask
;
240 indexes
[i
] = _mesa_lroundevenf(ctx
->PixelMaps
.ItoI
.Map
[j
]);
247 * Apply stencil index shift, offset and table lookup to an array
251 _mesa_apply_stencil_transfer_ops(const struct gl_context
*ctx
, GLuint n
,
254 if (ctx
->Pixel
.IndexShift
!= 0 || ctx
->Pixel
.IndexOffset
!= 0) {
255 const GLint offset
= ctx
->Pixel
.IndexOffset
;
256 GLint shift
= ctx
->Pixel
.IndexShift
;
259 for (i
= 0; i
< n
; i
++) {
260 stencil
[i
] = (stencil
[i
] << shift
) + offset
;
263 else if (shift
< 0) {
265 for (i
= 0; i
< n
; i
++) {
266 stencil
[i
] = (stencil
[i
] >> shift
) + offset
;
270 for (i
= 0; i
< n
; i
++) {
271 stencil
[i
] = stencil
[i
] + offset
;
275 if (ctx
->Pixel
.MapStencilFlag
) {
276 GLuint mask
= ctx
->PixelMaps
.StoS
.Size
- 1;
278 for (i
= 0; i
< n
; i
++) {
279 stencil
[i
] = (GLubyte
) ctx
->PixelMaps
.StoS
.Map
[ stencil
[i
] & mask
];