7162c6fef0a3eb943442892d94b0b327c19d3e84
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"
39 #include "main/dispatch.h"
42 /**********************************************************************/
43 /***** glPixelZoom *****/
44 /**********************************************************************/
47 _mesa_PixelZoom( GLfloat xfactor
, GLfloat yfactor
)
49 GET_CURRENT_CONTEXT(ctx
);
51 if (ctx
->Pixel
.ZoomX
== xfactor
&&
52 ctx
->Pixel
.ZoomY
== yfactor
)
55 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
56 ctx
->Pixel
.ZoomX
= xfactor
;
57 ctx
->Pixel
.ZoomY
= yfactor
;
62 /**********************************************************************/
63 /***** glPixelMap *****/
64 /**********************************************************************/
67 * Return pointer to a pixelmap by name.
69 static struct gl_pixelmap
*
70 get_pixelmap(struct gl_context
*ctx
, GLenum map
)
73 case GL_PIXEL_MAP_I_TO_I
:
74 return &ctx
->PixelMaps
.ItoI
;
75 case GL_PIXEL_MAP_S_TO_S
:
76 return &ctx
->PixelMaps
.StoS
;
77 case GL_PIXEL_MAP_I_TO_R
:
78 return &ctx
->PixelMaps
.ItoR
;
79 case GL_PIXEL_MAP_I_TO_G
:
80 return &ctx
->PixelMaps
.ItoG
;
81 case GL_PIXEL_MAP_I_TO_B
:
82 return &ctx
->PixelMaps
.ItoB
;
83 case GL_PIXEL_MAP_I_TO_A
:
84 return &ctx
->PixelMaps
.ItoA
;
85 case GL_PIXEL_MAP_R_TO_R
:
86 return &ctx
->PixelMaps
.RtoR
;
87 case GL_PIXEL_MAP_G_TO_G
:
88 return &ctx
->PixelMaps
.GtoG
;
89 case GL_PIXEL_MAP_B_TO_B
:
90 return &ctx
->PixelMaps
.BtoB
;
91 case GL_PIXEL_MAP_A_TO_A
:
92 return &ctx
->PixelMaps
.AtoA
;
100 * Helper routine used by the other _mesa_PixelMap() functions.
103 store_pixelmap(struct gl_context
*ctx
, GLenum map
, GLsizei mapsize
,
104 const GLfloat
*values
)
107 struct gl_pixelmap
*pm
= get_pixelmap(ctx
, map
);
109 _mesa_error(ctx
, GL_INVALID_ENUM
, "glPixelMap(map)");
114 case GL_PIXEL_MAP_S_TO_S
:
116 ctx
->PixelMaps
.StoS
.Size
= mapsize
;
117 for (i
= 0; i
< mapsize
; i
++) {
118 ctx
->PixelMaps
.StoS
.Map
[i
] = (GLfloat
)IROUND(values
[i
]);
121 case GL_PIXEL_MAP_I_TO_I
:
123 ctx
->PixelMaps
.ItoI
.Size
= mapsize
;
124 for (i
= 0; i
< mapsize
; i
++) {
125 ctx
->PixelMaps
.ItoI
.Map
[i
] = values
[i
];
131 for (i
= 0; i
< mapsize
; i
++) {
132 GLfloat val
= CLAMP(values
[i
], 0.0F
, 1.0F
);
140 * Convenience wrapper for _mesa_validate_pbo_access() for gl[Get]PixelMap().
143 validate_pbo_access(struct gl_context
*ctx
,
144 struct gl_pixelstore_attrib
*pack
, GLsizei mapsize
,
145 GLenum format
, GLenum type
, GLsizei clientMemSize
,
150 /* Note, need to use DefaultPacking and Unpack's buffer object */
151 _mesa_reference_buffer_object(ctx
,
152 &ctx
->DefaultPacking
.BufferObj
,
155 ok
= _mesa_validate_pbo_access(1, &ctx
->DefaultPacking
, mapsize
, 1, 1,
156 format
, type
, clientMemSize
, ptr
);
159 _mesa_reference_buffer_object(ctx
,
160 &ctx
->DefaultPacking
.BufferObj
,
161 ctx
->Shared
->NullBufferObj
);
164 if (_mesa_is_bufferobj(pack
->BufferObj
)) {
165 _mesa_error(ctx
, GL_INVALID_OPERATION
,
166 "gl[Get]PixelMap*v(out of bounds PBO access)");
168 _mesa_error(ctx
, GL_INVALID_OPERATION
,
169 "glGetnPixelMap*vARB(out of bounds access:"
170 " bufSize (%d) is too small)", clientMemSize
);
178 _mesa_PixelMapfv( GLenum map
, GLsizei mapsize
, const GLfloat
*values
)
180 GET_CURRENT_CONTEXT(ctx
);
182 /* XXX someday, test against ctx->Const.MaxPixelMapTableSize */
183 if (mapsize
< 1 || mapsize
> MAX_PIXEL_MAP_TABLE
) {
184 _mesa_error( ctx
, GL_INVALID_VALUE
, "glPixelMapfv(mapsize)" );
188 if (map
>= GL_PIXEL_MAP_S_TO_S
&& map
<= GL_PIXEL_MAP_I_TO_A
) {
189 /* test that mapsize is a power of two */
190 if (!_mesa_is_pow_two(mapsize
)) {
191 _mesa_error( ctx
, GL_INVALID_VALUE
, "glPixelMapfv(mapsize)" );
196 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
198 if (!validate_pbo_access(ctx
, &ctx
->Unpack
, mapsize
, GL_INTENSITY
,
199 GL_FLOAT
, INT_MAX
, values
)) {
203 values
= (const GLfloat
*) _mesa_map_pbo_source(ctx
, &ctx
->Unpack
, values
);
205 if (_mesa_is_bufferobj(ctx
->Unpack
.BufferObj
)) {
206 _mesa_error(ctx
, GL_INVALID_OPERATION
,
207 "glPixelMapfv(PBO is mapped)");
212 store_pixelmap(ctx
, map
, mapsize
, values
);
214 _mesa_unmap_pbo_source(ctx
, &ctx
->Unpack
);
219 _mesa_PixelMapuiv(GLenum map
, GLsizei mapsize
, const GLuint
*values
)
221 GLfloat fvalues
[MAX_PIXEL_MAP_TABLE
];
222 GET_CURRENT_CONTEXT(ctx
);
224 if (mapsize
< 1 || mapsize
> MAX_PIXEL_MAP_TABLE
) {
225 _mesa_error( ctx
, GL_INVALID_VALUE
, "glPixelMapuiv(mapsize)" );
229 if (map
>= GL_PIXEL_MAP_S_TO_S
&& map
<= GL_PIXEL_MAP_I_TO_A
) {
230 /* test that mapsize is a power of two */
231 if (!_mesa_is_pow_two(mapsize
)) {
232 _mesa_error( ctx
, GL_INVALID_VALUE
, "glPixelMapuiv(mapsize)" );
237 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
239 if (!validate_pbo_access(ctx
, &ctx
->Unpack
, mapsize
, GL_INTENSITY
,
240 GL_UNSIGNED_INT
, INT_MAX
, values
)) {
244 values
= (const GLuint
*) _mesa_map_pbo_source(ctx
, &ctx
->Unpack
, values
);
246 if (_mesa_is_bufferobj(ctx
->Unpack
.BufferObj
)) {
247 _mesa_error(ctx
, GL_INVALID_OPERATION
,
248 "glPixelMapuiv(PBO is mapped)");
253 /* convert to floats */
254 if (map
== GL_PIXEL_MAP_I_TO_I
|| map
== GL_PIXEL_MAP_S_TO_S
) {
256 for (i
= 0; i
< mapsize
; i
++) {
257 fvalues
[i
] = (GLfloat
) values
[i
];
262 for (i
= 0; i
< mapsize
; i
++) {
263 fvalues
[i
] = UINT_TO_FLOAT( values
[i
] );
267 _mesa_unmap_pbo_source(ctx
, &ctx
->Unpack
);
269 store_pixelmap(ctx
, map
, mapsize
, fvalues
);
274 _mesa_PixelMapusv(GLenum map
, GLsizei mapsize
, const GLushort
*values
)
276 GLfloat fvalues
[MAX_PIXEL_MAP_TABLE
];
277 GET_CURRENT_CONTEXT(ctx
);
279 if (mapsize
< 1 || mapsize
> MAX_PIXEL_MAP_TABLE
) {
280 _mesa_error( ctx
, GL_INVALID_VALUE
, "glPixelMapusv(mapsize)" );
284 if (map
>= GL_PIXEL_MAP_S_TO_S
&& map
<= GL_PIXEL_MAP_I_TO_A
) {
285 /* test that mapsize is a power of two */
286 if (!_mesa_is_pow_two(mapsize
)) {
287 _mesa_error( ctx
, GL_INVALID_VALUE
, "glPixelMapuiv(mapsize)" );
292 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
294 if (!validate_pbo_access(ctx
, &ctx
->Unpack
, mapsize
, GL_INTENSITY
,
295 GL_UNSIGNED_SHORT
, INT_MAX
, values
)) {
299 values
= (const GLushort
*) _mesa_map_pbo_source(ctx
, &ctx
->Unpack
, values
);
301 if (_mesa_is_bufferobj(ctx
->Unpack
.BufferObj
)) {
302 _mesa_error(ctx
, GL_INVALID_OPERATION
,
303 "glPixelMapusv(PBO is mapped)");
308 /* convert to floats */
309 if (map
== GL_PIXEL_MAP_I_TO_I
|| map
== GL_PIXEL_MAP_S_TO_S
) {
311 for (i
= 0; i
< mapsize
; i
++) {
312 fvalues
[i
] = (GLfloat
) values
[i
];
317 for (i
= 0; i
< mapsize
; i
++) {
318 fvalues
[i
] = USHORT_TO_FLOAT( values
[i
] );
322 _mesa_unmap_pbo_source(ctx
, &ctx
->Unpack
);
324 store_pixelmap(ctx
, map
, mapsize
, fvalues
);
329 _mesa_GetnPixelMapfvARB( GLenum map
, GLsizei bufSize
, GLfloat
*values
)
331 GET_CURRENT_CONTEXT(ctx
);
333 const struct gl_pixelmap
*pm
;
335 pm
= get_pixelmap(ctx
, map
);
337 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetPixelMapfv(map)");
343 if (!validate_pbo_access(ctx
, &ctx
->Pack
, mapsize
, GL_INTENSITY
,
344 GL_FLOAT
, bufSize
, values
)) {
348 values
= (GLfloat
*) _mesa_map_pbo_dest(ctx
, &ctx
->Pack
, values
);
350 if (_mesa_is_bufferobj(ctx
->Pack
.BufferObj
)) {
351 _mesa_error(ctx
, GL_INVALID_OPERATION
,
352 "glGetPixelMapfv(PBO is mapped)");
357 if (map
== GL_PIXEL_MAP_S_TO_S
) {
359 for (i
= 0; i
< mapsize
; i
++) {
360 values
[i
] = (GLfloat
) ctx
->PixelMaps
.StoS
.Map
[i
];
364 memcpy(values
, pm
->Map
, mapsize
* sizeof(GLfloat
));
367 _mesa_unmap_pbo_dest(ctx
, &ctx
->Pack
);
372 _mesa_GetPixelMapfv( GLenum map
, GLfloat
*values
)
374 _mesa_GetnPixelMapfvARB(map
, INT_MAX
, values
);
378 _mesa_GetnPixelMapuivARB( GLenum map
, GLsizei bufSize
, GLuint
*values
)
380 GET_CURRENT_CONTEXT(ctx
);
382 const struct gl_pixelmap
*pm
;
384 pm
= get_pixelmap(ctx
, map
);
386 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetPixelMapuiv(map)");
392 if (!validate_pbo_access(ctx
, &ctx
->Pack
, mapsize
, GL_INTENSITY
,
393 GL_UNSIGNED_INT
, bufSize
, values
)) {
397 values
= (GLuint
*) _mesa_map_pbo_dest(ctx
, &ctx
->Pack
, values
);
399 if (_mesa_is_bufferobj(ctx
->Pack
.BufferObj
)) {
400 _mesa_error(ctx
, GL_INVALID_OPERATION
,
401 "glGetPixelMapuiv(PBO is mapped)");
406 if (map
== GL_PIXEL_MAP_S_TO_S
) {
408 memcpy(values
, ctx
->PixelMaps
.StoS
.Map
, mapsize
* sizeof(GLint
));
411 for (i
= 0; i
< mapsize
; i
++) {
412 values
[i
] = FLOAT_TO_UINT( pm
->Map
[i
] );
416 _mesa_unmap_pbo_dest(ctx
, &ctx
->Pack
);
421 _mesa_GetPixelMapuiv( GLenum map
, GLuint
*values
)
423 _mesa_GetnPixelMapuivARB(map
, INT_MAX
, values
);
427 _mesa_GetnPixelMapusvARB( GLenum map
, GLsizei bufSize
, GLushort
*values
)
429 GET_CURRENT_CONTEXT(ctx
);
431 const struct gl_pixelmap
*pm
;
433 pm
= get_pixelmap(ctx
, map
);
435 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetPixelMapusv(map)");
441 if (!validate_pbo_access(ctx
, &ctx
->Pack
, mapsize
, GL_INTENSITY
,
442 GL_UNSIGNED_SHORT
, bufSize
, values
)) {
446 values
= (GLushort
*) _mesa_map_pbo_dest(ctx
, &ctx
->Pack
, values
);
448 if (_mesa_is_bufferobj(ctx
->Pack
.BufferObj
)) {
449 _mesa_error(ctx
, GL_INVALID_OPERATION
,
450 "glGetPixelMapusv(PBO is mapped)");
457 case GL_PIXEL_MAP_I_TO_I
:
458 for (i
= 0; i
< mapsize
; i
++) {
459 values
[i
] = (GLushort
) CLAMP(ctx
->PixelMaps
.ItoI
.Map
[i
], 0.0, 65535.);
462 case GL_PIXEL_MAP_S_TO_S
:
463 for (i
= 0; i
< mapsize
; i
++) {
464 values
[i
] = (GLushort
) CLAMP(ctx
->PixelMaps
.StoS
.Map
[i
], 0.0, 65535.);
468 for (i
= 0; i
< mapsize
; i
++) {
469 CLAMPED_FLOAT_TO_USHORT(values
[i
], pm
->Map
[i
] );
473 _mesa_unmap_pbo_dest(ctx
, &ctx
->Pack
);
478 _mesa_GetPixelMapusv( GLenum map
, GLushort
*values
)
480 _mesa_GetnPixelMapusvARB(map
, INT_MAX
, values
);
484 /**********************************************************************/
485 /***** glPixelTransfer *****/
486 /**********************************************************************/
490 * Implements glPixelTransfer[fi] whether called immediately or from a
494 _mesa_PixelTransferf( GLenum pname
, GLfloat param
)
496 GET_CURRENT_CONTEXT(ctx
);
500 if (ctx
->Pixel
.MapColorFlag
== (param
? GL_TRUE
: GL_FALSE
))
502 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
503 ctx
->Pixel
.MapColorFlag
= param
? GL_TRUE
: GL_FALSE
;
506 if (ctx
->Pixel
.MapStencilFlag
== (param
? GL_TRUE
: GL_FALSE
))
508 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
509 ctx
->Pixel
.MapStencilFlag
= param
? GL_TRUE
: GL_FALSE
;
512 if (ctx
->Pixel
.IndexShift
== (GLint
) param
)
514 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
515 ctx
->Pixel
.IndexShift
= (GLint
) param
;
517 case GL_INDEX_OFFSET
:
518 if (ctx
->Pixel
.IndexOffset
== (GLint
) param
)
520 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
521 ctx
->Pixel
.IndexOffset
= (GLint
) param
;
524 if (ctx
->Pixel
.RedScale
== param
)
526 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
527 ctx
->Pixel
.RedScale
= param
;
530 if (ctx
->Pixel
.RedBias
== param
)
532 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
533 ctx
->Pixel
.RedBias
= param
;
536 if (ctx
->Pixel
.GreenScale
== param
)
538 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
539 ctx
->Pixel
.GreenScale
= param
;
542 if (ctx
->Pixel
.GreenBias
== param
)
544 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
545 ctx
->Pixel
.GreenBias
= param
;
548 if (ctx
->Pixel
.BlueScale
== param
)
550 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
551 ctx
->Pixel
.BlueScale
= param
;
554 if (ctx
->Pixel
.BlueBias
== param
)
556 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
557 ctx
->Pixel
.BlueBias
= param
;
560 if (ctx
->Pixel
.AlphaScale
== param
)
562 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
563 ctx
->Pixel
.AlphaScale
= param
;
566 if (ctx
->Pixel
.AlphaBias
== param
)
568 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
569 ctx
->Pixel
.AlphaBias
= param
;
572 if (ctx
->Pixel
.DepthScale
== param
)
574 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
575 ctx
->Pixel
.DepthScale
= param
;
578 if (ctx
->Pixel
.DepthBias
== param
)
580 FLUSH_VERTICES(ctx
, _NEW_PIXEL
);
581 ctx
->Pixel
.DepthBias
= param
;
584 _mesa_error( ctx
, GL_INVALID_ENUM
, "glPixelTransfer(pname)" );
591 _mesa_PixelTransferi( GLenum pname
, GLint param
)
593 _mesa_PixelTransferf( pname
, (GLfloat
) param
);
598 /**********************************************************************/
599 /***** State Management *****/
600 /**********************************************************************/
603 * Return a bitmask of IMAGE_*_BIT flags which to indicate which
604 * pixel transfer operations are enabled.
607 update_image_transfer_state(struct gl_context
*ctx
)
611 if (ctx
->Pixel
.RedScale
!= 1.0F
|| ctx
->Pixel
.RedBias
!= 0.0F
||
612 ctx
->Pixel
.GreenScale
!= 1.0F
|| ctx
->Pixel
.GreenBias
!= 0.0F
||
613 ctx
->Pixel
.BlueScale
!= 1.0F
|| ctx
->Pixel
.BlueBias
!= 0.0F
||
614 ctx
->Pixel
.AlphaScale
!= 1.0F
|| ctx
->Pixel
.AlphaBias
!= 0.0F
)
615 mask
|= IMAGE_SCALE_BIAS_BIT
;
617 if (ctx
->Pixel
.IndexShift
|| ctx
->Pixel
.IndexOffset
)
618 mask
|= IMAGE_SHIFT_OFFSET_BIT
;
620 if (ctx
->Pixel
.MapColorFlag
)
621 mask
|= IMAGE_MAP_COLOR_BIT
;
623 ctx
->_ImageTransferState
= mask
;
628 * Update mesa pixel transfer derived state.
630 void _mesa_update_pixel( struct gl_context
*ctx
, GLuint new_state
)
632 if (new_state
& _NEW_PIXEL
)
633 update_image_transfer_state(ctx
);
637 /**********************************************************************/
638 /***** Initialization *****/
639 /**********************************************************************/
642 init_pixelmap(struct gl_pixelmap
*map
)
650 * Initialize the context's PIXEL attribute group.
653 _mesa_init_pixel( struct gl_context
*ctx
)
656 ctx
->Pixel
.RedBias
= 0.0;
657 ctx
->Pixel
.RedScale
= 1.0;
658 ctx
->Pixel
.GreenBias
= 0.0;
659 ctx
->Pixel
.GreenScale
= 1.0;
660 ctx
->Pixel
.BlueBias
= 0.0;
661 ctx
->Pixel
.BlueScale
= 1.0;
662 ctx
->Pixel
.AlphaBias
= 0.0;
663 ctx
->Pixel
.AlphaScale
= 1.0;
664 ctx
->Pixel
.DepthBias
= 0.0;
665 ctx
->Pixel
.DepthScale
= 1.0;
666 ctx
->Pixel
.IndexOffset
= 0;
667 ctx
->Pixel
.IndexShift
= 0;
668 ctx
->Pixel
.ZoomX
= 1.0;
669 ctx
->Pixel
.ZoomY
= 1.0;
670 ctx
->Pixel
.MapColorFlag
= GL_FALSE
;
671 ctx
->Pixel
.MapStencilFlag
= GL_FALSE
;
672 init_pixelmap(&ctx
->PixelMaps
.StoS
);
673 init_pixelmap(&ctx
->PixelMaps
.ItoI
);
674 init_pixelmap(&ctx
->PixelMaps
.ItoR
);
675 init_pixelmap(&ctx
->PixelMaps
.ItoG
);
676 init_pixelmap(&ctx
->PixelMaps
.ItoB
);
677 init_pixelmap(&ctx
->PixelMaps
.ItoA
);
678 init_pixelmap(&ctx
->PixelMaps
.RtoR
);
679 init_pixelmap(&ctx
->PixelMaps
.GtoG
);
680 init_pixelmap(&ctx
->PixelMaps
.BtoB
);
681 init_pixelmap(&ctx
->PixelMaps
.AtoA
);
683 if (ctx
->Visual
.doubleBufferMode
) {
684 ctx
->Pixel
.ReadBuffer
= GL_BACK
;
687 ctx
->Pixel
.ReadBuffer
= GL_FRONT
;
691 ctx
->_ImageTransferState
= 0;