Fixed typo
[reactos.git] / dll / opengl / mesa / main / pixel.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 7.1
4 *
5 * Copyright (C) 1999-2008 Brian Paul 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 * BRIAN PAUL 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 * \file pixel.c
27 * Pixel transfer functions (glPixelZoom, glPixelMap, glPixelTransfer)
28 */
29
30 #include <precomp.h>
31
32 #if FEATURE_pixel_transfer
33
34
35 /**********************************************************************/
36 /***** glPixelZoom *****/
37 /**********************************************************************/
38
39 static void GLAPIENTRY
40 _mesa_PixelZoom( GLfloat xfactor, GLfloat yfactor )
41 {
42 GET_CURRENT_CONTEXT(ctx);
43
44 ASSERT_OUTSIDE_BEGIN_END(ctx);
45
46 if (ctx->Pixel.ZoomX == xfactor &&
47 ctx->Pixel.ZoomY == yfactor)
48 return;
49
50 FLUSH_VERTICES(ctx, _NEW_PIXEL);
51 ctx->Pixel.ZoomX = xfactor;
52 ctx->Pixel.ZoomY = yfactor;
53 }
54
55
56
57 /**********************************************************************/
58 /***** glPixelMap *****/
59 /**********************************************************************/
60
61 /**
62 * Return pointer to a pixelmap by name.
63 */
64 static struct gl_pixelmap *
65 get_pixelmap(struct gl_context *ctx, GLenum map)
66 {
67 switch (map) {
68 case GL_PIXEL_MAP_I_TO_I:
69 return &ctx->PixelMaps.ItoI;
70 case GL_PIXEL_MAP_S_TO_S:
71 return &ctx->PixelMaps.StoS;
72 case GL_PIXEL_MAP_I_TO_R:
73 return &ctx->PixelMaps.ItoR;
74 case GL_PIXEL_MAP_I_TO_G:
75 return &ctx->PixelMaps.ItoG;
76 case GL_PIXEL_MAP_I_TO_B:
77 return &ctx->PixelMaps.ItoB;
78 case GL_PIXEL_MAP_I_TO_A:
79 return &ctx->PixelMaps.ItoA;
80 case GL_PIXEL_MAP_R_TO_R:
81 return &ctx->PixelMaps.RtoR;
82 case GL_PIXEL_MAP_G_TO_G:
83 return &ctx->PixelMaps.GtoG;
84 case GL_PIXEL_MAP_B_TO_B:
85 return &ctx->PixelMaps.BtoB;
86 case GL_PIXEL_MAP_A_TO_A:
87 return &ctx->PixelMaps.AtoA;
88 default:
89 return NULL;
90 }
91 }
92
93
94 /**
95 * Helper routine used by the other _mesa_PixelMap() functions.
96 */
97 static void
98 store_pixelmap(struct gl_context *ctx, GLenum map, GLsizei mapsize,
99 const GLfloat *values)
100 {
101 GLint i;
102 struct gl_pixelmap *pm = get_pixelmap(ctx, map);
103 if (!pm) {
104 _mesa_error(ctx, GL_INVALID_ENUM, "glPixelMap(map)");
105 return;
106 }
107
108 switch (map) {
109 case GL_PIXEL_MAP_S_TO_S:
110 /* special case */
111 ctx->PixelMaps.StoS.Size = mapsize;
112 for (i = 0; i < mapsize; i++) {
113 ctx->PixelMaps.StoS.Map[i] = (GLfloat)IROUND(values[i]);
114 }
115 break;
116 case GL_PIXEL_MAP_I_TO_I:
117 /* special case */
118 ctx->PixelMaps.ItoI.Size = mapsize;
119 for (i = 0; i < mapsize; i++) {
120 ctx->PixelMaps.ItoI.Map[i] = values[i];
121 }
122 break;
123 default:
124 /* general case */
125 pm->Size = mapsize;
126 for (i = 0; i < mapsize; i++) {
127 GLfloat val = CLAMP(values[i], 0.0F, 1.0F);
128 pm->Map[i] = val;
129 pm->Map8[i] = (GLint) (val * 255.0F);
130 }
131 }
132 }
133
134
135 static void GLAPIENTRY
136 _mesa_PixelMapfv( GLenum map, GLsizei mapsize, const GLfloat *values )
137 {
138 GET_CURRENT_CONTEXT(ctx);
139 ASSERT_OUTSIDE_BEGIN_END(ctx);
140
141 /* XXX someday, test against ctx->Const.MaxPixelMapTableSize */
142 if (mapsize < 1 || mapsize > MAX_PIXEL_MAP_TABLE) {
143 _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapfv(mapsize)" );
144 return;
145 }
146
147 if (map >= GL_PIXEL_MAP_S_TO_S && map <= GL_PIXEL_MAP_I_TO_A) {
148 /* test that mapsize is a power of two */
149 if (!_mesa_is_pow_two(mapsize)) {
150 _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapfv(mapsize)" );
151 return;
152 }
153 }
154
155 FLUSH_VERTICES(ctx, _NEW_PIXEL);
156
157 if (!values) {
158 return;
159 }
160
161 store_pixelmap(ctx, map, mapsize, values);
162 }
163
164
165 static void GLAPIENTRY
166 _mesa_PixelMapuiv(GLenum map, GLsizei mapsize, const GLuint *values )
167 {
168 GLfloat fvalues[MAX_PIXEL_MAP_TABLE];
169 GET_CURRENT_CONTEXT(ctx);
170 ASSERT_OUTSIDE_BEGIN_END(ctx);
171
172 if (mapsize < 1 || mapsize > MAX_PIXEL_MAP_TABLE) {
173 _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapuiv(mapsize)" );
174 return;
175 }
176
177 if (map >= GL_PIXEL_MAP_S_TO_S && map <= GL_PIXEL_MAP_I_TO_A) {
178 /* test that mapsize is a power of two */
179 if (!_mesa_is_pow_two(mapsize)) {
180 _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapuiv(mapsize)" );
181 return;
182 }
183 }
184
185 FLUSH_VERTICES(ctx, _NEW_PIXEL);
186
187 if (!values) {
188 return;
189 }
190
191 /* convert to floats */
192 if (map == GL_PIXEL_MAP_I_TO_I || map == GL_PIXEL_MAP_S_TO_S) {
193 GLint i;
194 for (i = 0; i < mapsize; i++) {
195 fvalues[i] = (GLfloat) values[i];
196 }
197 }
198 else {
199 GLint i;
200 for (i = 0; i < mapsize; i++) {
201 fvalues[i] = UINT_TO_FLOAT( values[i] );
202 }
203 }
204
205 store_pixelmap(ctx, map, mapsize, fvalues);
206 }
207
208
209 static void GLAPIENTRY
210 _mesa_PixelMapusv(GLenum map, GLsizei mapsize, const GLushort *values )
211 {
212 GLfloat fvalues[MAX_PIXEL_MAP_TABLE];
213 GET_CURRENT_CONTEXT(ctx);
214 ASSERT_OUTSIDE_BEGIN_END(ctx);
215
216 if (mapsize < 1 || mapsize > MAX_PIXEL_MAP_TABLE) {
217 _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapusv(mapsize)" );
218 return;
219 }
220
221 if (map >= GL_PIXEL_MAP_S_TO_S && map <= GL_PIXEL_MAP_I_TO_A) {
222 /* test that mapsize is a power of two */
223 if (!_mesa_is_pow_two(mapsize)) {
224 _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapuiv(mapsize)" );
225 return;
226 }
227 }
228
229 FLUSH_VERTICES(ctx, _NEW_PIXEL);
230
231 if (!values) {
232 return;
233 }
234
235 /* convert to floats */
236 if (map == GL_PIXEL_MAP_I_TO_I || map == GL_PIXEL_MAP_S_TO_S) {
237 GLint i;
238 for (i = 0; i < mapsize; i++) {
239 fvalues[i] = (GLfloat) values[i];
240 }
241 }
242 else {
243 GLint i;
244 for (i = 0; i < mapsize; i++) {
245 fvalues[i] = USHORT_TO_FLOAT( values[i] );
246 }
247 }
248
249 store_pixelmap(ctx, map, mapsize, fvalues);
250 }
251
252
253 static void GLAPIENTRY
254 _mesa_GetPixelMapfv( GLenum map, GLfloat *values )
255 {
256 GET_CURRENT_CONTEXT(ctx);
257 GLint mapsize, i;
258 const struct gl_pixelmap *pm;
259
260 ASSERT_OUTSIDE_BEGIN_END(ctx);
261
262 pm = get_pixelmap(ctx, map);
263 if (!pm) {
264 _mesa_error(ctx, GL_INVALID_ENUM, "glGetPixelMapfv(map)");
265 return;
266 }
267
268 mapsize = pm->Size;
269
270 if (!values) {
271 return;
272 }
273
274 if (map == GL_PIXEL_MAP_S_TO_S) {
275 /* special case */
276 for (i = 0; i < mapsize; i++) {
277 values[i] = (GLfloat) ctx->PixelMaps.StoS.Map[i];
278 }
279 }
280 else {
281 memcpy(values, pm->Map, mapsize * sizeof(GLfloat));
282 }
283 }
284
285
286 static void GLAPIENTRY
287 _mesa_GetPixelMapuiv( GLenum map, GLuint *values )
288 {
289 GET_CURRENT_CONTEXT(ctx);
290 GLint mapsize, i;
291 const struct gl_pixelmap *pm;
292
293 ASSERT_OUTSIDE_BEGIN_END(ctx);
294
295 pm = get_pixelmap(ctx, map);
296 if (!pm) {
297 _mesa_error(ctx, GL_INVALID_ENUM, "glGetPixelMapuiv(map)");
298 return;
299 }
300
301 mapsize = pm->Size;
302
303 if (!values) {
304 return;
305 }
306
307 if (map == GL_PIXEL_MAP_S_TO_S) {
308 /* special case */
309 memcpy(values, ctx->PixelMaps.StoS.Map, mapsize * sizeof(GLint));
310 }
311 else {
312 for (i = 0; i < mapsize; i++) {
313 values[i] = FLOAT_TO_UINT( pm->Map[i] );
314 }
315 }
316 }
317
318
319 static void GLAPIENTRY
320 _mesa_GetPixelMapusv( GLenum map, GLushort *values )
321 {
322 GET_CURRENT_CONTEXT(ctx);
323 GLint mapsize, i;
324 const struct gl_pixelmap *pm;
325
326 ASSERT_OUTSIDE_BEGIN_END(ctx);
327
328 pm = get_pixelmap(ctx, map);
329 if (!pm) {
330 _mesa_error(ctx, GL_INVALID_ENUM, "glGetPixelMapusv(map)");
331 return;
332 }
333
334 mapsize = pm->Size;
335
336 if (!values) {
337 return;
338 }
339
340 switch (map) {
341 /* special cases */
342 case GL_PIXEL_MAP_I_TO_I:
343 for (i = 0; i < mapsize; i++) {
344 values[i] = (GLushort) CLAMP(ctx->PixelMaps.ItoI.Map[i], 0.0, 65535.);
345 }
346 break;
347 case GL_PIXEL_MAP_S_TO_S:
348 for (i = 0; i < mapsize; i++) {
349 values[i] = (GLushort) CLAMP(ctx->PixelMaps.StoS.Map[i], 0.0, 65535.);
350 }
351 break;
352 default:
353 for (i = 0; i < mapsize; i++) {
354 CLAMPED_FLOAT_TO_USHORT(values[i], pm->Map[i] );
355 }
356 }
357 }
358
359
360 /**********************************************************************/
361 /***** glPixelTransfer *****/
362 /**********************************************************************/
363
364
365 /*
366 * Implements glPixelTransfer[fi] whether called immediately or from a
367 * display list.
368 */
369 void GLAPIENTRY
370 _mesa_PixelTransferf( GLenum pname, GLfloat param )
371 {
372 GET_CURRENT_CONTEXT(ctx);
373 ASSERT_OUTSIDE_BEGIN_END(ctx);
374
375 switch (pname) {
376 case GL_MAP_COLOR:
377 if (ctx->Pixel.MapColorFlag == (param ? GL_TRUE : GL_FALSE))
378 return;
379 FLUSH_VERTICES(ctx, _NEW_PIXEL);
380 ctx->Pixel.MapColorFlag = param ? GL_TRUE : GL_FALSE;
381 break;
382 case GL_MAP_STENCIL:
383 if (ctx->Pixel.MapStencilFlag == (param ? GL_TRUE : GL_FALSE))
384 return;
385 FLUSH_VERTICES(ctx, _NEW_PIXEL);
386 ctx->Pixel.MapStencilFlag = param ? GL_TRUE : GL_FALSE;
387 break;
388 case GL_INDEX_SHIFT:
389 if (ctx->Pixel.IndexShift == (GLint) param)
390 return;
391 FLUSH_VERTICES(ctx, _NEW_PIXEL);
392 ctx->Pixel.IndexShift = (GLint) param;
393 break;
394 case GL_INDEX_OFFSET:
395 if (ctx->Pixel.IndexOffset == (GLint) param)
396 return;
397 FLUSH_VERTICES(ctx, _NEW_PIXEL);
398 ctx->Pixel.IndexOffset = (GLint) param;
399 break;
400 case GL_RED_SCALE:
401 if (ctx->Pixel.RedScale == param)
402 return;
403 FLUSH_VERTICES(ctx, _NEW_PIXEL);
404 ctx->Pixel.RedScale = param;
405 break;
406 case GL_RED_BIAS:
407 if (ctx->Pixel.RedBias == param)
408 return;
409 FLUSH_VERTICES(ctx, _NEW_PIXEL);
410 ctx->Pixel.RedBias = param;
411 break;
412 case GL_GREEN_SCALE:
413 if (ctx->Pixel.GreenScale == param)
414 return;
415 FLUSH_VERTICES(ctx, _NEW_PIXEL);
416 ctx->Pixel.GreenScale = param;
417 break;
418 case GL_GREEN_BIAS:
419 if (ctx->Pixel.GreenBias == param)
420 return;
421 FLUSH_VERTICES(ctx, _NEW_PIXEL);
422 ctx->Pixel.GreenBias = param;
423 break;
424 case GL_BLUE_SCALE:
425 if (ctx->Pixel.BlueScale == param)
426 return;
427 FLUSH_VERTICES(ctx, _NEW_PIXEL);
428 ctx->Pixel.BlueScale = param;
429 break;
430 case GL_BLUE_BIAS:
431 if (ctx->Pixel.BlueBias == param)
432 return;
433 FLUSH_VERTICES(ctx, _NEW_PIXEL);
434 ctx->Pixel.BlueBias = param;
435 break;
436 case GL_ALPHA_SCALE:
437 if (ctx->Pixel.AlphaScale == param)
438 return;
439 FLUSH_VERTICES(ctx, _NEW_PIXEL);
440 ctx->Pixel.AlphaScale = param;
441 break;
442 case GL_ALPHA_BIAS:
443 if (ctx->Pixel.AlphaBias == param)
444 return;
445 FLUSH_VERTICES(ctx, _NEW_PIXEL);
446 ctx->Pixel.AlphaBias = param;
447 break;
448 case GL_DEPTH_SCALE:
449 if (ctx->Pixel.DepthScale == param)
450 return;
451 FLUSH_VERTICES(ctx, _NEW_PIXEL);
452 ctx->Pixel.DepthScale = param;
453 break;
454 case GL_DEPTH_BIAS:
455 if (ctx->Pixel.DepthBias == param)
456 return;
457 FLUSH_VERTICES(ctx, _NEW_PIXEL);
458 ctx->Pixel.DepthBias = param;
459 break;
460 default:
461 _mesa_error( ctx, GL_INVALID_ENUM, "glPixelTransfer(pname)" );
462 return;
463 }
464 }
465
466
467 static void GLAPIENTRY
468 _mesa_PixelTransferi( GLenum pname, GLint param )
469 {
470 _mesa_PixelTransferf( pname, (GLfloat) param );
471 }
472
473
474
475 /**********************************************************************/
476 /***** State Management *****/
477 /**********************************************************************/
478
479 /*
480 * Return a bitmask of IMAGE_*_BIT flags which to indicate which
481 * pixel transfer operations are enabled.
482 */
483 static void
484 update_image_transfer_state(struct gl_context *ctx)
485 {
486 GLuint mask = 0;
487
488 if (ctx->Pixel.RedScale != 1.0F || ctx->Pixel.RedBias != 0.0F ||
489 ctx->Pixel.GreenScale != 1.0F || ctx->Pixel.GreenBias != 0.0F ||
490 ctx->Pixel.BlueScale != 1.0F || ctx->Pixel.BlueBias != 0.0F ||
491 ctx->Pixel.AlphaScale != 1.0F || ctx->Pixel.AlphaBias != 0.0F)
492 mask |= IMAGE_SCALE_BIAS_BIT;
493
494 if (ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset)
495 mask |= IMAGE_SHIFT_OFFSET_BIT;
496
497 if (ctx->Pixel.MapColorFlag)
498 mask |= IMAGE_MAP_COLOR_BIT;
499
500 ctx->_ImageTransferState = mask;
501 }
502
503
504 /**
505 * Update mesa pixel transfer derived state.
506 */
507 void _mesa_update_pixel( struct gl_context *ctx, GLuint new_state )
508 {
509 if (new_state & _NEW_PIXEL)
510 update_image_transfer_state(ctx);
511 }
512
513
514 void
515 _mesa_init_pixel_dispatch(struct _glapi_table *disp)
516 {
517 SET_GetPixelMapfv(disp, _mesa_GetPixelMapfv);
518 SET_GetPixelMapuiv(disp, _mesa_GetPixelMapuiv);
519 SET_GetPixelMapusv(disp, _mesa_GetPixelMapusv);
520 SET_PixelMapfv(disp, _mesa_PixelMapfv);
521 SET_PixelMapuiv(disp, _mesa_PixelMapuiv);
522 SET_PixelMapusv(disp, _mesa_PixelMapusv);
523 SET_PixelTransferf(disp, _mesa_PixelTransferf);
524 SET_PixelTransferi(disp, _mesa_PixelTransferi);
525 SET_PixelZoom(disp, _mesa_PixelZoom);
526 }
527
528
529 #endif /* FEATURE_pixel_transfer */
530
531
532 /**********************************************************************/
533 /***** Initialization *****/
534 /**********************************************************************/
535
536 static void
537 init_pixelmap(struct gl_pixelmap *map)
538 {
539 map->Size = 1;
540 map->Map[0] = 0.0;
541 map->Map8[0] = 0;
542 }
543
544
545 /**
546 * Initialize the context's PIXEL attribute group.
547 */
548 void
549 _mesa_init_pixel( struct gl_context *ctx )
550 {
551 /* Pixel group */
552 ctx->Pixel.RedBias = 0.0;
553 ctx->Pixel.RedScale = 1.0;
554 ctx->Pixel.GreenBias = 0.0;
555 ctx->Pixel.GreenScale = 1.0;
556 ctx->Pixel.BlueBias = 0.0;
557 ctx->Pixel.BlueScale = 1.0;
558 ctx->Pixel.AlphaBias = 0.0;
559 ctx->Pixel.AlphaScale = 1.0;
560 ctx->Pixel.DepthBias = 0.0;
561 ctx->Pixel.DepthScale = 1.0;
562 ctx->Pixel.IndexOffset = 0;
563 ctx->Pixel.IndexShift = 0;
564 ctx->Pixel.ZoomX = 1.0;
565 ctx->Pixel.ZoomY = 1.0;
566 ctx->Pixel.MapColorFlag = GL_FALSE;
567 ctx->Pixel.MapStencilFlag = GL_FALSE;
568 init_pixelmap(&ctx->PixelMaps.StoS);
569 init_pixelmap(&ctx->PixelMaps.ItoI);
570 init_pixelmap(&ctx->PixelMaps.ItoR);
571 init_pixelmap(&ctx->PixelMaps.ItoG);
572 init_pixelmap(&ctx->PixelMaps.ItoB);
573 init_pixelmap(&ctx->PixelMaps.ItoA);
574 init_pixelmap(&ctx->PixelMaps.RtoR);
575 init_pixelmap(&ctx->PixelMaps.GtoG);
576 init_pixelmap(&ctx->PixelMaps.BtoB);
577 init_pixelmap(&ctx->PixelMaps.AtoA);
578
579 if (ctx->Visual.doubleBufferMode) {
580 ctx->Pixel.ReadBuffer = GL_BACK;
581 }
582 else {
583 ctx->Pixel.ReadBuffer = GL_FRONT;
584 }
585
586 /* Miscellaneous */
587 ctx->_ImageTransferState = 0;
588 }