Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / mesa / drivers / dri / radeon / radeon_pixel_read.c
1 /*
2  * Copyright (C) 2010 Maciej Cencora <m.cencora@gmail.com>
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/image.h"
32 #include "main/state.h"
33 #include "swrast/swrast.h"
34
35 #include "radeon_buffer_objects.h"
36 #include "radeon_common_context.h"
37 #include "radeon_debug.h"
38 #include "radeon_mipmap_tree.h"
39
40 static gl_format gl_format_and_type_to_mesa_format(GLenum format, GLenum type)
41 {
42     switch (format)
43     {
44         case GL_RGB:
45             switch (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;
50             }
51             break;
52         case GL_RGBA:
53             switch (type) {
54                 case GL_FLOAT:
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;
63             }
64             break;
65         case GL_BGRA:
66             switch (type) {
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;
80
81             }
82             break;
83     }
84
85     return MESA_FORMAT_NONE;
86 }
87
88 static GLboolean
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)
93 {
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;
100     intptr_t dst_offset;
101
102     /* It's not worth if number of pixels to copy is really small */
103     if (width * height < 100) {
104         return GL_FALSE;
105     }
106
107     if (dst_format == MESA_FORMAT_NONE ||
108         !radeon->vtbl.check_blit(dst_format) || !radeon->vtbl.blit) {
109         return GL_FALSE;
110     }
111
112     if (ctx->_ImageTransferState || ctx->Color._LogicOpEnabled) {
113         return GL_FALSE;
114     }
115
116     if (pack->SwapBytes || pack->LsbFirst) {
117         return GL_FALSE;
118     }
119
120     if (pack->RowLength > 0) {
121         dst_rowstride = pack->RowLength;
122     } else {
123         dst_rowstride = width;
124     }
125
126     if (!_mesa_clip_copytexsubimage(ctx, &dst_x, &dst_y, &x, &y, &width, &height)) {
127         return GL_TRUE;
128     }
129     assert(x >= 0 && y >= 0);
130
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)
134         return GL_FALSE;
135     dst_imagesize = get_texture_image_size(dst_format,
136                                            aligned_rowstride,
137                                            height, 1, 0);
138
139     if (!_mesa_is_bufferobj(pack->BufferObj))
140     {
141         dst_buffer = radeon_bo_open(radeon->radeonScreen->bom, 0, dst_imagesize, 1024, RADEON_GEM_DOMAIN_GTT, 0);
142         dst_offset = 0;
143     }
144     else
145     {
146         dst_buffer = get_radeon_buffer_object(pack->BufferObj)->bo;
147         dst_offset = (intptr_t)pixels;
148     }
149
150     /* Disable source Y flipping for FBOs */
151     flip_y = (ctx->ReadBuffer->Name == 0);
152     if (pack->Invert) {
153         y = rrb->base.Height - height - y;
154         flip_y = !flip_y;
155     }
156
157     if (radeon->vtbl.blit(ctx,
158                           rrb->bo,
159                           rrb->draw_offset,
160                           rrb->base.Format,
161                           rrb->pitch / rrb->cpp,
162                           rrb->base.Width,
163                           rrb->base.Height,
164                           x,
165                           y,
166                           dst_buffer,
167                           dst_offset,
168                           dst_format,
169                           aligned_rowstride / _mesa_get_format_bytes(dst_format),
170                           width,
171                           height,
172                           0, /* dst_x */
173                           0, /* dst_y */
174                           width,
175                           height,
176                           flip_y))
177     {
178         if (!_mesa_is_bufferobj(pack->BufferObj))
179         {
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);
185         }
186
187         return GL_TRUE;
188     }
189
190     if (!_mesa_is_bufferobj(pack->BufferObj))
191         radeon_bo_unref(dst_buffer);
192
193     return GL_FALSE;
194 }
195
196 void
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)
201 {
202     radeonContextPtr radeon = RADEON_CONTEXT(ctx);
203     radeon_prepare_render(radeon);
204
205     if (do_blit_readpixels(ctx, x, y, width, height, format, type, pack, pixels))
206         return;
207
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
211      * the spans code.
212      */
213
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));
217
218     if (ctx->NewState)
219         _mesa_update_state(ctx);
220
221     _swrast_ReadPixels(ctx, x, y, width, height, format, type, pack, pixels);
222 }