2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
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:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
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 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 * OTHER DEALINGS IN THE SOFTWARE.
29 * Pixel transfer functions (glPixelZoom, glPixelMap, glPixelTransfer)
33 #include "bufferobj.h"
40 #include "main/dispatch.h"
43 /**********************************************************************/
44 /***** glPixelZoom *****/
45 /**********************************************************************/
48 _mesa_PixelZoom( GLfloat xfactor
, GLfloat yfactor
)
50 GET_CURRENT_CONTEXT(ctx
);
52 if (ctx
->Pixel
.ZoomX
== xfactor
&&
53 ctx
->Pixel
.ZoomY
== yfactor
)
56 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
57 ctx
->Pixel
.ZoomX
= xfactor
;
58 ctx
->Pixel
.ZoomY
= yfactor
;
63 /**********************************************************************/
64 /***** glPixelMap *****/
65 /**********************************************************************/
68 * Return pointer to a pixelmap by name.
70 static struct gl_pixelmap
*
71 get_pixelmap(struct gl_context
*ctx
, GLenum map
)
74 case GL_PIXEL_MAP_I_TO_I
:
75 return &ctx
->PixelMaps
.ItoI
;
76 case GL_PIXEL_MAP_S_TO_S
:
77 return &ctx
->PixelMaps
.StoS
;
78 case GL_PIXEL_MAP_I_TO_R
:
79 return &ctx
->PixelMaps
.ItoR
;
80 case GL_PIXEL_MAP_I_TO_G
:
81 return &ctx
->PixelMaps
.ItoG
;
82 case GL_PIXEL_MAP_I_TO_B
:
83 return &ctx
->PixelMaps
.ItoB
;
84 case GL_PIXEL_MAP_I_TO_A
:
85 return &ctx
->PixelMaps
.ItoA
;
86 case GL_PIXEL_MAP_R_TO_R
:
87 return &ctx
->PixelMaps
.RtoR
;
88 case GL_PIXEL_MAP_G_TO_G
:
89 return &ctx
->PixelMaps
.GtoG
;
90 case GL_PIXEL_MAP_B_TO_B
:
91 return &ctx
->PixelMaps
.BtoB
;
92 case GL_PIXEL_MAP_A_TO_A
:
93 return &ctx
->PixelMaps
.AtoA
;
101 * Helper routine used by the other _mesa_PixelMap() functions.
104 store_pixelmap(struct gl_context
*ctx
, GLenum map
, GLsizei mapsize
,
105 const GLfloat
*values
)
108 struct gl_pixelmap
*pm
= get_pixelmap(ctx
, map
);
110 _mesa_error(ctx
, GL_INVALID_ENUM
, "glPixelMap(map)");
115 case GL_PIXEL_MAP_S_TO_S
:
117 ctx
->PixelMaps
.StoS
.Size
= mapsize
;
118 for (i
= 0; i
< mapsize
; i
++) {
119 ctx
->PixelMaps
.StoS
.Map
[i
] = (GLfloat
)IROUND(values
[i
]);
122 case GL_PIXEL_MAP_I_TO_I
:
124 ctx
->PixelMaps
.ItoI
.Size
= mapsize
;
125 for (i
= 0; i
< mapsize
; i
++) {
126 ctx
->PixelMaps
.ItoI
.Map
[i
] = values
[i
];
132 for (i
= 0; i
< mapsize
; i
++) {
133 GLfloat val
= CLAMP(values
[i
], 0.0F
, 1.0F
);
141 * Convenience wrapper for _mesa_validate_pbo_access() for gl[Get]PixelMap().
144 validate_pbo_access(struct gl_context
*ctx
,
145 struct gl_pixelstore_attrib
*pack
, GLsizei mapsize
,
146 GLenum format
, GLenum type
, GLsizei clientMemSize
,
151 /* Note, need to use DefaultPacking and Unpack's buffer object */
152 _mesa_reference_buffer_object(ctx
,
153 &ctx
->DefaultPacking
.BufferObj
,
156 ok
= _mesa_validate_pbo_access(1, &ctx
->DefaultPacking
, mapsize
, 1, 1,
157 format
, type
, clientMemSize
, ptr
);
160 _mesa_reference_buffer_object(ctx
,
161 &ctx
->DefaultPacking
.BufferObj
,
162 ctx
->Shared
->NullBufferObj
);
165 if (_mesa_is_bufferobj(pack
->BufferObj
)) {
166 _mesa_error(ctx
, GL_INVALID_OPERATION
,
167 "gl[Get]PixelMap*v(out of bounds PBO access)");
169 _mesa_error(ctx
, GL_INVALID_OPERATION
,
170 "glGetnPixelMap*vARB(out of bounds access:"
171 " bufSize (%d) is too small)", clientMemSize
);
179 _mesa_PixelMapfv( GLenum map
, GLsizei mapsize
, const GLfloat
*values
)
181 GET_CURRENT_CONTEXT(ctx
);
183 /* XXX someday, test against ctx->Const.MaxPixelMapTableSize */
184 if (mapsize
< 1 || mapsize
> MAX_PIXEL_MAP_TABLE
) {
185 _mesa_error( ctx
, GL_INVALID_VALUE
, "glPixelMapfv(mapsize)" );
189 if (map
>= GL_PIXEL_MAP_S_TO_S
&& map
<= GL_PIXEL_MAP_I_TO_A
) {
190 /* test that mapsize is a power of two */
191 if (!_mesa_is_pow_two(mapsize
)) {
192 _mesa_error( ctx
, GL_INVALID_VALUE
, "glPixelMapfv(mapsize)" );
197 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
199 if (!validate_pbo_access(ctx
, &ctx
->Unpack
, mapsize
, GL_INTENSITY
,
200 GL_FLOAT
, INT_MAX
, values
)) {
204 values
= (const GLfloat
*) _mesa_map_pbo_source(ctx
, &ctx
->Unpack
, values
);
206 if (_mesa_is_bufferobj(ctx
->Unpack
.BufferObj
)) {
207 _mesa_error(ctx
, GL_INVALID_OPERATION
,
208 "glPixelMapfv(PBO is mapped)");
213 store_pixelmap(ctx
, map
, mapsize
, values
);
215 _mesa_unmap_pbo_source(ctx
, &ctx
->Unpack
);
220 _mesa_PixelMapuiv(GLenum map
, GLsizei mapsize
, const GLuint
*values
)
222 GLfloat fvalues
[MAX_PIXEL_MAP_TABLE
];
223 GET_CURRENT_CONTEXT(ctx
);
225 if (mapsize
< 1 || mapsize
> MAX_PIXEL_MAP_TABLE
) {
226 _mesa_error( ctx
, GL_INVALID_VALUE
, "glPixelMapuiv(mapsize)" );
230 if (map
>= GL_PIXEL_MAP_S_TO_S
&& map
<= GL_PIXEL_MAP_I_TO_A
) {
231 /* test that mapsize is a power of two */
232 if (!_mesa_is_pow_two(mapsize
)) {
233 _mesa_error( ctx
, GL_INVALID_VALUE
, "glPixelMapuiv(mapsize)" );
238 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
240 if (!validate_pbo_access(ctx
, &ctx
->Unpack
, mapsize
, GL_INTENSITY
,
241 GL_UNSIGNED_INT
, INT_MAX
, values
)) {
245 values
= (const GLuint
*) _mesa_map_pbo_source(ctx
, &ctx
->Unpack
, values
);
247 if (_mesa_is_bufferobj(ctx
->Unpack
.BufferObj
)) {
248 _mesa_error(ctx
, GL_INVALID_OPERATION
,
249 "glPixelMapuiv(PBO is mapped)");
254 /* convert to floats */
255 if (map
== GL_PIXEL_MAP_I_TO_I
|| map
== GL_PIXEL_MAP_S_TO_S
) {
257 for (i
= 0; i
< mapsize
; i
++) {
258 fvalues
[i
] = (GLfloat
) values
[i
];
263 for (i
= 0; i
< mapsize
; i
++) {
264 fvalues
[i
] = UINT_TO_FLOAT( values
[i
] );
268 _mesa_unmap_pbo_source(ctx
, &ctx
->Unpack
);
270 store_pixelmap(ctx
, map
, mapsize
, fvalues
);
275 _mesa_PixelMapusv(GLenum map
, GLsizei mapsize
, const GLushort
*values
)
277 GLfloat fvalues
[MAX_PIXEL_MAP_TABLE
];
278 GET_CURRENT_CONTEXT(ctx
);
280 if (mapsize
< 1 || mapsize
> MAX_PIXEL_MAP_TABLE
) {
281 _mesa_error( ctx
, GL_INVALID_VALUE
, "glPixelMapusv(mapsize)" );
285 if (map
>= GL_PIXEL_MAP_S_TO_S
&& map
<= GL_PIXEL_MAP_I_TO_A
) {
286 /* test that mapsize is a power of two */
287 if (!_mesa_is_pow_two(mapsize
)) {
288 _mesa_error( ctx
, GL_INVALID_VALUE
, "glPixelMapuiv(mapsize)" );
293 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
295 if (!validate_pbo_access(ctx
, &ctx
->Unpack
, mapsize
, GL_INTENSITY
,
296 GL_UNSIGNED_SHORT
, INT_MAX
, values
)) {
300 values
= (const GLushort
*) _mesa_map_pbo_source(ctx
, &ctx
->Unpack
, values
);
302 if (_mesa_is_bufferobj(ctx
->Unpack
.BufferObj
)) {
303 _mesa_error(ctx
, GL_INVALID_OPERATION
,
304 "glPixelMapusv(PBO is mapped)");
309 /* convert to floats */
310 if (map
== GL_PIXEL_MAP_I_TO_I
|| map
== GL_PIXEL_MAP_S_TO_S
) {
312 for (i
= 0; i
< mapsize
; i
++) {
313 fvalues
[i
] = (GLfloat
) values
[i
];
318 for (i
= 0; i
< mapsize
; i
++) {
319 fvalues
[i
] = USHORT_TO_FLOAT( values
[i
] );
323 _mesa_unmap_pbo_source(ctx
, &ctx
->Unpack
);
325 store_pixelmap(ctx
, map
, mapsize
, fvalues
);
330 _mesa_GetnPixelMapfvARB( GLenum map
, GLsizei bufSize
, GLfloat
*values
)
332 GET_CURRENT_CONTEXT(ctx
);
334 const struct gl_pixelmap
*pm
;
336 pm
= get_pixelmap(ctx
, map
);
338 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetPixelMapfv(map)");
344 if (!validate_pbo_access(ctx
, &ctx
->Pack
, mapsize
, GL_INTENSITY
,
345 GL_FLOAT
, bufSize
, values
)) {
349 values
= (GLfloat
*) _mesa_map_pbo_dest(ctx
, &ctx
->Pack
, values
);
351 if (_mesa_is_bufferobj(ctx
->Pack
.BufferObj
)) {
352 _mesa_error(ctx
, GL_INVALID_OPERATION
,
353 "glGetPixelMapfv(PBO is mapped)");
358 if (map
== GL_PIXEL_MAP_S_TO_S
) {
360 for (i
= 0; i
< mapsize
; i
++) {
361 values
[i
] = (GLfloat
) ctx
->PixelMaps
.StoS
.Map
[i
];
365 memcpy(values
, pm
->Map
, mapsize
* sizeof(GLfloat
));
368 _mesa_unmap_pbo_dest(ctx
, &ctx
->Pack
);
373 _mesa_GetPixelMapfv( GLenum map
, GLfloat
*values
)
375 _mesa_GetnPixelMapfvARB(map
, INT_MAX
, values
);
379 _mesa_GetnPixelMapuivARB( GLenum map
, GLsizei bufSize
, GLuint
*values
)
381 GET_CURRENT_CONTEXT(ctx
);
383 const struct gl_pixelmap
*pm
;
385 pm
= get_pixelmap(ctx
, map
);
387 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetPixelMapuiv(map)");
393 if (!validate_pbo_access(ctx
, &ctx
->Pack
, mapsize
, GL_INTENSITY
,
394 GL_UNSIGNED_INT
, bufSize
, values
)) {
398 values
= (GLuint
*) _mesa_map_pbo_dest(ctx
, &ctx
->Pack
, values
);
400 if (_mesa_is_bufferobj(ctx
->Pack
.BufferObj
)) {
401 _mesa_error(ctx
, GL_INVALID_OPERATION
,
402 "glGetPixelMapuiv(PBO is mapped)");
407 if (map
== GL_PIXEL_MAP_S_TO_S
) {
409 memcpy(values
, ctx
->PixelMaps
.StoS
.Map
, mapsize
* sizeof(GLint
));
412 for (i
= 0; i
< mapsize
; i
++) {
413 values
[i
] = FLOAT_TO_UINT( pm
->Map
[i
] );
417 _mesa_unmap_pbo_dest(ctx
, &ctx
->Pack
);
422 _mesa_GetPixelMapuiv( GLenum map
, GLuint
*values
)
424 _mesa_GetnPixelMapuivARB(map
, INT_MAX
, values
);
428 _mesa_GetnPixelMapusvARB( GLenum map
, GLsizei bufSize
, GLushort
*values
)
430 GET_CURRENT_CONTEXT(ctx
);
432 const struct gl_pixelmap
*pm
;
434 pm
= get_pixelmap(ctx
, map
);
436 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetPixelMapusv(map)");
442 if (!validate_pbo_access(ctx
, &ctx
->Pack
, mapsize
, GL_INTENSITY
,
443 GL_UNSIGNED_SHORT
, bufSize
, values
)) {
447 values
= (GLushort
*) _mesa_map_pbo_dest(ctx
, &ctx
->Pack
, values
);
449 if (_mesa_is_bufferobj(ctx
->Pack
.BufferObj
)) {
450 _mesa_error(ctx
, GL_INVALID_OPERATION
,
451 "glGetPixelMapusv(PBO is mapped)");
458 case GL_PIXEL_MAP_I_TO_I
:
459 for (i
= 0; i
< mapsize
; i
++) {
460 values
[i
] = (GLushort
) CLAMP(ctx
->PixelMaps
.ItoI
.Map
[i
], 0.0, 65535.);
463 case GL_PIXEL_MAP_S_TO_S
:
464 for (i
= 0; i
< mapsize
; i
++) {
465 values
[i
] = (GLushort
) CLAMP(ctx
->PixelMaps
.StoS
.Map
[i
], 0.0, 65535.);
469 for (i
= 0; i
< mapsize
; i
++) {
470 CLAMPED_FLOAT_TO_USHORT(values
[i
], pm
->Map
[i
] );
474 _mesa_unmap_pbo_dest(ctx
, &ctx
->Pack
);
479 _mesa_GetPixelMapusv( GLenum map
, GLushort
*values
)
481 _mesa_GetnPixelMapusvARB(map
, INT_MAX
, values
);
485 /**********************************************************************/
486 /***** glPixelTransfer *****/
487 /**********************************************************************/
491 * Implements glPixelTransfer[fi] whether called immediately or from a
495 _mesa_PixelTransferf( GLenum pname
, GLfloat param
)
497 GET_CURRENT_CONTEXT(ctx
);
501 if (ctx
->Pixel
.MapColorFlag
== (param
? GL_TRUE
: GL_FALSE
))
503 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
504 ctx
->Pixel
.MapColorFlag
= param
? GL_TRUE
: GL_FALSE
;
507 if (ctx
->Pixel
.MapStencilFlag
== (param
? GL_TRUE
: GL_FALSE
))
509 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
510 ctx
->Pixel
.MapStencilFlag
= param
? GL_TRUE
: GL_FALSE
;
513 if (ctx
->Pixel
.IndexShift
== (GLint
) param
)
515 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
516 ctx
->Pixel
.IndexShift
= (GLint
) param
;
518 case GL_INDEX_OFFSET
:
519 if (ctx
->Pixel
.IndexOffset
== (GLint
) param
)
521 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
522 ctx
->Pixel
.IndexOffset
= (GLint
) param
;
525 if (ctx
->Pixel
.RedScale
== param
)
527 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
528 ctx
->Pixel
.RedScale
= param
;
531 if (ctx
->Pixel
.RedBias
== param
)
533 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
534 ctx
->Pixel
.RedBias
= param
;
537 if (ctx
->Pixel
.GreenScale
== param
)
539 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
540 ctx
->Pixel
.GreenScale
= param
;
543 if (ctx
->Pixel
.GreenBias
== param
)
545 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
546 ctx
->Pixel
.GreenBias
= param
;
549 if (ctx
->Pixel
.BlueScale
== param
)
551 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
552 ctx
->Pixel
.BlueScale
= param
;
555 if (ctx
->Pixel
.BlueBias
== param
)
557 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
558 ctx
->Pixel
.BlueBias
= param
;
561 if (ctx
->Pixel
.AlphaScale
== param
)
563 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
564 ctx
->Pixel
.AlphaScale
= param
;
567 if (ctx
->Pixel
.AlphaBias
== param
)
569 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
570 ctx
->Pixel
.AlphaBias
= param
;
573 if (ctx
->Pixel
.DepthScale
== param
)
575 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
576 ctx
->Pixel
.DepthScale
= param
;
579 if (ctx
->Pixel
.DepthBias
== param
)
581 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
582 ctx
->Pixel
.DepthBias
= param
;
585 _mesa_error( ctx
, GL_INVALID_ENUM
, "glPixelTransfer(pname)" );
592 _mesa_PixelTransferi( GLenum pname
, GLint param
)
594 _mesa_PixelTransferf( pname
, (GLfloat
) param
);
599 /**********************************************************************/
600 /***** State Management *****/
601 /**********************************************************************/
604 * Return a bitmask of IMAGE_*_BIT flags which to indicate which
605 * pixel transfer operations are enabled.
608 update_image_transfer_state(struct gl_context
*ctx
)
612 if (ctx
->Pixel
.RedScale
!= 1.0F
|| ctx
->Pixel
.RedBias
!= 0.0F
||
613 ctx
->Pixel
.GreenScale
!= 1.0F
|| ctx
->Pixel
.GreenBias
!= 0.0F
||
614 ctx
->Pixel
.BlueScale
!= 1.0F
|| ctx
->Pixel
.BlueBias
!= 0.0F
||
615 ctx
->Pixel
.AlphaScale
!= 1.0F
|| ctx
->Pixel
.AlphaBias
!= 0.0F
)
616 mask
|= IMAGE_SCALE_BIAS_BIT
;
618 if (ctx
->Pixel
.IndexShift
|| ctx
->Pixel
.IndexOffset
)
619 mask
|= IMAGE_SHIFT_OFFSET_BIT
;
621 if (ctx
->Pixel
.MapColorFlag
)
622 mask
|= IMAGE_MAP_COLOR_BIT
;
624 ctx
->_ImageTransferState
= mask
;
629 * Update mesa pixel transfer derived state.
631 void _mesa_update_pixel( struct gl_context
*ctx
, GLuint new_state
)
633 if (new_state
& _NEW_PIXEL
)
634 update_image_transfer_state(ctx
);
638 /**********************************************************************/
639 /***** Initialization *****/
640 /**********************************************************************/
643 init_pixelmap(struct gl_pixelmap
*map
)
651 * Initialize the context's PIXEL attribute group.
654 _mesa_init_pixel( struct gl_context
*ctx
)
657 ctx
->Pixel
.RedBias
= 0.0;
658 ctx
->Pixel
.RedScale
= 1.0;
659 ctx
->Pixel
.GreenBias
= 0.0;
660 ctx
->Pixel
.GreenScale
= 1.0;
661 ctx
->Pixel
.BlueBias
= 0.0;
662 ctx
->Pixel
.BlueScale
= 1.0;
663 ctx
->Pixel
.AlphaBias
= 0.0;
664 ctx
->Pixel
.AlphaScale
= 1.0;
665 ctx
->Pixel
.DepthBias
= 0.0;
666 ctx
->Pixel
.DepthScale
= 1.0;
667 ctx
->Pixel
.IndexOffset
= 0;
668 ctx
->Pixel
.IndexShift
= 0;
669 ctx
->Pixel
.ZoomX
= 1.0;
670 ctx
->Pixel
.ZoomY
= 1.0;
671 ctx
->Pixel
.MapColorFlag
= GL_FALSE
;
672 ctx
->Pixel
.MapStencilFlag
= GL_FALSE
;
673 init_pixelmap(&ctx
->PixelMaps
.StoS
);
674 init_pixelmap(&ctx
->PixelMaps
.ItoI
);
675 init_pixelmap(&ctx
->PixelMaps
.ItoR
);
676 init_pixelmap(&ctx
->PixelMaps
.ItoG
);
677 init_pixelmap(&ctx
->PixelMaps
.ItoB
);
678 init_pixelmap(&ctx
->PixelMaps
.ItoA
);
679 init_pixelmap(&ctx
->PixelMaps
.RtoR
);
680 init_pixelmap(&ctx
->PixelMaps
.GtoG
);
681 init_pixelmap(&ctx
->PixelMaps
.BtoB
);
682 init_pixelmap(&ctx
->PixelMaps
.AtoA
);
684 if (ctx
->Visual
.doubleBufferMode
) {
685 ctx
->Pixel
.ReadBuffer
= GL_BACK
;
688 ctx
->Pixel
.ReadBuffer
= GL_FRONT
;
692 ctx
->_ImageTransferState
= 0;