mesa: additional integer formats in _mesa_bytes_per_pixel()
[mesa.git] / src / mesa / main / pixeltransfer.c
1 /*
2 * Mesa 3-D graphics library
3 *
4 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
5 * Copyright (C) 2009-2010 VMware, Inc. All Rights Reserved.
6 *
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:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
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.
23 */
24
25
26 /**
27 * \file pixeltransfer.c
28 * Pixel transfer operations (scale, bias, table lookups, etc)
29 */
30
31
32 #include "glheader.h"
33 #include "colormac.h"
34 #include "pixeltransfer.h"
35 #include "imports.h"
36
37
38 /*
39 * Apply scale and bias factors to an array of RGBA pixels.
40 */
41 void
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)
47 {
48 if (rScale != 1.0 || rBias != 0.0) {
49 GLuint i;
50 for (i = 0; i < n; i++) {
51 rgba[i][RCOMP] = rgba[i][RCOMP] * rScale + rBias;
52 }
53 }
54 if (gScale != 1.0 || gBias != 0.0) {
55 GLuint i;
56 for (i = 0; i < n; i++) {
57 rgba[i][GCOMP] = rgba[i][GCOMP] * gScale + gBias;
58 }
59 }
60 if (bScale != 1.0 || bBias != 0.0) {
61 GLuint i;
62 for (i = 0; i < n; i++) {
63 rgba[i][BCOMP] = rgba[i][BCOMP] * bScale + bBias;
64 }
65 }
66 if (aScale != 1.0 || aBias != 0.0) {
67 GLuint i;
68 for (i = 0; i < n; i++) {
69 rgba[i][ACOMP] = rgba[i][ACOMP] * aScale + aBias;
70 }
71 }
72 }
73
74
75 /*
76 * Apply pixel mapping to an array of floating point RGBA pixels.
77 */
78 void
79 _mesa_map_rgba( const struct gl_context *ctx, GLuint n, GLfloat rgba[][4] )
80 {
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;
89 GLuint i;
90 for (i=0;i<n;i++) {
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)];
99 }
100 }
101
102 /**
103 * Apply a color table lookup to an array of floating point RGBA colors.
104 */
105 void
106 _mesa_lookup_rgba_float(const struct gl_color_table *table,
107 GLuint n, GLfloat rgba[][4])
108 {
109 const GLint max = table->Size - 1;
110 const GLfloat scale = (GLfloat) max;
111 const GLfloat *lut = table->TableF;
112 GLuint i;
113
114 if (!table->TableF || table->Size == 0)
115 return;
116
117 switch (table->_BaseFormat) {
118 case GL_INTENSITY:
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)];
123 rgba[i][RCOMP] =
124 rgba[i][GCOMP] =
125 rgba[i][BCOMP] =
126 rgba[i][ACOMP] = c;
127 }
128 break;
129 case GL_LUMINANCE:
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)];
134 rgba[i][RCOMP] =
135 rgba[i][GCOMP] =
136 rgba[i][BCOMP] = c;
137 }
138 break;
139 case GL_ALPHA:
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)];
144 }
145 break;
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];
156 rgba[i][RCOMP] =
157 rgba[i][GCOMP] =
158 rgba[i][BCOMP] = luminance;
159 rgba[i][ACOMP] = alpha;;
160 }
161 break;
162 case GL_RED:
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];
168 }
169 break;
170 case GL_RG:
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];
179 }
180 break;
181 case GL_RGB:
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];
193 }
194 break;
195 case GL_RGBA:
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];
210 }
211 break;
212 default:
213 _mesa_problem(NULL, "Bad format in _mesa_lookup_rgba_float");
214 return;
215 }
216 }
217
218
219
220 /**
221 * Apply a color table lookup to an array of ubyte/RGBA colors.
222 */
223 void
224 _mesa_lookup_rgba_ubyte(const struct gl_color_table *table,
225 GLuint n, GLubyte rgba[][4])
226 {
227 const GLubyte *lut = table->TableUB;
228 const GLfloat scale = (GLfloat) (table->Size - 1) / (GLfloat)255.0;
229 GLuint i;
230
231 if (!table->TableUB || table->Size == 0)
232 return;
233
234 switch (table->_BaseFormat) {
235 case GL_INTENSITY:
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]];
240 rgba[i][RCOMP] =
241 rgba[i][GCOMP] =
242 rgba[i][BCOMP] =
243 rgba[i][ACOMP] = c;
244 }
245 }
246 else {
247 for (i = 0; i < n; i++) {
248 GLint j = IROUND((GLfloat) rgba[i][RCOMP] * scale);
249 rgba[i][RCOMP] =
250 rgba[i][GCOMP] =
251 rgba[i][BCOMP] =
252 rgba[i][ACOMP] = lut[j];
253 }
254 }
255 break;
256 case GL_LUMINANCE:
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]];
261 rgba[i][RCOMP] =
262 rgba[i][GCOMP] =
263 rgba[i][BCOMP] = c;
264 }
265 }
266 else {
267 for (i = 0; i < n; i++) {
268 GLint j = IROUND((GLfloat) rgba[i][RCOMP] * scale);
269 rgba[i][RCOMP] =
270 rgba[i][GCOMP] =
271 rgba[i][BCOMP] = lut[j];
272 }
273 }
274 break;
275 case GL_ALPHA:
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]];
280 }
281 }
282 else {
283 for (i = 0; i < n; i++) {
284 GLint j = IROUND((GLfloat) rgba[i][ACOMP] * scale);
285 rgba[i][ACOMP] = lut[j];
286 }
287 }
288 break;
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];;
295 rgba[i][RCOMP] =
296 rgba[i][GCOMP] =
297 rgba[i][BCOMP] = l;
298 rgba[i][ACOMP] = a;
299 }
300 }
301 else {
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];
307 rgba[i][RCOMP] =
308 rgba[i][GCOMP] =
309 rgba[i][BCOMP] = luminance;
310 rgba[i][ACOMP] = alpha;
311 }
312 }
313 break;
314 case GL_RGB:
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];
320 }
321 }
322 else {
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];
330 }
331 }
332 break;
333 case GL_RGBA:
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];
340 }
341 }
342 else {
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]);
352 }
353 }
354 break;
355 default:
356 _mesa_problem(NULL, "Bad format in _mesa_lookup_rgba_chan");
357 return;
358 }
359 }
360
361
362
363 /*
364 * Map color indexes to float rgba values.
365 */
366 void
367 _mesa_map_ci_to_rgba( const struct gl_context *ctx, GLuint n,
368 const GLuint index[], GLfloat rgba[][4] )
369 {
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;
378 GLuint i;
379 for (i=0;i<n;i++) {
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];
384 }
385 }
386
387
388 /**
389 * Map ubyte color indexes to ubyte/RGBA values.
390 */
391 void
392 _mesa_map_ci8_to_rgba8(const struct gl_context *ctx,
393 GLuint n, const GLubyte index[],
394 GLubyte rgba[][4])
395 {
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;
404 GLuint i;
405 for (i=0;i<n;i++) {
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];
410 }
411 }
412
413
414 void
415 _mesa_scale_and_bias_depth(const struct gl_context *ctx, GLuint n,
416 GLfloat depthValues[])
417 {
418 const GLfloat scale = ctx->Pixel.DepthScale;
419 const GLfloat bias = ctx->Pixel.DepthBias;
420 GLuint i;
421 for (i = 0; i < n; i++) {
422 GLfloat d = depthValues[i] * scale + bias;
423 depthValues[i] = CLAMP(d, 0.0F, 1.0F);
424 }
425 }
426
427
428 void
429 _mesa_scale_and_bias_depth_uint(const struct gl_context *ctx, GLuint n,
430 GLuint depthValues[])
431 {
432 const GLdouble max = (double) 0xffffffff;
433 const GLdouble scale = ctx->Pixel.DepthScale;
434 const GLdouble bias = ctx->Pixel.DepthBias * max;
435 GLuint i;
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;
440 }
441 }
442
443 /**
444 * Apply various pixel transfer operations to an array of RGBA pixels
445 * as indicated by the transferOps bitmask
446 */
447 void
448 _mesa_apply_rgba_transfer_ops(struct gl_context *ctx, GLbitfield transferOps,
449 GLuint n, GLfloat rgba[][4])
450 {
451 /* scale & bias */
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);
458 }
459 /* color map lookup */
460 if (transferOps & IMAGE_MAP_COLOR_BIT) {
461 _mesa_map_rgba( ctx, n, rgba );
462 }
463
464 /* clamping to [0,1] */
465 if (transferOps & IMAGE_CLAMP_BIT) {
466 GLuint i;
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);
472 }
473 }
474 }
475
476
477 /*
478 * Apply color index shift and offset to an array of pixels.
479 */
480 void
481 _mesa_shift_and_offset_ci(const struct gl_context *ctx,
482 GLuint n, GLuint indexes[])
483 {
484 GLint shift = ctx->Pixel.IndexShift;
485 GLint offset = ctx->Pixel.IndexOffset;
486 GLuint i;
487 if (shift > 0) {
488 for (i=0;i<n;i++) {
489 indexes[i] = (indexes[i] << shift) + offset;
490 }
491 }
492 else if (shift < 0) {
493 shift = -shift;
494 for (i=0;i<n;i++) {
495 indexes[i] = (indexes[i] >> shift) + offset;
496 }
497 }
498 else {
499 for (i=0;i<n;i++) {
500 indexes[i] = indexes[i] + offset;
501 }
502 }
503 }
504
505
506
507 /**
508 * Apply color index shift, offset and table lookup to an array
509 * of color indexes;
510 */
511 void
512 _mesa_apply_ci_transfer_ops(const struct gl_context *ctx,
513 GLbitfield transferOps,
514 GLuint n, GLuint indexes[])
515 {
516 if (transferOps & IMAGE_SHIFT_OFFSET_BIT) {
517 _mesa_shift_and_offset_ci(ctx, n, indexes);
518 }
519 if (transferOps & IMAGE_MAP_COLOR_BIT) {
520 const GLuint mask = ctx->PixelMaps.ItoI.Size - 1;
521 GLuint i;
522 for (i = 0; i < n; i++) {
523 const GLuint j = indexes[i] & mask;
524 indexes[i] = IROUND(ctx->PixelMaps.ItoI.Map[j]);
525 }
526 }
527 }
528
529
530 /**
531 * Apply stencil index shift, offset and table lookup to an array
532 * of stencil values.
533 */
534 void
535 _mesa_apply_stencil_transfer_ops(const struct gl_context *ctx, GLuint n,
536 GLstencil stencil[])
537 {
538 if (ctx->Pixel.IndexShift != 0 || ctx->Pixel.IndexOffset != 0) {
539 const GLint offset = ctx->Pixel.IndexOffset;
540 GLint shift = ctx->Pixel.IndexShift;
541 GLuint i;
542 if (shift > 0) {
543 for (i = 0; i < n; i++) {
544 stencil[i] = (stencil[i] << shift) + offset;
545 }
546 }
547 else if (shift < 0) {
548 shift = -shift;
549 for (i = 0; i < n; i++) {
550 stencil[i] = (stencil[i] >> shift) + offset;
551 }
552 }
553 else {
554 for (i = 0; i < n; i++) {
555 stencil[i] = stencil[i] + offset;
556 }
557 }
558 }
559 if (ctx->Pixel.MapStencilFlag) {
560 GLuint mask = ctx->PixelMaps.StoS.Size - 1;
561 GLuint i;
562 for (i = 0; i < n; i++) {
563 stencil[i] = (GLstencil)ctx->PixelMaps.StoS.Map[ stencil[i] & mask ];
564 }
565 }
566 }