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"
38 #include "main/dispatch.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
] = (GLfloat
)IROUND(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
,
160 ctx
->Shared
->NullBufferObj
);
163 if (_mesa_is_bufferobj(pack
->BufferObj
)) {
164 _mesa_error(ctx
, GL_INVALID_OPERATION
,
165 "gl[Get]PixelMap*v(out of bounds PBO access)");
167 _mesa_error(ctx
, GL_INVALID_OPERATION
,
168 "glGetnPixelMap*vARB(out of bounds access:"
169 " bufSize (%d) is too small)", clientMemSize
);
177 _mesa_PixelMapfv( GLenum map
, GLsizei mapsize
, const GLfloat
*values
)
179 GET_CURRENT_CONTEXT(ctx
);
181 /* XXX someday, test against ctx->Const.MaxPixelMapTableSize */
182 if (mapsize
< 1 || mapsize
> MAX_PIXEL_MAP_TABLE
) {
183 _mesa_error( ctx
, GL_INVALID_VALUE
, "glPixelMapfv(mapsize)" );
187 if (map
>= GL_PIXEL_MAP_S_TO_S
&& map
<= GL_PIXEL_MAP_I_TO_A
) {
188 /* test that mapsize is a power of two */
189 if (!_mesa_is_pow_two(mapsize
)) {
190 _mesa_error( ctx
, GL_INVALID_VALUE
, "glPixelMapfv(mapsize)" );
195 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
197 if (!validate_pbo_access(ctx
, &ctx
->Unpack
, mapsize
, GL_INTENSITY
,
198 GL_FLOAT
, INT_MAX
, values
)) {
202 values
= (const GLfloat
*) _mesa_map_pbo_source(ctx
, &ctx
->Unpack
, values
);
204 if (_mesa_is_bufferobj(ctx
->Unpack
.BufferObj
)) {
205 _mesa_error(ctx
, GL_INVALID_OPERATION
,
206 "glPixelMapfv(PBO is mapped)");
211 store_pixelmap(ctx
, map
, mapsize
, values
);
213 _mesa_unmap_pbo_source(ctx
, &ctx
->Unpack
);
218 _mesa_PixelMapuiv(GLenum map
, GLsizei mapsize
, const GLuint
*values
)
220 GLfloat fvalues
[MAX_PIXEL_MAP_TABLE
];
221 GET_CURRENT_CONTEXT(ctx
);
223 if (mapsize
< 1 || mapsize
> MAX_PIXEL_MAP_TABLE
) {
224 _mesa_error( ctx
, GL_INVALID_VALUE
, "glPixelMapuiv(mapsize)" );
228 if (map
>= GL_PIXEL_MAP_S_TO_S
&& map
<= GL_PIXEL_MAP_I_TO_A
) {
229 /* test that mapsize is a power of two */
230 if (!_mesa_is_pow_two(mapsize
)) {
231 _mesa_error( ctx
, GL_INVALID_VALUE
, "glPixelMapuiv(mapsize)" );
236 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
238 if (!validate_pbo_access(ctx
, &ctx
->Unpack
, mapsize
, GL_INTENSITY
,
239 GL_UNSIGNED_INT
, INT_MAX
, values
)) {
243 values
= (const GLuint
*) _mesa_map_pbo_source(ctx
, &ctx
->Unpack
, values
);
245 if (_mesa_is_bufferobj(ctx
->Unpack
.BufferObj
)) {
246 _mesa_error(ctx
, GL_INVALID_OPERATION
,
247 "glPixelMapuiv(PBO is mapped)");
252 /* convert to floats */
253 if (map
== GL_PIXEL_MAP_I_TO_I
|| map
== GL_PIXEL_MAP_S_TO_S
) {
255 for (i
= 0; i
< mapsize
; i
++) {
256 fvalues
[i
] = (GLfloat
) values
[i
];
261 for (i
= 0; i
< mapsize
; i
++) {
262 fvalues
[i
] = UINT_TO_FLOAT( values
[i
] );
266 _mesa_unmap_pbo_source(ctx
, &ctx
->Unpack
);
268 store_pixelmap(ctx
, map
, mapsize
, fvalues
);
273 _mesa_PixelMapusv(GLenum map
, GLsizei mapsize
, const GLushort
*values
)
275 GLfloat fvalues
[MAX_PIXEL_MAP_TABLE
];
276 GET_CURRENT_CONTEXT(ctx
);
278 if (mapsize
< 1 || mapsize
> MAX_PIXEL_MAP_TABLE
) {
279 _mesa_error( ctx
, GL_INVALID_VALUE
, "glPixelMapusv(mapsize)" );
283 if (map
>= GL_PIXEL_MAP_S_TO_S
&& map
<= GL_PIXEL_MAP_I_TO_A
) {
284 /* test that mapsize is a power of two */
285 if (!_mesa_is_pow_two(mapsize
)) {
286 _mesa_error( ctx
, GL_INVALID_VALUE
, "glPixelMapuiv(mapsize)" );
291 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
293 if (!validate_pbo_access(ctx
, &ctx
->Unpack
, mapsize
, GL_INTENSITY
,
294 GL_UNSIGNED_SHORT
, INT_MAX
, values
)) {
298 values
= (const GLushort
*) _mesa_map_pbo_source(ctx
, &ctx
->Unpack
, values
);
300 if (_mesa_is_bufferobj(ctx
->Unpack
.BufferObj
)) {
301 _mesa_error(ctx
, GL_INVALID_OPERATION
,
302 "glPixelMapusv(PBO is mapped)");
307 /* convert to floats */
308 if (map
== GL_PIXEL_MAP_I_TO_I
|| map
== GL_PIXEL_MAP_S_TO_S
) {
310 for (i
= 0; i
< mapsize
; i
++) {
311 fvalues
[i
] = (GLfloat
) values
[i
];
316 for (i
= 0; i
< mapsize
; i
++) {
317 fvalues
[i
] = USHORT_TO_FLOAT( values
[i
] );
321 _mesa_unmap_pbo_source(ctx
, &ctx
->Unpack
);
323 store_pixelmap(ctx
, map
, mapsize
, fvalues
);
328 _mesa_GetnPixelMapfvARB( GLenum map
, GLsizei bufSize
, GLfloat
*values
)
330 GET_CURRENT_CONTEXT(ctx
);
332 const struct gl_pixelmap
*pm
;
334 pm
= get_pixelmap(ctx
, map
);
336 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetPixelMapfv(map)");
342 if (!validate_pbo_access(ctx
, &ctx
->Pack
, mapsize
, GL_INTENSITY
,
343 GL_FLOAT
, bufSize
, values
)) {
347 values
= (GLfloat
*) _mesa_map_pbo_dest(ctx
, &ctx
->Pack
, values
);
349 if (_mesa_is_bufferobj(ctx
->Pack
.BufferObj
)) {
350 _mesa_error(ctx
, GL_INVALID_OPERATION
,
351 "glGetPixelMapfv(PBO is mapped)");
356 if (map
== GL_PIXEL_MAP_S_TO_S
) {
358 for (i
= 0; i
< mapsize
; i
++) {
359 values
[i
] = (GLfloat
) ctx
->PixelMaps
.StoS
.Map
[i
];
363 memcpy(values
, pm
->Map
, mapsize
* sizeof(GLfloat
));
366 _mesa_unmap_pbo_dest(ctx
, &ctx
->Pack
);
371 _mesa_GetPixelMapfv( GLenum map
, GLfloat
*values
)
373 _mesa_GetnPixelMapfvARB(map
, INT_MAX
, values
);
377 _mesa_GetnPixelMapuivARB( GLenum map
, GLsizei bufSize
, GLuint
*values
)
379 GET_CURRENT_CONTEXT(ctx
);
381 const struct gl_pixelmap
*pm
;
383 pm
= get_pixelmap(ctx
, map
);
385 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetPixelMapuiv(map)");
391 if (!validate_pbo_access(ctx
, &ctx
->Pack
, mapsize
, GL_INTENSITY
,
392 GL_UNSIGNED_INT
, bufSize
, values
)) {
396 values
= (GLuint
*) _mesa_map_pbo_dest(ctx
, &ctx
->Pack
, values
);
398 if (_mesa_is_bufferobj(ctx
->Pack
.BufferObj
)) {
399 _mesa_error(ctx
, GL_INVALID_OPERATION
,
400 "glGetPixelMapuiv(PBO is mapped)");
405 if (map
== GL_PIXEL_MAP_S_TO_S
) {
407 memcpy(values
, ctx
->PixelMaps
.StoS
.Map
, mapsize
* sizeof(GLint
));
410 for (i
= 0; i
< mapsize
; i
++) {
411 values
[i
] = FLOAT_TO_UINT( pm
->Map
[i
] );
415 _mesa_unmap_pbo_dest(ctx
, &ctx
->Pack
);
420 _mesa_GetPixelMapuiv( GLenum map
, GLuint
*values
)
422 _mesa_GetnPixelMapuivARB(map
, INT_MAX
, values
);
426 _mesa_GetnPixelMapusvARB( GLenum map
, GLsizei bufSize
, GLushort
*values
)
428 GET_CURRENT_CONTEXT(ctx
);
430 const struct gl_pixelmap
*pm
;
432 pm
= get_pixelmap(ctx
, map
);
434 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetPixelMapusv(map)");
440 if (!validate_pbo_access(ctx
, &ctx
->Pack
, mapsize
, GL_INTENSITY
,
441 GL_UNSIGNED_SHORT
, bufSize
, values
)) {
445 values
= (GLushort
*) _mesa_map_pbo_dest(ctx
, &ctx
->Pack
, values
);
447 if (_mesa_is_bufferobj(ctx
->Pack
.BufferObj
)) {
448 _mesa_error(ctx
, GL_INVALID_OPERATION
,
449 "glGetPixelMapusv(PBO is mapped)");
456 case GL_PIXEL_MAP_I_TO_I
:
457 for (i
= 0; i
< mapsize
; i
++) {
458 values
[i
] = (GLushort
) CLAMP(ctx
->PixelMaps
.ItoI
.Map
[i
], 0.0, 65535.);
461 case GL_PIXEL_MAP_S_TO_S
:
462 for (i
= 0; i
< mapsize
; i
++) {
463 values
[i
] = (GLushort
) CLAMP(ctx
->PixelMaps
.StoS
.Map
[i
], 0.0, 65535.);
467 for (i
= 0; i
< mapsize
; i
++) {
468 CLAMPED_FLOAT_TO_USHORT(values
[i
], pm
->Map
[i
] );
472 _mesa_unmap_pbo_dest(ctx
, &ctx
->Pack
);
477 _mesa_GetPixelMapusv( GLenum map
, GLushort
*values
)
479 _mesa_GetnPixelMapusvARB(map
, INT_MAX
, values
);
483 /**********************************************************************/
484 /***** glPixelTransfer *****/
485 /**********************************************************************/
489 * Implements glPixelTransfer[fi] whether called immediately or from a
493 _mesa_PixelTransferf( GLenum pname
, GLfloat param
)
495 GET_CURRENT_CONTEXT(ctx
);
499 if (ctx
->Pixel
.MapColorFlag
== (param
? GL_TRUE
: GL_FALSE
))
501 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
502 ctx
->Pixel
.MapColorFlag
= param
? GL_TRUE
: GL_FALSE
;
505 if (ctx
->Pixel
.MapStencilFlag
== (param
? GL_TRUE
: GL_FALSE
))
507 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
508 ctx
->Pixel
.MapStencilFlag
= param
? GL_TRUE
: GL_FALSE
;
511 if (ctx
->Pixel
.IndexShift
== (GLint
) param
)
513 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
514 ctx
->Pixel
.IndexShift
= (GLint
) param
;
516 case GL_INDEX_OFFSET
:
517 if (ctx
->Pixel
.IndexOffset
== (GLint
) param
)
519 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
520 ctx
->Pixel
.IndexOffset
= (GLint
) param
;
523 if (ctx
->Pixel
.RedScale
== param
)
525 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
526 ctx
->Pixel
.RedScale
= param
;
529 if (ctx
->Pixel
.RedBias
== param
)
531 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
532 ctx
->Pixel
.RedBias
= param
;
535 if (ctx
->Pixel
.GreenScale
== param
)
537 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
538 ctx
->Pixel
.GreenScale
= param
;
541 if (ctx
->Pixel
.GreenBias
== param
)
543 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
544 ctx
->Pixel
.GreenBias
= param
;
547 if (ctx
->Pixel
.BlueScale
== param
)
549 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
550 ctx
->Pixel
.BlueScale
= param
;
553 if (ctx
->Pixel
.BlueBias
== param
)
555 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
556 ctx
->Pixel
.BlueBias
= param
;
559 if (ctx
->Pixel
.AlphaScale
== param
)
561 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
562 ctx
->Pixel
.AlphaScale
= param
;
565 if (ctx
->Pixel
.AlphaBias
== param
)
567 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
568 ctx
->Pixel
.AlphaBias
= param
;
571 if (ctx
->Pixel
.DepthScale
== param
)
573 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
574 ctx
->Pixel
.DepthScale
= param
;
577 if (ctx
->Pixel
.DepthBias
== param
)
579 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
580 ctx
->Pixel
.DepthBias
= param
;
583 _mesa_error( ctx
, GL_INVALID_ENUM
, "glPixelTransfer(pname)" );
590 _mesa_PixelTransferi( GLenum pname
, GLint param
)
592 _mesa_PixelTransferf( pname
, (GLfloat
) param
);
597 /**********************************************************************/
598 /***** State Management *****/
599 /**********************************************************************/
602 * Return a bitmask of IMAGE_*_BIT flags which to indicate which
603 * pixel transfer operations are enabled.
606 update_image_transfer_state(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
;
627 * Update mesa pixel transfer derived state.
629 void _mesa_update_pixel( struct gl_context
*ctx
, GLuint new_state
)
631 if (new_state
& _NEW_PIXEL
)
632 update_image_transfer_state(ctx
);
636 /**********************************************************************/
637 /***** Initialization *****/
638 /**********************************************************************/
641 init_pixelmap(struct gl_pixelmap
*map
)
649 * Initialize the context's PIXEL attribute group.
652 _mesa_init_pixel( struct gl_context
*ctx
)
655 ctx
->Pixel
.RedBias
= 0.0;
656 ctx
->Pixel
.RedScale
= 1.0;
657 ctx
->Pixel
.GreenBias
= 0.0;
658 ctx
->Pixel
.GreenScale
= 1.0;
659 ctx
->Pixel
.BlueBias
= 0.0;
660 ctx
->Pixel
.BlueScale
= 1.0;
661 ctx
->Pixel
.AlphaBias
= 0.0;
662 ctx
->Pixel
.AlphaScale
= 1.0;
663 ctx
->Pixel
.DepthBias
= 0.0;
664 ctx
->Pixel
.DepthScale
= 1.0;
665 ctx
->Pixel
.IndexOffset
= 0;
666 ctx
->Pixel
.IndexShift
= 0;
667 ctx
->Pixel
.ZoomX
= 1.0;
668 ctx
->Pixel
.ZoomY
= 1.0;
669 ctx
->Pixel
.MapColorFlag
= GL_FALSE
;
670 ctx
->Pixel
.MapStencilFlag
= GL_FALSE
;
671 init_pixelmap(&ctx
->PixelMaps
.StoS
);
672 init_pixelmap(&ctx
->PixelMaps
.ItoI
);
673 init_pixelmap(&ctx
->PixelMaps
.ItoR
);
674 init_pixelmap(&ctx
->PixelMaps
.ItoG
);
675 init_pixelmap(&ctx
->PixelMaps
.ItoB
);
676 init_pixelmap(&ctx
->PixelMaps
.ItoA
);
677 init_pixelmap(&ctx
->PixelMaps
.RtoR
);
678 init_pixelmap(&ctx
->PixelMaps
.GtoG
);
679 init_pixelmap(&ctx
->PixelMaps
.BtoB
);
680 init_pixelmap(&ctx
->PixelMaps
.AtoA
);
682 if (ctx
->Visual
.doubleBufferMode
) {
683 ctx
->Pixel
.ReadBuffer
= GL_BACK
;
686 ctx
->Pixel
.ReadBuffer
= GL_FRONT
;
690 ctx
->_ImageTransferState
= 0;