pixeltransfer.c revision 3464ebd5
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#include "mtypes.h" 37 38 39/* 40 * Apply scale and bias factors to an array of RGBA pixels. 41 */ 42void 43_mesa_scale_and_bias_rgba(GLuint n, GLfloat rgba[][4], 44 GLfloat rScale, GLfloat gScale, 45 GLfloat bScale, GLfloat aScale, 46 GLfloat rBias, GLfloat gBias, 47 GLfloat bBias, GLfloat aBias) 48{ 49 if (rScale != 1.0 || rBias != 0.0) { 50 GLuint i; 51 for (i = 0; i < n; i++) { 52 rgba[i][RCOMP] = rgba[i][RCOMP] * rScale + rBias; 53 } 54 } 55 if (gScale != 1.0 || gBias != 0.0) { 56 GLuint i; 57 for (i = 0; i < n; i++) { 58 rgba[i][GCOMP] = rgba[i][GCOMP] * gScale + gBias; 59 } 60 } 61 if (bScale != 1.0 || bBias != 0.0) { 62 GLuint i; 63 for (i = 0; i < n; i++) { 64 rgba[i][BCOMP] = rgba[i][BCOMP] * bScale + bBias; 65 } 66 } 67 if (aScale != 1.0 || aBias != 0.0) { 68 GLuint i; 69 for (i = 0; i < n; i++) { 70 rgba[i][ACOMP] = rgba[i][ACOMP] * aScale + aBias; 71 } 72 } 73} 74 75 76/* 77 * Apply pixel mapping to an array of floating point RGBA pixels. 78 */ 79void 80_mesa_map_rgba( const struct gl_context *ctx, GLuint n, GLfloat rgba[][4] ) 81{ 82 const GLfloat rscale = (GLfloat) (ctx->PixelMaps.RtoR.Size - 1); 83 const GLfloat gscale = (GLfloat) (ctx->PixelMaps.GtoG.Size - 1); 84 const GLfloat bscale = (GLfloat) (ctx->PixelMaps.BtoB.Size - 1); 85 const GLfloat ascale = (GLfloat) (ctx->PixelMaps.AtoA.Size - 1); 86 const GLfloat *rMap = ctx->PixelMaps.RtoR.Map; 87 const GLfloat *gMap = ctx->PixelMaps.GtoG.Map; 88 const GLfloat *bMap = ctx->PixelMaps.BtoB.Map; 89 const GLfloat *aMap = ctx->PixelMaps.AtoA.Map; 90 GLuint i; 91 for (i=0;i<n;i++) { 92 GLfloat r = CLAMP(rgba[i][RCOMP], 0.0F, 1.0F); 93 GLfloat g = CLAMP(rgba[i][GCOMP], 0.0F, 1.0F); 94 GLfloat b = CLAMP(rgba[i][BCOMP], 0.0F, 1.0F); 95 GLfloat a = CLAMP(rgba[i][ACOMP], 0.0F, 1.0F); 96 rgba[i][RCOMP] = rMap[IROUND(r * rscale)]; 97 rgba[i][GCOMP] = gMap[IROUND(g * gscale)]; 98 rgba[i][BCOMP] = bMap[IROUND(b * bscale)]; 99 rgba[i][ACOMP] = aMap[IROUND(a * ascale)]; 100 } 101} 102 103/** 104 * Apply a color table lookup to an array of floating point RGBA colors. 105 */ 106void 107_mesa_lookup_rgba_float(const struct gl_color_table *table, 108 GLuint n, GLfloat rgba[][4]) 109{ 110 const GLint max = table->Size - 1; 111 const GLfloat scale = (GLfloat) max; 112 const GLfloat *lut = table->TableF; 113 GLuint i; 114 115 if (!table->TableF || table->Size == 0) 116 return; 117 118 switch (table->_BaseFormat) { 119 case GL_INTENSITY: 120 /* replace RGBA with I */ 121 for (i = 0; i < n; i++) { 122 GLint j = IROUND(rgba[i][RCOMP] * scale); 123 GLfloat c = lut[CLAMP(j, 0, max)]; 124 rgba[i][RCOMP] = 125 rgba[i][GCOMP] = 126 rgba[i][BCOMP] = 127 rgba[i][ACOMP] = c; 128 } 129 break; 130 case GL_LUMINANCE: 131 /* replace RGB with L */ 132 for (i = 0; i < n; i++) { 133 GLint j = IROUND(rgba[i][RCOMP] * scale); 134 GLfloat c = lut[CLAMP(j, 0, max)]; 135 rgba[i][RCOMP] = 136 rgba[i][GCOMP] = 137 rgba[i][BCOMP] = c; 138 } 139 break; 140 case GL_ALPHA: 141 /* replace A with A */ 142 for (i = 0; i < n; i++) { 143 GLint j = IROUND(rgba[i][ACOMP] * scale); 144 rgba[i][ACOMP] = lut[CLAMP(j, 0, max)]; 145 } 146 break; 147 case GL_LUMINANCE_ALPHA: 148 /* replace RGBA with LLLA */ 149 for (i = 0; i < n; i++) { 150 GLint jL = IROUND(rgba[i][RCOMP] * scale); 151 GLint jA = IROUND(rgba[i][ACOMP] * scale); 152 GLfloat luminance, alpha; 153 jL = CLAMP(jL, 0, max); 154 jA = CLAMP(jA, 0, max); 155 luminance = lut[jL * 2 + 0]; 156 alpha = lut[jA * 2 + 1]; 157 rgba[i][RCOMP] = 158 rgba[i][GCOMP] = 159 rgba[i][BCOMP] = luminance; 160 rgba[i][ACOMP] = alpha;; 161 } 162 break; 163 case GL_RED: 164 /* replace RGB with RGB */ 165 for (i = 0; i < n; i++) { 166 GLint jR = IROUND(rgba[i][RCOMP] * scale); 167 jR = CLAMP(jR, 0, max); 168 rgba[i][RCOMP] = lut[jR * 3 + 0]; 169 } 170 break; 171 case GL_RG: 172 /* replace RG with RG */ 173 for (i = 0; i < n; i++) { 174 GLint jR = IROUND(rgba[i][RCOMP] * scale); 175 GLint jG = IROUND(rgba[i][GCOMP] * scale); 176 jR = CLAMP(jR, 0, max); 177 jG = CLAMP(jG, 0, max); 178 rgba[i][RCOMP] = lut[jR * 3 + 0]; 179 rgba[i][GCOMP] = lut[jG * 3 + 1]; 180 } 181 break; 182 case GL_RGB: 183 /* replace RGB with RGB */ 184 for (i = 0; i < n; i++) { 185 GLint jR = IROUND(rgba[i][RCOMP] * scale); 186 GLint jG = IROUND(rgba[i][GCOMP] * scale); 187 GLint jB = IROUND(rgba[i][BCOMP] * scale); 188 jR = CLAMP(jR, 0, max); 189 jG = CLAMP(jG, 0, max); 190 jB = CLAMP(jB, 0, max); 191 rgba[i][RCOMP] = lut[jR * 3 + 0]; 192 rgba[i][GCOMP] = lut[jG * 3 + 1]; 193 rgba[i][BCOMP] = lut[jB * 3 + 2]; 194 } 195 break; 196 case GL_RGBA: 197 /* replace RGBA with RGBA */ 198 for (i = 0; i < n; i++) { 199 GLint jR = IROUND(rgba[i][RCOMP] * scale); 200 GLint jG = IROUND(rgba[i][GCOMP] * scale); 201 GLint jB = IROUND(rgba[i][BCOMP] * scale); 202 GLint jA = IROUND(rgba[i][ACOMP] * scale); 203 jR = CLAMP(jR, 0, max); 204 jG = CLAMP(jG, 0, max); 205 jB = CLAMP(jB, 0, max); 206 jA = CLAMP(jA, 0, max); 207 rgba[i][RCOMP] = lut[jR * 4 + 0]; 208 rgba[i][GCOMP] = lut[jG * 4 + 1]; 209 rgba[i][BCOMP] = lut[jB * 4 + 2]; 210 rgba[i][ACOMP] = lut[jA * 4 + 3]; 211 } 212 break; 213 default: 214 _mesa_problem(NULL, "Bad format in _mesa_lookup_rgba_float"); 215 return; 216 } 217} 218 219 220 221/** 222 * Apply a color table lookup to an array of ubyte/RGBA colors. 223 */ 224void 225_mesa_lookup_rgba_ubyte(const struct gl_color_table *table, 226 GLuint n, GLubyte rgba[][4]) 227{ 228 const GLubyte *lut = table->TableUB; 229 const GLfloat scale = (GLfloat) (table->Size - 1) / (GLfloat)255.0; 230 GLuint i; 231 232 if (!table->TableUB || table->Size == 0) 233 return; 234 235 switch (table->_BaseFormat) { 236 case GL_INTENSITY: 237 /* replace RGBA with I */ 238 if (table->Size == 256) { 239 for (i = 0; i < n; i++) { 240 const GLubyte c = lut[rgba[i][RCOMP]]; 241 rgba[i][RCOMP] = 242 rgba[i][GCOMP] = 243 rgba[i][BCOMP] = 244 rgba[i][ACOMP] = c; 245 } 246 } 247 else { 248 for (i = 0; i < n; i++) { 249 GLint j = IROUND((GLfloat) rgba[i][RCOMP] * scale); 250 rgba[i][RCOMP] = 251 rgba[i][GCOMP] = 252 rgba[i][BCOMP] = 253 rgba[i][ACOMP] = lut[j]; 254 } 255 } 256 break; 257 case GL_LUMINANCE: 258 /* replace RGB with L */ 259 if (table->Size == 256) { 260 for (i = 0; i < n; i++) { 261 const GLubyte c = lut[rgba[i][RCOMP]]; 262 rgba[i][RCOMP] = 263 rgba[i][GCOMP] = 264 rgba[i][BCOMP] = c; 265 } 266 } 267 else { 268 for (i = 0; i < n; i++) { 269 GLint j = IROUND((GLfloat) rgba[i][RCOMP] * scale); 270 rgba[i][RCOMP] = 271 rgba[i][GCOMP] = 272 rgba[i][BCOMP] = lut[j]; 273 } 274 } 275 break; 276 case GL_ALPHA: 277 /* replace A with A */ 278 if (table->Size == 256) { 279 for (i = 0; i < n; i++) { 280 rgba[i][ACOMP] = lut[rgba[i][ACOMP]]; 281 } 282 } 283 else { 284 for (i = 0; i < n; i++) { 285 GLint j = IROUND((GLfloat) rgba[i][ACOMP] * scale); 286 rgba[i][ACOMP] = lut[j]; 287 } 288 } 289 break; 290 case GL_LUMINANCE_ALPHA: 291 /* replace RGBA with LLLA */ 292 if (table->Size == 256) { 293 for (i = 0; i < n; i++) { 294 GLubyte l = lut[rgba[i][RCOMP] * 2 + 0]; 295 GLubyte a = lut[rgba[i][ACOMP] * 2 + 1];; 296 rgba[i][RCOMP] = 297 rgba[i][GCOMP] = 298 rgba[i][BCOMP] = l; 299 rgba[i][ACOMP] = a; 300 } 301 } 302 else { 303 for (i = 0; i < n; i++) { 304 GLint jL = IROUND((GLfloat) rgba[i][RCOMP] * scale); 305 GLint jA = IROUND((GLfloat) rgba[i][ACOMP] * scale); 306 GLubyte luminance = lut[jL * 2 + 0]; 307 GLubyte alpha = lut[jA * 2 + 1]; 308 rgba[i][RCOMP] = 309 rgba[i][GCOMP] = 310 rgba[i][BCOMP] = luminance; 311 rgba[i][ACOMP] = alpha; 312 } 313 } 314 break; 315 case GL_RGB: 316 if (table->Size == 256) { 317 for (i = 0; i < n; i++) { 318 rgba[i][RCOMP] = lut[rgba[i][RCOMP] * 3 + 0]; 319 rgba[i][GCOMP] = lut[rgba[i][GCOMP] * 3 + 1]; 320 rgba[i][BCOMP] = lut[rgba[i][BCOMP] * 3 + 2]; 321 } 322 } 323 else { 324 for (i = 0; i < n; i++) { 325 GLint jR = IROUND((GLfloat) rgba[i][RCOMP] * scale); 326 GLint jG = IROUND((GLfloat) rgba[i][GCOMP] * scale); 327 GLint jB = IROUND((GLfloat) rgba[i][BCOMP] * scale); 328 rgba[i][RCOMP] = lut[jR * 3 + 0]; 329 rgba[i][GCOMP] = lut[jG * 3 + 1]; 330 rgba[i][BCOMP] = lut[jB * 3 + 2]; 331 } 332 } 333 break; 334 case GL_RGBA: 335 if (table->Size == 256) { 336 for (i = 0; i < n; i++) { 337 rgba[i][RCOMP] = lut[rgba[i][RCOMP] * 4 + 0]; 338 rgba[i][GCOMP] = lut[rgba[i][GCOMP] * 4 + 1]; 339 rgba[i][BCOMP] = lut[rgba[i][BCOMP] * 4 + 2]; 340 rgba[i][ACOMP] = lut[rgba[i][ACOMP] * 4 + 3]; 341 } 342 } 343 else { 344 for (i = 0; i < n; i++) { 345 GLint jR = IROUND((GLfloat) rgba[i][RCOMP] * scale); 346 GLint jG = IROUND((GLfloat) rgba[i][GCOMP] * scale); 347 GLint jB = IROUND((GLfloat) rgba[i][BCOMP] * scale); 348 GLint jA = IROUND((GLfloat) rgba[i][ACOMP] * scale); 349 CLAMPED_FLOAT_TO_CHAN(rgba[i][RCOMP], lut[jR * 4 + 0]); 350 CLAMPED_FLOAT_TO_CHAN(rgba[i][GCOMP], lut[jG * 4 + 1]); 351 CLAMPED_FLOAT_TO_CHAN(rgba[i][BCOMP], lut[jB * 4 + 2]); 352 CLAMPED_FLOAT_TO_CHAN(rgba[i][ACOMP], lut[jA * 4 + 3]); 353 } 354 } 355 break; 356 default: 357 _mesa_problem(NULL, "Bad format in _mesa_lookup_rgba_chan"); 358 return; 359 } 360} 361 362 363 364/* 365 * Map color indexes to float rgba values. 366 */ 367void 368_mesa_map_ci_to_rgba( const struct gl_context *ctx, GLuint n, 369 const GLuint index[], GLfloat rgba[][4] ) 370{ 371 GLuint rmask = ctx->PixelMaps.ItoR.Size - 1; 372 GLuint gmask = ctx->PixelMaps.ItoG.Size - 1; 373 GLuint bmask = ctx->PixelMaps.ItoB.Size - 1; 374 GLuint amask = ctx->PixelMaps.ItoA.Size - 1; 375 const GLfloat *rMap = ctx->PixelMaps.ItoR.Map; 376 const GLfloat *gMap = ctx->PixelMaps.ItoG.Map; 377 const GLfloat *bMap = ctx->PixelMaps.ItoB.Map; 378 const GLfloat *aMap = ctx->PixelMaps.ItoA.Map; 379 GLuint i; 380 for (i=0;i<n;i++) { 381 rgba[i][RCOMP] = rMap[index[i] & rmask]; 382 rgba[i][GCOMP] = gMap[index[i] & gmask]; 383 rgba[i][BCOMP] = bMap[index[i] & bmask]; 384 rgba[i][ACOMP] = aMap[index[i] & amask]; 385 } 386} 387 388 389/** 390 * Map ubyte color indexes to ubyte/RGBA values. 391 */ 392void 393_mesa_map_ci8_to_rgba8(const struct gl_context *ctx, 394 GLuint n, const GLubyte index[], 395 GLubyte rgba[][4]) 396{ 397 GLuint rmask = ctx->PixelMaps.ItoR.Size - 1; 398 GLuint gmask = ctx->PixelMaps.ItoG.Size - 1; 399 GLuint bmask = ctx->PixelMaps.ItoB.Size - 1; 400 GLuint amask = ctx->PixelMaps.ItoA.Size - 1; 401 const GLubyte *rMap = ctx->PixelMaps.ItoR.Map8; 402 const GLubyte *gMap = ctx->PixelMaps.ItoG.Map8; 403 const GLubyte *bMap = ctx->PixelMaps.ItoB.Map8; 404 const GLubyte *aMap = ctx->PixelMaps.ItoA.Map8; 405 GLuint i; 406 for (i=0;i<n;i++) { 407 rgba[i][RCOMP] = rMap[index[i] & rmask]; 408 rgba[i][GCOMP] = gMap[index[i] & gmask]; 409 rgba[i][BCOMP] = bMap[index[i] & bmask]; 410 rgba[i][ACOMP] = aMap[index[i] & amask]; 411 } 412} 413 414 415void 416_mesa_scale_and_bias_depth(const struct gl_context *ctx, GLuint n, 417 GLfloat depthValues[]) 418{ 419 const GLfloat scale = ctx->Pixel.DepthScale; 420 const GLfloat bias = ctx->Pixel.DepthBias; 421 GLuint i; 422 for (i = 0; i < n; i++) { 423 GLfloat d = depthValues[i] * scale + bias; 424 depthValues[i] = CLAMP(d, 0.0F, 1.0F); 425 } 426} 427 428 429void 430_mesa_scale_and_bias_depth_uint(const struct gl_context *ctx, GLuint n, 431 GLuint depthValues[]) 432{ 433 const GLdouble max = (double) 0xffffffff; 434 const GLdouble scale = ctx->Pixel.DepthScale; 435 const GLdouble bias = ctx->Pixel.DepthBias * max; 436 GLuint i; 437 for (i = 0; i < n; i++) { 438 GLdouble d = (GLdouble) depthValues[i] * scale + bias; 439 d = CLAMP(d, 0.0, max); 440 depthValues[i] = (GLuint) d; 441 } 442} 443 444/** 445 * Apply various pixel transfer operations to an array of RGBA pixels 446 * as indicated by the transferOps bitmask 447 */ 448void 449_mesa_apply_rgba_transfer_ops(struct gl_context *ctx, GLbitfield transferOps, 450 GLuint n, GLfloat rgba[][4]) 451{ 452 /* scale & bias */ 453 if (transferOps & IMAGE_SCALE_BIAS_BIT) { 454 _mesa_scale_and_bias_rgba(n, rgba, 455 ctx->Pixel.RedScale, ctx->Pixel.GreenScale, 456 ctx->Pixel.BlueScale, ctx->Pixel.AlphaScale, 457 ctx->Pixel.RedBias, ctx->Pixel.GreenBias, 458 ctx->Pixel.BlueBias, ctx->Pixel.AlphaBias); 459 } 460 /* color map lookup */ 461 if (transferOps & IMAGE_MAP_COLOR_BIT) { 462 _mesa_map_rgba( ctx, n, rgba ); 463 } 464 465 /* clamping to [0,1] */ 466 if (transferOps & IMAGE_CLAMP_BIT) { 467 GLuint i; 468 for (i = 0; i < n; i++) { 469 rgba[i][RCOMP] = CLAMP(rgba[i][RCOMP], 0.0F, 1.0F); 470 rgba[i][GCOMP] = CLAMP(rgba[i][GCOMP], 0.0F, 1.0F); 471 rgba[i][BCOMP] = CLAMP(rgba[i][BCOMP], 0.0F, 1.0F); 472 rgba[i][ACOMP] = CLAMP(rgba[i][ACOMP], 0.0F, 1.0F); 473 } 474 } 475} 476 477 478/* 479 * Apply color index shift and offset to an array of pixels. 480 */ 481void 482_mesa_shift_and_offset_ci(const struct gl_context *ctx, 483 GLuint n, GLuint indexes[]) 484{ 485 GLint shift = ctx->Pixel.IndexShift; 486 GLint offset = ctx->Pixel.IndexOffset; 487 GLuint i; 488 if (shift > 0) { 489 for (i=0;i<n;i++) { 490 indexes[i] = (indexes[i] << shift) + offset; 491 } 492 } 493 else if (shift < 0) { 494 shift = -shift; 495 for (i=0;i<n;i++) { 496 indexes[i] = (indexes[i] >> shift) + offset; 497 } 498 } 499 else { 500 for (i=0;i<n;i++) { 501 indexes[i] = indexes[i] + offset; 502 } 503 } 504} 505 506 507 508/** 509 * Apply color index shift, offset and table lookup to an array 510 * of color indexes; 511 */ 512void 513_mesa_apply_ci_transfer_ops(const struct gl_context *ctx, 514 GLbitfield transferOps, 515 GLuint n, GLuint indexes[]) 516{ 517 if (transferOps & IMAGE_SHIFT_OFFSET_BIT) { 518 _mesa_shift_and_offset_ci(ctx, n, indexes); 519 } 520 if (transferOps & IMAGE_MAP_COLOR_BIT) { 521 const GLuint mask = ctx->PixelMaps.ItoI.Size - 1; 522 GLuint i; 523 for (i = 0; i < n; i++) { 524 const GLuint j = indexes[i] & mask; 525 indexes[i] = IROUND(ctx->PixelMaps.ItoI.Map[j]); 526 } 527 } 528} 529 530 531/** 532 * Apply stencil index shift, offset and table lookup to an array 533 * of stencil values. 534 */ 535void 536_mesa_apply_stencil_transfer_ops(const struct gl_context *ctx, GLuint n, 537 GLstencil stencil[]) 538{ 539 if (ctx->Pixel.IndexShift != 0 || ctx->Pixel.IndexOffset != 0) { 540 const GLint offset = ctx->Pixel.IndexOffset; 541 GLint shift = ctx->Pixel.IndexShift; 542 GLuint i; 543 if (shift > 0) { 544 for (i = 0; i < n; i++) { 545 stencil[i] = (stencil[i] << shift) + offset; 546 } 547 } 548 else if (shift < 0) { 549 shift = -shift; 550 for (i = 0; i < n; i++) { 551 stencil[i] = (stencil[i] >> shift) + offset; 552 } 553 } 554 else { 555 for (i = 0; i < n; i++) { 556 stencil[i] = stencil[i] + offset; 557 } 558 } 559 } 560 if (ctx->Pixel.MapStencilFlag) { 561 GLuint mask = ctx->PixelMaps.StoS.Size - 1; 562 GLuint i; 563 for (i = 0; i < n; i++) { 564 stencil[i] = (GLstencil)ctx->PixelMaps.StoS.Map[ stencil[i] & mask ]; 565 } 566 } 567} 568