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/fbobject.h"
32 #include "main/image.h"
33 #include "main/readpix.h"
34 #include "main/state.h"
36 #include "radeon_common_context.h"
37 #include "radeon_buffer_objects.h"
38 #include "radeon_debug.h"
39 #include "radeon_mipmap_tree.h"
41 static mesa_format
gl_format_and_type_to_mesa_format(GLenum format
, GLenum type
)
47 case GL_UNSIGNED_SHORT_5_6_5
:
48 return MESA_FORMAT_B5G6R5_UNORM
;
49 case GL_UNSIGNED_SHORT_5_6_5_REV
:
50 return MESA_FORMAT_R5G6B5_UNORM
;
56 return MESA_FORMAT_RGBA_FLOAT32
;
57 case GL_UNSIGNED_SHORT_5_5_5_1
:
58 return MESA_FORMAT_A1B5G5R5_UNORM
;
59 case GL_UNSIGNED_INT_8_8_8_8
:
60 return MESA_FORMAT_A8B8G8R8_UNORM
;
61 case GL_UNSIGNED_BYTE
:
62 case GL_UNSIGNED_INT_8_8_8_8_REV
:
63 return MESA_FORMAT_R8G8B8A8_UNORM
;
68 case GL_UNSIGNED_SHORT_4_4_4_4
:
69 return MESA_FORMAT_A4R4G4B4_UNORM
;
70 case GL_UNSIGNED_SHORT_4_4_4_4_REV
:
71 return MESA_FORMAT_B4G4R4A4_UNORM
;
72 case GL_UNSIGNED_SHORT_5_5_5_1
:
73 return MESA_FORMAT_A1R5G5B5_UNORM
;
74 case GL_UNSIGNED_SHORT_1_5_5_5_REV
:
75 return MESA_FORMAT_B5G5R5A1_UNORM
;
76 case GL_UNSIGNED_INT_8_8_8_8
:
77 return MESA_FORMAT_A8R8G8B8_UNORM
;
78 case GL_UNSIGNED_BYTE
:
79 case GL_UNSIGNED_INT_8_8_8_8_REV
:
80 return MESA_FORMAT_B8G8R8A8_UNORM
;
86 return MESA_FORMAT_NONE
;
90 do_blit_readpixels(struct gl_context
* ctx
,
91 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
92 GLenum format
, GLenum type
,
93 const struct gl_pixelstore_attrib
*pack
, GLvoid
* pixels
)
95 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
96 const struct radeon_renderbuffer
*rrb
= radeon_renderbuffer(ctx
->ReadBuffer
->_ColorReadBuffer
);
97 const mesa_format dst_format
= gl_format_and_type_to_mesa_format(format
, type
);
98 unsigned dst_rowstride
, dst_imagesize
, aligned_rowstride
, flip_y
;
99 struct radeon_bo
*dst_buffer
;
100 GLint dst_x
= 0, dst_y
= 0;
103 /* It's not worth if number of pixels to copy is really small */
104 if (width
* height
< 100) {
108 if (dst_format
== MESA_FORMAT_NONE
||
109 !radeon
->vtbl
.check_blit(dst_format
, rrb
->pitch
/ rrb
->cpp
) || !radeon
->vtbl
.blit
) {
113 if (ctx
->_ImageTransferState
|| ctx
->Color
.ColorLogicOpEnabled
) {
117 if (pack
->SwapBytes
|| pack
->LsbFirst
) {
121 if (pack
->RowLength
> 0) {
122 dst_rowstride
= pack
->RowLength
;
124 dst_rowstride
= width
;
127 if (!_mesa_clip_copytexsubimage(ctx
, &dst_x
, &dst_y
, &x
, &y
, &width
, &height
)) {
130 assert(x
>= 0 && y
>= 0);
132 aligned_rowstride
= get_texture_image_row_stride(radeon
, dst_format
, dst_rowstride
, 0, GL_TEXTURE_2D
);
133 dst_rowstride
*= _mesa_get_format_bytes(dst_format
);
134 if (_mesa_is_bufferobj(pack
->BufferObj
) && aligned_rowstride
!= dst_rowstride
)
136 dst_imagesize
= get_texture_image_size(dst_format
,
140 if (!_mesa_is_bufferobj(pack
->BufferObj
))
142 dst_buffer
= radeon_bo_open(radeon
->radeonScreen
->bom
, 0, dst_imagesize
, 1024, RADEON_GEM_DOMAIN_GTT
, 0);
147 dst_buffer
= get_radeon_buffer_object(pack
->BufferObj
)->bo
;
148 dst_offset
= (intptr_t)pixels
;
151 /* Disable source Y flipping for FBOs */
152 flip_y
= _mesa_is_winsys_fbo(ctx
->ReadBuffer
);
154 y
= rrb
->base
.Base
.Height
- height
- y
;
158 if (radeon
->vtbl
.blit(ctx
,
161 rrb
->base
.Base
.Format
,
162 rrb
->pitch
/ rrb
->cpp
,
163 rrb
->base
.Base
.Width
,
164 rrb
->base
.Base
.Height
,
170 aligned_rowstride
/ _mesa_get_format_bytes(dst_format
),
179 if (!_mesa_is_bufferobj(pack
->BufferObj
))
181 radeon_bo_map(dst_buffer
, 0);
182 copy_rows(pixels
, dst_rowstride
, dst_buffer
->ptr
,
183 aligned_rowstride
, height
, dst_rowstride
);
184 radeon_bo_unmap(dst_buffer
);
185 radeon_bo_unref(dst_buffer
);
191 if (!_mesa_is_bufferobj(pack
->BufferObj
))
192 radeon_bo_unref(dst_buffer
);
198 radeonReadPixels(struct gl_context
* ctx
,
199 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
200 GLenum format
, GLenum type
,
201 const struct gl_pixelstore_attrib
*pack
, GLvoid
* pixels
)
203 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
204 radeon_prepare_render(radeon
);
206 if (do_blit_readpixels(ctx
, x
, y
, width
, height
, format
, type
, pack
, pixels
))
209 /* Update Mesa state before calling _mesa_readpixels().
210 * XXX this may not be needed since ReadPixels no longer uses the
213 radeon_print(RADEON_FALLBACKS
, RADEON_NORMAL
,
214 "Falling back to sw for ReadPixels (format %s, type %s)\n",
215 _mesa_enum_to_string(format
), _mesa_enum_to_string(type
));
218 _mesa_update_state(ctx
);
220 _mesa_readpixels(ctx
, x
, y
, width
, height
, format
, type
, pack
, pixels
);