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_buffer_objects.h"
36 #include "radeon_common_context.h"
37 #include "radeon_debug.h"
38 #include "radeon_mipmap_tree.h"
40 static gl_format
gl_format_and_type_to_mesa_format(GLenum format
, GLenum type
)
46 case GL_UNSIGNED_SHORT_5_6_5
:
47 return MESA_FORMAT_RGB565
;
48 case GL_UNSIGNED_SHORT_5_6_5_REV
:
49 return MESA_FORMAT_RGB565_REV
;
55 return MESA_FORMAT_RGBA_FLOAT32
;
56 case GL_UNSIGNED_SHORT_5_5_5_1
:
57 return MESA_FORMAT_RGBA5551
;
58 case GL_UNSIGNED_INT_8_8_8_8
:
59 return MESA_FORMAT_RGBA8888
;
60 case GL_UNSIGNED_BYTE
:
61 case GL_UNSIGNED_INT_8_8_8_8_REV
:
62 return MESA_FORMAT_RGBA8888_REV
;
67 case GL_UNSIGNED_SHORT_4_4_4_4
:
68 return MESA_FORMAT_ARGB4444_REV
;
69 case GL_UNSIGNED_SHORT_4_4_4_4_REV
:
70 return MESA_FORMAT_ARGB4444
;
71 case GL_UNSIGNED_SHORT_5_5_5_1
:
72 return MESA_FORMAT_ARGB1555_REV
;
73 case GL_UNSIGNED_SHORT_1_5_5_5_REV
:
74 return MESA_FORMAT_ARGB1555
;
75 case GL_UNSIGNED_INT_8_8_8_8
:
76 return MESA_FORMAT_ARGB8888_REV
;
77 case GL_UNSIGNED_BYTE
:
78 case GL_UNSIGNED_INT_8_8_8_8_REV
:
79 return MESA_FORMAT_ARGB8888
;
85 return MESA_FORMAT_NONE
;
89 do_blit_readpixels(struct gl_context
* ctx
,
90 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
91 GLenum format
, GLenum type
,
92 const struct gl_pixelstore_attrib
*pack
, GLvoid
* pixels
)
94 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
95 const struct radeon_renderbuffer
*rrb
= radeon_renderbuffer(ctx
->ReadBuffer
->_ColorReadBuffer
);
96 const gl_format dst_format
= gl_format_and_type_to_mesa_format(format
, type
);
97 unsigned dst_rowstride
, dst_imagesize
, aligned_rowstride
, flip_y
;
98 struct radeon_bo
*dst_buffer
;
99 GLint dst_x
= 0, dst_y
= 0;
102 /* It's not worth if number of pixels to copy is really small */
103 if (width
* height
< 100) {
107 if (dst_format
== MESA_FORMAT_NONE
||
108 !radeon
->vtbl
.check_blit(dst_format
) || !radeon
->vtbl
.blit
) {
112 if (ctx
->_ImageTransferState
|| ctx
->Color
._LogicOpEnabled
) {
116 if (pack
->SwapBytes
|| pack
->LsbFirst
) {
120 if (pack
->RowLength
> 0) {
121 dst_rowstride
= pack
->RowLength
;
123 dst_rowstride
= width
;
126 if (!_mesa_clip_copytexsubimage(ctx
, &dst_x
, &dst_y
, &x
, &y
, &width
, &height
)) {
129 assert(x
>= 0 && y
>= 0);
131 aligned_rowstride
= get_texture_image_row_stride(radeon
, dst_format
, dst_rowstride
, 0);
132 dst_rowstride
*= _mesa_get_format_bytes(dst_format
);
133 if (_mesa_is_bufferobj(pack
->BufferObj
) && aligned_rowstride
!= dst_rowstride
)
135 dst_imagesize
= get_texture_image_size(dst_format
,
139 if (!_mesa_is_bufferobj(pack
->BufferObj
))
141 dst_buffer
= radeon_bo_open(radeon
->radeonScreen
->bom
, 0, dst_imagesize
, 1024, RADEON_GEM_DOMAIN_GTT
, 0);
146 dst_buffer
= get_radeon_buffer_object(pack
->BufferObj
)->bo
;
147 dst_offset
= (intptr_t)pixels
;
150 /* Disable source Y flipping for FBOs */
151 flip_y
= (ctx
->ReadBuffer
->Name
== 0);
153 y
= rrb
->base
.Height
- height
- y
;
157 if (radeon
->vtbl
.blit(ctx
,
161 rrb
->pitch
/ rrb
->cpp
,
169 aligned_rowstride
/ _mesa_get_format_bytes(dst_format
),
178 if (!_mesa_is_bufferobj(pack
->BufferObj
))
180 radeon_bo_map(dst_buffer
, 0);
181 copy_rows(pixels
, dst_rowstride
, dst_buffer
->ptr
,
182 aligned_rowstride
, height
, dst_rowstride
);
183 radeon_bo_unmap(dst_buffer
);
184 radeon_bo_unref(dst_buffer
);
190 if (!_mesa_is_bufferobj(pack
->BufferObj
))
191 radeon_bo_unref(dst_buffer
);
197 radeonReadPixels(struct gl_context
* ctx
,
198 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
199 GLenum format
, GLenum type
,
200 const struct gl_pixelstore_attrib
*pack
, GLvoid
* pixels
)
202 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
203 radeon_prepare_render(radeon
);
205 if (do_blit_readpixels(ctx
, x
, y
, width
, height
, format
, type
, pack
, pixels
))
208 /* Update Mesa state before calling down into _swrast_ReadPixels, as
209 * the spans code requires the computed buffer states to be up to date,
210 * but _swrast_ReadPixels only updates Mesa state after setting up
214 radeon_print(RADEON_FALLBACKS
, RADEON_NORMAL
,
215 "Falling back to sw for ReadPixels (format %s, type %s)\n",
216 _mesa_lookup_enum_by_nr(format
), _mesa_lookup_enum_by_nr(type
));
219 _mesa_update_state(ctx
);
221 _swrast_ReadPixels(ctx
, x
, y
, width
, height
, format
, type
, pack
, pixels
);