Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5564 | serge | 1 | /* |
2 | * Copyright (C) 2010 Maciej Cencora |
||
3 | * |
||
4 | * All Rights Reserved. |
||
5 | * |
||
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: |
||
13 | * |
||
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. |
||
17 | * |
||
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. |
||
25 | * |
||
26 | */ |
||
27 | |||
28 | #include "stdint.h" |
||
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" |
||
35 | |||
36 | #include "radeon_common_context.h" |
||
37 | #include "radeon_buffer_objects.h" |
||
38 | #include "radeon_debug.h" |
||
39 | #include "radeon_mipmap_tree.h" |
||
40 | |||
41 | static mesa_format gl_format_and_type_to_mesa_format(GLenum format, GLenum type) |
||
42 | { |
||
43 | switch (format) |
||
44 | { |
||
45 | case GL_RGB: |
||
46 | switch (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; |
||
51 | } |
||
52 | break; |
||
53 | case GL_RGBA: |
||
54 | switch (type) { |
||
55 | case GL_FLOAT: |
||
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; |
||
64 | } |
||
65 | break; |
||
66 | case GL_BGRA: |
||
67 | switch (type) { |
||
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; |
||
81 | |||
82 | } |
||
83 | break; |
||
84 | } |
||
85 | |||
86 | return MESA_FORMAT_NONE; |
||
87 | } |
||
88 | |||
89 | static GLboolean |
||
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) |
||
94 | { |
||
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; |
||
101 | intptr_t dst_offset; |
||
102 | |||
103 | /* It's not worth if number of pixels to copy is really small */ |
||
104 | if (width * height < 100) { |
||
105 | return GL_FALSE; |
||
106 | } |
||
107 | |||
108 | if (dst_format == MESA_FORMAT_NONE || |
||
109 | !radeon->vtbl.check_blit(dst_format, rrb->pitch / rrb->cpp) || !radeon->vtbl.blit) { |
||
110 | return GL_FALSE; |
||
111 | } |
||
112 | |||
113 | if (ctx->_ImageTransferState || ctx->Color.ColorLogicOpEnabled) { |
||
114 | return GL_FALSE; |
||
115 | } |
||
116 | |||
117 | if (pack->SwapBytes || pack->LsbFirst) { |
||
118 | return GL_FALSE; |
||
119 | } |
||
120 | |||
121 | if (pack->RowLength > 0) { |
||
122 | dst_rowstride = pack->RowLength; |
||
123 | } else { |
||
124 | dst_rowstride = width; |
||
125 | } |
||
126 | |||
127 | if (!_mesa_clip_copytexsubimage(ctx, &dst_x, &dst_y, &x, &y, &width, &height)) { |
||
128 | return GL_TRUE; |
||
129 | } |
||
130 | assert(x >= 0 && y >= 0); |
||
131 | |||
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) |
||
135 | return GL_FALSE; |
||
136 | dst_imagesize = get_texture_image_size(dst_format, |
||
137 | aligned_rowstride, |
||
138 | height, 1, 0); |
||
139 | |||
140 | if (!_mesa_is_bufferobj(pack->BufferObj)) |
||
141 | { |
||
142 | dst_buffer = radeon_bo_open(radeon->radeonScreen->bom, 0, dst_imagesize, 1024, RADEON_GEM_DOMAIN_GTT, 0); |
||
143 | dst_offset = 0; |
||
144 | } |
||
145 | else |
||
146 | { |
||
147 | dst_buffer = get_radeon_buffer_object(pack->BufferObj)->bo; |
||
148 | dst_offset = (intptr_t)pixels; |
||
149 | } |
||
150 | |||
151 | /* Disable source Y flipping for FBOs */ |
||
152 | flip_y = _mesa_is_winsys_fbo(ctx->ReadBuffer); |
||
153 | if (pack->Invert) { |
||
154 | y = rrb->base.Base.Height - height - y; |
||
155 | flip_y = !flip_y; |
||
156 | } |
||
157 | |||
158 | if (radeon->vtbl.blit(ctx, |
||
159 | rrb->bo, |
||
160 | rrb->draw_offset, |
||
161 | rrb->base.Base.Format, |
||
162 | rrb->pitch / rrb->cpp, |
||
163 | rrb->base.Base.Width, |
||
164 | rrb->base.Base.Height, |
||
165 | x, |
||
166 | y, |
||
167 | dst_buffer, |
||
168 | dst_offset, |
||
169 | dst_format, |
||
170 | aligned_rowstride / _mesa_get_format_bytes(dst_format), |
||
171 | width, |
||
172 | height, |
||
173 | 0, /* dst_x */ |
||
174 | 0, /* dst_y */ |
||
175 | width, |
||
176 | height, |
||
177 | flip_y)) |
||
178 | { |
||
179 | if (!_mesa_is_bufferobj(pack->BufferObj)) |
||
180 | { |
||
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); |
||
186 | } |
||
187 | |||
188 | return GL_TRUE; |
||
189 | } |
||
190 | |||
191 | if (!_mesa_is_bufferobj(pack->BufferObj)) |
||
192 | radeon_bo_unref(dst_buffer); |
||
193 | |||
194 | return GL_FALSE; |
||
195 | } |
||
196 | |||
197 | void |
||
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) |
||
202 | { |
||
203 | radeonContextPtr radeon = RADEON_CONTEXT(ctx); |
||
204 | radeon_prepare_render(radeon); |
||
205 | |||
206 | if (do_blit_readpixels(ctx, x, y, width, height, format, type, pack, pixels)) |
||
207 | return; |
||
208 | |||
209 | /* Update Mesa state before calling _mesa_readpixels(). |
||
210 | * XXX this may not be needed since ReadPixels no longer uses the |
||
211 | * span code. |
||
212 | */ |
||
213 | radeon_print(RADEON_FALLBACKS, RADEON_NORMAL, |
||
214 | "Falling back to sw for ReadPixels (format %s, type %s)\n", |
||
215 | _mesa_lookup_enum_by_nr(format), _mesa_lookup_enum_by_nr(type)); |
||
216 | |||
217 | if (ctx->NewState) |
||
218 | _mesa_update_state(ctx); |
||
219 | |||
220 | _mesa_readpixels(ctx, x, y, width, height, format, type, pack, pixels); |
||
221 | }> |