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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 * \file pixeltransfer.c
28 * Pixel transfer operations (scale, bias, table lookups, etc)
34 #include "pixeltransfer.h"
39 * Apply scale and bias factors to an array of RGBA pixels.
42 _mesa_scale_and_bias_rgba(GLuint n
, GLfloat rgba
[][4],
43 GLfloat rScale
, GLfloat gScale
,
44 GLfloat bScale
, GLfloat aScale
,
45 GLfloat rBias
, GLfloat gBias
,
46 GLfloat bBias
, GLfloat aBias
)
48 if (rScale
!= 1.0 || rBias
!= 0.0) {
50 for (i
= 0; i
< n
; i
++) {
51 rgba
[i
][RCOMP
] = rgba
[i
][RCOMP
] * rScale
+ rBias
;
54 if (gScale
!= 1.0 || gBias
!= 0.0) {
56 for (i
= 0; i
< n
; i
++) {
57 rgba
[i
][GCOMP
] = rgba
[i
][GCOMP
] * gScale
+ gBias
;
60 if (bScale
!= 1.0 || bBias
!= 0.0) {
62 for (i
= 0; i
< n
; i
++) {
63 rgba
[i
][BCOMP
] = rgba
[i
][BCOMP
] * bScale
+ bBias
;
66 if (aScale
!= 1.0 || aBias
!= 0.0) {
68 for (i
= 0; i
< n
; i
++) {
69 rgba
[i
][ACOMP
] = rgba
[i
][ACOMP
] * aScale
+ aBias
;
76 * Apply pixel mapping to an array of floating point RGBA pixels.
79 _mesa_map_rgba( const struct gl_context
*ctx
, GLuint n
, GLfloat rgba
[][4] )
81 const GLfloat rscale
= (GLfloat
) (ctx
->PixelMaps
.RtoR
.Size
- 1);
82 const GLfloat gscale
= (GLfloat
) (ctx
->PixelMaps
.GtoG
.Size
- 1);
83 const GLfloat bscale
= (GLfloat
) (ctx
->PixelMaps
.BtoB
.Size
- 1);
84 const GLfloat ascale
= (GLfloat
) (ctx
->PixelMaps
.AtoA
.Size
- 1);
85 const GLfloat
*rMap
= ctx
->PixelMaps
.RtoR
.Map
;
86 const GLfloat
*gMap
= ctx
->PixelMaps
.GtoG
.Map
;
87 const GLfloat
*bMap
= ctx
->PixelMaps
.BtoB
.Map
;
88 const GLfloat
*aMap
= ctx
->PixelMaps
.AtoA
.Map
;
91 GLfloat r
= CLAMP(rgba
[i
][RCOMP
], 0.0F
, 1.0F
);
92 GLfloat g
= CLAMP(rgba
[i
][GCOMP
], 0.0F
, 1.0F
);
93 GLfloat b
= CLAMP(rgba
[i
][BCOMP
], 0.0F
, 1.0F
);
94 GLfloat a
= CLAMP(rgba
[i
][ACOMP
], 0.0F
, 1.0F
);
95 rgba
[i
][RCOMP
] = rMap
[IROUND(r
* rscale
)];
96 rgba
[i
][GCOMP
] = gMap
[IROUND(g
* gscale
)];
97 rgba
[i
][BCOMP
] = bMap
[IROUND(b
* bscale
)];
98 rgba
[i
][ACOMP
] = aMap
[IROUND(a
* ascale
)];
103 * Apply a color table lookup to an array of floating point RGBA colors.
106 _mesa_lookup_rgba_float(const struct gl_color_table
*table
,
107 GLuint n
, GLfloat rgba
[][4])
109 const GLint max
= table
->Size
- 1;
110 const GLfloat scale
= (GLfloat
) max
;
111 const GLfloat
*lut
= table
->TableF
;
114 if (!table
->TableF
|| table
->Size
== 0)
117 switch (table
->_BaseFormat
) {
119 /* replace RGBA with I */
120 for (i
= 0; i
< n
; i
++) {
121 GLint j
= IROUND(rgba
[i
][RCOMP
] * scale
);
122 GLfloat c
= lut
[CLAMP(j
, 0, max
)];
130 /* replace RGB with L */
131 for (i
= 0; i
< n
; i
++) {
132 GLint j
= IROUND(rgba
[i
][RCOMP
] * scale
);
133 GLfloat c
= lut
[CLAMP(j
, 0, max
)];
140 /* replace A with A */
141 for (i
= 0; i
< n
; i
++) {
142 GLint j
= IROUND(rgba
[i
][ACOMP
] * scale
);
143 rgba
[i
][ACOMP
] = lut
[CLAMP(j
, 0, max
)];
146 case GL_LUMINANCE_ALPHA
:
147 /* replace RGBA with LLLA */
148 for (i
= 0; i
< n
; i
++) {
149 GLint jL
= IROUND(rgba
[i
][RCOMP
] * scale
);
150 GLint jA
= IROUND(rgba
[i
][ACOMP
] * scale
);
151 GLfloat luminance
, alpha
;
152 jL
= CLAMP(jL
, 0, max
);
153 jA
= CLAMP(jA
, 0, max
);
154 luminance
= lut
[jL
* 2 + 0];
155 alpha
= lut
[jA
* 2 + 1];
158 rgba
[i
][BCOMP
] = luminance
;
159 rgba
[i
][ACOMP
] = alpha
;;
163 /* replace RGB with RGB */
164 for (i
= 0; i
< n
; i
++) {
165 GLint jR
= IROUND(rgba
[i
][RCOMP
] * scale
);
166 jR
= CLAMP(jR
, 0, max
);
167 rgba
[i
][RCOMP
] = lut
[jR
* 3 + 0];
171 /* replace RG with RG */
172 for (i
= 0; i
< n
; i
++) {
173 GLint jR
= IROUND(rgba
[i
][RCOMP
] * scale
);
174 GLint jG
= IROUND(rgba
[i
][GCOMP
] * scale
);
175 jR
= CLAMP(jR
, 0, max
);
176 jG
= CLAMP(jG
, 0, max
);
177 rgba
[i
][RCOMP
] = lut
[jR
* 3 + 0];
178 rgba
[i
][GCOMP
] = lut
[jG
* 3 + 1];
182 /* replace RGB with RGB */
183 for (i
= 0; i
< n
; i
++) {
184 GLint jR
= IROUND(rgba
[i
][RCOMP
] * scale
);
185 GLint jG
= IROUND(rgba
[i
][GCOMP
] * scale
);
186 GLint jB
= IROUND(rgba
[i
][BCOMP
] * scale
);
187 jR
= CLAMP(jR
, 0, max
);
188 jG
= CLAMP(jG
, 0, max
);
189 jB
= CLAMP(jB
, 0, max
);
190 rgba
[i
][RCOMP
] = lut
[jR
* 3 + 0];
191 rgba
[i
][GCOMP
] = lut
[jG
* 3 + 1];
192 rgba
[i
][BCOMP
] = lut
[jB
* 3 + 2];
196 /* replace RGBA with RGBA */
197 for (i
= 0; i
< n
; i
++) {
198 GLint jR
= IROUND(rgba
[i
][RCOMP
] * scale
);
199 GLint jG
= IROUND(rgba
[i
][GCOMP
] * scale
);
200 GLint jB
= IROUND(rgba
[i
][BCOMP
] * scale
);
201 GLint jA
= IROUND(rgba
[i
][ACOMP
] * scale
);
202 jR
= CLAMP(jR
, 0, max
);
203 jG
= CLAMP(jG
, 0, max
);
204 jB
= CLAMP(jB
, 0, max
);
205 jA
= CLAMP(jA
, 0, max
);
206 rgba
[i
][RCOMP
] = lut
[jR
* 4 + 0];
207 rgba
[i
][GCOMP
] = lut
[jG
* 4 + 1];
208 rgba
[i
][BCOMP
] = lut
[jB
* 4 + 2];
209 rgba
[i
][ACOMP
] = lut
[jA
* 4 + 3];
213 _mesa_problem(NULL
, "Bad format in _mesa_lookup_rgba_float");
221 * Apply a color table lookup to an array of ubyte/RGBA colors.
224 _mesa_lookup_rgba_ubyte(const struct gl_color_table
*table
,
225 GLuint n
, GLubyte rgba
[][4])
227 const GLubyte
*lut
= table
->TableUB
;
228 const GLfloat scale
= (GLfloat
) (table
->Size
- 1) / (GLfloat
)255.0;
231 if (!table
->TableUB
|| table
->Size
== 0)
234 switch (table
->_BaseFormat
) {
236 /* replace RGBA with I */
237 if (table
->Size
== 256) {
238 for (i
= 0; i
< n
; i
++) {
239 const GLubyte c
= lut
[rgba
[i
][RCOMP
]];
247 for (i
= 0; i
< n
; i
++) {
248 GLint j
= IROUND((GLfloat
) rgba
[i
][RCOMP
] * scale
);
252 rgba
[i
][ACOMP
] = lut
[j
];
257 /* replace RGB with L */
258 if (table
->Size
== 256) {
259 for (i
= 0; i
< n
; i
++) {
260 const GLubyte c
= lut
[rgba
[i
][RCOMP
]];
267 for (i
= 0; i
< n
; i
++) {
268 GLint j
= IROUND((GLfloat
) rgba
[i
][RCOMP
] * scale
);
271 rgba
[i
][BCOMP
] = lut
[j
];
276 /* replace A with A */
277 if (table
->Size
== 256) {
278 for (i
= 0; i
< n
; i
++) {
279 rgba
[i
][ACOMP
] = lut
[rgba
[i
][ACOMP
]];
283 for (i
= 0; i
< n
; i
++) {
284 GLint j
= IROUND((GLfloat
) rgba
[i
][ACOMP
] * scale
);
285 rgba
[i
][ACOMP
] = lut
[j
];
289 case GL_LUMINANCE_ALPHA
:
290 /* replace RGBA with LLLA */
291 if (table
->Size
== 256) {
292 for (i
= 0; i
< n
; i
++) {
293 GLubyte l
= lut
[rgba
[i
][RCOMP
] * 2 + 0];
294 GLubyte a
= lut
[rgba
[i
][ACOMP
] * 2 + 1];;
302 for (i
= 0; i
< n
; i
++) {
303 GLint jL
= IROUND((GLfloat
) rgba
[i
][RCOMP
] * scale
);
304 GLint jA
= IROUND((GLfloat
) rgba
[i
][ACOMP
] * scale
);
305 GLubyte luminance
= lut
[jL
* 2 + 0];
306 GLubyte alpha
= lut
[jA
* 2 + 1];
309 rgba
[i
][BCOMP
] = luminance
;
310 rgba
[i
][ACOMP
] = alpha
;
315 if (table
->Size
== 256) {
316 for (i
= 0; i
< n
; i
++) {
317 rgba
[i
][RCOMP
] = lut
[rgba
[i
][RCOMP
] * 3 + 0];
318 rgba
[i
][GCOMP
] = lut
[rgba
[i
][GCOMP
] * 3 + 1];
319 rgba
[i
][BCOMP
] = lut
[rgba
[i
][BCOMP
] * 3 + 2];
323 for (i
= 0; i
< n
; i
++) {
324 GLint jR
= IROUND((GLfloat
) rgba
[i
][RCOMP
] * scale
);
325 GLint jG
= IROUND((GLfloat
) rgba
[i
][GCOMP
] * scale
);
326 GLint jB
= IROUND((GLfloat
) rgba
[i
][BCOMP
] * scale
);
327 rgba
[i
][RCOMP
] = lut
[jR
* 3 + 0];
328 rgba
[i
][GCOMP
] = lut
[jG
* 3 + 1];
329 rgba
[i
][BCOMP
] = lut
[jB
* 3 + 2];
334 if (table
->Size
== 256) {
335 for (i
= 0; i
< n
; i
++) {
336 rgba
[i
][RCOMP
] = lut
[rgba
[i
][RCOMP
] * 4 + 0];
337 rgba
[i
][GCOMP
] = lut
[rgba
[i
][GCOMP
] * 4 + 1];
338 rgba
[i
][BCOMP
] = lut
[rgba
[i
][BCOMP
] * 4 + 2];
339 rgba
[i
][ACOMP
] = lut
[rgba
[i
][ACOMP
] * 4 + 3];
343 for (i
= 0; i
< n
; i
++) {
344 GLint jR
= IROUND((GLfloat
) rgba
[i
][RCOMP
] * scale
);
345 GLint jG
= IROUND((GLfloat
) rgba
[i
][GCOMP
] * scale
);
346 GLint jB
= IROUND((GLfloat
) rgba
[i
][BCOMP
] * scale
);
347 GLint jA
= IROUND((GLfloat
) rgba
[i
][ACOMP
] * scale
);
348 CLAMPED_FLOAT_TO_CHAN(rgba
[i
][RCOMP
], lut
[jR
* 4 + 0]);
349 CLAMPED_FLOAT_TO_CHAN(rgba
[i
][GCOMP
], lut
[jG
* 4 + 1]);
350 CLAMPED_FLOAT_TO_CHAN(rgba
[i
][BCOMP
], lut
[jB
* 4 + 2]);
351 CLAMPED_FLOAT_TO_CHAN(rgba
[i
][ACOMP
], lut
[jA
* 4 + 3]);
356 _mesa_problem(NULL
, "Bad format in _mesa_lookup_rgba_chan");
364 * Map color indexes to float rgba values.
367 _mesa_map_ci_to_rgba( const struct gl_context
*ctx
, GLuint n
,
368 const GLuint index
[], GLfloat rgba
[][4] )
370 GLuint rmask
= ctx
->PixelMaps
.ItoR
.Size
- 1;
371 GLuint gmask
= ctx
->PixelMaps
.ItoG
.Size
- 1;
372 GLuint bmask
= ctx
->PixelMaps
.ItoB
.Size
- 1;
373 GLuint amask
= ctx
->PixelMaps
.ItoA
.Size
- 1;
374 const GLfloat
*rMap
= ctx
->PixelMaps
.ItoR
.Map
;
375 const GLfloat
*gMap
= ctx
->PixelMaps
.ItoG
.Map
;
376 const GLfloat
*bMap
= ctx
->PixelMaps
.ItoB
.Map
;
377 const GLfloat
*aMap
= ctx
->PixelMaps
.ItoA
.Map
;
380 rgba
[i
][RCOMP
] = rMap
[index
[i
] & rmask
];
381 rgba
[i
][GCOMP
] = gMap
[index
[i
] & gmask
];
382 rgba
[i
][BCOMP
] = bMap
[index
[i
] & bmask
];
383 rgba
[i
][ACOMP
] = aMap
[index
[i
] & amask
];
389 * Map ubyte color indexes to ubyte/RGBA values.
392 _mesa_map_ci8_to_rgba8(const struct gl_context
*ctx
,
393 GLuint n
, const GLubyte index
[],
396 GLuint rmask
= ctx
->PixelMaps
.ItoR
.Size
- 1;
397 GLuint gmask
= ctx
->PixelMaps
.ItoG
.Size
- 1;
398 GLuint bmask
= ctx
->PixelMaps
.ItoB
.Size
- 1;
399 GLuint amask
= ctx
->PixelMaps
.ItoA
.Size
- 1;
400 const GLubyte
*rMap
= ctx
->PixelMaps
.ItoR
.Map8
;
401 const GLubyte
*gMap
= ctx
->PixelMaps
.ItoG
.Map8
;
402 const GLubyte
*bMap
= ctx
->PixelMaps
.ItoB
.Map8
;
403 const GLubyte
*aMap
= ctx
->PixelMaps
.ItoA
.Map8
;
406 rgba
[i
][RCOMP
] = rMap
[index
[i
] & rmask
];
407 rgba
[i
][GCOMP
] = gMap
[index
[i
] & gmask
];
408 rgba
[i
][BCOMP
] = bMap
[index
[i
] & bmask
];
409 rgba
[i
][ACOMP
] = aMap
[index
[i
] & amask
];
415 _mesa_scale_and_bias_depth(const struct gl_context
*ctx
, GLuint n
,
416 GLfloat depthValues
[])
418 const GLfloat scale
= ctx
->Pixel
.DepthScale
;
419 const GLfloat bias
= ctx
->Pixel
.DepthBias
;
421 for (i
= 0; i
< n
; i
++) {
422 GLfloat d
= depthValues
[i
] * scale
+ bias
;
423 depthValues
[i
] = CLAMP(d
, 0.0F
, 1.0F
);
429 _mesa_scale_and_bias_depth_uint(const struct gl_context
*ctx
, GLuint n
,
430 GLuint depthValues
[])
432 const GLdouble max
= (double) 0xffffffff;
433 const GLdouble scale
= ctx
->Pixel
.DepthScale
;
434 const GLdouble bias
= ctx
->Pixel
.DepthBias
* max
;
436 for (i
= 0; i
< n
; i
++) {
437 GLdouble d
= (GLdouble
) depthValues
[i
] * scale
+ bias
;
438 d
= CLAMP(d
, 0.0, max
);
439 depthValues
[i
] = (GLuint
) d
;
444 * Apply various pixel transfer operations to an array of RGBA pixels
445 * as indicated by the transferOps bitmask
448 _mesa_apply_rgba_transfer_ops(struct gl_context
*ctx
, GLbitfield transferOps
,
449 GLuint n
, GLfloat rgba
[][4])
452 if (transferOps
& IMAGE_SCALE_BIAS_BIT
) {
453 _mesa_scale_and_bias_rgba(n
, rgba
,
454 ctx
->Pixel
.RedScale
, ctx
->Pixel
.GreenScale
,
455 ctx
->Pixel
.BlueScale
, ctx
->Pixel
.AlphaScale
,
456 ctx
->Pixel
.RedBias
, ctx
->Pixel
.GreenBias
,
457 ctx
->Pixel
.BlueBias
, ctx
->Pixel
.AlphaBias
);
459 /* color map lookup */
460 if (transferOps
& IMAGE_MAP_COLOR_BIT
) {
461 _mesa_map_rgba( ctx
, n
, rgba
);
464 /* clamping to [0,1] */
465 if (transferOps
& IMAGE_CLAMP_BIT
) {
467 for (i
= 0; i
< n
; i
++) {
468 rgba
[i
][RCOMP
] = CLAMP(rgba
[i
][RCOMP
], 0.0F
, 1.0F
);
469 rgba
[i
][GCOMP
] = CLAMP(rgba
[i
][GCOMP
], 0.0F
, 1.0F
);
470 rgba
[i
][BCOMP
] = CLAMP(rgba
[i
][BCOMP
], 0.0F
, 1.0F
);
471 rgba
[i
][ACOMP
] = CLAMP(rgba
[i
][ACOMP
], 0.0F
, 1.0F
);
478 * Apply color index shift and offset to an array of pixels.
481 _mesa_shift_and_offset_ci(const struct gl_context
*ctx
,
482 GLuint n
, GLuint indexes
[])
484 GLint shift
= ctx
->Pixel
.IndexShift
;
485 GLint offset
= ctx
->Pixel
.IndexOffset
;
489 indexes
[i
] = (indexes
[i
] << shift
) + offset
;
492 else if (shift
< 0) {
495 indexes
[i
] = (indexes
[i
] >> shift
) + offset
;
500 indexes
[i
] = indexes
[i
] + offset
;
508 * Apply color index shift, offset and table lookup to an array
512 _mesa_apply_ci_transfer_ops(const struct gl_context
*ctx
,
513 GLbitfield transferOps
,
514 GLuint n
, GLuint indexes
[])
516 if (transferOps
& IMAGE_SHIFT_OFFSET_BIT
) {
517 _mesa_shift_and_offset_ci(ctx
, n
, indexes
);
519 if (transferOps
& IMAGE_MAP_COLOR_BIT
) {
520 const GLuint mask
= ctx
->PixelMaps
.ItoI
.Size
- 1;
522 for (i
= 0; i
< n
; i
++) {
523 const GLuint j
= indexes
[i
] & mask
;
524 indexes
[i
] = IROUND(ctx
->PixelMaps
.ItoI
.Map
[j
]);
531 * Apply stencil index shift, offset and table lookup to an array
535 _mesa_apply_stencil_transfer_ops(const struct gl_context
*ctx
, GLuint n
,
538 if (ctx
->Pixel
.IndexShift
!= 0 || ctx
->Pixel
.IndexOffset
!= 0) {
539 const GLint offset
= ctx
->Pixel
.IndexOffset
;
540 GLint shift
= ctx
->Pixel
.IndexShift
;
543 for (i
= 0; i
< n
; i
++) {
544 stencil
[i
] = (stencil
[i
] << shift
) + offset
;
547 else if (shift
< 0) {
549 for (i
= 0; i
< n
; i
++) {
550 stencil
[i
] = (stencil
[i
] >> shift
) + offset
;
554 for (i
= 0; i
< n
; i
++) {
555 stencil
[i
] = stencil
[i
] + offset
;
559 if (ctx
->Pixel
.MapStencilFlag
) {
560 GLuint mask
= ctx
->PixelMaps
.StoS
.Size
- 1;
562 for (i
= 0; i
< n
; i
++) {
563 stencil
[i
] = (GLstencil
)ctx
->PixelMaps
.StoS
.Map
[ stencil
[i
] & mask
];