2 * Copyright (C) 2010 Maciej Cencora <m.cencora@gmail.com>
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial
16 * portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
22 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 #include "main/bufferobj.h"
30 #include "main/enums.h"
31 #include "main/image.h"
32 #include "main/state.h"
33 #include "swrast/swrast.h"
35 #include "radeon_common_context.h"
36 #include "radeon_debug.h"
37 #include "radeon_mipmap_tree.h"
39 static gl_format
gl_format_and_type_to_mesa_format(GLenum format
, GLenum type
)
45 case GL_UNSIGNED_SHORT_5_6_5
:
46 return MESA_FORMAT_RGB565
;
47 case GL_UNSIGNED_SHORT_5_6_5_REV
:
48 return MESA_FORMAT_RGB565_REV
;
54 return MESA_FORMAT_RGBA_FLOAT32
;
55 case GL_UNSIGNED_SHORT_5_5_5_1
:
56 return MESA_FORMAT_RGBA5551
;
57 case GL_UNSIGNED_INT_8_8_8_8
:
58 return MESA_FORMAT_RGBA8888
;
59 case GL_UNSIGNED_BYTE
:
60 case GL_UNSIGNED_INT_8_8_8_8_REV
:
61 return MESA_FORMAT_RGBA8888_REV
;
66 case GL_UNSIGNED_SHORT_4_4_4_4
:
67 return MESA_FORMAT_ARGB4444_REV
;
68 case GL_UNSIGNED_SHORT_4_4_4_4_REV
:
69 return MESA_FORMAT_ARGB4444
;
70 case GL_UNSIGNED_SHORT_5_5_5_1
:
71 return MESA_FORMAT_ARGB1555_REV
;
72 case GL_UNSIGNED_SHORT_1_5_5_5_REV
:
73 return MESA_FORMAT_ARGB1555
;
74 case GL_UNSIGNED_INT_8_8_8_8
:
75 return MESA_FORMAT_ARGB8888_REV
;
76 case GL_UNSIGNED_BYTE
:
77 case GL_UNSIGNED_INT_8_8_8_8_REV
:
78 return MESA_FORMAT_ARGB8888
;
84 return MESA_FORMAT_NONE
;
88 do_blit_readpixels(GLcontext
* ctx
,
89 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
90 GLenum format
, GLenum type
,
91 const struct gl_pixelstore_attrib
*pack
, GLvoid
* pixels
)
93 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
94 const struct radeon_renderbuffer
*rrb
= radeon_renderbuffer(ctx
->ReadBuffer
->_ColorReadBuffer
);
95 const gl_format dst_format
= gl_format_and_type_to_mesa_format(format
, type
);
96 unsigned dst_rowstride
, dst_imagesize
, aligned_rowstride
, flip_y
;
97 struct radeon_bo
*dst_buffer
;
98 GLint dst_x
= 0, dst_y
= 0;
100 /* It's not worth if number of pixels to copy is really small */
101 if (width
* height
< 100) {
105 if (dst_format
== MESA_FORMAT_NONE
||
106 !radeon
->vtbl
.check_blit(dst_format
) || !radeon
->vtbl
.blit
) {
110 if (ctx
->_ImageTransferState
|| ctx
->Color
._LogicOpEnabled
) {
114 if (pack
->SwapBytes
|| pack
->LsbFirst
) {
118 if (pack
->RowLength
> 0) {
119 dst_rowstride
= pack
->RowLength
;
121 dst_rowstride
= width
;
124 if (!_mesa_clip_copytexsubimage(ctx
, &dst_x
, &dst_y
, &x
, &y
, &width
, &height
)) {
127 assert(x
>= 0 && y
>= 0);
129 aligned_rowstride
= get_texture_image_row_stride(radeon
, dst_format
, dst_rowstride
, 0);
130 dst_imagesize
= get_texture_image_size(dst_format
,
133 dst_buffer
= radeon_bo_open(radeon
->radeonScreen
->bom
, 0, dst_imagesize
, 1024, RADEON_GEM_DOMAIN_GTT
, 0);
135 /* Disable source Y flipping for FBOs */
136 flip_y
= (ctx
->ReadBuffer
->Name
== 0);
138 y
= rrb
->base
.Height
- height
- y
;
142 if (radeon
->vtbl
.blit(ctx
,
146 rrb
->pitch
/ rrb
->cpp
,
154 aligned_rowstride
/ _mesa_get_format_bytes(dst_format
),
163 radeon_bo_map(dst_buffer
, 0);
164 dst_rowstride
*= _mesa_get_format_bytes(dst_format
);
165 copy_rows(pixels
, dst_rowstride
, dst_buffer
->ptr
,
166 aligned_rowstride
, height
, dst_rowstride
);
167 radeon_bo_unmap(dst_buffer
);
168 radeon_bo_unref(dst_buffer
);
171 radeon_bo_unref(dst_buffer
);
177 radeonReadPixels(GLcontext
* ctx
,
178 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
179 GLenum format
, GLenum type
,
180 const struct gl_pixelstore_attrib
*pack
, GLvoid
* pixels
)
182 if (do_blit_readpixels(ctx
, x
, y
, width
, height
, format
, type
, pack
, pixels
))
185 /* Update Mesa state before calling down into _swrast_ReadPixels, as
186 * the spans code requires the computed buffer states to be up to date,
187 * but _swrast_ReadPixels only updates Mesa state after setting up
191 radeon_print(RADEON_FALLBACKS
, RADEON_NORMAL
,
192 "Falling back to sw for ReadPixels (format %s, type %s)\n",
193 _mesa_lookup_enum_by_nr(format
), _mesa_lookup_enum_by_nr(type
));
196 _mesa_update_state(ctx
);
198 _swrast_ReadPixels(ctx
, x
, y
, width
, height
, format
, type
, pack
, pixels
);