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)
32 #include "bufferobj.h"
40 /**********************************************************************/
41 /***** glPixelZoom *****/
42 /**********************************************************************/
45 _mesa_PixelZoom( GLfloat xfactor
, GLfloat yfactor
)
47 GET_CURRENT_CONTEXT(ctx
);
49 if (ctx
->Pixel
.ZoomX
== xfactor
&&
50 ctx
->Pixel
.ZoomY
== yfactor
)
53 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
54 ctx
->Pixel
.ZoomX
= xfactor
;
55 ctx
->Pixel
.ZoomY
= yfactor
;
60 /**********************************************************************/
61 /***** glPixelMap *****/
62 /**********************************************************************/
65 * Return pointer to a pixelmap by name.
67 static struct gl_pixelmap
*
68 get_pixelmap(struct gl_context
*ctx
, GLenum map
)
71 case GL_PIXEL_MAP_I_TO_I
:
72 return &ctx
->PixelMaps
.ItoI
;
73 case GL_PIXEL_MAP_S_TO_S
:
74 return &ctx
->PixelMaps
.StoS
;
75 case GL_PIXEL_MAP_I_TO_R
:
76 return &ctx
->PixelMaps
.ItoR
;
77 case GL_PIXEL_MAP_I_TO_G
:
78 return &ctx
->PixelMaps
.ItoG
;
79 case GL_PIXEL_MAP_I_TO_B
:
80 return &ctx
->PixelMaps
.ItoB
;
81 case GL_PIXEL_MAP_I_TO_A
:
82 return &ctx
->PixelMaps
.ItoA
;
83 case GL_PIXEL_MAP_R_TO_R
:
84 return &ctx
->PixelMaps
.RtoR
;
85 case GL_PIXEL_MAP_G_TO_G
:
86 return &ctx
->PixelMaps
.GtoG
;
87 case GL_PIXEL_MAP_B_TO_B
:
88 return &ctx
->PixelMaps
.BtoB
;
89 case GL_PIXEL_MAP_A_TO_A
:
90 return &ctx
->PixelMaps
.AtoA
;
98 * Helper routine used by the other _mesa_PixelMap() functions.
101 store_pixelmap(struct gl_context
*ctx
, GLenum map
, GLsizei mapsize
,
102 const GLfloat
*values
)
105 struct gl_pixelmap
*pm
= get_pixelmap(ctx
, map
);
107 _mesa_error(ctx
, GL_INVALID_ENUM
, "glPixelMap(map)");
112 case GL_PIXEL_MAP_S_TO_S
:
114 ctx
->PixelMaps
.StoS
.Size
= mapsize
;
115 for (i
= 0; i
< mapsize
; i
++) {
116 ctx
->PixelMaps
.StoS
.Map
[i
] = (GLfloat
)IROUND(values
[i
]);
119 case GL_PIXEL_MAP_I_TO_I
:
121 ctx
->PixelMaps
.ItoI
.Size
= mapsize
;
122 for (i
= 0; i
< mapsize
; i
++) {
123 ctx
->PixelMaps
.ItoI
.Map
[i
] = values
[i
];
129 for (i
= 0; i
< mapsize
; i
++) {
130 GLfloat val
= CLAMP(values
[i
], 0.0F
, 1.0F
);
138 * Convenience wrapper for _mesa_validate_pbo_access() for gl[Get]PixelMap().
141 validate_pbo_access(struct gl_context
*ctx
,
142 struct gl_pixelstore_attrib
*pack
, GLsizei mapsize
,
143 GLenum format
, GLenum type
, GLsizei clientMemSize
,
148 /* Note, need to use DefaultPacking and Unpack's buffer object */
149 _mesa_reference_buffer_object(ctx
,
150 &ctx
->DefaultPacking
.BufferObj
,
153 ok
= _mesa_validate_pbo_access(1, &ctx
->DefaultPacking
, mapsize
, 1, 1,
154 format
, type
, clientMemSize
, ptr
);
157 _mesa_reference_buffer_object(ctx
,
158 &ctx
->DefaultPacking
.BufferObj
, NULL
);
161 if (_mesa_is_bufferobj(pack
->BufferObj
)) {
162 _mesa_error(ctx
, GL_INVALID_OPERATION
,
163 "gl[Get]PixelMap*v(out of bounds PBO access)");
165 _mesa_error(ctx
, GL_INVALID_OPERATION
,
166 "glGetnPixelMap*vARB(out of bounds access:"
167 " bufSize (%d) is too small)", clientMemSize
);
175 _mesa_PixelMapfv( GLenum map
, GLsizei mapsize
, const GLfloat
*values
)
177 GET_CURRENT_CONTEXT(ctx
);
179 /* XXX someday, test against ctx->Const.MaxPixelMapTableSize */
180 if (mapsize
< 1 || mapsize
> MAX_PIXEL_MAP_TABLE
) {
181 _mesa_error( ctx
, GL_INVALID_VALUE
, "glPixelMapfv(mapsize)" );
185 if (map
>= GL_PIXEL_MAP_S_TO_S
&& map
<= GL_PIXEL_MAP_I_TO_A
) {
186 /* test that mapsize is a power of two */
187 if (!_mesa_is_pow_two(mapsize
)) {
188 _mesa_error( ctx
, GL_INVALID_VALUE
, "glPixelMapfv(mapsize)" );
193 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
195 if (!validate_pbo_access(ctx
, &ctx
->Unpack
, mapsize
, GL_INTENSITY
,
196 GL_FLOAT
, INT_MAX
, values
)) {
200 values
= (const GLfloat
*) _mesa_map_pbo_source(ctx
, &ctx
->Unpack
, values
);
202 if (_mesa_is_bufferobj(ctx
->Unpack
.BufferObj
)) {
203 _mesa_error(ctx
, GL_INVALID_OPERATION
,
204 "glPixelMapfv(PBO is mapped)");
209 store_pixelmap(ctx
, map
, mapsize
, values
);
211 _mesa_unmap_pbo_source(ctx
, &ctx
->Unpack
);
216 _mesa_PixelMapuiv(GLenum map
, GLsizei mapsize
, const GLuint
*values
)
218 GLfloat fvalues
[MAX_PIXEL_MAP_TABLE
];
219 GET_CURRENT_CONTEXT(ctx
);
221 if (mapsize
< 1 || mapsize
> MAX_PIXEL_MAP_TABLE
) {
222 _mesa_error( ctx
, GL_INVALID_VALUE
, "glPixelMapuiv(mapsize)" );
226 if (map
>= GL_PIXEL_MAP_S_TO_S
&& map
<= GL_PIXEL_MAP_I_TO_A
) {
227 /* test that mapsize is a power of two */
228 if (!_mesa_is_pow_two(mapsize
)) {
229 _mesa_error( ctx
, GL_INVALID_VALUE
, "glPixelMapuiv(mapsize)" );
234 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
236 if (!validate_pbo_access(ctx
, &ctx
->Unpack
, mapsize
, GL_INTENSITY
,
237 GL_UNSIGNED_INT
, INT_MAX
, values
)) {
241 values
= (const GLuint
*) _mesa_map_pbo_source(ctx
, &ctx
->Unpack
, values
);
243 if (_mesa_is_bufferobj(ctx
->Unpack
.BufferObj
)) {
244 _mesa_error(ctx
, GL_INVALID_OPERATION
,
245 "glPixelMapuiv(PBO is mapped)");
250 /* convert to floats */
251 if (map
== GL_PIXEL_MAP_I_TO_I
|| map
== GL_PIXEL_MAP_S_TO_S
) {
253 for (i
= 0; i
< mapsize
; i
++) {
254 fvalues
[i
] = (GLfloat
) values
[i
];
259 for (i
= 0; i
< mapsize
; i
++) {
260 fvalues
[i
] = UINT_TO_FLOAT( values
[i
] );
264 _mesa_unmap_pbo_source(ctx
, &ctx
->Unpack
);
266 store_pixelmap(ctx
, map
, mapsize
, fvalues
);
271 _mesa_PixelMapusv(GLenum map
, GLsizei mapsize
, const GLushort
*values
)
273 GLfloat fvalues
[MAX_PIXEL_MAP_TABLE
];
274 GET_CURRENT_CONTEXT(ctx
);
276 if (mapsize
< 1 || mapsize
> MAX_PIXEL_MAP_TABLE
) {
277 _mesa_error( ctx
, GL_INVALID_VALUE
, "glPixelMapusv(mapsize)" );
281 if (map
>= GL_PIXEL_MAP_S_TO_S
&& map
<= GL_PIXEL_MAP_I_TO_A
) {
282 /* test that mapsize is a power of two */
283 if (!_mesa_is_pow_two(mapsize
)) {
284 _mesa_error( ctx
, GL_INVALID_VALUE
, "glPixelMapusv(mapsize)" );
289 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
291 if (!validate_pbo_access(ctx
, &ctx
->Unpack
, mapsize
, GL_INTENSITY
,
292 GL_UNSIGNED_SHORT
, INT_MAX
, values
)) {
296 values
= (const GLushort
*) _mesa_map_pbo_source(ctx
, &ctx
->Unpack
, values
);
298 if (_mesa_is_bufferobj(ctx
->Unpack
.BufferObj
)) {
299 _mesa_error(ctx
, GL_INVALID_OPERATION
,
300 "glPixelMapusv(PBO is mapped)");
305 /* convert to floats */
306 if (map
== GL_PIXEL_MAP_I_TO_I
|| map
== GL_PIXEL_MAP_S_TO_S
) {
308 for (i
= 0; i
< mapsize
; i
++) {
309 fvalues
[i
] = (GLfloat
) values
[i
];
314 for (i
= 0; i
< mapsize
; i
++) {
315 fvalues
[i
] = USHORT_TO_FLOAT( values
[i
] );
319 _mesa_unmap_pbo_source(ctx
, &ctx
->Unpack
);
321 store_pixelmap(ctx
, map
, mapsize
, fvalues
);
326 _mesa_GetnPixelMapfvARB( GLenum map
, GLsizei bufSize
, GLfloat
*values
)
328 GET_CURRENT_CONTEXT(ctx
);
330 const struct gl_pixelmap
*pm
;
332 pm
= get_pixelmap(ctx
, map
);
334 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetPixelMapfv(map)");
340 if (!validate_pbo_access(ctx
, &ctx
->Pack
, mapsize
, GL_INTENSITY
,
341 GL_FLOAT
, bufSize
, values
)) {
345 values
= (GLfloat
*) _mesa_map_pbo_dest(ctx
, &ctx
->Pack
, values
);
347 if (_mesa_is_bufferobj(ctx
->Pack
.BufferObj
)) {
348 _mesa_error(ctx
, GL_INVALID_OPERATION
,
349 "glGetPixelMapfv(PBO is mapped)");
354 if (map
== GL_PIXEL_MAP_S_TO_S
) {
356 for (i
= 0; i
< mapsize
; i
++) {
357 values
[i
] = (GLfloat
) ctx
->PixelMaps
.StoS
.Map
[i
];
361 memcpy(values
, pm
->Map
, mapsize
* sizeof(GLfloat
));
364 _mesa_unmap_pbo_dest(ctx
, &ctx
->Pack
);
369 _mesa_GetPixelMapfv( GLenum map
, GLfloat
*values
)
371 _mesa_GetnPixelMapfvARB(map
, INT_MAX
, values
);
375 _mesa_GetnPixelMapuivARB( GLenum map
, GLsizei bufSize
, GLuint
*values
)
377 GET_CURRENT_CONTEXT(ctx
);
379 const struct gl_pixelmap
*pm
;
381 pm
= get_pixelmap(ctx
, map
);
383 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetPixelMapuiv(map)");
389 if (!validate_pbo_access(ctx
, &ctx
->Pack
, mapsize
, GL_INTENSITY
,
390 GL_UNSIGNED_INT
, bufSize
, values
)) {
394 values
= (GLuint
*) _mesa_map_pbo_dest(ctx
, &ctx
->Pack
, values
);
396 if (_mesa_is_bufferobj(ctx
->Pack
.BufferObj
)) {
397 _mesa_error(ctx
, GL_INVALID_OPERATION
,
398 "glGetPixelMapuiv(PBO is mapped)");
403 if (map
== GL_PIXEL_MAP_S_TO_S
) {
405 memcpy(values
, ctx
->PixelMaps
.StoS
.Map
, mapsize
* sizeof(GLint
));
408 for (i
= 0; i
< mapsize
; i
++) {
409 values
[i
] = FLOAT_TO_UINT( pm
->Map
[i
] );
413 _mesa_unmap_pbo_dest(ctx
, &ctx
->Pack
);
418 _mesa_GetPixelMapuiv( GLenum map
, GLuint
*values
)
420 _mesa_GetnPixelMapuivARB(map
, INT_MAX
, values
);
424 _mesa_GetnPixelMapusvARB( GLenum map
, GLsizei bufSize
, GLushort
*values
)
426 GET_CURRENT_CONTEXT(ctx
);
428 const struct gl_pixelmap
*pm
;
430 pm
= get_pixelmap(ctx
, map
);
432 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetPixelMapusv(map)");
438 if (!validate_pbo_access(ctx
, &ctx
->Pack
, mapsize
, GL_INTENSITY
,
439 GL_UNSIGNED_SHORT
, bufSize
, values
)) {
443 values
= (GLushort
*) _mesa_map_pbo_dest(ctx
, &ctx
->Pack
, values
);
445 if (_mesa_is_bufferobj(ctx
->Pack
.BufferObj
)) {
446 _mesa_error(ctx
, GL_INVALID_OPERATION
,
447 "glGetPixelMapusv(PBO is mapped)");
454 case GL_PIXEL_MAP_I_TO_I
:
455 for (i
= 0; i
< mapsize
; i
++) {
456 values
[i
] = (GLushort
) CLAMP(ctx
->PixelMaps
.ItoI
.Map
[i
], 0.0F
, 65535.0F
);
459 case GL_PIXEL_MAP_S_TO_S
:
460 for (i
= 0; i
< mapsize
; i
++) {
461 values
[i
] = (GLushort
) CLAMP(ctx
->PixelMaps
.StoS
.Map
[i
], 0.0F
, 65535.0F
);
465 for (i
= 0; i
< mapsize
; i
++) {
466 CLAMPED_FLOAT_TO_USHORT(values
[i
], pm
->Map
[i
] );
470 _mesa_unmap_pbo_dest(ctx
, &ctx
->Pack
);
475 _mesa_GetPixelMapusv( GLenum map
, GLushort
*values
)
477 _mesa_GetnPixelMapusvARB(map
, INT_MAX
, values
);
481 /**********************************************************************/
482 /***** glPixelTransfer *****/
483 /**********************************************************************/
487 * Implements glPixelTransfer[fi] whether called immediately or from a
491 _mesa_PixelTransferf( GLenum pname
, GLfloat param
)
493 GET_CURRENT_CONTEXT(ctx
);
497 if (ctx
->Pixel
.MapColorFlag
== (param
? GL_TRUE
: GL_FALSE
))
499 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
500 ctx
->Pixel
.MapColorFlag
= param
? GL_TRUE
: GL_FALSE
;
503 if (ctx
->Pixel
.MapStencilFlag
== (param
? GL_TRUE
: GL_FALSE
))
505 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
506 ctx
->Pixel
.MapStencilFlag
= param
? GL_TRUE
: GL_FALSE
;
509 if (ctx
->Pixel
.IndexShift
== (GLint
) param
)
511 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
512 ctx
->Pixel
.IndexShift
= (GLint
) param
;
514 case GL_INDEX_OFFSET
:
515 if (ctx
->Pixel
.IndexOffset
== (GLint
) param
)
517 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
518 ctx
->Pixel
.IndexOffset
= (GLint
) param
;
521 if (ctx
->Pixel
.RedScale
== param
)
523 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
524 ctx
->Pixel
.RedScale
= param
;
527 if (ctx
->Pixel
.RedBias
== param
)
529 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
530 ctx
->Pixel
.RedBias
= param
;
533 if (ctx
->Pixel
.GreenScale
== param
)
535 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
536 ctx
->Pixel
.GreenScale
= param
;
539 if (ctx
->Pixel
.GreenBias
== param
)
541 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
542 ctx
->Pixel
.GreenBias
= param
;
545 if (ctx
->Pixel
.BlueScale
== param
)
547 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
548 ctx
->Pixel
.BlueScale
= param
;
551 if (ctx
->Pixel
.BlueBias
== param
)
553 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
554 ctx
->Pixel
.BlueBias
= param
;
557 if (ctx
->Pixel
.AlphaScale
== param
)
559 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
560 ctx
->Pixel
.AlphaScale
= param
;
563 if (ctx
->Pixel
.AlphaBias
== param
)
565 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
566 ctx
->Pixel
.AlphaBias
= param
;
569 if (ctx
->Pixel
.DepthScale
== param
)
571 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
572 ctx
->Pixel
.DepthScale
= param
;
575 if (ctx
->Pixel
.DepthBias
== param
)
577 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
578 ctx
->Pixel
.DepthBias
= param
;
581 _mesa_error( ctx
, GL_INVALID_ENUM
, "glPixelTransfer(pname)" );
588 _mesa_PixelTransferi( GLenum pname
, GLint param
)
590 _mesa_PixelTransferf( pname
, (GLfloat
) param
);
595 /**********************************************************************/
596 /***** State Management *****/
597 /**********************************************************************/
601 * Update mesa pixel transfer derived state to indicate which operations are
605 _mesa_update_pixel( struct gl_context
*ctx
)
609 if (ctx
->Pixel
.RedScale
!= 1.0F
|| ctx
->Pixel
.RedBias
!= 0.0F
||
610 ctx
->Pixel
.GreenScale
!= 1.0F
|| ctx
->Pixel
.GreenBias
!= 0.0F
||
611 ctx
->Pixel
.BlueScale
!= 1.0F
|| ctx
->Pixel
.BlueBias
!= 0.0F
||
612 ctx
->Pixel
.AlphaScale
!= 1.0F
|| ctx
->Pixel
.AlphaBias
!= 0.0F
)
613 mask
|= IMAGE_SCALE_BIAS_BIT
;
615 if (ctx
->Pixel
.IndexShift
|| ctx
->Pixel
.IndexOffset
)
616 mask
|= IMAGE_SHIFT_OFFSET_BIT
;
618 if (ctx
->Pixel
.MapColorFlag
)
619 mask
|= IMAGE_MAP_COLOR_BIT
;
621 ctx
->_ImageTransferState
= mask
;
625 /**********************************************************************/
626 /***** Initialization *****/
627 /**********************************************************************/
630 init_pixelmap(struct gl_pixelmap
*map
)
638 * Initialize the context's PIXEL attribute group.
641 _mesa_init_pixel( struct gl_context
*ctx
)
644 ctx
->Pixel
.RedBias
= 0.0;
645 ctx
->Pixel
.RedScale
= 1.0;
646 ctx
->Pixel
.GreenBias
= 0.0;
647 ctx
->Pixel
.GreenScale
= 1.0;
648 ctx
->Pixel
.BlueBias
= 0.0;
649 ctx
->Pixel
.BlueScale
= 1.0;
650 ctx
->Pixel
.AlphaBias
= 0.0;
651 ctx
->Pixel
.AlphaScale
= 1.0;
652 ctx
->Pixel
.DepthBias
= 0.0;
653 ctx
->Pixel
.DepthScale
= 1.0;
654 ctx
->Pixel
.IndexOffset
= 0;
655 ctx
->Pixel
.IndexShift
= 0;
656 ctx
->Pixel
.ZoomX
= 1.0;
657 ctx
->Pixel
.ZoomY
= 1.0;
658 ctx
->Pixel
.MapColorFlag
= GL_FALSE
;
659 ctx
->Pixel
.MapStencilFlag
= GL_FALSE
;
660 init_pixelmap(&ctx
->PixelMaps
.StoS
);
661 init_pixelmap(&ctx
->PixelMaps
.ItoI
);
662 init_pixelmap(&ctx
->PixelMaps
.ItoR
);
663 init_pixelmap(&ctx
->PixelMaps
.ItoG
);
664 init_pixelmap(&ctx
->PixelMaps
.ItoB
);
665 init_pixelmap(&ctx
->PixelMaps
.ItoA
);
666 init_pixelmap(&ctx
->PixelMaps
.RtoR
);
667 init_pixelmap(&ctx
->PixelMaps
.GtoG
);
668 init_pixelmap(&ctx
->PixelMaps
.BtoB
);
669 init_pixelmap(&ctx
->PixelMaps
.AtoA
);
671 if (ctx
->Visual
.doubleBufferMode
) {
672 ctx
->Pixel
.ReadBuffer
= GL_BACK
;
675 ctx
->Pixel
.ReadBuffer
= GL_FRONT
;
679 ctx
->_ImageTransferState
= 0;