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