2 * Mesa 3-D graphics library
4 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
28 * Pixel transfer functions (glPixelZoom, glPixelMap, glPixelTransfer)
33 #include "bufferobj.h"
41 /**********************************************************************/
42 /***** glPixelZoom *****/
43 /**********************************************************************/
46 _mesa_PixelZoom( GLfloat xfactor
, GLfloat yfactor
)
48 GET_CURRENT_CONTEXT(ctx
);
50 if (ctx
->Pixel
.ZoomX
== xfactor
&&
51 ctx
->Pixel
.ZoomY
== yfactor
)
54 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
55 ctx
->Pixel
.ZoomX
= xfactor
;
56 ctx
->Pixel
.ZoomY
= yfactor
;
61 /**********************************************************************/
62 /***** glPixelMap *****/
63 /**********************************************************************/
66 * Return pointer to a pixelmap by name.
68 static struct gl_pixelmap
*
69 get_pixelmap(struct gl_context
*ctx
, GLenum map
)
72 case GL_PIXEL_MAP_I_TO_I
:
73 return &ctx
->PixelMaps
.ItoI
;
74 case GL_PIXEL_MAP_S_TO_S
:
75 return &ctx
->PixelMaps
.StoS
;
76 case GL_PIXEL_MAP_I_TO_R
:
77 return &ctx
->PixelMaps
.ItoR
;
78 case GL_PIXEL_MAP_I_TO_G
:
79 return &ctx
->PixelMaps
.ItoG
;
80 case GL_PIXEL_MAP_I_TO_B
:
81 return &ctx
->PixelMaps
.ItoB
;
82 case GL_PIXEL_MAP_I_TO_A
:
83 return &ctx
->PixelMaps
.ItoA
;
84 case GL_PIXEL_MAP_R_TO_R
:
85 return &ctx
->PixelMaps
.RtoR
;
86 case GL_PIXEL_MAP_G_TO_G
:
87 return &ctx
->PixelMaps
.GtoG
;
88 case GL_PIXEL_MAP_B_TO_B
:
89 return &ctx
->PixelMaps
.BtoB
;
90 case GL_PIXEL_MAP_A_TO_A
:
91 return &ctx
->PixelMaps
.AtoA
;
99 * Helper routine used by the other _mesa_PixelMap() functions.
102 store_pixelmap(struct gl_context
*ctx
, GLenum map
, GLsizei mapsize
,
103 const GLfloat
*values
)
106 struct gl_pixelmap
*pm
= get_pixelmap(ctx
, map
);
108 _mesa_error(ctx
, GL_INVALID_ENUM
, "glPixelMap(map)");
113 case GL_PIXEL_MAP_S_TO_S
:
115 ctx
->PixelMaps
.StoS
.Size
= mapsize
;
116 for (i
= 0; i
< mapsize
; i
++) {
117 ctx
->PixelMaps
.StoS
.Map
[i
] = roundf(values
[i
]);
120 case GL_PIXEL_MAP_I_TO_I
:
122 ctx
->PixelMaps
.ItoI
.Size
= mapsize
;
123 for (i
= 0; i
< mapsize
; i
++) {
124 ctx
->PixelMaps
.ItoI
.Map
[i
] = values
[i
];
130 for (i
= 0; i
< mapsize
; i
++) {
131 GLfloat val
= CLAMP(values
[i
], 0.0F
, 1.0F
);
139 * Convenience wrapper for _mesa_validate_pbo_access() for gl[Get]PixelMap().
142 validate_pbo_access(struct gl_context
*ctx
,
143 struct gl_pixelstore_attrib
*pack
, GLsizei mapsize
,
144 GLenum format
, GLenum type
, GLsizei clientMemSize
,
149 /* Note, need to use DefaultPacking and Unpack's buffer object */
150 _mesa_reference_buffer_object(ctx
,
151 &ctx
->DefaultPacking
.BufferObj
,
154 ok
= _mesa_validate_pbo_access(1, &ctx
->DefaultPacking
, mapsize
, 1, 1,
155 format
, type
, clientMemSize
, ptr
);
158 _mesa_reference_buffer_object(ctx
,
159 &ctx
->DefaultPacking
.BufferObj
, NULL
);
162 if (pack
->BufferObj
) {
163 _mesa_error(ctx
, GL_INVALID_OPERATION
,
164 "gl[Get]PixelMap*v(out of bounds PBO access)");
166 _mesa_error(ctx
, GL_INVALID_OPERATION
,
167 "glGetnPixelMap*vARB(out of bounds access:"
168 " bufSize (%d) is too small)", clientMemSize
);
176 _mesa_PixelMapfv( GLenum map
, GLsizei mapsize
, const GLfloat
*values
)
178 GET_CURRENT_CONTEXT(ctx
);
180 /* XXX someday, test against ctx->Const.MaxPixelMapTableSize */
181 if (mapsize
< 1 || mapsize
> MAX_PIXEL_MAP_TABLE
) {
182 _mesa_error( ctx
, GL_INVALID_VALUE
, "glPixelMapfv(mapsize)" );
186 if (map
>= GL_PIXEL_MAP_S_TO_S
&& map
<= GL_PIXEL_MAP_I_TO_A
) {
187 /* test that mapsize is a power of two */
188 if (!util_is_power_of_two_or_zero(mapsize
)) {
189 _mesa_error( ctx
, GL_INVALID_VALUE
, "glPixelMapfv(mapsize)" );
194 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
196 if (!validate_pbo_access(ctx
, &ctx
->Unpack
, mapsize
, GL_INTENSITY
,
197 GL_FLOAT
, INT_MAX
, values
)) {
201 values
= (const GLfloat
*) _mesa_map_pbo_source(ctx
, &ctx
->Unpack
, values
);
203 if (ctx
->Unpack
.BufferObj
) {
204 _mesa_error(ctx
, GL_INVALID_OPERATION
,
205 "glPixelMapfv(PBO is mapped)");
210 store_pixelmap(ctx
, map
, mapsize
, values
);
212 _mesa_unmap_pbo_source(ctx
, &ctx
->Unpack
);
217 _mesa_PixelMapuiv(GLenum map
, GLsizei mapsize
, const GLuint
*values
)
219 GLfloat fvalues
[MAX_PIXEL_MAP_TABLE
];
220 GET_CURRENT_CONTEXT(ctx
);
222 if (mapsize
< 1 || mapsize
> MAX_PIXEL_MAP_TABLE
) {
223 _mesa_error( ctx
, GL_INVALID_VALUE
, "glPixelMapuiv(mapsize)" );
227 if (map
>= GL_PIXEL_MAP_S_TO_S
&& map
<= GL_PIXEL_MAP_I_TO_A
) {
228 /* test that mapsize is a power of two */
229 if (!util_is_power_of_two_or_zero(mapsize
)) {
230 _mesa_error( ctx
, GL_INVALID_VALUE
, "glPixelMapuiv(mapsize)" );
235 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
237 if (!validate_pbo_access(ctx
, &ctx
->Unpack
, mapsize
, GL_INTENSITY
,
238 GL_UNSIGNED_INT
, INT_MAX
, values
)) {
242 values
= (const GLuint
*) _mesa_map_pbo_source(ctx
, &ctx
->Unpack
, values
);
244 if (ctx
->Unpack
.BufferObj
) {
245 _mesa_error(ctx
, GL_INVALID_OPERATION
,
246 "glPixelMapuiv(PBO is mapped)");
251 /* convert to floats */
252 if (map
== GL_PIXEL_MAP_I_TO_I
|| map
== GL_PIXEL_MAP_S_TO_S
) {
254 for (i
= 0; i
< mapsize
; i
++) {
255 fvalues
[i
] = (GLfloat
) values
[i
];
260 for (i
= 0; i
< mapsize
; i
++) {
261 fvalues
[i
] = UINT_TO_FLOAT( values
[i
] );
265 _mesa_unmap_pbo_source(ctx
, &ctx
->Unpack
);
267 store_pixelmap(ctx
, map
, mapsize
, fvalues
);
272 _mesa_PixelMapusv(GLenum map
, GLsizei mapsize
, const GLushort
*values
)
274 GLfloat fvalues
[MAX_PIXEL_MAP_TABLE
];
275 GET_CURRENT_CONTEXT(ctx
);
277 if (mapsize
< 1 || mapsize
> MAX_PIXEL_MAP_TABLE
) {
278 _mesa_error( ctx
, GL_INVALID_VALUE
, "glPixelMapusv(mapsize)" );
282 if (map
>= GL_PIXEL_MAP_S_TO_S
&& map
<= GL_PIXEL_MAP_I_TO_A
) {
283 /* test that mapsize is a power of two */
284 if (!util_is_power_of_two_or_zero(mapsize
)) {
285 _mesa_error( ctx
, GL_INVALID_VALUE
, "glPixelMapusv(mapsize)" );
290 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
292 if (!validate_pbo_access(ctx
, &ctx
->Unpack
, mapsize
, GL_INTENSITY
,
293 GL_UNSIGNED_SHORT
, INT_MAX
, values
)) {
297 values
= (const GLushort
*) _mesa_map_pbo_source(ctx
, &ctx
->Unpack
, values
);
299 if (ctx
->Unpack
.BufferObj
) {
300 _mesa_error(ctx
, GL_INVALID_OPERATION
,
301 "glPixelMapusv(PBO is mapped)");
306 /* convert to floats */
307 if (map
== GL_PIXEL_MAP_I_TO_I
|| map
== GL_PIXEL_MAP_S_TO_S
) {
309 for (i
= 0; i
< mapsize
; i
++) {
310 fvalues
[i
] = (GLfloat
) values
[i
];
315 for (i
= 0; i
< mapsize
; i
++) {
316 fvalues
[i
] = USHORT_TO_FLOAT( values
[i
] );
320 _mesa_unmap_pbo_source(ctx
, &ctx
->Unpack
);
322 store_pixelmap(ctx
, map
, mapsize
, fvalues
);
327 _mesa_GetnPixelMapfvARB( GLenum map
, GLsizei bufSize
, GLfloat
*values
)
329 GET_CURRENT_CONTEXT(ctx
);
331 const struct gl_pixelmap
*pm
;
333 pm
= get_pixelmap(ctx
, map
);
335 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetPixelMapfv(map)");
341 if (!validate_pbo_access(ctx
, &ctx
->Pack
, mapsize
, GL_INTENSITY
,
342 GL_FLOAT
, bufSize
, values
)) {
346 values
= (GLfloat
*) _mesa_map_pbo_dest(ctx
, &ctx
->Pack
, values
);
348 if (ctx
->Pack
.BufferObj
) {
349 _mesa_error(ctx
, GL_INVALID_OPERATION
,
350 "glGetPixelMapfv(PBO is mapped)");
355 if (map
== GL_PIXEL_MAP_S_TO_S
) {
357 for (i
= 0; i
< mapsize
; i
++) {
358 values
[i
] = (GLfloat
) ctx
->PixelMaps
.StoS
.Map
[i
];
362 memcpy(values
, pm
->Map
, mapsize
* sizeof(GLfloat
));
365 _mesa_unmap_pbo_dest(ctx
, &ctx
->Pack
);
370 _mesa_GetPixelMapfv( GLenum map
, GLfloat
*values
)
372 _mesa_GetnPixelMapfvARB(map
, INT_MAX
, values
);
376 _mesa_GetnPixelMapuivARB( GLenum map
, GLsizei bufSize
, GLuint
*values
)
378 GET_CURRENT_CONTEXT(ctx
);
380 const struct gl_pixelmap
*pm
;
382 pm
= get_pixelmap(ctx
, map
);
384 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetPixelMapuiv(map)");
390 if (!validate_pbo_access(ctx
, &ctx
->Pack
, mapsize
, GL_INTENSITY
,
391 GL_UNSIGNED_INT
, bufSize
, values
)) {
395 values
= (GLuint
*) _mesa_map_pbo_dest(ctx
, &ctx
->Pack
, values
);
397 if (ctx
->Pack
.BufferObj
) {
398 _mesa_error(ctx
, GL_INVALID_OPERATION
,
399 "glGetPixelMapuiv(PBO is mapped)");
404 if (map
== GL_PIXEL_MAP_S_TO_S
) {
406 memcpy(values
, ctx
->PixelMaps
.StoS
.Map
, mapsize
* sizeof(GLint
));
409 for (i
= 0; i
< mapsize
; i
++) {
410 values
[i
] = FLOAT_TO_UINT( pm
->Map
[i
] );
414 _mesa_unmap_pbo_dest(ctx
, &ctx
->Pack
);
419 _mesa_GetPixelMapuiv( GLenum map
, GLuint
*values
)
421 _mesa_GetnPixelMapuivARB(map
, INT_MAX
, values
);
425 _mesa_GetnPixelMapusvARB( GLenum map
, GLsizei bufSize
, GLushort
*values
)
427 GET_CURRENT_CONTEXT(ctx
);
429 const struct gl_pixelmap
*pm
;
431 pm
= get_pixelmap(ctx
, map
);
433 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetPixelMapusv(map)");
439 if (!validate_pbo_access(ctx
, &ctx
->Pack
, mapsize
, GL_INTENSITY
,
440 GL_UNSIGNED_SHORT
, bufSize
, values
)) {
444 values
= (GLushort
*) _mesa_map_pbo_dest(ctx
, &ctx
->Pack
, values
);
446 if (ctx
->Pack
.BufferObj
) {
447 _mesa_error(ctx
, GL_INVALID_OPERATION
,
448 "glGetPixelMapusv(PBO is mapped)");
455 case GL_PIXEL_MAP_I_TO_I
:
456 for (i
= 0; i
< mapsize
; i
++) {
457 values
[i
] = (GLushort
) CLAMP(ctx
->PixelMaps
.ItoI
.Map
[i
], 0.0F
, 65535.0F
);
460 case GL_PIXEL_MAP_S_TO_S
:
461 for (i
= 0; i
< mapsize
; i
++) {
462 values
[i
] = (GLushort
) CLAMP(ctx
->PixelMaps
.StoS
.Map
[i
], 0.0F
, 65535.0F
);
466 for (i
= 0; i
< mapsize
; i
++) {
467 CLAMPED_FLOAT_TO_USHORT(values
[i
], pm
->Map
[i
] );
471 _mesa_unmap_pbo_dest(ctx
, &ctx
->Pack
);
476 _mesa_GetPixelMapusv( GLenum map
, GLushort
*values
)
478 _mesa_GetnPixelMapusvARB(map
, INT_MAX
, values
);
482 /**********************************************************************/
483 /***** glPixelTransfer *****/
484 /**********************************************************************/
488 * Implements glPixelTransfer[fi] whether called immediately or from a
492 _mesa_PixelTransferf( GLenum pname
, GLfloat param
)
494 GET_CURRENT_CONTEXT(ctx
);
498 if (ctx
->Pixel
.MapColorFlag
== (param
? GL_TRUE
: GL_FALSE
))
500 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
501 ctx
->Pixel
.MapColorFlag
= param
? GL_TRUE
: GL_FALSE
;
504 if (ctx
->Pixel
.MapStencilFlag
== (param
? GL_TRUE
: GL_FALSE
))
506 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
507 ctx
->Pixel
.MapStencilFlag
= param
? GL_TRUE
: GL_FALSE
;
510 if (ctx
->Pixel
.IndexShift
== (GLint
) param
)
512 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
513 ctx
->Pixel
.IndexShift
= (GLint
) param
;
515 case GL_INDEX_OFFSET
:
516 if (ctx
->Pixel
.IndexOffset
== (GLint
) param
)
518 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
519 ctx
->Pixel
.IndexOffset
= (GLint
) param
;
522 if (ctx
->Pixel
.RedScale
== param
)
524 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
525 ctx
->Pixel
.RedScale
= param
;
528 if (ctx
->Pixel
.RedBias
== param
)
530 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
531 ctx
->Pixel
.RedBias
= param
;
534 if (ctx
->Pixel
.GreenScale
== param
)
536 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
537 ctx
->Pixel
.GreenScale
= param
;
540 if (ctx
->Pixel
.GreenBias
== param
)
542 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
543 ctx
->Pixel
.GreenBias
= param
;
546 if (ctx
->Pixel
.BlueScale
== param
)
548 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
549 ctx
->Pixel
.BlueScale
= param
;
552 if (ctx
->Pixel
.BlueBias
== param
)
554 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
555 ctx
->Pixel
.BlueBias
= param
;
558 if (ctx
->Pixel
.AlphaScale
== param
)
560 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
561 ctx
->Pixel
.AlphaScale
= param
;
564 if (ctx
->Pixel
.AlphaBias
== param
)
566 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
567 ctx
->Pixel
.AlphaBias
= param
;
570 if (ctx
->Pixel
.DepthScale
== param
)
572 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
573 ctx
->Pixel
.DepthScale
= param
;
576 if (ctx
->Pixel
.DepthBias
== param
)
578 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
579 ctx
->Pixel
.DepthBias
= param
;
582 _mesa_error( ctx
, GL_INVALID_ENUM
, "glPixelTransfer(pname)" );
589 _mesa_PixelTransferi( GLenum pname
, GLint param
)
591 _mesa_PixelTransferf( pname
, (GLfloat
) param
);
596 /**********************************************************************/
597 /***** State Management *****/
598 /**********************************************************************/
602 * Update mesa pixel transfer derived state to indicate which operations are
606 _mesa_update_pixel( struct gl_context
*ctx
)
610 if (ctx
->Pixel
.RedScale
!= 1.0F
|| ctx
->Pixel
.RedBias
!= 0.0F
||
611 ctx
->Pixel
.GreenScale
!= 1.0F
|| ctx
->Pixel
.GreenBias
!= 0.0F
||
612 ctx
->Pixel
.BlueScale
!= 1.0F
|| ctx
->Pixel
.BlueBias
!= 0.0F
||
613 ctx
->Pixel
.AlphaScale
!= 1.0F
|| ctx
->Pixel
.AlphaBias
!= 0.0F
)
614 mask
|= IMAGE_SCALE_BIAS_BIT
;
616 if (ctx
->Pixel
.IndexShift
|| ctx
->Pixel
.IndexOffset
)
617 mask
|= IMAGE_SHIFT_OFFSET_BIT
;
619 if (ctx
->Pixel
.MapColorFlag
)
620 mask
|= IMAGE_MAP_COLOR_BIT
;
622 ctx
->_ImageTransferState
= mask
;
626 /**********************************************************************/
627 /***** Initialization *****/
628 /**********************************************************************/
631 init_pixelmap(struct gl_pixelmap
*map
)
639 * Initialize the context's PIXEL attribute group.
642 _mesa_init_pixel( struct gl_context
*ctx
)
645 ctx
->Pixel
.RedBias
= 0.0;
646 ctx
->Pixel
.RedScale
= 1.0;
647 ctx
->Pixel
.GreenBias
= 0.0;
648 ctx
->Pixel
.GreenScale
= 1.0;
649 ctx
->Pixel
.BlueBias
= 0.0;
650 ctx
->Pixel
.BlueScale
= 1.0;
651 ctx
->Pixel
.AlphaBias
= 0.0;
652 ctx
->Pixel
.AlphaScale
= 1.0;
653 ctx
->Pixel
.DepthBias
= 0.0;
654 ctx
->Pixel
.DepthScale
= 1.0;
655 ctx
->Pixel
.IndexOffset
= 0;
656 ctx
->Pixel
.IndexShift
= 0;
657 ctx
->Pixel
.ZoomX
= 1.0;
658 ctx
->Pixel
.ZoomY
= 1.0;
659 ctx
->Pixel
.MapColorFlag
= GL_FALSE
;
660 ctx
->Pixel
.MapStencilFlag
= GL_FALSE
;
661 init_pixelmap(&ctx
->PixelMaps
.StoS
);
662 init_pixelmap(&ctx
->PixelMaps
.ItoI
);
663 init_pixelmap(&ctx
->PixelMaps
.ItoR
);
664 init_pixelmap(&ctx
->PixelMaps
.ItoG
);
665 init_pixelmap(&ctx
->PixelMaps
.ItoB
);
666 init_pixelmap(&ctx
->PixelMaps
.ItoA
);
667 init_pixelmap(&ctx
->PixelMaps
.RtoR
);
668 init_pixelmap(&ctx
->PixelMaps
.GtoG
);
669 init_pixelmap(&ctx
->PixelMaps
.BtoB
);
670 init_pixelmap(&ctx
->PixelMaps
.AtoA
);
672 if (ctx
->Visual
.doubleBufferMode
) {
673 ctx
->Pixel
.ReadBuffer
= GL_BACK
;
676 ctx
->Pixel
.ReadBuffer
= GL_FRONT
;
680 ctx
->_ImageTransferState
= 0;