intel_pixel_read.c revision c8e6a0f2f8637d803006d207bb2fb8e4292bdb28
1/************************************************************************** 2 * 3 * Copyright 2003 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/glheader.h" 29#include "main/enums.h" 30#include "main/mtypes.h" 31#include "main/macros.h" 32#include "main/image.h" 33#include "main/bufferobj.h" 34#include "main/state.h" 35#include "swrast/swrast.h" 36 37#include "intel_screen.h" 38#include "intel_context.h" 39#include "intel_blit.h" 40#include "intel_buffers.h" 41#include "intel_regions.h" 42#include "intel_pixel.h" 43#include "intel_buffer_objects.h" 44 45/* For many applications, the new ability to pull the source buffers 46 * back out of the GTT and then do the packing/conversion operations 47 * in software will be as much of an improvement as trying to get the 48 * blitter and/or texture engine to do the work. 49 * 50 * This step is gated on private backbuffers. 51 * 52 * Obviously the frontbuffer can't be pulled back, so that is either 53 * an argument for blit/texture readpixels, or for blitting to a 54 * temporary and then pulling that back. 55 * 56 * When the destination is a pbo, however, it's not clear if it is 57 * ever going to be pulled to main memory (though the access param 58 * will be a good hint). So it sounds like we do want to be able to 59 * choose between blit/texture implementation on the gpu and pullback 60 * and cpu-based copying. 61 * 62 * Unless you can magically turn client memory into a PBO for the 63 * duration of this call, there will be a cpu-based copying step in 64 * any case. 65 */ 66 67 68static GLboolean 69do_texture_readpixels(GLcontext * ctx, 70 GLint x, GLint y, GLsizei width, GLsizei height, 71 GLenum format, GLenum type, 72 const struct gl_pixelstore_attrib *pack, 73 struct intel_region *dest_region) 74{ 75#if 0 76 struct intel_context *intel = intel_context(ctx); 77 intelScreenPrivate *screen = intel->intelScreen; 78 GLint pitch = pack->RowLength ? pack->RowLength : width; 79 __DRIdrawable *dPriv = intel->driDrawable; 80 int textureFormat; 81 GLenum glTextureFormat; 82 int destFormat, depthFormat, destPitch; 83 drm_clip_rect_t tmp; 84 85 if (INTEL_DEBUG & DEBUG_PIXEL) 86 fprintf(stderr, "%s\n", __FUNCTION__); 87 88 89 if (ctx->_ImageTransferState || 90 pack->SwapBytes || pack->LsbFirst || !pack->Invert) { 91 if (INTEL_DEBUG & DEBUG_PIXEL) 92 fprintf(stderr, "%s: check_color failed\n", __FUNCTION__); 93 return GL_FALSE; 94 } 95 96 intel->vtbl.meta_texrect_source(intel, intel_readbuf_region(intel)); 97 98 if (!intel->vtbl.meta_render_dest(intel, dest_region, type, format)) { 99 if (INTEL_DEBUG & DEBUG_PIXEL) 100 fprintf(stderr, "%s: couldn't set dest %s/%s\n", 101 __FUNCTION__, 102 _mesa_lookup_enum_by_nr(type), 103 _mesa_lookup_enum_by_nr(format)); 104 return GL_FALSE; 105 } 106 107 if (intel->driDrawable->numClipRects) { 108 intel->vtbl.install_meta_state(intel); 109 intel->vtbl.meta_no_depth_write(intel); 110 intel->vtbl.meta_no_stencil_write(intel); 111 112 if (!driClipRectToFramebuffer(ctx->ReadBuffer, &x, &y, &width, &height)) { 113 SET_STATE(i830, state); 114 if (INTEL_DEBUG & DEBUG_PIXEL) 115 fprintf(stderr, "%s: cliprect failed\n", __FUNCTION__); 116 return GL_TRUE; 117 } 118 119 y = dPriv->h - y - height; 120 x += dPriv->x; 121 y += dPriv->y; 122 123 124 /* Set the frontbuffer up as a large rectangular texture. 125 */ 126 intel->vtbl.meta_tex_rect_source(intel, src_region, textureFormat); 127 128 129 intel->vtbl.meta_texture_blend_replace(i830, glTextureFormat); 130 131 132 /* Set the 3d engine to draw into the destination region: 133 */ 134 135 intel->vtbl.meta_draw_region(intel, dest_region); 136 intel->vtbl.meta_draw_format(intel, destFormat, depthFormat); /* ?? */ 137 138 139 /* Draw a single quad, no cliprects: 140 */ 141 intel->vtbl.meta_disable_cliprects(intel); 142 143 intel->vtbl.draw_quad(intel, 144 0, width, 0, height, 145 0x00ff00ff, x, x + width, y, y + height); 146 147 intel->vtbl.leave_meta_state(intel); 148 } 149 150 intel_region_wait_fence(ctx, dest_region); /* required by GL */ 151 return GL_TRUE; 152#endif 153 154 return GL_FALSE; 155} 156 157 158 159 160static GLboolean 161do_blit_readpixels(GLcontext * ctx, 162 GLint x, GLint y, GLsizei width, GLsizei height, 163 GLenum format, GLenum type, 164 const struct gl_pixelstore_attrib *pack, GLvoid * pixels) 165{ 166 struct intel_context *intel = intel_context(ctx); 167 struct intel_region *src = intel_readbuf_region(intel); 168 struct intel_buffer_object *dst = intel_buffer_object(pack->BufferObj); 169 GLuint dst_offset; 170 GLuint rowLength; 171 drm_intel_bo *dst_buffer; 172 GLboolean all; 173 GLint dst_x, dst_y; 174 175 if (INTEL_DEBUG & DEBUG_PIXEL) 176 _mesa_printf("%s\n", __FUNCTION__); 177 178 if (!src) 179 return GL_FALSE; 180 181 if (!_mesa_is_bufferobj(pack->BufferObj)) { 182 /* PBO only for now: 183 */ 184 if (INTEL_DEBUG & DEBUG_PIXEL) 185 _mesa_printf("%s - not PBO\n", __FUNCTION__); 186 return GL_FALSE; 187 } 188 189 190 if (ctx->_ImageTransferState || 191 !intel_check_blit_format(src, format, type)) { 192 if (INTEL_DEBUG & DEBUG_PIXEL) 193 _mesa_printf("%s - bad format for blit\n", __FUNCTION__); 194 return GL_FALSE; 195 } 196 197 if (pack->Alignment != 1 || pack->SwapBytes || pack->LsbFirst) { 198 if (INTEL_DEBUG & DEBUG_PIXEL) 199 _mesa_printf("%s: bad packing params\n", __FUNCTION__); 200 return GL_FALSE; 201 } 202 203 if (pack->RowLength > 0) 204 rowLength = pack->RowLength; 205 else 206 rowLength = width; 207 208 if (pack->Invert) { 209 if (INTEL_DEBUG & DEBUG_PIXEL) 210 _mesa_printf("%s: MESA_PACK_INVERT not done yet\n", __FUNCTION__); 211 return GL_FALSE; 212 } 213 else { 214 if (ctx->ReadBuffer->Name == 0) 215 rowLength = -rowLength; 216 } 217 218 dst_offset = (GLintptr) _mesa_image_address(2, pack, pixels, width, height, 219 format, type, 0, 0, 0); 220 221 if (!_mesa_clip_copytexsubimage(ctx, 222 &dst_x, &dst_y, 223 &x, &y, 224 &width, &height)) { 225 return GL_TRUE; 226 } 227 228 all = (width * height * src->cpp == dst->Base.Size && 229 x == 0 && dst_offset == 0); 230 231 dst_x = 0; 232 dst_y = 0; 233 234 dst_buffer = intel_bufferobj_buffer(intel, dst, 235 all ? INTEL_WRITE_FULL : 236 INTEL_WRITE_PART); 237 238 if (ctx->ReadBuffer->Name == 0) 239 y = ctx->ReadBuffer->Height - (y + height); 240 241 if (!intelEmitCopyBlit(intel, 242 src->cpp, 243 src->pitch, src->buffer, 0, src->tiling, 244 rowLength, dst_buffer, dst_offset, GL_FALSE, 245 x, y, 246 dst_x, dst_y, 247 width, height, 248 GL_COPY)) { 249 return GL_FALSE; 250 } 251 252 if (INTEL_DEBUG & DEBUG_PIXEL) 253 _mesa_printf("%s - DONE\n", __FUNCTION__); 254 255 return GL_TRUE; 256} 257 258void 259intelReadPixels(GLcontext * ctx, 260 GLint x, GLint y, GLsizei width, GLsizei height, 261 GLenum format, GLenum type, 262 const struct gl_pixelstore_attrib *pack, GLvoid * pixels) 263{ 264 if (INTEL_DEBUG & DEBUG_PIXEL) 265 fprintf(stderr, "%s\n", __FUNCTION__); 266 267 intelFlush(ctx); 268 269 if (do_blit_readpixels 270 (ctx, x, y, width, height, format, type, pack, pixels)) 271 return; 272 273#ifdef I915 274 if (do_texture_readpixels 275 (ctx, x, y, width, height, format, type, pack, pixels)) 276 return; 277#else 278 (void)do_blit_readpixels; 279 (void)do_texture_readpixels; 280#endif 281 282 if (INTEL_DEBUG & DEBUG_PIXEL) 283 _mesa_printf("%s: fallback to swrast\n", __FUNCTION__); 284 285 /* Update Mesa state before calling down into _swrast_ReadPixels, as 286 * the spans code requires the computed buffer states to be up to date, 287 * but _swrast_ReadPixels only updates Mesa state after setting up 288 * the spans code. 289 */ 290 291 if (ctx->NewState) 292 _mesa_update_state(ctx); 293 294 _swrast_ReadPixels(ctx, x, y, width, height, format, type, pack, pixels); 295} 296