pixel.c revision 848b8605
1848b8605Smrg/*
2848b8605Smrg * Mesa 3-D graphics library
3848b8605Smrg *
4848b8605Smrg * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
5848b8605Smrg *
6848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a
7848b8605Smrg * copy of this software and associated documentation files (the "Software"),
8848b8605Smrg * to deal in the Software without restriction, including without limitation
9848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the
11848b8605Smrg * Software is furnished to do so, subject to the following conditions:
12848b8605Smrg *
13848b8605Smrg * The above copyright notice and this permission notice shall be included
14848b8605Smrg * in all copies or substantial portions of the Software.
15848b8605Smrg *
16848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20848b8605Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21848b8605Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22848b8605Smrg * OTHER DEALINGS IN THE SOFTWARE.
23848b8605Smrg */
24848b8605Smrg
25848b8605Smrg
26848b8605Smrg/**
27848b8605Smrg * \file pixel.c
28848b8605Smrg * Pixel transfer functions (glPixelZoom, glPixelMap, glPixelTransfer)
29848b8605Smrg */
30848b8605Smrg
31848b8605Smrg#include "glheader.h"
32848b8605Smrg#include "bufferobj.h"
33848b8605Smrg#include "colormac.h"
34848b8605Smrg#include "context.h"
35848b8605Smrg#include "macros.h"
36848b8605Smrg#include "pixel.h"
37848b8605Smrg#include "pbo.h"
38848b8605Smrg#include "mtypes.h"
39848b8605Smrg#include "main/dispatch.h"
40848b8605Smrg
41848b8605Smrg
42848b8605Smrg/**********************************************************************/
43848b8605Smrg/*****                    glPixelZoom                             *****/
44848b8605Smrg/**********************************************************************/
45848b8605Smrg
46848b8605Smrgvoid GLAPIENTRY
47848b8605Smrg_mesa_PixelZoom( GLfloat xfactor, GLfloat yfactor )
48848b8605Smrg{
49848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
50848b8605Smrg
51848b8605Smrg   if (ctx->Pixel.ZoomX == xfactor &&
52848b8605Smrg       ctx->Pixel.ZoomY == yfactor)
53848b8605Smrg      return;
54848b8605Smrg
55848b8605Smrg   FLUSH_VERTICES(ctx, _NEW_PIXEL);
56848b8605Smrg   ctx->Pixel.ZoomX = xfactor;
57848b8605Smrg   ctx->Pixel.ZoomY = yfactor;
58848b8605Smrg}
59848b8605Smrg
60848b8605Smrg
61848b8605Smrg
62848b8605Smrg/**********************************************************************/
63848b8605Smrg/*****                         glPixelMap                         *****/
64848b8605Smrg/**********************************************************************/
65848b8605Smrg
66848b8605Smrg/**
67848b8605Smrg * Return pointer to a pixelmap by name.
68848b8605Smrg */
69848b8605Smrgstatic struct gl_pixelmap *
70848b8605Smrgget_pixelmap(struct gl_context *ctx, GLenum map)
71848b8605Smrg{
72848b8605Smrg   switch (map) {
73848b8605Smrg   case GL_PIXEL_MAP_I_TO_I:
74848b8605Smrg      return &ctx->PixelMaps.ItoI;
75848b8605Smrg   case GL_PIXEL_MAP_S_TO_S:
76848b8605Smrg      return &ctx->PixelMaps.StoS;
77848b8605Smrg   case GL_PIXEL_MAP_I_TO_R:
78848b8605Smrg      return &ctx->PixelMaps.ItoR;
79848b8605Smrg   case GL_PIXEL_MAP_I_TO_G:
80848b8605Smrg      return &ctx->PixelMaps.ItoG;
81848b8605Smrg   case GL_PIXEL_MAP_I_TO_B:
82848b8605Smrg      return &ctx->PixelMaps.ItoB;
83848b8605Smrg   case GL_PIXEL_MAP_I_TO_A:
84848b8605Smrg      return &ctx->PixelMaps.ItoA;
85848b8605Smrg   case GL_PIXEL_MAP_R_TO_R:
86848b8605Smrg      return &ctx->PixelMaps.RtoR;
87848b8605Smrg   case GL_PIXEL_MAP_G_TO_G:
88848b8605Smrg      return &ctx->PixelMaps.GtoG;
89848b8605Smrg   case GL_PIXEL_MAP_B_TO_B:
90848b8605Smrg      return &ctx->PixelMaps.BtoB;
91848b8605Smrg   case GL_PIXEL_MAP_A_TO_A:
92848b8605Smrg      return &ctx->PixelMaps.AtoA;
93848b8605Smrg   default:
94848b8605Smrg      return NULL;
95848b8605Smrg   }
96848b8605Smrg}
97848b8605Smrg
98848b8605Smrg
99848b8605Smrg/**
100848b8605Smrg * Helper routine used by the other _mesa_PixelMap() functions.
101848b8605Smrg */
102848b8605Smrgstatic void
103848b8605Smrgstore_pixelmap(struct gl_context *ctx, GLenum map, GLsizei mapsize,
104848b8605Smrg               const GLfloat *values)
105848b8605Smrg{
106848b8605Smrg   GLint i;
107848b8605Smrg   struct gl_pixelmap *pm = get_pixelmap(ctx, map);
108848b8605Smrg   if (!pm) {
109848b8605Smrg      _mesa_error(ctx, GL_INVALID_ENUM, "glPixelMap(map)");
110848b8605Smrg      return;
111848b8605Smrg   }
112848b8605Smrg
113848b8605Smrg   switch (map) {
114848b8605Smrg   case GL_PIXEL_MAP_S_TO_S:
115848b8605Smrg      /* special case */
116848b8605Smrg      ctx->PixelMaps.StoS.Size = mapsize;
117848b8605Smrg      for (i = 0; i < mapsize; i++) {
118848b8605Smrg         ctx->PixelMaps.StoS.Map[i] = (GLfloat)IROUND(values[i]);
119848b8605Smrg      }
120848b8605Smrg      break;
121848b8605Smrg   case GL_PIXEL_MAP_I_TO_I:
122848b8605Smrg      /* special case */
123848b8605Smrg      ctx->PixelMaps.ItoI.Size = mapsize;
124848b8605Smrg      for (i = 0; i < mapsize; i++) {
125848b8605Smrg         ctx->PixelMaps.ItoI.Map[i] = values[i];
126848b8605Smrg      }
127848b8605Smrg      break;
128848b8605Smrg   default:
129848b8605Smrg      /* general case */
130848b8605Smrg      pm->Size = mapsize;
131848b8605Smrg      for (i = 0; i < mapsize; i++) {
132848b8605Smrg         GLfloat val = CLAMP(values[i], 0.0F, 1.0F);
133848b8605Smrg         pm->Map[i] = val;
134848b8605Smrg      }
135848b8605Smrg   }
136848b8605Smrg}
137848b8605Smrg
138848b8605Smrg
139848b8605Smrg/**
140848b8605Smrg * Convenience wrapper for _mesa_validate_pbo_access() for gl[Get]PixelMap().
141848b8605Smrg */
142848b8605Smrgstatic GLboolean
143848b8605Smrgvalidate_pbo_access(struct gl_context *ctx,
144848b8605Smrg                    struct gl_pixelstore_attrib *pack, GLsizei mapsize,
145848b8605Smrg                    GLenum format, GLenum type, GLsizei clientMemSize,
146848b8605Smrg                    const GLvoid *ptr)
147848b8605Smrg{
148848b8605Smrg   GLboolean ok;
149848b8605Smrg
150848b8605Smrg   /* Note, need to use DefaultPacking and Unpack's buffer object */
151848b8605Smrg   _mesa_reference_buffer_object(ctx,
152848b8605Smrg                                 &ctx->DefaultPacking.BufferObj,
153848b8605Smrg                                 pack->BufferObj);
154848b8605Smrg
155848b8605Smrg   ok = _mesa_validate_pbo_access(1, &ctx->DefaultPacking, mapsize, 1, 1,
156848b8605Smrg                                  format, type, clientMemSize, ptr);
157848b8605Smrg
158848b8605Smrg   /* restore */
159848b8605Smrg   _mesa_reference_buffer_object(ctx,
160848b8605Smrg                                 &ctx->DefaultPacking.BufferObj,
161848b8605Smrg                                 ctx->Shared->NullBufferObj);
162848b8605Smrg
163848b8605Smrg   if (!ok) {
164848b8605Smrg      if (_mesa_is_bufferobj(pack->BufferObj)) {
165848b8605Smrg         _mesa_error(ctx, GL_INVALID_OPERATION,
166848b8605Smrg                     "gl[Get]PixelMap*v(out of bounds PBO access)");
167848b8605Smrg      } else {
168848b8605Smrg         _mesa_error(ctx, GL_INVALID_OPERATION,
169848b8605Smrg                     "glGetnPixelMap*vARB(out of bounds access:"
170848b8605Smrg                     " bufSize (%d) is too small)", clientMemSize);
171848b8605Smrg      }
172848b8605Smrg   }
173848b8605Smrg   return ok;
174848b8605Smrg}
175848b8605Smrg
176848b8605Smrg
177848b8605Smrgvoid GLAPIENTRY
178848b8605Smrg_mesa_PixelMapfv( GLenum map, GLsizei mapsize, const GLfloat *values )
179848b8605Smrg{
180848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
181848b8605Smrg
182848b8605Smrg   /* XXX someday, test against ctx->Const.MaxPixelMapTableSize */
183848b8605Smrg   if (mapsize < 1 || mapsize > MAX_PIXEL_MAP_TABLE) {
184848b8605Smrg      _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapfv(mapsize)" );
185848b8605Smrg      return;
186848b8605Smrg   }
187848b8605Smrg
188848b8605Smrg   if (map >= GL_PIXEL_MAP_S_TO_S && map <= GL_PIXEL_MAP_I_TO_A) {
189848b8605Smrg      /* test that mapsize is a power of two */
190848b8605Smrg      if (!_mesa_is_pow_two(mapsize)) {
191848b8605Smrg	 _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapfv(mapsize)" );
192848b8605Smrg         return;
193848b8605Smrg      }
194848b8605Smrg   }
195848b8605Smrg
196848b8605Smrg   FLUSH_VERTICES(ctx, _NEW_PIXEL);
197848b8605Smrg
198848b8605Smrg   if (!validate_pbo_access(ctx, &ctx->Unpack, mapsize, GL_INTENSITY,
199848b8605Smrg                            GL_FLOAT, INT_MAX, values)) {
200848b8605Smrg      return;
201848b8605Smrg   }
202848b8605Smrg
203848b8605Smrg   values = (const GLfloat *) _mesa_map_pbo_source(ctx, &ctx->Unpack, values);
204848b8605Smrg   if (!values) {
205848b8605Smrg      if (_mesa_is_bufferobj(ctx->Unpack.BufferObj)) {
206848b8605Smrg         _mesa_error(ctx, GL_INVALID_OPERATION,
207848b8605Smrg                     "glPixelMapfv(PBO is mapped)");
208848b8605Smrg      }
209848b8605Smrg      return;
210848b8605Smrg   }
211848b8605Smrg
212848b8605Smrg   store_pixelmap(ctx, map, mapsize, values);
213848b8605Smrg
214848b8605Smrg   _mesa_unmap_pbo_source(ctx, &ctx->Unpack);
215848b8605Smrg}
216848b8605Smrg
217848b8605Smrg
218848b8605Smrgvoid GLAPIENTRY
219848b8605Smrg_mesa_PixelMapuiv(GLenum map, GLsizei mapsize, const GLuint *values )
220848b8605Smrg{
221848b8605Smrg   GLfloat fvalues[MAX_PIXEL_MAP_TABLE];
222848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
223848b8605Smrg
224848b8605Smrg   if (mapsize < 1 || mapsize > MAX_PIXEL_MAP_TABLE) {
225848b8605Smrg      _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapuiv(mapsize)" );
226848b8605Smrg      return;
227848b8605Smrg   }
228848b8605Smrg
229848b8605Smrg   if (map >= GL_PIXEL_MAP_S_TO_S && map <= GL_PIXEL_MAP_I_TO_A) {
230848b8605Smrg      /* test that mapsize is a power of two */
231848b8605Smrg      if (!_mesa_is_pow_two(mapsize)) {
232848b8605Smrg	 _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapuiv(mapsize)" );
233848b8605Smrg         return;
234848b8605Smrg      }
235848b8605Smrg   }
236848b8605Smrg
237848b8605Smrg   FLUSH_VERTICES(ctx, _NEW_PIXEL);
238848b8605Smrg
239848b8605Smrg   if (!validate_pbo_access(ctx, &ctx->Unpack, mapsize, GL_INTENSITY,
240848b8605Smrg                            GL_UNSIGNED_INT, INT_MAX, values)) {
241848b8605Smrg      return;
242848b8605Smrg   }
243848b8605Smrg
244848b8605Smrg   values = (const GLuint *) _mesa_map_pbo_source(ctx, &ctx->Unpack, values);
245848b8605Smrg   if (!values) {
246848b8605Smrg      if (_mesa_is_bufferobj(ctx->Unpack.BufferObj)) {
247848b8605Smrg         _mesa_error(ctx, GL_INVALID_OPERATION,
248848b8605Smrg                     "glPixelMapuiv(PBO is mapped)");
249848b8605Smrg      }
250848b8605Smrg      return;
251848b8605Smrg   }
252848b8605Smrg
253848b8605Smrg   /* convert to floats */
254848b8605Smrg   if (map == GL_PIXEL_MAP_I_TO_I || map == GL_PIXEL_MAP_S_TO_S) {
255848b8605Smrg      GLint i;
256848b8605Smrg      for (i = 0; i < mapsize; i++) {
257848b8605Smrg         fvalues[i] = (GLfloat) values[i];
258848b8605Smrg      }
259848b8605Smrg   }
260848b8605Smrg   else {
261848b8605Smrg      GLint i;
262848b8605Smrg      for (i = 0; i < mapsize; i++) {
263848b8605Smrg         fvalues[i] = UINT_TO_FLOAT( values[i] );
264848b8605Smrg      }
265848b8605Smrg   }
266848b8605Smrg
267848b8605Smrg   _mesa_unmap_pbo_source(ctx, &ctx->Unpack);
268848b8605Smrg
269848b8605Smrg   store_pixelmap(ctx, map, mapsize, fvalues);
270848b8605Smrg}
271848b8605Smrg
272848b8605Smrg
273848b8605Smrgvoid GLAPIENTRY
274848b8605Smrg_mesa_PixelMapusv(GLenum map, GLsizei mapsize, const GLushort *values )
275848b8605Smrg{
276848b8605Smrg   GLfloat fvalues[MAX_PIXEL_MAP_TABLE];
277848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
278848b8605Smrg
279848b8605Smrg   if (mapsize < 1 || mapsize > MAX_PIXEL_MAP_TABLE) {
280848b8605Smrg      _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapusv(mapsize)" );
281848b8605Smrg      return;
282848b8605Smrg   }
283848b8605Smrg
284848b8605Smrg   if (map >= GL_PIXEL_MAP_S_TO_S && map <= GL_PIXEL_MAP_I_TO_A) {
285848b8605Smrg      /* test that mapsize is a power of two */
286848b8605Smrg      if (!_mesa_is_pow_two(mapsize)) {
287848b8605Smrg	 _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapuiv(mapsize)" );
288848b8605Smrg         return;
289848b8605Smrg      }
290848b8605Smrg   }
291848b8605Smrg
292848b8605Smrg   FLUSH_VERTICES(ctx, _NEW_PIXEL);
293848b8605Smrg
294848b8605Smrg   if (!validate_pbo_access(ctx, &ctx->Unpack, mapsize, GL_INTENSITY,
295848b8605Smrg                            GL_UNSIGNED_SHORT, INT_MAX, values)) {
296848b8605Smrg      return;
297848b8605Smrg   }
298848b8605Smrg
299848b8605Smrg   values = (const GLushort *) _mesa_map_pbo_source(ctx, &ctx->Unpack, values);
300848b8605Smrg   if (!values) {
301848b8605Smrg      if (_mesa_is_bufferobj(ctx->Unpack.BufferObj)) {
302848b8605Smrg         _mesa_error(ctx, GL_INVALID_OPERATION,
303848b8605Smrg                     "glPixelMapusv(PBO is mapped)");
304848b8605Smrg      }
305848b8605Smrg      return;
306848b8605Smrg   }
307848b8605Smrg
308848b8605Smrg   /* convert to floats */
309848b8605Smrg   if (map == GL_PIXEL_MAP_I_TO_I || map == GL_PIXEL_MAP_S_TO_S) {
310848b8605Smrg      GLint i;
311848b8605Smrg      for (i = 0; i < mapsize; i++) {
312848b8605Smrg         fvalues[i] = (GLfloat) values[i];
313848b8605Smrg      }
314848b8605Smrg   }
315848b8605Smrg   else {
316848b8605Smrg      GLint i;
317848b8605Smrg      for (i = 0; i < mapsize; i++) {
318848b8605Smrg         fvalues[i] = USHORT_TO_FLOAT( values[i] );
319848b8605Smrg      }
320848b8605Smrg   }
321848b8605Smrg
322848b8605Smrg   _mesa_unmap_pbo_source(ctx, &ctx->Unpack);
323848b8605Smrg
324848b8605Smrg   store_pixelmap(ctx, map, mapsize, fvalues);
325848b8605Smrg}
326848b8605Smrg
327848b8605Smrg
328848b8605Smrgvoid GLAPIENTRY
329848b8605Smrg_mesa_GetnPixelMapfvARB( GLenum map, GLsizei bufSize, GLfloat *values )
330848b8605Smrg{
331848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
332848b8605Smrg   GLint mapsize, i;
333848b8605Smrg   const struct gl_pixelmap *pm;
334848b8605Smrg
335848b8605Smrg   pm = get_pixelmap(ctx, map);
336848b8605Smrg   if (!pm) {
337848b8605Smrg      _mesa_error(ctx, GL_INVALID_ENUM, "glGetPixelMapfv(map)");
338848b8605Smrg      return;
339848b8605Smrg   }
340848b8605Smrg
341848b8605Smrg   mapsize = pm->Size;
342848b8605Smrg
343848b8605Smrg   if (!validate_pbo_access(ctx, &ctx->Pack, mapsize, GL_INTENSITY,
344848b8605Smrg                            GL_FLOAT, bufSize, values)) {
345848b8605Smrg      return;
346848b8605Smrg   }
347848b8605Smrg
348848b8605Smrg   values = (GLfloat *) _mesa_map_pbo_dest(ctx, &ctx->Pack, values);
349848b8605Smrg   if (!values) {
350848b8605Smrg      if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
351848b8605Smrg         _mesa_error(ctx, GL_INVALID_OPERATION,
352848b8605Smrg                     "glGetPixelMapfv(PBO is mapped)");
353848b8605Smrg      }
354848b8605Smrg      return;
355848b8605Smrg   }
356848b8605Smrg
357848b8605Smrg   if (map == GL_PIXEL_MAP_S_TO_S) {
358848b8605Smrg      /* special case */
359848b8605Smrg      for (i = 0; i < mapsize; i++) {
360848b8605Smrg         values[i] = (GLfloat) ctx->PixelMaps.StoS.Map[i];
361848b8605Smrg      }
362848b8605Smrg   }
363848b8605Smrg   else {
364848b8605Smrg      memcpy(values, pm->Map, mapsize * sizeof(GLfloat));
365848b8605Smrg   }
366848b8605Smrg
367848b8605Smrg   _mesa_unmap_pbo_dest(ctx, &ctx->Pack);
368848b8605Smrg}
369848b8605Smrg
370848b8605Smrg
371848b8605Smrgvoid GLAPIENTRY
372848b8605Smrg_mesa_GetPixelMapfv( GLenum map, GLfloat *values )
373848b8605Smrg{
374848b8605Smrg   _mesa_GetnPixelMapfvARB(map, INT_MAX, values);
375848b8605Smrg}
376848b8605Smrg
377848b8605Smrgvoid GLAPIENTRY
378848b8605Smrg_mesa_GetnPixelMapuivARB( GLenum map, GLsizei bufSize, GLuint *values )
379848b8605Smrg{
380848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
381848b8605Smrg   GLint mapsize, i;
382848b8605Smrg   const struct gl_pixelmap *pm;
383848b8605Smrg
384848b8605Smrg   pm = get_pixelmap(ctx, map);
385848b8605Smrg   if (!pm) {
386848b8605Smrg      _mesa_error(ctx, GL_INVALID_ENUM, "glGetPixelMapuiv(map)");
387848b8605Smrg      return;
388848b8605Smrg   }
389848b8605Smrg
390848b8605Smrg   mapsize = pm->Size;
391848b8605Smrg
392848b8605Smrg   if (!validate_pbo_access(ctx, &ctx->Pack, mapsize, GL_INTENSITY,
393848b8605Smrg                            GL_UNSIGNED_INT, bufSize, values)) {
394848b8605Smrg      return;
395848b8605Smrg   }
396848b8605Smrg
397848b8605Smrg   values = (GLuint *) _mesa_map_pbo_dest(ctx, &ctx->Pack, values);
398848b8605Smrg   if (!values) {
399848b8605Smrg      if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
400848b8605Smrg         _mesa_error(ctx, GL_INVALID_OPERATION,
401848b8605Smrg                     "glGetPixelMapuiv(PBO is mapped)");
402848b8605Smrg      }
403848b8605Smrg      return;
404848b8605Smrg   }
405848b8605Smrg
406848b8605Smrg   if (map == GL_PIXEL_MAP_S_TO_S) {
407848b8605Smrg      /* special case */
408848b8605Smrg      memcpy(values, ctx->PixelMaps.StoS.Map, mapsize * sizeof(GLint));
409848b8605Smrg   }
410848b8605Smrg   else {
411848b8605Smrg      for (i = 0; i < mapsize; i++) {
412848b8605Smrg         values[i] = FLOAT_TO_UINT( pm->Map[i] );
413848b8605Smrg      }
414848b8605Smrg   }
415848b8605Smrg
416848b8605Smrg   _mesa_unmap_pbo_dest(ctx, &ctx->Pack);
417848b8605Smrg}
418848b8605Smrg
419848b8605Smrg
420848b8605Smrgvoid GLAPIENTRY
421848b8605Smrg_mesa_GetPixelMapuiv( GLenum map, GLuint *values )
422848b8605Smrg{
423848b8605Smrg   _mesa_GetnPixelMapuivARB(map, INT_MAX, values);
424848b8605Smrg}
425848b8605Smrg
426848b8605Smrgvoid GLAPIENTRY
427848b8605Smrg_mesa_GetnPixelMapusvARB( GLenum map, GLsizei bufSize, GLushort *values )
428848b8605Smrg{
429848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
430848b8605Smrg   GLint mapsize, i;
431848b8605Smrg   const struct gl_pixelmap *pm;
432848b8605Smrg
433848b8605Smrg   pm = get_pixelmap(ctx, map);
434848b8605Smrg   if (!pm) {
435848b8605Smrg      _mesa_error(ctx, GL_INVALID_ENUM, "glGetPixelMapusv(map)");
436848b8605Smrg      return;
437848b8605Smrg   }
438848b8605Smrg
439848b8605Smrg   mapsize = pm->Size;
440848b8605Smrg
441848b8605Smrg   if (!validate_pbo_access(ctx, &ctx->Pack, mapsize, GL_INTENSITY,
442848b8605Smrg                            GL_UNSIGNED_SHORT, bufSize, values)) {
443848b8605Smrg      return;
444848b8605Smrg   }
445848b8605Smrg
446848b8605Smrg   values = (GLushort *) _mesa_map_pbo_dest(ctx, &ctx->Pack, values);
447848b8605Smrg   if (!values) {
448848b8605Smrg      if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
449848b8605Smrg         _mesa_error(ctx, GL_INVALID_OPERATION,
450848b8605Smrg                     "glGetPixelMapusv(PBO is mapped)");
451848b8605Smrg      }
452848b8605Smrg      return;
453848b8605Smrg   }
454848b8605Smrg
455848b8605Smrg   switch (map) {
456848b8605Smrg   /* special cases */
457848b8605Smrg   case GL_PIXEL_MAP_I_TO_I:
458848b8605Smrg      for (i = 0; i < mapsize; i++) {
459848b8605Smrg         values[i] = (GLushort) CLAMP(ctx->PixelMaps.ItoI.Map[i], 0.0, 65535.);
460848b8605Smrg      }
461848b8605Smrg      break;
462848b8605Smrg   case GL_PIXEL_MAP_S_TO_S:
463848b8605Smrg      for (i = 0; i < mapsize; i++) {
464848b8605Smrg         values[i] = (GLushort) CLAMP(ctx->PixelMaps.StoS.Map[i], 0.0, 65535.);
465848b8605Smrg      }
466848b8605Smrg      break;
467848b8605Smrg   default:
468848b8605Smrg      for (i = 0; i < mapsize; i++) {
469848b8605Smrg         CLAMPED_FLOAT_TO_USHORT(values[i], pm->Map[i] );
470848b8605Smrg      }
471848b8605Smrg   }
472848b8605Smrg
473848b8605Smrg   _mesa_unmap_pbo_dest(ctx, &ctx->Pack);
474848b8605Smrg}
475848b8605Smrg
476848b8605Smrg
477848b8605Smrgvoid GLAPIENTRY
478848b8605Smrg_mesa_GetPixelMapusv( GLenum map, GLushort *values )
479848b8605Smrg{
480848b8605Smrg   _mesa_GetnPixelMapusvARB(map, INT_MAX, values);
481848b8605Smrg}
482848b8605Smrg
483848b8605Smrg
484848b8605Smrg/**********************************************************************/
485848b8605Smrg/*****                       glPixelTransfer                      *****/
486848b8605Smrg/**********************************************************************/
487848b8605Smrg
488848b8605Smrg
489848b8605Smrg/*
490848b8605Smrg * Implements glPixelTransfer[fi] whether called immediately or from a
491848b8605Smrg * display list.
492848b8605Smrg */
493848b8605Smrgvoid GLAPIENTRY
494848b8605Smrg_mesa_PixelTransferf( GLenum pname, GLfloat param )
495848b8605Smrg{
496848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
497848b8605Smrg
498848b8605Smrg   switch (pname) {
499848b8605Smrg      case GL_MAP_COLOR:
500848b8605Smrg         if (ctx->Pixel.MapColorFlag == (param ? GL_TRUE : GL_FALSE))
501848b8605Smrg	    return;
502848b8605Smrg	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
503848b8605Smrg         ctx->Pixel.MapColorFlag = param ? GL_TRUE : GL_FALSE;
504848b8605Smrg	 break;
505848b8605Smrg      case GL_MAP_STENCIL:
506848b8605Smrg         if (ctx->Pixel.MapStencilFlag == (param ? GL_TRUE : GL_FALSE))
507848b8605Smrg	    return;
508848b8605Smrg	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
509848b8605Smrg         ctx->Pixel.MapStencilFlag = param ? GL_TRUE : GL_FALSE;
510848b8605Smrg	 break;
511848b8605Smrg      case GL_INDEX_SHIFT:
512848b8605Smrg         if (ctx->Pixel.IndexShift == (GLint) param)
513848b8605Smrg	    return;
514848b8605Smrg	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
515848b8605Smrg         ctx->Pixel.IndexShift = (GLint) param;
516848b8605Smrg	 break;
517848b8605Smrg      case GL_INDEX_OFFSET:
518848b8605Smrg         if (ctx->Pixel.IndexOffset == (GLint) param)
519848b8605Smrg	    return;
520848b8605Smrg	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
521848b8605Smrg         ctx->Pixel.IndexOffset = (GLint) param;
522848b8605Smrg	 break;
523848b8605Smrg      case GL_RED_SCALE:
524848b8605Smrg         if (ctx->Pixel.RedScale == param)
525848b8605Smrg	    return;
526848b8605Smrg	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
527848b8605Smrg         ctx->Pixel.RedScale = param;
528848b8605Smrg	 break;
529848b8605Smrg      case GL_RED_BIAS:
530848b8605Smrg         if (ctx->Pixel.RedBias == param)
531848b8605Smrg	    return;
532848b8605Smrg	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
533848b8605Smrg         ctx->Pixel.RedBias = param;
534848b8605Smrg	 break;
535848b8605Smrg      case GL_GREEN_SCALE:
536848b8605Smrg         if (ctx->Pixel.GreenScale == param)
537848b8605Smrg	    return;
538848b8605Smrg	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
539848b8605Smrg         ctx->Pixel.GreenScale = param;
540848b8605Smrg	 break;
541848b8605Smrg      case GL_GREEN_BIAS:
542848b8605Smrg         if (ctx->Pixel.GreenBias == param)
543848b8605Smrg	    return;
544848b8605Smrg	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
545848b8605Smrg         ctx->Pixel.GreenBias = param;
546848b8605Smrg	 break;
547848b8605Smrg      case GL_BLUE_SCALE:
548848b8605Smrg         if (ctx->Pixel.BlueScale == param)
549848b8605Smrg	    return;
550848b8605Smrg	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
551848b8605Smrg         ctx->Pixel.BlueScale = param;
552848b8605Smrg	 break;
553848b8605Smrg      case GL_BLUE_BIAS:
554848b8605Smrg         if (ctx->Pixel.BlueBias == param)
555848b8605Smrg	    return;
556848b8605Smrg	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
557848b8605Smrg         ctx->Pixel.BlueBias = param;
558848b8605Smrg	 break;
559848b8605Smrg      case GL_ALPHA_SCALE:
560848b8605Smrg         if (ctx->Pixel.AlphaScale == param)
561848b8605Smrg	    return;
562848b8605Smrg	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
563848b8605Smrg         ctx->Pixel.AlphaScale = param;
564848b8605Smrg	 break;
565848b8605Smrg      case GL_ALPHA_BIAS:
566848b8605Smrg         if (ctx->Pixel.AlphaBias == param)
567848b8605Smrg	    return;
568848b8605Smrg	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
569848b8605Smrg         ctx->Pixel.AlphaBias = param;
570848b8605Smrg	 break;
571848b8605Smrg      case GL_DEPTH_SCALE:
572848b8605Smrg         if (ctx->Pixel.DepthScale == param)
573848b8605Smrg	    return;
574848b8605Smrg	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
575848b8605Smrg         ctx->Pixel.DepthScale = param;
576848b8605Smrg	 break;
577848b8605Smrg      case GL_DEPTH_BIAS:
578848b8605Smrg         if (ctx->Pixel.DepthBias == param)
579848b8605Smrg	    return;
580848b8605Smrg	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
581848b8605Smrg         ctx->Pixel.DepthBias = param;
582848b8605Smrg	 break;
583848b8605Smrg      default:
584848b8605Smrg         _mesa_error( ctx, GL_INVALID_ENUM, "glPixelTransfer(pname)" );
585848b8605Smrg         return;
586848b8605Smrg   }
587848b8605Smrg}
588848b8605Smrg
589848b8605Smrg
590848b8605Smrgvoid GLAPIENTRY
591848b8605Smrg_mesa_PixelTransferi( GLenum pname, GLint param )
592848b8605Smrg{
593848b8605Smrg   _mesa_PixelTransferf( pname, (GLfloat) param );
594848b8605Smrg}
595848b8605Smrg
596848b8605Smrg
597848b8605Smrg
598848b8605Smrg/**********************************************************************/
599848b8605Smrg/*****                    State Management                        *****/
600848b8605Smrg/**********************************************************************/
601848b8605Smrg
602848b8605Smrg/*
603848b8605Smrg * Return a bitmask of IMAGE_*_BIT flags which to indicate which
604848b8605Smrg * pixel transfer operations are enabled.
605848b8605Smrg */
606848b8605Smrgstatic void
607848b8605Smrgupdate_image_transfer_state(struct gl_context *ctx)
608848b8605Smrg{
609848b8605Smrg   GLuint mask = 0;
610848b8605Smrg
611848b8605Smrg   if (ctx->Pixel.RedScale   != 1.0F || ctx->Pixel.RedBias   != 0.0F ||
612848b8605Smrg       ctx->Pixel.GreenScale != 1.0F || ctx->Pixel.GreenBias != 0.0F ||
613848b8605Smrg       ctx->Pixel.BlueScale  != 1.0F || ctx->Pixel.BlueBias  != 0.0F ||
614848b8605Smrg       ctx->Pixel.AlphaScale != 1.0F || ctx->Pixel.AlphaBias != 0.0F)
615848b8605Smrg      mask |= IMAGE_SCALE_BIAS_BIT;
616848b8605Smrg
617848b8605Smrg   if (ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset)
618848b8605Smrg      mask |= IMAGE_SHIFT_OFFSET_BIT;
619848b8605Smrg
620848b8605Smrg   if (ctx->Pixel.MapColorFlag)
621848b8605Smrg      mask |= IMAGE_MAP_COLOR_BIT;
622848b8605Smrg
623848b8605Smrg   ctx->_ImageTransferState = mask;
624848b8605Smrg}
625848b8605Smrg
626848b8605Smrg
627848b8605Smrg/**
628848b8605Smrg * Update mesa pixel transfer derived state.
629848b8605Smrg */
630848b8605Smrgvoid _mesa_update_pixel( struct gl_context *ctx, GLuint new_state )
631848b8605Smrg{
632848b8605Smrg   if (new_state & _NEW_PIXEL)
633848b8605Smrg      update_image_transfer_state(ctx);
634848b8605Smrg}
635848b8605Smrg
636848b8605Smrg
637848b8605Smrg/**********************************************************************/
638848b8605Smrg/*****                      Initialization                        *****/
639848b8605Smrg/**********************************************************************/
640848b8605Smrg
641848b8605Smrgstatic void
642848b8605Smrginit_pixelmap(struct gl_pixelmap *map)
643848b8605Smrg{
644848b8605Smrg   map->Size = 1;
645848b8605Smrg   map->Map[0] = 0.0;
646848b8605Smrg}
647848b8605Smrg
648848b8605Smrg
649848b8605Smrg/**
650848b8605Smrg * Initialize the context's PIXEL attribute group.
651848b8605Smrg */
652848b8605Smrgvoid
653848b8605Smrg_mesa_init_pixel( struct gl_context *ctx )
654848b8605Smrg{
655848b8605Smrg   /* Pixel group */
656848b8605Smrg   ctx->Pixel.RedBias = 0.0;
657848b8605Smrg   ctx->Pixel.RedScale = 1.0;
658848b8605Smrg   ctx->Pixel.GreenBias = 0.0;
659848b8605Smrg   ctx->Pixel.GreenScale = 1.0;
660848b8605Smrg   ctx->Pixel.BlueBias = 0.0;
661848b8605Smrg   ctx->Pixel.BlueScale = 1.0;
662848b8605Smrg   ctx->Pixel.AlphaBias = 0.0;
663848b8605Smrg   ctx->Pixel.AlphaScale = 1.0;
664848b8605Smrg   ctx->Pixel.DepthBias = 0.0;
665848b8605Smrg   ctx->Pixel.DepthScale = 1.0;
666848b8605Smrg   ctx->Pixel.IndexOffset = 0;
667848b8605Smrg   ctx->Pixel.IndexShift = 0;
668848b8605Smrg   ctx->Pixel.ZoomX = 1.0;
669848b8605Smrg   ctx->Pixel.ZoomY = 1.0;
670848b8605Smrg   ctx->Pixel.MapColorFlag = GL_FALSE;
671848b8605Smrg   ctx->Pixel.MapStencilFlag = GL_FALSE;
672848b8605Smrg   init_pixelmap(&ctx->PixelMaps.StoS);
673848b8605Smrg   init_pixelmap(&ctx->PixelMaps.ItoI);
674848b8605Smrg   init_pixelmap(&ctx->PixelMaps.ItoR);
675848b8605Smrg   init_pixelmap(&ctx->PixelMaps.ItoG);
676848b8605Smrg   init_pixelmap(&ctx->PixelMaps.ItoB);
677848b8605Smrg   init_pixelmap(&ctx->PixelMaps.ItoA);
678848b8605Smrg   init_pixelmap(&ctx->PixelMaps.RtoR);
679848b8605Smrg   init_pixelmap(&ctx->PixelMaps.GtoG);
680848b8605Smrg   init_pixelmap(&ctx->PixelMaps.BtoB);
681848b8605Smrg   init_pixelmap(&ctx->PixelMaps.AtoA);
682848b8605Smrg
683848b8605Smrg   if (ctx->Visual.doubleBufferMode) {
684848b8605Smrg      ctx->Pixel.ReadBuffer = GL_BACK;
685848b8605Smrg   }
686848b8605Smrg   else {
687848b8605Smrg      ctx->Pixel.ReadBuffer = GL_FRONT;
688848b8605Smrg   }
689848b8605Smrg
690848b8605Smrg   /* Miscellaneous */
691848b8605Smrg   ctx->_ImageTransferState = 0;
692848b8605Smrg}
693