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 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.
24  */
25 
26 
27 /**
28  * \file pixeltransfer.c
29  * Pixel transfer operations (scale, bias, table lookups, etc)
30  */
31 
32 
33 #include "glheader.h"
34 #include "macros.h"
35 #include "pixeltransfer.h"
36 
37 #include "mtypes.h"
38 #include "util/rounding.h"
39 
40 
41 /*
42  * Apply scale and bias factors to an array of RGBA pixels.
43  */
44 void
_mesa_scale_and_bias_rgba(GLuint n,GLfloat rgba[][4],GLfloat rScale,GLfloat gScale,GLfloat bScale,GLfloat aScale,GLfloat rBias,GLfloat gBias,GLfloat bBias,GLfloat aBias)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)
50 {
51    if (rScale != 1.0F || rBias != 0.0F) {
52       GLuint i;
53       for (i = 0; i < n; i++) {
54          rgba[i][RCOMP] = rgba[i][RCOMP] * rScale + rBias;
55       }
56    }
57    if (gScale != 1.0F || gBias != 0.0F) {
58       GLuint i;
59       for (i = 0; i < n; i++) {
60          rgba[i][GCOMP] = rgba[i][GCOMP] * gScale + gBias;
61       }
62    }
63    if (bScale != 1.0F || bBias != 0.0F) {
64       GLuint i;
65       for (i = 0; i < n; i++) {
66          rgba[i][BCOMP] = rgba[i][BCOMP] * bScale + bBias;
67       }
68    }
69    if (aScale != 1.0F || aBias != 0.0F) {
70       GLuint i;
71       for (i = 0; i < n; i++) {
72          rgba[i][ACOMP] = rgba[i][ACOMP] * aScale + aBias;
73       }
74    }
75 }
76 
77 
78 /*
79  * Apply pixel mapping to an array of floating point RGBA pixels.
80  */
81 void
_mesa_map_rgba(const struct gl_context * ctx,GLuint n,GLfloat rgba[][4])82 _mesa_map_rgba( const struct gl_context *ctx, GLuint n, GLfloat rgba[][4] )
83 {
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;
92    GLuint i;
93    for (i=0;i<n;i++) {
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)];
102    }
103 }
104 
105 /*
106  * Map color indexes to float rgba values.
107  */
108 void
_mesa_map_ci_to_rgba(const struct gl_context * ctx,GLuint n,const GLuint index[],GLfloat rgba[][4])109 _mesa_map_ci_to_rgba( const struct gl_context *ctx, GLuint n,
110                       const GLuint index[], GLfloat rgba[][4] )
111 {
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;
120    GLuint i;
121    for (i=0;i<n;i++) {
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];
126    }
127 }
128 
129 
130 void
_mesa_scale_and_bias_depth(const struct gl_context * ctx,GLuint n,GLfloat depthValues[])131 _mesa_scale_and_bias_depth(const struct gl_context *ctx, GLuint n,
132                            GLfloat depthValues[])
133 {
134    const GLfloat scale = ctx->Pixel.DepthScale;
135    const GLfloat bias = ctx->Pixel.DepthBias;
136    GLuint i;
137    for (i = 0; i < n; i++) {
138       GLfloat d = depthValues[i] * scale + bias;
139       depthValues[i] = CLAMP(d, 0.0F, 1.0F);
140    }
141 }
142 
143 
144 void
_mesa_scale_and_bias_depth_uint(const struct gl_context * ctx,GLuint n,GLuint depthValues[])145 _mesa_scale_and_bias_depth_uint(const struct gl_context *ctx, GLuint n,
146                                 GLuint depthValues[])
147 {
148    const GLdouble max = (double) 0xffffffff;
149    const GLdouble scale = ctx->Pixel.DepthScale;
150    const GLdouble bias = ctx->Pixel.DepthBias * max;
151    GLuint i;
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;
156    }
157 }
158 
159 /**
160  * Apply various pixel transfer operations to an array of RGBA pixels
161  * as indicated by the transferOps bitmask
162  */
163 void
_mesa_apply_rgba_transfer_ops(struct gl_context * ctx,GLbitfield transferOps,GLuint n,GLfloat rgba[][4])164 _mesa_apply_rgba_transfer_ops(struct gl_context *ctx, GLbitfield transferOps,
165                               GLuint n, GLfloat rgba[][4])
166 {
167    /* scale & bias */
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);
174    }
175    /* color map lookup */
176    if (transferOps & IMAGE_MAP_COLOR_BIT) {
177       _mesa_map_rgba( ctx, n, rgba );
178    }
179 
180    /* clamping to [0,1] */
181    if (transferOps & IMAGE_CLAMP_BIT) {
182       GLuint i;
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);
188       }
189    }
190 }
191 
192 
193 /*
194  * Apply color index shift and offset to an array of pixels.
195  */
196 void
_mesa_shift_and_offset_ci(const struct gl_context * ctx,GLuint n,GLuint indexes[])197 _mesa_shift_and_offset_ci(const struct gl_context *ctx,
198                           GLuint n, GLuint indexes[])
199 {
200    GLint shift = ctx->Pixel.IndexShift;
201    GLint offset = ctx->Pixel.IndexOffset;
202    GLuint i;
203    if (shift > 0) {
204       for (i=0;i<n;i++) {
205          indexes[i] = (indexes[i] << shift) + offset;
206       }
207    }
208    else if (shift < 0) {
209       shift = -shift;
210       for (i=0;i<n;i++) {
211          indexes[i] = (indexes[i] >> shift) + offset;
212       }
213    }
214    else {
215       for (i=0;i<n;i++) {
216          indexes[i] = indexes[i] + offset;
217       }
218    }
219 }
220 
221 
222 
223 /**
224  * Apply color index shift, offset and table lookup to an array
225  * of color indexes;
226  */
227 void
_mesa_apply_ci_transfer_ops(const struct gl_context * ctx,GLbitfield transferOps,GLuint n,GLuint indexes[])228 _mesa_apply_ci_transfer_ops(const struct gl_context *ctx,
229                             GLbitfield transferOps,
230                             GLuint n, GLuint indexes[])
231 {
232    if (transferOps & IMAGE_SHIFT_OFFSET_BIT) {
233       _mesa_shift_and_offset_ci(ctx, n, indexes);
234    }
235    if (transferOps & IMAGE_MAP_COLOR_BIT) {
236       const GLuint mask = ctx->PixelMaps.ItoI.Size - 1;
237       GLuint i;
238       for (i = 0; i < n; i++) {
239          const GLuint j = indexes[i] & mask;
240          indexes[i] = _mesa_lroundevenf(ctx->PixelMaps.ItoI.Map[j]);
241       }
242    }
243 }
244 
245 
246 /**
247  * Apply stencil index shift, offset and table lookup to an array
248  * of stencil values.
249  */
250 void
_mesa_apply_stencil_transfer_ops(const struct gl_context * ctx,GLuint n,GLubyte stencil[])251 _mesa_apply_stencil_transfer_ops(const struct gl_context *ctx, GLuint n,
252                                  GLubyte stencil[])
253 {
254    if (ctx->Pixel.IndexShift != 0 || ctx->Pixel.IndexOffset != 0) {
255       const GLint offset = ctx->Pixel.IndexOffset;
256       GLint shift = ctx->Pixel.IndexShift;
257       GLuint i;
258       if (shift > 0) {
259          for (i = 0; i < n; i++) {
260             stencil[i] = (stencil[i] << shift) + offset;
261          }
262       }
263       else if (shift < 0) {
264          shift = -shift;
265          for (i = 0; i < n; i++) {
266             stencil[i] = (stencil[i] >> shift) + offset;
267          }
268       }
269       else {
270          for (i = 0; i < n; i++) {
271             stencil[i] = stencil[i] + offset;
272          }
273       }
274    }
275    if (ctx->Pixel.MapStencilFlag) {
276       GLuint mask = ctx->PixelMaps.StoS.Size - 1;
277       GLuint i;
278       for (i = 0; i < n; i++) {
279          stencil[i] = (GLubyte) ctx->PixelMaps.StoS.Map[ stencil[i] & mask ];
280       }
281    }
282 }
283