intel_pixel_read.c revision 2855ee82c6d74066e8d9e44b17b2ce3b5782110e
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 "swrast/swrast.h" 35 36#include "intel_screen.h" 37#include "intel_context.h" 38#include "intel_batchbuffer.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 __DRIdrawablePrivate *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 LOCK_HARDWARE(intel); 108 109 if (intel->driDrawable->numClipRects) { 110 intel->vtbl.install_meta_state(intel); 111 intel->vtbl.meta_no_depth_write(intel); 112 intel->vtbl.meta_no_stencil_write(intel); 113 114 if (!driClipRectToFramebuffer(ctx->ReadBuffer, &x, &y, &width, &height)) { 115 UNLOCK_HARDWARE(intel); 116 SET_STATE(i830, state); 117 if (INTEL_DEBUG & DEBUG_PIXEL) 118 fprintf(stderr, "%s: cliprect failed\n", __FUNCTION__); 119 return GL_TRUE; 120 } 121 122 y = dPriv->h - y - height; 123 x += dPriv->x; 124 y += dPriv->y; 125 126 127 /* Set the frontbuffer up as a large rectangular texture. 128 */ 129 intel->vtbl.meta_tex_rect_source(intel, src_region, textureFormat); 130 131 132 intel->vtbl.meta_texture_blend_replace(i830, glTextureFormat); 133 134 135 /* Set the 3d engine to draw into the destination region: 136 */ 137 138 intel->vtbl.meta_draw_region(intel, dest_region); 139 intel->vtbl.meta_draw_format(intel, destFormat, depthFormat); /* ?? */ 140 141 142 /* Draw a single quad, no cliprects: 143 */ 144 intel->vtbl.meta_disable_cliprects(intel); 145 146 intel->vtbl.draw_quad(intel, 147 0, width, 0, height, 148 0x00ff00ff, x, x + width, y, y + height); 149 150 intel->vtbl.leave_meta_state(intel); 151 } 152 UNLOCK_HARDWARE(intel); 153 154 intel_region_wait_fence(ctx, dest_region); /* required by GL */ 155 return GL_TRUE; 156#endif 157 158 return GL_FALSE; 159} 160 161 162 163 164static GLboolean 165do_blit_readpixels(GLcontext * ctx, 166 GLint x, GLint y, GLsizei width, GLsizei height, 167 GLenum format, GLenum type, 168 const struct gl_pixelstore_attrib *pack, GLvoid * pixels) 169{ 170 struct intel_context *intel = intel_context(ctx); 171 struct intel_region *src = intel_readbuf_region(intel); 172 struct intel_buffer_object *dst = intel_buffer_object(pack->BufferObj); 173 GLuint dst_offset; 174 GLuint rowLength; 175 176 if (INTEL_DEBUG & DEBUG_PIXEL) 177 _mesa_printf("%s\n", __FUNCTION__); 178 179 if (!src) 180 return GL_FALSE; 181 182 if (dst) { 183 /* XXX This validation should be done by core mesa: 184 */ 185 if (!_mesa_validate_pbo_access(2, pack, width, height, 1, 186 format, type, pixels)) { 187 _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawPixels"); 188 return GL_TRUE; 189 } 190 } 191 else { 192 /* PBO only for now: 193 */ 194 if (INTEL_DEBUG & DEBUG_PIXEL) 195 _mesa_printf("%s - not PBO\n", __FUNCTION__); 196 return GL_FALSE; 197 } 198 199 200 if (ctx->_ImageTransferState || 201 !intel_check_blit_format(src, format, type)) { 202 if (INTEL_DEBUG & DEBUG_PIXEL) 203 _mesa_printf("%s - bad format for blit\n", __FUNCTION__); 204 return GL_FALSE; 205 } 206 207 if (pack->Alignment != 1 || pack->SwapBytes || pack->LsbFirst) { 208 if (INTEL_DEBUG & DEBUG_PIXEL) 209 _mesa_printf("%s: bad packing params\n", __FUNCTION__); 210 return GL_FALSE; 211 } 212 213 if (pack->RowLength > 0) 214 rowLength = pack->RowLength; 215 else 216 rowLength = width; 217 218 if (pack->Invert) { 219 if (INTEL_DEBUG & DEBUG_PIXEL) 220 _mesa_printf("%s: MESA_PACK_INVERT not done yet\n", __FUNCTION__); 221 return GL_FALSE; 222 } 223 else { 224 rowLength = -rowLength; 225 } 226 227 /* XXX 64-bit cast? */ 228 dst_offset = (GLuint) _mesa_image_address(2, pack, pixels, width, height, 229 format, type, 0, 0, 0); 230 231 232 /* Although the blits go on the command buffer, need to do this and 233 * fire with lock held to guarentee cliprects are correct. 234 */ 235 intelFlush(&intel->ctx); 236 LOCK_HARDWARE(intel); 237 238 if (intel->driDrawable->numClipRects) { 239 GLboolean all = (width * height * src->cpp == dst->Base.Size && 240 x == 0 && dst_offset == 0); 241 242 dri_bo *dst_buffer = intel_bufferobj_buffer(intel, dst, 243 all ? INTEL_WRITE_FULL : 244 INTEL_WRITE_PART); 245 __DRIdrawablePrivate *dPriv = intel->driDrawable; 246 int nbox = dPriv->numClipRects; 247 drm_clip_rect_t *box = dPriv->pClipRects; 248 drm_clip_rect_t rect; 249 drm_clip_rect_t src_rect; 250 int i; 251 252 src_rect.x1 = dPriv->x + x; 253 src_rect.y1 = dPriv->y + dPriv->h - (y + height); 254 src_rect.x2 = src_rect.x1 + width; 255 src_rect.y2 = src_rect.y1 + height; 256 257 258 259 for (i = 0; i < nbox; i++) { 260 if (!intel_intersect_cliprects(&rect, &src_rect, &box[i])) 261 continue; 262 263 intelEmitCopyBlit(intel, 264 src->cpp, 265 src->pitch, src->buffer, 0, src->tiling, 266 rowLength, dst_buffer, dst_offset, GL_FALSE, 267 rect.x1, 268 rect.y1, 269 rect.x1 - src_rect.x1, 270 rect.y2 - src_rect.y2, 271 rect.x2 - rect.x1, rect.y2 - rect.y1, 272 GL_COPY); 273 } 274 } 275 UNLOCK_HARDWARE(intel); 276 277 if (INTEL_DEBUG & DEBUG_PIXEL) 278 _mesa_printf("%s - DONE\n", __FUNCTION__); 279 280 return GL_TRUE; 281} 282 283void 284intelReadPixels(GLcontext * ctx, 285 GLint x, GLint y, GLsizei width, GLsizei height, 286 GLenum format, GLenum type, 287 const struct gl_pixelstore_attrib *pack, GLvoid * pixels) 288{ 289 if (INTEL_DEBUG & DEBUG_PIXEL) 290 fprintf(stderr, "%s\n", __FUNCTION__); 291 292 intelFlush(ctx); 293 294#ifdef I915 295 if (do_blit_readpixels 296 (ctx, x, y, width, height, format, type, pack, pixels)) 297 return; 298 299 if (do_texture_readpixels 300 (ctx, x, y, width, height, format, type, pack, pixels)) 301 return; 302#endif 303 304 if (INTEL_DEBUG & DEBUG_PIXEL) 305 _mesa_printf("%s: fallback to swrast\n", __FUNCTION__); 306 307 /* Update Mesa state before calling down into _swrast_ReadPixels, as 308 * the spans code requires the computed buffer states to be up to date, 309 * but _swrast_ReadPixels only updates Mesa state after setting up 310 * the spans code. 311 */ 312 313 if (ctx->NewState) 314 _mesa_update_state(ctx); 315 316 _swrast_ReadPixels(ctx, x, y, width, height, format, type, pack, pixels); 317} 318