glsl: add ir_emit_vertex and ir_end_primitive instruction types
[mesa.git] / src / mesa / state_tracker / st_cb_readpixels.c
1 /**************************************************************************
2 *
3 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * 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, sub license, 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 portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 #include "main/image.h"
29 #include "main/pbo.h"
30 #include "main/imports.h"
31 #include "main/readpix.h"
32 #include "main/enums.h"
33 #include "main/framebuffer.h"
34 #include "util/u_inlines.h"
35 #include "util/u_format.h"
36
37 #include "st_cb_fbo.h"
38 #include "st_atom.h"
39 #include "st_context.h"
40 #include "st_cb_bitmap.h"
41 #include "st_cb_readpixels.h"
42 #include "state_tracker/st_cb_texture.h"
43 #include "state_tracker/st_format.h"
44 #include "state_tracker/st_texture.h"
45
46
47 /**
48 * This uses a blit to copy the read buffer to a texture format which matches
49 * the format and type combo and then a fast read-back is done using memcpy.
50 * We can do arbitrary X/Y/Z/W/0/1 swizzling here as long as there is
51 * a format which matches the swizzling.
52 *
53 * If such a format isn't available, we fall back to _mesa_readpixels.
54 *
55 * NOTE: Some drivers use a blit to convert between tiled and linear
56 * texture layouts during texture uploads/downloads, so the blit
57 * we do here should be free in such cases.
58 */
59 static void
60 st_readpixels(struct gl_context *ctx, GLint x, GLint y,
61 GLsizei width, GLsizei height,
62 GLenum format, GLenum type,
63 const struct gl_pixelstore_attrib *pack,
64 GLvoid *pixels)
65 {
66 struct st_context *st = st_context(ctx);
67 struct gl_renderbuffer *rb =
68 _mesa_get_read_renderbuffer_for_format(ctx, format);
69 struct st_renderbuffer *strb = st_renderbuffer(rb);
70 struct pipe_context *pipe = st->pipe;
71 struct pipe_screen *screen = pipe->screen;
72 struct pipe_resource *src;
73 struct pipe_resource *dst = NULL;
74 struct pipe_resource dst_templ;
75 enum pipe_format dst_format, src_format;
76 struct pipe_blit_info blit;
77 unsigned bind = PIPE_BIND_TRANSFER_READ;
78 struct pipe_transfer *tex_xfer;
79 ubyte *map = NULL;
80
81 /* Validate state (to be sure we have up-to-date framebuffer surfaces)
82 * and flush the bitmap cache prior to reading. */
83 st_validate_state(st);
84 st_flush_bitmap_cache(st);
85
86 if (!st->prefer_blit_based_texture_transfer) {
87 goto fallback;
88 }
89
90 /* This must be done after state validation. */
91 src = strb->texture;
92
93 /* XXX Fallback for depth-stencil formats due to an incomplete
94 * stencil blit implementation in some drivers. */
95 if (format == GL_DEPTH_STENCIL) {
96 goto fallback;
97 }
98
99 /* We are creating a texture of the size of the region being read back.
100 * Need to check for NPOT texture support. */
101 if (!screen->get_param(screen, PIPE_CAP_NPOT_TEXTURES) &&
102 (!util_is_power_of_two(width) ||
103 !util_is_power_of_two(height))) {
104 goto fallback;
105 }
106
107 /* If the base internal format and the texture format don't match, we have
108 * to use the slow path. */
109 if (rb->_BaseFormat !=
110 _mesa_get_format_base_format(rb->Format)) {
111 goto fallback;
112 }
113
114 /* See if the texture format already matches the format and type,
115 * in which case the memcpy-based fast path will likely be used and
116 * we don't have to blit. */
117 if (_mesa_format_matches_format_and_type(rb->Format, format,
118 type, pack->SwapBytes)) {
119 goto fallback;
120 }
121
122 if (_mesa_readpixels_needs_slow_path(ctx, format, type, GL_TRUE)) {
123 goto fallback;
124 }
125
126 /* Convert the source format to what is expected by ReadPixels
127 * and see if it's supported. */
128 src_format = util_format_linear(src->format);
129 src_format = util_format_luminance_to_red(src_format);
130 src_format = util_format_intensity_to_red(src_format);
131
132 if (!src_format ||
133 !screen->is_format_supported(screen, src_format, src->target,
134 src->nr_samples,
135 PIPE_BIND_SAMPLER_VIEW)) {
136 goto fallback;
137 }
138
139 if (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL)
140 bind |= PIPE_BIND_DEPTH_STENCIL;
141 else
142 bind |= PIPE_BIND_RENDER_TARGET;
143
144 /* Choose the destination format by finding the best match
145 * for the format+type combo. */
146 dst_format = st_choose_matching_format(screen, bind, format, type,
147 pack->SwapBytes);
148 if (dst_format == PIPE_FORMAT_NONE) {
149 goto fallback;
150 }
151
152 /* create the destination texture */
153 memset(&dst_templ, 0, sizeof(dst_templ));
154 dst_templ.target = PIPE_TEXTURE_2D;
155 dst_templ.format = dst_format;
156 dst_templ.bind = bind;
157 dst_templ.usage = PIPE_USAGE_STAGING;
158
159 st_gl_texture_dims_to_pipe_dims(GL_TEXTURE_2D, width, height, 1,
160 &dst_templ.width0, &dst_templ.height0,
161 &dst_templ.depth0, &dst_templ.array_size);
162
163 dst = screen->resource_create(screen, &dst_templ);
164 if (!dst) {
165 goto fallback;
166 }
167
168 blit.src.resource = src;
169 blit.src.level = strb->rtt_level;
170 blit.src.format = src_format;
171 blit.dst.resource = dst;
172 blit.dst.level = 0;
173 blit.dst.format = dst->format;
174 blit.src.box.x = x;
175 blit.dst.box.x = 0;
176 blit.src.box.y = y;
177 blit.dst.box.y = 0;
178 blit.src.box.z = strb->rtt_face + strb->rtt_slice;
179 blit.dst.box.z = 0;
180 blit.src.box.width = blit.dst.box.width = width;
181 blit.src.box.height = blit.dst.box.height = height;
182 blit.src.box.depth = blit.dst.box.depth = 1;
183 blit.mask = st_get_blit_mask(rb->_BaseFormat, format);
184 blit.filter = PIPE_TEX_FILTER_NEAREST;
185 blit.scissor_enable = FALSE;
186
187 if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) {
188 blit.src.box.y = rb->Height - blit.src.box.y;
189 blit.src.box.height = -blit.src.box.height;
190 }
191
192 /* blit */
193 st->pipe->blit(st->pipe, &blit);
194
195 /* map resources */
196 pixels = _mesa_map_pbo_dest(ctx, pack, pixels);
197
198 map = pipe_transfer_map_3d(pipe, dst, 0, PIPE_TRANSFER_READ,
199 0, 0, 0, width, height, 1, &tex_xfer);
200 if (!map) {
201 _mesa_unmap_pbo_dest(ctx, pack);
202 pipe_resource_reference(&dst, NULL);
203 goto fallback;
204 }
205
206 /* memcpy data into a user buffer */
207 {
208 const uint bytesPerRow = width * util_format_get_blocksize(dst_format);
209 GLuint row;
210
211 for (row = 0; row < (unsigned) height; row++) {
212 GLvoid *dest = _mesa_image_address3d(pack, pixels,
213 width, height, format,
214 type, 0, row, 0);
215 memcpy(dest, map, bytesPerRow);
216 map += tex_xfer->stride;
217 }
218 }
219
220 pipe_transfer_unmap(pipe, tex_xfer);
221 _mesa_unmap_pbo_dest(ctx, pack);
222 pipe_resource_reference(&dst, NULL);
223 return;
224
225 fallback:
226 _mesa_readpixels(ctx, x, y, width, height, format, type, pack, pixels);
227 }
228
229 void st_init_readpixels_functions(struct dd_function_table *functions)
230 {
231 functions->ReadPixels = st_readpixels;
232 }