2 * \file radeon_subset_readpix.c
3 * \brief Pixel reading.
5 * \author Keith Whitwell <keith@tungstengraphics.com>
6 * \author Brian Paul <brian@tungstengraphics.com>
10 * Copyright 2003 ATI Technologies Inc., Ontario, Canada, and
11 * Tungsten Graphics Inc., Cedar Park, Texas.
13 * All Rights Reserved.
15 * Permission is hereby granted, free of charge, to any person obtaining a
16 * copy of this software and associated documentation files (the "Software"),
17 * to deal in the Software without restriction, including without limitation
18 * on the rights to use, copy, modify, merge, publish, distribute, sub
19 * license, and/or sell copies of the Software, and to permit persons to whom
20 * the Software is furnished to do so, subject to the following conditions:
22 * The above copyright notice and this permission notice (including the next
23 * paragraph) shall be included in all copies or substantial portions of the
26 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
27 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
28 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
29 * ATI, TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
30 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
31 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
32 * USE OR OTHER DEALINGS IN THE SOFTWARE.
43 /*#include "mmath.h" */
47 #include "radeon_context.h"
48 #include "radeon_ioctl.h"
49 #include "radeon_state.h"
50 #include "radeon_subset.h"
53 * \brief Read pixel in RGBA format on a Radeon 16bpp frame buffer.
55 * \param rgba destination pointer.
56 * \param ptr pointer to the pixel in the frame buffer.
58 #define READ_RGBA_16( rgba, ptr ) \
60 GLushort p = *(GLushort *)ptr; \
61 rgba[0] = ((p >> 8) & 0xf8) * 255 / 0xf8; \
62 rgba[1] = ((p >> 3) & 0xfc) * 255 / 0xfc; \
63 rgba[2] = ((p << 3) & 0xf8) * 255 / 0xf8; \
68 * \brief Read pixel in RGBA format on a Radeon 32bpp frame buffer.
70 * \param rgba destination pointer.
71 * \param ptr pointer to the pixel in the frame buffer.
73 #define READ_RGBA_32( rgba, ptr ) \
75 GLuint p = *(GLuint *)ptr; \
76 rgba[0] = (p >> 16) & 0xff; \
77 rgba[1] = (p >> 8) & 0xff; \
78 rgba[2] = (p >> 0) & 0xff; \
79 rgba[3] = (p >> 24) & 0xff; \
83 * \brief Read a span in RGBA format.
85 * \param ctx GL context.
86 * \param n number of pixels in the span.
87 * \param x x position of the span start.
88 * \param y y position of the span.
89 * \param rgba destination buffer.
91 * Calculates the pointer to the span start in the frame buffer and uses either
92 * #READ_RGBA_16 or #READ_RGBA_32 macros to copy the values.
94 static void ReadRGBASpan( const GLcontext
*ctx
,
95 GLuint n
, GLint x
, GLint y
,
98 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
99 radeonScreenPtr radeonScreen
= rmesa
->radeonScreen
;
100 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
101 GLuint cpp
= radeonScreen
->cpp
;
102 GLuint pitch
= radeonScreen
->frontPitch
* cpp
;
105 if (ctx
->_RotateMode
) {
106 char *ptr
= (char *)(rmesa
->dri
.screen
->pFB
+
107 rmesa
->state
.pixel
.readOffset
+
108 ((dPriv
->x
+ (dPriv
->w
- y
- 1)) * cpp
) +
109 ((dPriv
->y
+ (dPriv
->h
- x
- 1)) * pitch
));
112 for (i
= 0; i
< n
; i
++, ptr
-= pitch
)
113 READ_RGBA_32( rgba
[i
], ptr
);
115 for (i
= 0; i
< n
; i
++, ptr
-= pitch
)
116 READ_RGBA_16( rgba
[i
], ptr
);
119 char *ptr
= (char *)(rmesa
->dri
.screen
->pFB
+
120 rmesa
->state
.pixel
.readOffset
+
121 ((dPriv
->x
+ x
) * cpp
) +
122 ((dPriv
->y
+ (dPriv
->h
- y
- 1)) * pitch
));
125 for (i
= 0; i
< n
; i
++, ptr
+= cpp
)
126 READ_RGBA_32( rgba
[i
], ptr
);
128 for (i
= 0; i
< n
; i
++, ptr
+= cpp
)
129 READ_RGBA_16( rgba
[i
], ptr
);
135 * \brief Optimized glReadPixels().
137 * To be used with particular pixel formats GL_UNSIGNED_BYTE and GL_RGBA, when pixel
138 * scaling, biasing and mapping are disabled.
140 * \param x x start position of the reading rectangle.
141 * \param y y start position of the reading rectangle.
142 * \param width width of the reading rectangle.
143 * \param height height of the reading rectangle.
144 * \param format pixel format. Must be GL_RGBA.
145 * \param type pixel type. Must be GL_UNSIGNED_BYTE.
146 * \param pixels pixel data.
148 * After asserting the above conditions, compensates for clipping and calls
149 * ReadRGBASpan() to read each row.
151 void radeonReadPixels( GLint x
, GLint y
,
152 GLsizei width
, GLsizei height
,
153 GLenum format
, GLenum type
,
156 GET_CURRENT_CONTEXT(ctx
);
159 GLint readWidth
= width
; /* actual width read */
160 GLint readHeight
= height
; /* actual height read */
161 const struct gl_pixelstore_attrib
*packing
= &ctx
->Pack
;
162 GLint skipRows
= packing
->SkipRows
;
163 GLint skipPixels
= packing
->SkipPixels
;
165 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
169 tmp
= x
; x
= y
; y
= tmp
;
170 tmps
= width
; width
= height
; height
= tmps
;
173 if (width
< 0 || height
< 0) {
174 _mesa_error( ctx
, GL_INVALID_VALUE
,
175 "glReadPixels(width=%d height=%d)", width
, height
);
180 _mesa_error( ctx
, GL_INVALID_VALUE
, "glReadPixels(pixels)" );
185 _mesa_update_state(ctx
);
188 /* can't do scale, bias, mapping, etc */
189 assert(!ctx
->_ImageTransferState
);
191 /* can't do fancy pixel packing */
192 assert (packing
->Alignment
== 1 &&
193 !packing
->SwapBytes
&&
197 if (packing
->RowLength
> 0)
198 rowLength
= packing
->RowLength
;
202 /* horizontal clipping */
208 if (srcX
+ readWidth
> (GLint
) ctx
->ReadBuffer
->Width
)
209 readWidth
-= (srcX
+ readWidth
- (GLint
) ctx
->ReadBuffer
->Width
);
213 /* vertical clipping */
219 if (srcY
+ readHeight
> (GLint
) ctx
->ReadBuffer
->Height
)
220 readHeight
-= (srcY
+ readHeight
- (GLint
) ctx
->ReadBuffer
->Height
);
226 * The window region at (destX, destY) of size (readWidth, readHeight)
228 * We'll write pixel data to buffer pointed to by "pixels" but we'll
229 * skip "skipRows" rows and skip "skipPixels" pixels/row.
231 if (format
== GL_RGBA
&& type
== GL_UNSIGNED_BYTE
) {
232 GLchan
*dest
= (GLchan
*) pixels
233 + (skipRows
* rowLength
+ skipPixels
) * 4;
236 for (row
=0; row
<readHeight
; row
++) {
237 ReadRGBASpan(ctx
, readWidth
, srcX
, srcY
, (GLchan (*)[4]) dest
);
238 dest
+= rowLength
* 4;
243 /* can't do this format/type combination */