pixel.c revision 7117f1b4
1/*
2 * Mesa 3-D graphics library
3 * Version:  6.5.3
4 *
5 * Copyright (C) 1999-2007  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#include "glheader.h"
26#include "bufferobj.h"
27#include "colormac.h"
28#include "context.h"
29#include "image.h"
30#include "macros.h"
31#include "pixel.h"
32#include "mtypes.h"
33
34
35/**********************************************************************/
36/*****                    glPixelZoom                             *****/
37/**********************************************************************/
38
39
40
41void GLAPIENTRY
42_mesa_PixelZoom( GLfloat xfactor, GLfloat yfactor )
43{
44   GET_CURRENT_CONTEXT(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/*****                    glPixelStore                            *****/
59/**********************************************************************/
60
61
62void GLAPIENTRY
63_mesa_PixelStorei( GLenum pname, GLint param )
64{
65   /* NOTE: this call can't be compiled into the display list */
66   GET_CURRENT_CONTEXT(ctx);
67   ASSERT_OUTSIDE_BEGIN_END(ctx);
68
69   switch (pname) {
70      case GL_PACK_SWAP_BYTES:
71	 if (param == (GLint)ctx->Pack.SwapBytes)
72	    return;
73	 FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
74         ctx->Pack.SwapBytes = param ? GL_TRUE : GL_FALSE;
75	 break;
76      case GL_PACK_LSB_FIRST:
77	 if (param == (GLint)ctx->Pack.LsbFirst)
78	    return;
79	 FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
80         ctx->Pack.LsbFirst = param ? GL_TRUE : GL_FALSE;
81	 break;
82      case GL_PACK_ROW_LENGTH:
83	 if (param<0) {
84	    _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" );
85	    return;
86	 }
87	 if (ctx->Pack.RowLength == param)
88	    return;
89	 FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
90	 ctx->Pack.RowLength = param;
91	 break;
92      case GL_PACK_IMAGE_HEIGHT:
93         if (param<0) {
94            _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" );
95	    return;
96	 }
97	 if (ctx->Pack.ImageHeight == param)
98	    return;
99	 FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
100	 ctx->Pack.ImageHeight = param;
101         break;
102      case GL_PACK_SKIP_PIXELS:
103	 if (param<0) {
104	    _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" );
105	    return;
106	 }
107	 if (ctx->Pack.SkipPixels == param)
108	    return;
109	 FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
110	 ctx->Pack.SkipPixels = param;
111	 break;
112      case GL_PACK_SKIP_ROWS:
113	 if (param<0) {
114	    _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" );
115	    return;
116	 }
117	 if (ctx->Pack.SkipRows == param)
118	    return;
119	 FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
120	 ctx->Pack.SkipRows = param;
121	 break;
122      case GL_PACK_SKIP_IMAGES:
123	 if (param<0) {
124	    _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" );
125	    return;
126	 }
127	 if (ctx->Pack.SkipImages == param)
128	    return;
129	 FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
130	 ctx->Pack.SkipImages = param;
131	 break;
132      case GL_PACK_ALIGNMENT:
133         if (param!=1 && param!=2 && param!=4 && param!=8) {
134	    _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" );
135	    return;
136	 }
137	 if (ctx->Pack.Alignment == param)
138	    return;
139	 FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
140	 ctx->Pack.Alignment = param;
141	 break;
142      case GL_PACK_INVERT_MESA:
143         if (!ctx->Extensions.MESA_pack_invert) {
144            _mesa_error( ctx, GL_INVALID_ENUM, "glPixelstore(pname)" );
145            return;
146         }
147         if (ctx->Pack.Invert == param)
148            return;
149         FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
150         ctx->Pack.Invert = param;
151         break;
152
153      case GL_UNPACK_SWAP_BYTES:
154	 if (param == (GLint)ctx->Unpack.SwapBytes)
155	    return;
156	 if ((GLint)ctx->Unpack.SwapBytes == param)
157	    return;
158	 FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
159	 ctx->Unpack.SwapBytes = param ? GL_TRUE : GL_FALSE;
160         break;
161      case GL_UNPACK_LSB_FIRST:
162	 if (param == (GLint)ctx->Unpack.LsbFirst)
163	    return;
164	 if ((GLint)ctx->Unpack.LsbFirst == param)
165	    return;
166	 FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
167	 ctx->Unpack.LsbFirst = param ? GL_TRUE : GL_FALSE;
168	 break;
169      case GL_UNPACK_ROW_LENGTH:
170	 if (param<0) {
171	    _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" );
172	    return;
173	 }
174	 if (ctx->Unpack.RowLength == param)
175	    return;
176	 FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
177	 ctx->Unpack.RowLength = param;
178	 break;
179      case GL_UNPACK_IMAGE_HEIGHT:
180         if (param<0) {
181            _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" );
182	    return;
183	 }
184	 if (ctx->Unpack.ImageHeight == param)
185	    return;
186
187	 FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
188	 ctx->Unpack.ImageHeight = param;
189         break;
190      case GL_UNPACK_SKIP_PIXELS:
191	 if (param<0) {
192	    _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" );
193	    return;
194	 }
195	 if (ctx->Unpack.SkipPixels == param)
196	    return;
197	 FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
198	 ctx->Unpack.SkipPixels = param;
199	 break;
200      case GL_UNPACK_SKIP_ROWS:
201	 if (param<0) {
202	    _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" );
203	    return;
204	 }
205	 if (ctx->Unpack.SkipRows == param)
206	    return;
207	 FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
208	 ctx->Unpack.SkipRows = param;
209	 break;
210      case GL_UNPACK_SKIP_IMAGES:
211	 if (param < 0) {
212	    _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" );
213	    return;
214	 }
215	 if (ctx->Unpack.SkipImages == param)
216	    return;
217	 FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
218	 ctx->Unpack.SkipImages = param;
219	 break;
220      case GL_UNPACK_ALIGNMENT:
221         if (param!=1 && param!=2 && param!=4 && param!=8) {
222	    _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore" );
223	    return;
224	 }
225	 if (ctx->Unpack.Alignment == param)
226	    return;
227	 FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
228	 ctx->Unpack.Alignment = param;
229	 break;
230      case GL_UNPACK_CLIENT_STORAGE_APPLE:
231         if (param == (GLint)ctx->Unpack.ClientStorage)
232            return;
233         FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
234         ctx->Unpack.ClientStorage = param ? GL_TRUE : GL_FALSE;
235         break;
236      default:
237	 _mesa_error( ctx, GL_INVALID_ENUM, "glPixelStore" );
238	 return;
239   }
240}
241
242
243void GLAPIENTRY
244_mesa_PixelStoref( GLenum pname, GLfloat param )
245{
246   _mesa_PixelStorei( pname, (GLint) param );
247}
248
249
250
251/**********************************************************************/
252/*****                         glPixelMap                         *****/
253/**********************************************************************/
254
255/**
256 * Return pointer to a pixelmap by name.
257 */
258static struct gl_pixelmap *
259get_pixelmap(GLcontext *ctx, GLenum map)
260{
261   switch (map) {
262   case GL_PIXEL_MAP_I_TO_I:
263      return &ctx->PixelMaps.ItoI;
264   case GL_PIXEL_MAP_S_TO_S:
265      return &ctx->PixelMaps.StoS;
266   case GL_PIXEL_MAP_I_TO_R:
267      return &ctx->PixelMaps.ItoR;
268   case GL_PIXEL_MAP_I_TO_G:
269      return &ctx->PixelMaps.ItoG;
270   case GL_PIXEL_MAP_I_TO_B:
271      return &ctx->PixelMaps.ItoB;
272   case GL_PIXEL_MAP_I_TO_A:
273      return &ctx->PixelMaps.ItoA;
274   case GL_PIXEL_MAP_R_TO_R:
275      return &ctx->PixelMaps.RtoR;
276   case GL_PIXEL_MAP_G_TO_G:
277      return &ctx->PixelMaps.GtoG;
278   case GL_PIXEL_MAP_B_TO_B:
279      return &ctx->PixelMaps.BtoB;
280   case GL_PIXEL_MAP_A_TO_A:
281      return &ctx->PixelMaps.AtoA;
282   default:
283      return NULL;
284   }
285}
286
287
288/**
289 * Helper routine used by the other _mesa_PixelMap() functions.
290 */
291static void
292store_pixelmap(GLcontext *ctx, GLenum map, GLsizei mapsize,
293               const GLfloat *values)
294{
295   GLint i;
296   struct gl_pixelmap *pm = get_pixelmap(ctx, map);
297   if (!pm) {
298      _mesa_error(ctx, GL_INVALID_ENUM, "glPixelMap(map)");
299      return;
300   }
301
302   switch (map) {
303   case GL_PIXEL_MAP_S_TO_S:
304      /* special case */
305      ctx->PixelMaps.StoS.Size = mapsize;
306      for (i = 0; i < mapsize; i++) {
307         ctx->PixelMaps.StoS.Map[i] = IROUND(values[i]);
308      }
309      break;
310   case GL_PIXEL_MAP_I_TO_I:
311      /* special case */
312      ctx->PixelMaps.ItoI.Size = mapsize;
313      for (i = 0; i < mapsize; i++) {
314         ctx->PixelMaps.ItoI.Map[i] = values[i];
315      }
316      break;
317   default:
318      /* general case */
319      pm->Size = mapsize;
320      for (i = 0; i < mapsize; i++) {
321         GLfloat val = CLAMP(values[i], 0.0F, 1.0F);
322         pm->Map[i] = val;
323         pm->Map8[i] = (GLint) (val * 255.0F);
324      }
325   }
326}
327
328
329void GLAPIENTRY
330_mesa_PixelMapfv( GLenum map, GLsizei mapsize, const GLfloat *values )
331{
332   GET_CURRENT_CONTEXT(ctx);
333   ASSERT_OUTSIDE_BEGIN_END(ctx);
334
335   /* XXX someday, test against ctx->Const.MaxPixelMapTableSize */
336   if (mapsize < 1 || mapsize > MAX_PIXEL_MAP_TABLE) {
337      _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapfv(mapsize)" );
338      return;
339   }
340
341   if (map >= GL_PIXEL_MAP_S_TO_S && map <= GL_PIXEL_MAP_I_TO_A) {
342      /* test that mapsize is a power of two */
343      if (_mesa_bitcount((GLuint) mapsize) != 1) {
344	 _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapfv(mapsize)" );
345         return;
346      }
347   }
348
349   FLUSH_VERTICES(ctx, _NEW_PIXEL);
350
351   if (ctx->Unpack.BufferObj->Name) {
352      /* unpack pixelmap from PBO */
353      GLubyte *buf;
354      /* Note, need to use DefaultPacking and Unpack's buffer object */
355      ctx->DefaultPacking.BufferObj = ctx->Unpack.BufferObj;
356      if (!_mesa_validate_pbo_access(1, &ctx->DefaultPacking, mapsize, 1, 1,
357                                     GL_INTENSITY, GL_FLOAT, values)) {
358         _mesa_error(ctx, GL_INVALID_OPERATION,
359                     "glPixelMapfv(invalid PBO access)");
360         return;
361      }
362      /* restore */
363      ctx->DefaultPacking.BufferObj = ctx->Array.NullBufferObj;
364      buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
365                                              GL_READ_ONLY_ARB,
366                                              ctx->Unpack.BufferObj);
367      if (!buf) {
368         /* buffer is already mapped - that's an error */
369         _mesa_error(ctx, GL_INVALID_OPERATION,
370                     "glPixelMapfv(PBO is mapped)");
371         return;
372      }
373      values = (const GLfloat *) ADD_POINTERS(buf, values);
374   }
375   else if (!values) {
376      return;
377   }
378
379   store_pixelmap(ctx, map, mapsize, values);
380
381   if (ctx->Unpack.BufferObj->Name) {
382      ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
383                              ctx->Unpack.BufferObj);
384   }
385}
386
387
388void GLAPIENTRY
389_mesa_PixelMapuiv(GLenum map, GLsizei mapsize, const GLuint *values )
390{
391   GLfloat fvalues[MAX_PIXEL_MAP_TABLE];
392   GET_CURRENT_CONTEXT(ctx);
393   ASSERT_OUTSIDE_BEGIN_END(ctx);
394
395   if (mapsize < 1 || mapsize > MAX_PIXEL_MAP_TABLE) {
396      _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapuiv(mapsize)" );
397      return;
398   }
399
400   if (map >= GL_PIXEL_MAP_S_TO_S && map <= GL_PIXEL_MAP_I_TO_A) {
401      /* test that mapsize is a power of two */
402      if (_mesa_bitcount((GLuint) mapsize) != 1) {
403	 _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapuiv(mapsize)" );
404         return;
405      }
406   }
407
408   FLUSH_VERTICES(ctx, _NEW_PIXEL);
409
410   if (ctx->Unpack.BufferObj->Name) {
411      /* unpack pixelmap from PBO */
412      GLubyte *buf;
413      /* Note, need to use DefaultPacking and Unpack's buffer object */
414      ctx->DefaultPacking.BufferObj = ctx->Unpack.BufferObj;
415      if (!_mesa_validate_pbo_access(1, &ctx->DefaultPacking, mapsize, 1, 1,
416                                     GL_INTENSITY, GL_UNSIGNED_INT, values)) {
417         _mesa_error(ctx, GL_INVALID_OPERATION,
418                     "glPixelMapuiv(invalid PBO access)");
419         return;
420      }
421      /* restore */
422      ctx->DefaultPacking.BufferObj = ctx->Array.NullBufferObj;
423      buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
424                                              GL_READ_ONLY_ARB,
425                                              ctx->Unpack.BufferObj);
426      if (!buf) {
427         /* buffer is already mapped - that's an error */
428         _mesa_error(ctx, GL_INVALID_OPERATION,
429                     "glPixelMapuiv(PBO is mapped)");
430         return;
431      }
432      values = (const GLuint *) ADD_POINTERS(buf, values);
433   }
434   else if (!values) {
435      return;
436   }
437
438   /* convert to floats */
439   if (map == GL_PIXEL_MAP_I_TO_I || map == GL_PIXEL_MAP_S_TO_S) {
440      GLint i;
441      for (i = 0; i < mapsize; i++) {
442         fvalues[i] = (GLfloat) values[i];
443      }
444   }
445   else {
446      GLint i;
447      for (i = 0; i < mapsize; i++) {
448         fvalues[i] = UINT_TO_FLOAT( values[i] );
449      }
450   }
451
452   if (ctx->Unpack.BufferObj->Name) {
453      ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
454                              ctx->Unpack.BufferObj);
455   }
456
457   store_pixelmap(ctx, map, mapsize, fvalues);
458}
459
460
461void GLAPIENTRY
462_mesa_PixelMapusv(GLenum map, GLsizei mapsize, const GLushort *values )
463{
464   GLfloat fvalues[MAX_PIXEL_MAP_TABLE];
465   GET_CURRENT_CONTEXT(ctx);
466   ASSERT_OUTSIDE_BEGIN_END(ctx);
467
468   if (mapsize < 1 || mapsize > MAX_PIXEL_MAP_TABLE) {
469      _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapusv(mapsize)" );
470      return;
471   }
472
473   if (map >= GL_PIXEL_MAP_S_TO_S && map <= GL_PIXEL_MAP_I_TO_A) {
474      /* test that mapsize is a power of two */
475      if (_mesa_bitcount((GLuint) mapsize) != 1) {
476	 _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapuiv(mapsize)" );
477         return;
478      }
479   }
480
481   FLUSH_VERTICES(ctx, _NEW_PIXEL);
482
483   if (ctx->Unpack.BufferObj->Name) {
484      /* unpack pixelmap from PBO */
485      GLubyte *buf;
486      /* Note, need to use DefaultPacking and Unpack's buffer object */
487      ctx->DefaultPacking.BufferObj = ctx->Unpack.BufferObj;
488      if (!_mesa_validate_pbo_access(1, &ctx->DefaultPacking, mapsize, 1, 1,
489                                     GL_INTENSITY, GL_UNSIGNED_SHORT,
490                                     values)) {
491         _mesa_error(ctx, GL_INVALID_OPERATION,
492                     "glPixelMapusv(invalid PBO access)");
493         return;
494      }
495      /* restore */
496      ctx->DefaultPacking.BufferObj = ctx->Array.NullBufferObj;
497      buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
498                                              GL_READ_ONLY_ARB,
499                                              ctx->Unpack.BufferObj);
500      if (!buf) {
501         /* buffer is already mapped - that's an error */
502         _mesa_error(ctx, GL_INVALID_OPERATION,
503                     "glPixelMapusv(PBO is mapped)");
504         return;
505      }
506      values = (const GLushort *) ADD_POINTERS(buf, values);
507   }
508   else if (!values) {
509      return;
510   }
511
512   /* convert to floats */
513   if (map == GL_PIXEL_MAP_I_TO_I || map == GL_PIXEL_MAP_S_TO_S) {
514      GLint i;
515      for (i = 0; i < mapsize; i++) {
516         fvalues[i] = (GLfloat) values[i];
517      }
518   }
519   else {
520      GLint i;
521      for (i = 0; i < mapsize; i++) {
522         fvalues[i] = USHORT_TO_FLOAT( values[i] );
523      }
524   }
525
526   if (ctx->Unpack.BufferObj->Name) {
527      ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
528                              ctx->Unpack.BufferObj);
529   }
530
531   store_pixelmap(ctx, map, mapsize, fvalues);
532}
533
534
535void GLAPIENTRY
536_mesa_GetPixelMapfv( GLenum map, GLfloat *values )
537{
538   GET_CURRENT_CONTEXT(ctx);
539   GLuint mapsize, i;
540   const struct gl_pixelmap *pm;
541
542   ASSERT_OUTSIDE_BEGIN_END(ctx);
543
544   pm = get_pixelmap(ctx, map);
545   if (!pm) {
546      _mesa_error(ctx, GL_INVALID_ENUM, "glGetPixelMapfv(map)");
547      return;
548   }
549
550   mapsize = pm->Size;
551
552   if (ctx->Pack.BufferObj->Name) {
553      /* pack pixelmap into PBO */
554      GLubyte *buf;
555      /* Note, need to use DefaultPacking and Pack's buffer object */
556      ctx->DefaultPacking.BufferObj = ctx->Pack.BufferObj;
557      if (!_mesa_validate_pbo_access(1, &ctx->DefaultPacking, mapsize, 1, 1,
558                                     GL_INTENSITY, GL_FLOAT, values)) {
559         _mesa_error(ctx, GL_INVALID_OPERATION,
560                     "glGetPixelMapfv(invalid PBO access)");
561         return;
562      }
563      /* restore */
564      ctx->DefaultPacking.BufferObj = ctx->Array.NullBufferObj;
565      buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
566                                              GL_WRITE_ONLY_ARB,
567                                              ctx->Pack.BufferObj);
568      if (!buf) {
569         /* buffer is already mapped - that's an error */
570         _mesa_error(ctx, GL_INVALID_OPERATION,
571                     "glGetPixelMapfv(PBO is mapped)");
572         return;
573      }
574      values = (GLfloat *) ADD_POINTERS(buf, values);
575   }
576   else if (!values) {
577      return;
578   }
579
580   if (map == GL_PIXEL_MAP_S_TO_S) {
581      /* special case */
582      for (i = 0; i < mapsize; i++) {
583         values[i] = (GLfloat) ctx->PixelMaps.StoS.Map[i];
584      }
585   }
586   else {
587      MEMCPY(values, pm->Map, mapsize * sizeof(GLfloat));
588   }
589
590   if (ctx->Pack.BufferObj->Name) {
591      ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
592                              ctx->Pack.BufferObj);
593   }
594}
595
596
597void GLAPIENTRY
598_mesa_GetPixelMapuiv( GLenum map, GLuint *values )
599{
600   GET_CURRENT_CONTEXT(ctx);
601   GLint mapsize, i;
602   const struct gl_pixelmap *pm;
603
604   ASSERT_OUTSIDE_BEGIN_END(ctx);
605
606   pm = get_pixelmap(ctx, map);
607   if (!pm) {
608      _mesa_error(ctx, GL_INVALID_ENUM, "glGetPixelMapuiv(map)");
609      return;
610   }
611   mapsize = pm->Size;
612
613   if (ctx->Pack.BufferObj->Name) {
614      /* pack pixelmap into PBO */
615      GLubyte *buf;
616      /* Note, need to use DefaultPacking and Pack's buffer object */
617      ctx->DefaultPacking.BufferObj = ctx->Pack.BufferObj;
618      if (!_mesa_validate_pbo_access(1, &ctx->DefaultPacking, mapsize, 1, 1,
619                                     GL_INTENSITY, GL_UNSIGNED_INT, values)) {
620         _mesa_error(ctx, GL_INVALID_OPERATION,
621                     "glGetPixelMapuiv(invalid PBO access)");
622         return;
623      }
624      /* restore */
625      ctx->DefaultPacking.BufferObj = ctx->Array.NullBufferObj;
626      buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
627                                              GL_WRITE_ONLY_ARB,
628                                              ctx->Pack.BufferObj);
629      if (!buf) {
630         /* buffer is already mapped - that's an error */
631         _mesa_error(ctx, GL_INVALID_OPERATION,
632                     "glGetPixelMapuiv(PBO is mapped)");
633         return;
634      }
635      values = (GLuint *) ADD_POINTERS(buf, values);
636   }
637   else if (!values) {
638      return;
639   }
640
641   if (map == GL_PIXEL_MAP_S_TO_S) {
642      /* special case */
643      MEMCPY(values, ctx->PixelMaps.StoS.Map, mapsize * sizeof(GLint));
644   }
645   else {
646      for (i = 0; i < mapsize; i++) {
647         values[i] = FLOAT_TO_UINT( pm->Map[i] );
648      }
649   }
650
651   if (ctx->Pack.BufferObj->Name) {
652      ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
653                              ctx->Pack.BufferObj);
654   }
655}
656
657
658void GLAPIENTRY
659_mesa_GetPixelMapusv( GLenum map, GLushort *values )
660{
661   GET_CURRENT_CONTEXT(ctx);
662   GLint mapsize, i;
663   const struct gl_pixelmap *pm;
664
665   ASSERT_OUTSIDE_BEGIN_END(ctx);
666
667   pm = get_pixelmap(ctx, map);
668   if (!pm) {
669      _mesa_error(ctx, GL_INVALID_ENUM, "glGetPixelMapusv(map)");
670      return;
671   }
672   mapsize = pm ? pm->Size : 0;
673
674   if (ctx->Pack.BufferObj->Name) {
675      /* pack pixelmap into PBO */
676      GLubyte *buf;
677      /* Note, need to use DefaultPacking and Pack's buffer object */
678      ctx->DefaultPacking.BufferObj = ctx->Pack.BufferObj;
679      if (!_mesa_validate_pbo_access(1, &ctx->DefaultPacking, mapsize, 1, 1,
680                                     GL_INTENSITY, GL_UNSIGNED_SHORT,
681                                     values)) {
682         _mesa_error(ctx, GL_INVALID_OPERATION,
683                     "glGetPixelMapusv(invalid PBO access)");
684         return;
685      }
686      /* restore */
687      ctx->DefaultPacking.BufferObj = ctx->Array.NullBufferObj;
688      buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
689                                              GL_WRITE_ONLY_ARB,
690                                              ctx->Pack.BufferObj);
691      if (!buf) {
692         /* buffer is already mapped - that's an error */
693         _mesa_error(ctx, GL_INVALID_OPERATION,
694                     "glGetPixelMapusv(PBO is mapped)");
695         return;
696      }
697      values = (GLushort *) ADD_POINTERS(buf, values);
698   }
699   else if (!values) {
700      return;
701   }
702
703   switch (map) {
704   /* special cases */
705   case GL_PIXEL_MAP_I_TO_I:
706      for (i = 0; i < mapsize; i++) {
707         values[i] = (GLushort) CLAMP(ctx->PixelMaps.ItoI.Map[i], 0.0, 65535.);
708      }
709      break;
710   case GL_PIXEL_MAP_S_TO_S:
711      for (i = 0; i < mapsize; i++) {
712         values[i] = (GLushort) CLAMP(ctx->PixelMaps.StoS.Map[i], 0.0, 65535.);
713      }
714      break;
715   default:
716      for (i = 0; i < mapsize; i++) {
717         CLAMPED_FLOAT_TO_USHORT(values[i], pm->Map[i] );
718      }
719   }
720
721   if (ctx->Pack.BufferObj->Name) {
722      ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
723                              ctx->Pack.BufferObj);
724   }
725}
726
727
728
729/**********************************************************************/
730/*****                       glPixelTransfer                      *****/
731/**********************************************************************/
732
733
734/*
735 * Implements glPixelTransfer[fi] whether called immediately or from a
736 * display list.
737 */
738void GLAPIENTRY
739_mesa_PixelTransferf( GLenum pname, GLfloat param )
740{
741   GET_CURRENT_CONTEXT(ctx);
742   ASSERT_OUTSIDE_BEGIN_END(ctx);
743
744   switch (pname) {
745      case GL_MAP_COLOR:
746         if (ctx->Pixel.MapColorFlag == (param ? GL_TRUE : GL_FALSE))
747	    return;
748	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
749         ctx->Pixel.MapColorFlag = param ? GL_TRUE : GL_FALSE;
750	 break;
751      case GL_MAP_STENCIL:
752         if (ctx->Pixel.MapStencilFlag == (param ? GL_TRUE : GL_FALSE))
753	    return;
754	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
755         ctx->Pixel.MapStencilFlag = param ? GL_TRUE : GL_FALSE;
756	 break;
757      case GL_INDEX_SHIFT:
758         if (ctx->Pixel.IndexShift == (GLint) param)
759	    return;
760	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
761         ctx->Pixel.IndexShift = (GLint) param;
762	 break;
763      case GL_INDEX_OFFSET:
764         if (ctx->Pixel.IndexOffset == (GLint) param)
765	    return;
766	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
767         ctx->Pixel.IndexOffset = (GLint) param;
768	 break;
769      case GL_RED_SCALE:
770         if (ctx->Pixel.RedScale == param)
771	    return;
772	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
773         ctx->Pixel.RedScale = param;
774	 break;
775      case GL_RED_BIAS:
776         if (ctx->Pixel.RedBias == param)
777	    return;
778	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
779         ctx->Pixel.RedBias = param;
780	 break;
781      case GL_GREEN_SCALE:
782         if (ctx->Pixel.GreenScale == param)
783	    return;
784	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
785         ctx->Pixel.GreenScale = param;
786	 break;
787      case GL_GREEN_BIAS:
788         if (ctx->Pixel.GreenBias == param)
789	    return;
790	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
791         ctx->Pixel.GreenBias = param;
792	 break;
793      case GL_BLUE_SCALE:
794         if (ctx->Pixel.BlueScale == param)
795	    return;
796	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
797         ctx->Pixel.BlueScale = param;
798	 break;
799      case GL_BLUE_BIAS:
800         if (ctx->Pixel.BlueBias == param)
801	    return;
802	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
803         ctx->Pixel.BlueBias = param;
804	 break;
805      case GL_ALPHA_SCALE:
806         if (ctx->Pixel.AlphaScale == param)
807	    return;
808	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
809         ctx->Pixel.AlphaScale = param;
810	 break;
811      case GL_ALPHA_BIAS:
812         if (ctx->Pixel.AlphaBias == param)
813	    return;
814	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
815         ctx->Pixel.AlphaBias = param;
816	 break;
817      case GL_DEPTH_SCALE:
818         if (ctx->Pixel.DepthScale == param)
819	    return;
820	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
821         ctx->Pixel.DepthScale = param;
822	 break;
823      case GL_DEPTH_BIAS:
824         if (ctx->Pixel.DepthBias == param)
825	    return;
826	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
827         ctx->Pixel.DepthBias = param;
828	 break;
829      case GL_POST_COLOR_MATRIX_RED_SCALE:
830         if (ctx->Pixel.PostColorMatrixScale[0] == param)
831	    return;
832	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
833         ctx->Pixel.PostColorMatrixScale[0] = param;
834	 break;
835      case GL_POST_COLOR_MATRIX_RED_BIAS:
836         if (ctx->Pixel.PostColorMatrixBias[0] == param)
837	    return;
838	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
839         ctx->Pixel.PostColorMatrixBias[0] = param;
840	 break;
841      case GL_POST_COLOR_MATRIX_GREEN_SCALE:
842         if (ctx->Pixel.PostColorMatrixScale[1] == param)
843	    return;
844	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
845         ctx->Pixel.PostColorMatrixScale[1] = param;
846	 break;
847      case GL_POST_COLOR_MATRIX_GREEN_BIAS:
848         if (ctx->Pixel.PostColorMatrixBias[1] == param)
849	    return;
850	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
851         ctx->Pixel.PostColorMatrixBias[1] = param;
852	 break;
853      case GL_POST_COLOR_MATRIX_BLUE_SCALE:
854         if (ctx->Pixel.PostColorMatrixScale[2] == param)
855	    return;
856	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
857         ctx->Pixel.PostColorMatrixScale[2] = param;
858	 break;
859      case GL_POST_COLOR_MATRIX_BLUE_BIAS:
860         if (ctx->Pixel.PostColorMatrixBias[2] == param)
861	    return;
862	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
863         ctx->Pixel.PostColorMatrixBias[2] = param;
864	 break;
865      case GL_POST_COLOR_MATRIX_ALPHA_SCALE:
866         if (ctx->Pixel.PostColorMatrixScale[3] == param)
867	    return;
868	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
869         ctx->Pixel.PostColorMatrixScale[3] = param;
870	 break;
871      case GL_POST_COLOR_MATRIX_ALPHA_BIAS:
872         if (ctx->Pixel.PostColorMatrixBias[3] == param)
873	    return;
874	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
875         ctx->Pixel.PostColorMatrixBias[3] = param;
876	 break;
877      case GL_POST_CONVOLUTION_RED_SCALE:
878         if (ctx->Pixel.PostConvolutionScale[0] == param)
879	    return;
880	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
881         ctx->Pixel.PostConvolutionScale[0] = param;
882	 break;
883      case GL_POST_CONVOLUTION_RED_BIAS:
884         if (ctx->Pixel.PostConvolutionBias[0] == param)
885	    return;
886	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
887         ctx->Pixel.PostConvolutionBias[0] = param;
888	 break;
889      case GL_POST_CONVOLUTION_GREEN_SCALE:
890         if (ctx->Pixel.PostConvolutionScale[1] == param)
891	    return;
892	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
893         ctx->Pixel.PostConvolutionScale[1] = param;
894	 break;
895      case GL_POST_CONVOLUTION_GREEN_BIAS:
896         if (ctx->Pixel.PostConvolutionBias[1] == param)
897	    return;
898	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
899         ctx->Pixel.PostConvolutionBias[1] = param;
900	 break;
901      case GL_POST_CONVOLUTION_BLUE_SCALE:
902         if (ctx->Pixel.PostConvolutionScale[2] == param)
903	    return;
904	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
905         ctx->Pixel.PostConvolutionScale[2] = param;
906	 break;
907      case GL_POST_CONVOLUTION_BLUE_BIAS:
908         if (ctx->Pixel.PostConvolutionBias[2] == param)
909	    return;
910	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
911         ctx->Pixel.PostConvolutionBias[2] = param;
912	 break;
913      case GL_POST_CONVOLUTION_ALPHA_SCALE:
914         if (ctx->Pixel.PostConvolutionScale[3] == param)
915	    return;
916	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
917         ctx->Pixel.PostConvolutionScale[3] = param;
918	 break;
919      case GL_POST_CONVOLUTION_ALPHA_BIAS:
920         if (ctx->Pixel.PostConvolutionBias[3] == param)
921	    return;
922	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
923         ctx->Pixel.PostConvolutionBias[3] = param;
924	 break;
925      default:
926         _mesa_error( ctx, GL_INVALID_ENUM, "glPixelTransfer(pname)" );
927         return;
928   }
929}
930
931
932void GLAPIENTRY
933_mesa_PixelTransferi( GLenum pname, GLint param )
934{
935   _mesa_PixelTransferf( pname, (GLfloat) param );
936}
937
938
939
940/**********************************************************************/
941/*****                  Pixel processing functions               ******/
942/**********************************************************************/
943
944/*
945 * Apply scale and bias factors to an array of RGBA pixels.
946 */
947void
948_mesa_scale_and_bias_rgba(GLuint n, GLfloat rgba[][4],
949                          GLfloat rScale, GLfloat gScale,
950                          GLfloat bScale, GLfloat aScale,
951                          GLfloat rBias, GLfloat gBias,
952                          GLfloat bBias, GLfloat aBias)
953{
954   if (rScale != 1.0 || rBias != 0.0) {
955      GLuint i;
956      for (i = 0; i < n; i++) {
957         rgba[i][RCOMP] = rgba[i][RCOMP] * rScale + rBias;
958      }
959   }
960   if (gScale != 1.0 || gBias != 0.0) {
961      GLuint i;
962      for (i = 0; i < n; i++) {
963         rgba[i][GCOMP] = rgba[i][GCOMP] * gScale + gBias;
964      }
965   }
966   if (bScale != 1.0 || bBias != 0.0) {
967      GLuint i;
968      for (i = 0; i < n; i++) {
969         rgba[i][BCOMP] = rgba[i][BCOMP] * bScale + bBias;
970      }
971   }
972   if (aScale != 1.0 || aBias != 0.0) {
973      GLuint i;
974      for (i = 0; i < n; i++) {
975         rgba[i][ACOMP] = rgba[i][ACOMP] * aScale + aBias;
976      }
977   }
978}
979
980
981/*
982 * Apply pixel mapping to an array of floating point RGBA pixels.
983 */
984void
985_mesa_map_rgba( const GLcontext *ctx, GLuint n, GLfloat rgba[][4] )
986{
987   const GLfloat rscale = (GLfloat) (ctx->PixelMaps.RtoR.Size - 1);
988   const GLfloat gscale = (GLfloat) (ctx->PixelMaps.GtoG.Size - 1);
989   const GLfloat bscale = (GLfloat) (ctx->PixelMaps.BtoB.Size - 1);
990   const GLfloat ascale = (GLfloat) (ctx->PixelMaps.AtoA.Size - 1);
991   const GLfloat *rMap = ctx->PixelMaps.RtoR.Map;
992   const GLfloat *gMap = ctx->PixelMaps.GtoG.Map;
993   const GLfloat *bMap = ctx->PixelMaps.BtoB.Map;
994   const GLfloat *aMap = ctx->PixelMaps.AtoA.Map;
995   GLuint i;
996   for (i=0;i<n;i++) {
997      GLfloat r = CLAMP(rgba[i][RCOMP], 0.0F, 1.0F);
998      GLfloat g = CLAMP(rgba[i][GCOMP], 0.0F, 1.0F);
999      GLfloat b = CLAMP(rgba[i][BCOMP], 0.0F, 1.0F);
1000      GLfloat a = CLAMP(rgba[i][ACOMP], 0.0F, 1.0F);
1001      rgba[i][RCOMP] = rMap[IROUND(r * rscale)];
1002      rgba[i][GCOMP] = gMap[IROUND(g * gscale)];
1003      rgba[i][BCOMP] = bMap[IROUND(b * bscale)];
1004      rgba[i][ACOMP] = aMap[IROUND(a * ascale)];
1005   }
1006}
1007
1008
1009/*
1010 * Apply the color matrix and post color matrix scaling and biasing.
1011 */
1012void
1013_mesa_transform_rgba(const GLcontext *ctx, GLuint n, GLfloat rgba[][4])
1014{
1015   const GLfloat rs = ctx->Pixel.PostColorMatrixScale[0];
1016   const GLfloat rb = ctx->Pixel.PostColorMatrixBias[0];
1017   const GLfloat gs = ctx->Pixel.PostColorMatrixScale[1];
1018   const GLfloat gb = ctx->Pixel.PostColorMatrixBias[1];
1019   const GLfloat bs = ctx->Pixel.PostColorMatrixScale[2];
1020   const GLfloat bb = ctx->Pixel.PostColorMatrixBias[2];
1021   const GLfloat as = ctx->Pixel.PostColorMatrixScale[3];
1022   const GLfloat ab = ctx->Pixel.PostColorMatrixBias[3];
1023   const GLfloat *m = ctx->ColorMatrixStack.Top->m;
1024   GLuint i;
1025   for (i = 0; i < n; i++) {
1026      const GLfloat r = rgba[i][RCOMP];
1027      const GLfloat g = rgba[i][GCOMP];
1028      const GLfloat b = rgba[i][BCOMP];
1029      const GLfloat a = rgba[i][ACOMP];
1030      rgba[i][RCOMP] = (m[0] * r + m[4] * g + m[ 8] * b + m[12] * a) * rs + rb;
1031      rgba[i][GCOMP] = (m[1] * r + m[5] * g + m[ 9] * b + m[13] * a) * gs + gb;
1032      rgba[i][BCOMP] = (m[2] * r + m[6] * g + m[10] * b + m[14] * a) * bs + bb;
1033      rgba[i][ACOMP] = (m[3] * r + m[7] * g + m[11] * b + m[15] * a) * as + ab;
1034   }
1035}
1036
1037
1038/**
1039 * Apply a color table lookup to an array of floating point RGBA colors.
1040 */
1041void
1042_mesa_lookup_rgba_float(const struct gl_color_table *table,
1043                        GLuint n, GLfloat rgba[][4])
1044{
1045   const GLint max = table->Size - 1;
1046   const GLfloat scale = (GLfloat) max;
1047   const GLfloat *lut = table->TableF;
1048   GLuint i;
1049
1050   if (!table->TableF || table->Size == 0)
1051      return;
1052
1053   switch (table->_BaseFormat) {
1054      case GL_INTENSITY:
1055         /* replace RGBA with I */
1056         for (i = 0; i < n; i++) {
1057            GLint j = IROUND(rgba[i][RCOMP] * scale);
1058            GLfloat c = lut[CLAMP(j, 0, max)];
1059            rgba[i][RCOMP] =
1060            rgba[i][GCOMP] =
1061            rgba[i][BCOMP] =
1062            rgba[i][ACOMP] = c;
1063         }
1064         break;
1065      case GL_LUMINANCE:
1066         /* replace RGB with L */
1067         for (i = 0; i < n; i++) {
1068            GLint j = IROUND(rgba[i][RCOMP] * scale);
1069            GLfloat c = lut[CLAMP(j, 0, max)];
1070            rgba[i][RCOMP] =
1071            rgba[i][GCOMP] =
1072            rgba[i][BCOMP] = c;
1073         }
1074         break;
1075      case GL_ALPHA:
1076         /* replace A with A */
1077         for (i = 0; i < n; i++) {
1078            GLint j = IROUND(rgba[i][ACOMP] * scale);
1079            rgba[i][ACOMP] = lut[CLAMP(j, 0, max)];
1080         }
1081         break;
1082      case GL_LUMINANCE_ALPHA:
1083         /* replace RGBA with LLLA */
1084         for (i = 0; i < n; i++) {
1085            GLint jL = IROUND(rgba[i][RCOMP] * scale);
1086            GLint jA = IROUND(rgba[i][ACOMP] * scale);
1087            GLfloat luminance, alpha;
1088            jL = CLAMP(jL, 0, max);
1089            jA = CLAMP(jA, 0, max);
1090            luminance = lut[jL * 2 + 0];
1091            alpha     = lut[jA * 2 + 1];
1092            rgba[i][RCOMP] =
1093            rgba[i][GCOMP] =
1094            rgba[i][BCOMP] = luminance;
1095            rgba[i][ACOMP] = alpha;;
1096         }
1097         break;
1098      case GL_RGB:
1099         /* replace RGB with RGB */
1100         for (i = 0; i < n; i++) {
1101            GLint jR = IROUND(rgba[i][RCOMP] * scale);
1102            GLint jG = IROUND(rgba[i][GCOMP] * scale);
1103            GLint jB = IROUND(rgba[i][BCOMP] * scale);
1104            jR = CLAMP(jR, 0, max);
1105            jG = CLAMP(jG, 0, max);
1106            jB = CLAMP(jB, 0, max);
1107            rgba[i][RCOMP] = lut[jR * 3 + 0];
1108            rgba[i][GCOMP] = lut[jG * 3 + 1];
1109            rgba[i][BCOMP] = lut[jB * 3 + 2];
1110         }
1111         break;
1112      case GL_RGBA:
1113         /* replace RGBA with RGBA */
1114         for (i = 0; i < n; i++) {
1115            GLint jR = IROUND(rgba[i][RCOMP] * scale);
1116            GLint jG = IROUND(rgba[i][GCOMP] * scale);
1117            GLint jB = IROUND(rgba[i][BCOMP] * scale);
1118            GLint jA = IROUND(rgba[i][ACOMP] * scale);
1119            jR = CLAMP(jR, 0, max);
1120            jG = CLAMP(jG, 0, max);
1121            jB = CLAMP(jB, 0, max);
1122            jA = CLAMP(jA, 0, max);
1123            rgba[i][RCOMP] = lut[jR * 4 + 0];
1124            rgba[i][GCOMP] = lut[jG * 4 + 1];
1125            rgba[i][BCOMP] = lut[jB * 4 + 2];
1126            rgba[i][ACOMP] = lut[jA * 4 + 3];
1127         }
1128         break;
1129      default:
1130         _mesa_problem(NULL, "Bad format in _mesa_lookup_rgba_float");
1131         return;
1132   }
1133}
1134
1135
1136
1137/**
1138 * Apply a color table lookup to an array of ubyte/RGBA colors.
1139 */
1140void
1141_mesa_lookup_rgba_ubyte(const struct gl_color_table *table,
1142                        GLuint n, GLubyte rgba[][4])
1143{
1144   const GLubyte *lut = table->TableUB;
1145   const GLfloat scale = (GLfloat) (table->Size - 1) / 255.0;
1146   GLuint i;
1147
1148   if (!table->TableUB || table->Size == 0)
1149      return;
1150
1151   switch (table->_BaseFormat) {
1152   case GL_INTENSITY:
1153      /* replace RGBA with I */
1154      if (table->Size == 256) {
1155         for (i = 0; i < n; i++) {
1156            const GLubyte c = lut[rgba[i][RCOMP]];
1157            rgba[i][RCOMP] =
1158            rgba[i][GCOMP] =
1159            rgba[i][BCOMP] =
1160            rgba[i][ACOMP] = c;
1161         }
1162      }
1163      else {
1164         for (i = 0; i < n; i++) {
1165            GLint j = IROUND((GLfloat) rgba[i][RCOMP] * scale);
1166            rgba[i][RCOMP] =
1167            rgba[i][GCOMP] =
1168            rgba[i][BCOMP] =
1169            rgba[i][ACOMP] = lut[j];
1170         }
1171      }
1172      break;
1173   case GL_LUMINANCE:
1174      /* replace RGB with L */
1175      if (table->Size == 256) {
1176         for (i = 0; i < n; i++) {
1177            const GLubyte c = lut[rgba[i][RCOMP]];
1178            rgba[i][RCOMP] =
1179            rgba[i][GCOMP] =
1180            rgba[i][BCOMP] = c;
1181         }
1182      }
1183      else {
1184         for (i = 0; i < n; i++) {
1185            GLint j = IROUND((GLfloat) rgba[i][RCOMP] * scale);
1186            rgba[i][RCOMP] =
1187            rgba[i][GCOMP] =
1188            rgba[i][BCOMP] = lut[j];
1189         }
1190      }
1191      break;
1192   case GL_ALPHA:
1193      /* replace A with A */
1194      if (table->Size == 256) {
1195         for (i = 0; i < n; i++) {
1196            rgba[i][ACOMP] = lut[rgba[i][ACOMP]];
1197         }
1198      }
1199      else {
1200         for (i = 0; i < n; i++) {
1201            GLint j = IROUND((GLfloat) rgba[i][ACOMP] * scale);
1202            rgba[i][ACOMP] = lut[j];
1203         }
1204      }
1205      break;
1206   case GL_LUMINANCE_ALPHA:
1207      /* replace RGBA with LLLA */
1208      if (table->Size == 256) {
1209         for (i = 0; i < n; i++) {
1210            GLubyte l = lut[rgba[i][RCOMP] * 2 + 0];
1211            GLubyte a = lut[rgba[i][ACOMP] * 2 + 1];;
1212            rgba[i][RCOMP] =
1213            rgba[i][GCOMP] =
1214            rgba[i][BCOMP] = l;
1215            rgba[i][ACOMP] = a;
1216         }
1217      }
1218      else {
1219         for (i = 0; i < n; i++) {
1220            GLint jL = IROUND((GLfloat) rgba[i][RCOMP] * scale);
1221            GLint jA = IROUND((GLfloat) rgba[i][ACOMP] * scale);
1222            GLubyte luminance = lut[jL * 2 + 0];
1223            GLubyte alpha     = lut[jA * 2 + 1];
1224            rgba[i][RCOMP] =
1225            rgba[i][GCOMP] =
1226            rgba[i][BCOMP] = luminance;
1227            rgba[i][ACOMP] = alpha;
1228         }
1229      }
1230      break;
1231   case GL_RGB:
1232      if (table->Size == 256) {
1233         for (i = 0; i < n; i++) {
1234            rgba[i][RCOMP] = lut[rgba[i][RCOMP] * 3 + 0];
1235            rgba[i][GCOMP] = lut[rgba[i][GCOMP] * 3 + 1];
1236            rgba[i][BCOMP] = lut[rgba[i][BCOMP] * 3 + 2];
1237         }
1238      }
1239      else {
1240         for (i = 0; i < n; i++) {
1241            GLint jR = IROUND((GLfloat) rgba[i][RCOMP] * scale);
1242            GLint jG = IROUND((GLfloat) rgba[i][GCOMP] * scale);
1243            GLint jB = IROUND((GLfloat) rgba[i][BCOMP] * scale);
1244            rgba[i][RCOMP] = lut[jR * 3 + 0];
1245            rgba[i][GCOMP] = lut[jG * 3 + 1];
1246            rgba[i][BCOMP] = lut[jB * 3 + 2];
1247         }
1248      }
1249      break;
1250   case GL_RGBA:
1251      if (table->Size == 256) {
1252         for (i = 0; i < n; i++) {
1253            rgba[i][RCOMP] = lut[rgba[i][RCOMP] * 4 + 0];
1254            rgba[i][GCOMP] = lut[rgba[i][GCOMP] * 4 + 1];
1255            rgba[i][BCOMP] = lut[rgba[i][BCOMP] * 4 + 2];
1256            rgba[i][ACOMP] = lut[rgba[i][ACOMP] * 4 + 3];
1257         }
1258      }
1259      else {
1260         for (i = 0; i < n; i++) {
1261            GLint jR = IROUND((GLfloat) rgba[i][RCOMP] * scale);
1262            GLint jG = IROUND((GLfloat) rgba[i][GCOMP] * scale);
1263            GLint jB = IROUND((GLfloat) rgba[i][BCOMP] * scale);
1264            GLint jA = IROUND((GLfloat) rgba[i][ACOMP] * scale);
1265            CLAMPED_FLOAT_TO_CHAN(rgba[i][RCOMP], lut[jR * 4 + 0]);
1266            CLAMPED_FLOAT_TO_CHAN(rgba[i][GCOMP], lut[jG * 4 + 1]);
1267            CLAMPED_FLOAT_TO_CHAN(rgba[i][BCOMP], lut[jB * 4 + 2]);
1268            CLAMPED_FLOAT_TO_CHAN(rgba[i][ACOMP], lut[jA * 4 + 3]);
1269         }
1270      }
1271      break;
1272   default:
1273      _mesa_problem(NULL, "Bad format in _mesa_lookup_rgba_chan");
1274      return;
1275   }
1276}
1277
1278
1279
1280/*
1281 * Map color indexes to float rgba values.
1282 */
1283void
1284_mesa_map_ci_to_rgba( const GLcontext *ctx, GLuint n,
1285                      const GLuint index[], GLfloat rgba[][4] )
1286{
1287   GLuint rmask = ctx->PixelMaps.ItoR.Size - 1;
1288   GLuint gmask = ctx->PixelMaps.ItoG.Size - 1;
1289   GLuint bmask = ctx->PixelMaps.ItoB.Size - 1;
1290   GLuint amask = ctx->PixelMaps.ItoA.Size - 1;
1291   const GLfloat *rMap = ctx->PixelMaps.ItoR.Map;
1292   const GLfloat *gMap = ctx->PixelMaps.ItoG.Map;
1293   const GLfloat *bMap = ctx->PixelMaps.ItoB.Map;
1294   const GLfloat *aMap = ctx->PixelMaps.ItoA.Map;
1295   GLuint i;
1296   for (i=0;i<n;i++) {
1297      rgba[i][RCOMP] = rMap[index[i] & rmask];
1298      rgba[i][GCOMP] = gMap[index[i] & gmask];
1299      rgba[i][BCOMP] = bMap[index[i] & bmask];
1300      rgba[i][ACOMP] = aMap[index[i] & amask];
1301   }
1302}
1303
1304
1305/**
1306 * Map ubyte color indexes to ubyte/RGBA values.
1307 */
1308void
1309_mesa_map_ci8_to_rgba8(const GLcontext *ctx, GLuint n, const GLubyte index[],
1310                       GLubyte rgba[][4])
1311{
1312   GLuint rmask = ctx->PixelMaps.ItoR.Size - 1;
1313   GLuint gmask = ctx->PixelMaps.ItoG.Size - 1;
1314   GLuint bmask = ctx->PixelMaps.ItoB.Size - 1;
1315   GLuint amask = ctx->PixelMaps.ItoA.Size - 1;
1316   const GLubyte *rMap = ctx->PixelMaps.ItoR.Map8;
1317   const GLubyte *gMap = ctx->PixelMaps.ItoG.Map8;
1318   const GLubyte *bMap = ctx->PixelMaps.ItoB.Map8;
1319   const GLubyte *aMap = ctx->PixelMaps.ItoA.Map8;
1320   GLuint i;
1321   for (i=0;i<n;i++) {
1322      rgba[i][RCOMP] = rMap[index[i] & rmask];
1323      rgba[i][GCOMP] = gMap[index[i] & gmask];
1324      rgba[i][BCOMP] = bMap[index[i] & bmask];
1325      rgba[i][ACOMP] = aMap[index[i] & amask];
1326   }
1327}
1328
1329
1330void
1331_mesa_scale_and_bias_depth(const GLcontext *ctx, GLuint n,
1332                           GLfloat depthValues[])
1333{
1334   const GLfloat scale = ctx->Pixel.DepthScale;
1335   const GLfloat bias = ctx->Pixel.DepthBias;
1336   GLuint i;
1337   for (i = 0; i < n; i++) {
1338      GLfloat d = depthValues[i] * scale + bias;
1339      depthValues[i] = CLAMP(d, 0.0F, 1.0F);
1340   }
1341}
1342
1343
1344
1345/**********************************************************************/
1346/*****                    State Management                        *****/
1347/**********************************************************************/
1348
1349/*
1350 * Return a bitmask of IMAGE_*_BIT flags which to indicate which
1351 * pixel transfer operations are enabled.
1352 */
1353static void
1354update_image_transfer_state(GLcontext *ctx)
1355{
1356   GLuint mask = 0;
1357
1358   if (ctx->Pixel.RedScale   != 1.0F || ctx->Pixel.RedBias   != 0.0F ||
1359       ctx->Pixel.GreenScale != 1.0F || ctx->Pixel.GreenBias != 0.0F ||
1360       ctx->Pixel.BlueScale  != 1.0F || ctx->Pixel.BlueBias  != 0.0F ||
1361       ctx->Pixel.AlphaScale != 1.0F || ctx->Pixel.AlphaBias != 0.0F)
1362      mask |= IMAGE_SCALE_BIAS_BIT;
1363
1364   if (ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset)
1365      mask |= IMAGE_SHIFT_OFFSET_BIT;
1366
1367   if (ctx->Pixel.MapColorFlag)
1368      mask |= IMAGE_MAP_COLOR_BIT;
1369
1370   if (ctx->Pixel.ColorTableEnabled[COLORTABLE_PRECONVOLUTION])
1371      mask |= IMAGE_COLOR_TABLE_BIT;
1372
1373   if (ctx->Pixel.Convolution1DEnabled ||
1374       ctx->Pixel.Convolution2DEnabled ||
1375       ctx->Pixel.Separable2DEnabled) {
1376      mask |= IMAGE_CONVOLUTION_BIT;
1377      if (ctx->Pixel.PostConvolutionScale[0] != 1.0F ||
1378          ctx->Pixel.PostConvolutionScale[1] != 1.0F ||
1379          ctx->Pixel.PostConvolutionScale[2] != 1.0F ||
1380          ctx->Pixel.PostConvolutionScale[3] != 1.0F ||
1381          ctx->Pixel.PostConvolutionBias[0] != 0.0F ||
1382          ctx->Pixel.PostConvolutionBias[1] != 0.0F ||
1383          ctx->Pixel.PostConvolutionBias[2] != 0.0F ||
1384          ctx->Pixel.PostConvolutionBias[3] != 0.0F) {
1385         mask |= IMAGE_POST_CONVOLUTION_SCALE_BIAS;
1386      }
1387   }
1388
1389   if (ctx->Pixel.ColorTableEnabled[COLORTABLE_POSTCONVOLUTION])
1390      mask |= IMAGE_POST_CONVOLUTION_COLOR_TABLE_BIT;
1391
1392   if (ctx->ColorMatrixStack.Top->type != MATRIX_IDENTITY ||
1393       ctx->Pixel.PostColorMatrixScale[0] != 1.0F ||
1394       ctx->Pixel.PostColorMatrixBias[0]  != 0.0F ||
1395       ctx->Pixel.PostColorMatrixScale[1] != 1.0F ||
1396       ctx->Pixel.PostColorMatrixBias[1]  != 0.0F ||
1397       ctx->Pixel.PostColorMatrixScale[2] != 1.0F ||
1398       ctx->Pixel.PostColorMatrixBias[2]  != 0.0F ||
1399       ctx->Pixel.PostColorMatrixScale[3] != 1.0F ||
1400       ctx->Pixel.PostColorMatrixBias[3]  != 0.0F)
1401      mask |= IMAGE_COLOR_MATRIX_BIT;
1402
1403   if (ctx->Pixel.ColorTableEnabled[COLORTABLE_POSTCOLORMATRIX])
1404      mask |= IMAGE_POST_COLOR_MATRIX_COLOR_TABLE_BIT;
1405
1406   if (ctx->Pixel.HistogramEnabled)
1407      mask |= IMAGE_HISTOGRAM_BIT;
1408
1409   if (ctx->Pixel.MinMaxEnabled)
1410      mask |= IMAGE_MIN_MAX_BIT;
1411
1412   ctx->_ImageTransferState = mask;
1413}
1414
1415
1416void _mesa_update_pixel( GLcontext *ctx, GLuint new_state )
1417{
1418   if (new_state & _NEW_COLOR_MATRIX)
1419      _math_matrix_analyse( ctx->ColorMatrixStack.Top );
1420
1421   /* References ColorMatrix.type (derived above).
1422    */
1423   if (new_state & _IMAGE_NEW_TRANSFER_STATE)
1424      update_image_transfer_state(ctx);
1425}
1426
1427
1428/**********************************************************************/
1429/*****                      Initialization                        *****/
1430/**********************************************************************/
1431
1432static void
1433init_pixelmap(struct gl_pixelmap *map)
1434{
1435   map->Size = 1;
1436   map->Map[0] = 0.0;
1437   map->Map8[0] = 0;
1438}
1439
1440
1441/**
1442 * Initialize the context's PIXEL attribute group.
1443 */
1444void
1445_mesa_init_pixel( GLcontext *ctx )
1446{
1447   int i;
1448
1449   /* Pixel group */
1450   ctx->Pixel.RedBias = 0.0;
1451   ctx->Pixel.RedScale = 1.0;
1452   ctx->Pixel.GreenBias = 0.0;
1453   ctx->Pixel.GreenScale = 1.0;
1454   ctx->Pixel.BlueBias = 0.0;
1455   ctx->Pixel.BlueScale = 1.0;
1456   ctx->Pixel.AlphaBias = 0.0;
1457   ctx->Pixel.AlphaScale = 1.0;
1458   ctx->Pixel.DepthBias = 0.0;
1459   ctx->Pixel.DepthScale = 1.0;
1460   ctx->Pixel.IndexOffset = 0;
1461   ctx->Pixel.IndexShift = 0;
1462   ctx->Pixel.ZoomX = 1.0;
1463   ctx->Pixel.ZoomY = 1.0;
1464   ctx->Pixel.MapColorFlag = GL_FALSE;
1465   ctx->Pixel.MapStencilFlag = GL_FALSE;
1466   init_pixelmap(&ctx->PixelMaps.StoS);
1467   init_pixelmap(&ctx->PixelMaps.ItoI);
1468   init_pixelmap(&ctx->PixelMaps.ItoR);
1469   init_pixelmap(&ctx->PixelMaps.ItoG);
1470   init_pixelmap(&ctx->PixelMaps.ItoB);
1471   init_pixelmap(&ctx->PixelMaps.ItoA);
1472   init_pixelmap(&ctx->PixelMaps.RtoR);
1473   init_pixelmap(&ctx->PixelMaps.GtoG);
1474   init_pixelmap(&ctx->PixelMaps.BtoB);
1475   init_pixelmap(&ctx->PixelMaps.AtoA);
1476   ctx->Pixel.HistogramEnabled = GL_FALSE;
1477   ctx->Pixel.MinMaxEnabled = GL_FALSE;
1478   ASSIGN_4V(ctx->Pixel.PostColorMatrixScale, 1.0, 1.0, 1.0, 1.0);
1479   ASSIGN_4V(ctx->Pixel.PostColorMatrixBias, 0.0, 0.0, 0.0, 0.0);
1480   for (i = 0; i < COLORTABLE_MAX; i++) {
1481      ASSIGN_4V(ctx->Pixel.ColorTableScale[i], 1.0, 1.0, 1.0, 1.0);
1482      ASSIGN_4V(ctx->Pixel.ColorTableBias[i], 0.0, 0.0, 0.0, 0.0);
1483      ctx->Pixel.ColorTableEnabled[i] = GL_FALSE;
1484   }
1485   ctx->Pixel.Convolution1DEnabled = GL_FALSE;
1486   ctx->Pixel.Convolution2DEnabled = GL_FALSE;
1487   ctx->Pixel.Separable2DEnabled = GL_FALSE;
1488   for (i = 0; i < 3; i++) {
1489      ASSIGN_4V(ctx->Pixel.ConvolutionBorderColor[i], 0.0, 0.0, 0.0, 0.0);
1490      ctx->Pixel.ConvolutionBorderMode[i] = GL_REDUCE;
1491      ASSIGN_4V(ctx->Pixel.ConvolutionFilterScale[i], 1.0, 1.0, 1.0, 1.0);
1492      ASSIGN_4V(ctx->Pixel.ConvolutionFilterBias[i], 0.0, 0.0, 0.0, 0.0);
1493   }
1494   for (i = 0; i < MAX_CONVOLUTION_WIDTH * MAX_CONVOLUTION_WIDTH * 4; i++) {
1495      ctx->Convolution1D.Filter[i] = 0.0;
1496      ctx->Convolution2D.Filter[i] = 0.0;
1497      ctx->Separable2D.Filter[i] = 0.0;
1498   }
1499   ASSIGN_4V(ctx->Pixel.PostConvolutionScale, 1.0, 1.0, 1.0, 1.0);
1500   ASSIGN_4V(ctx->Pixel.PostConvolutionBias, 0.0, 0.0, 0.0, 0.0);
1501   /* GL_SGI_texture_color_table */
1502   ASSIGN_4V(ctx->Pixel.TextureColorTableScale, 1.0, 1.0, 1.0, 1.0);
1503   ASSIGN_4V(ctx->Pixel.TextureColorTableBias, 0.0, 0.0, 0.0, 0.0);
1504
1505   /* Pixel transfer */
1506   ctx->Pack.Alignment = 4;
1507   ctx->Pack.RowLength = 0;
1508   ctx->Pack.ImageHeight = 0;
1509   ctx->Pack.SkipPixels = 0;
1510   ctx->Pack.SkipRows = 0;
1511   ctx->Pack.SkipImages = 0;
1512   ctx->Pack.SwapBytes = GL_FALSE;
1513   ctx->Pack.LsbFirst = GL_FALSE;
1514   ctx->Pack.ClientStorage = GL_FALSE;
1515   ctx->Pack.Invert = GL_FALSE;
1516#if FEATURE_EXT_pixel_buffer_object
1517   ctx->Pack.BufferObj = ctx->Array.NullBufferObj;
1518#endif
1519   ctx->Unpack.Alignment = 4;
1520   ctx->Unpack.RowLength = 0;
1521   ctx->Unpack.ImageHeight = 0;
1522   ctx->Unpack.SkipPixels = 0;
1523   ctx->Unpack.SkipRows = 0;
1524   ctx->Unpack.SkipImages = 0;
1525   ctx->Unpack.SwapBytes = GL_FALSE;
1526   ctx->Unpack.LsbFirst = GL_FALSE;
1527   ctx->Unpack.ClientStorage = GL_FALSE;
1528   ctx->Unpack.Invert = GL_FALSE;
1529#if FEATURE_EXT_pixel_buffer_object
1530   ctx->Unpack.BufferObj = ctx->Array.NullBufferObj;
1531#endif
1532
1533   /*
1534    * _mesa_unpack_image() returns image data in this format.  When we
1535    * execute image commands (glDrawPixels(), glTexImage(), etc) from
1536    * within display lists we have to be sure to set the current
1537    * unpacking parameters to these values!
1538    */
1539   ctx->DefaultPacking.Alignment = 1;
1540   ctx->DefaultPacking.RowLength = 0;
1541   ctx->DefaultPacking.SkipPixels = 0;
1542   ctx->DefaultPacking.SkipRows = 0;
1543   ctx->DefaultPacking.ImageHeight = 0;
1544   ctx->DefaultPacking.SkipImages = 0;
1545   ctx->DefaultPacking.SwapBytes = GL_FALSE;
1546   ctx->DefaultPacking.LsbFirst = GL_FALSE;
1547   ctx->DefaultPacking.ClientStorage = GL_FALSE;
1548   ctx->DefaultPacking.Invert = GL_FALSE;
1549#if FEATURE_EXT_pixel_buffer_object
1550   ctx->DefaultPacking.BufferObj = ctx->Array.NullBufferObj;
1551#endif
1552
1553   if (ctx->Visual.doubleBufferMode) {
1554      ctx->Pixel.ReadBuffer = GL_BACK;
1555   }
1556   else {
1557      ctx->Pixel.ReadBuffer = GL_FRONT;
1558   }
1559
1560   /* Miscellaneous */
1561   ctx->_ImageTransferState = 0;
1562}
1563