1/************************************************************************** 2 * 3 * Copyright 2003 VMware, Inc. 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 VMWARE 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/fbobject.h" 33#include "main/image.h" 34#include "main/bufferobj.h" 35#include "main/readpix.h" 36#include "main/state.h" 37 38#include "intel_screen.h" 39#include "intel_context.h" 40#include "intel_blit.h" 41#include "intel_buffers.h" 42#include "intel_fbo.h" 43#include "intel_mipmap_tree.h" 44#include "intel_regions.h" 45#include "intel_pixel.h" 46#include "intel_buffer_objects.h" 47 48#define FILE_DEBUG_FLAG DEBUG_PIXEL 49 50/* For many applications, the new ability to pull the source buffers 51 * back out of the GTT and then do the packing/conversion operations 52 * in software will be as much of an improvement as trying to get the 53 * blitter and/or texture engine to do the work. 54 * 55 * This step is gated on private backbuffers. 56 * 57 * Obviously the frontbuffer can't be pulled back, so that is either 58 * an argument for blit/texture readpixels, or for blitting to a 59 * temporary and then pulling that back. 60 * 61 * When the destination is a pbo, however, it's not clear if it is 62 * ever going to be pulled to main memory (though the access param 63 * will be a good hint). So it sounds like we do want to be able to 64 * choose between blit/texture implementation on the gpu and pullback 65 * and cpu-based copying. 66 * 67 * Unless you can magically turn client memory into a PBO for the 68 * duration of this call, there will be a cpu-based copying step in 69 * any case. 70 */ 71 72static bool 73do_blit_readpixels(struct gl_context * ctx, 74 GLint x, GLint y, GLsizei width, GLsizei height, 75 GLenum format, GLenum type, 76 const struct gl_pixelstore_attrib *pack, GLvoid * pixels) 77{ 78 struct intel_context *intel = intel_context(ctx); 79 struct intel_buffer_object *dst = intel_buffer_object(pack->BufferObj); 80 GLuint dst_offset; 81 drm_intel_bo *dst_buffer; 82 GLint dst_x, dst_y; 83 GLuint dirty; 84 85 DBG("%s\n", __func__); 86 87 assert(_mesa_is_bufferobj(pack->BufferObj)); 88 89 struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer; 90 struct intel_renderbuffer *irb = intel_renderbuffer(rb); 91 92 if (ctx->_ImageTransferState || 93 !_mesa_format_matches_format_and_type(irb->mt->format, format, type, 94 false, NULL)) { 95 DBG("%s - bad format for blit\n", __func__); 96 return false; 97 } 98 99 if (pack->SwapBytes || pack->LsbFirst) { 100 DBG("%s: bad packing params\n", __func__); 101 return false; 102 } 103 104 int dst_stride = _mesa_image_row_stride(pack, width, format, type); 105 bool dst_flip = false; 106 /* Mesa flips the dst_stride for pack->Invert, but we want our mt to have a 107 * normal dst_stride. 108 */ 109 if (pack->Invert) { 110 dst_stride = -dst_stride; 111 dst_flip = true; 112 } 113 114 dst_offset = (GLintptr)pixels; 115 dst_offset += _mesa_image_offset(2, pack, width, height, 116 format, type, 0, 0, 0); 117 118 if (!_mesa_clip_copytexsubimage(ctx, 119 &dst_x, &dst_y, 120 &x, &y, 121 &width, &height)) { 122 return true; 123 } 124 125 dirty = intel->front_buffer_dirty; 126 intel_prepare_render(intel); 127 intel->front_buffer_dirty = dirty; 128 129 dst_buffer = intel_bufferobj_buffer(intel, dst); 130 131 struct intel_mipmap_tree *pbo_mt = 132 intel_miptree_create_for_bo(intel, 133 dst_buffer, 134 irb->mt->format, 135 dst_offset, 136 width, height, 137 dst_stride, I915_TILING_NONE); 138 139 if (!intel_miptree_blit(intel, 140 irb->mt, irb->mt_level, irb->mt_layer, 141 x, y, _mesa_is_winsys_fbo(ctx->ReadBuffer), 142 pbo_mt, 0, 0, 143 0, 0, dst_flip, 144 width, height, COLOR_LOGICOP_COPY)) { 145 intel_miptree_release(&pbo_mt); 146 return false; 147 } 148 149 intel_miptree_release(&pbo_mt); 150 151 DBG("%s - DONE\n", __func__); 152 153 return true; 154} 155 156void 157intelReadPixels(struct gl_context * ctx, 158 GLint x, GLint y, GLsizei width, GLsizei height, 159 GLenum format, GLenum type, 160 const struct gl_pixelstore_attrib *pack, GLvoid * pixels) 161{ 162 struct intel_context *intel = intel_context(ctx); 163 bool dirty; 164 165 intel_flush_rendering_to_batch(ctx); 166 167 DBG("%s\n", __func__); 168 169 if (_mesa_is_bufferobj(pack->BufferObj)) { 170 /* Using PBOs, so try the BLT based path. */ 171 if (do_blit_readpixels(ctx, x, y, width, height, format, type, pack, 172 pixels)) { 173 return; 174 } 175 176 perf_debug("%s: fallback to CPU mapping in PBO case\n", __func__); 177 } 178 179 /* glReadPixels() wont dirty the front buffer, so reset the dirty 180 * flag after calling intel_prepare_render(). */ 181 dirty = intel->front_buffer_dirty; 182 intel_prepare_render(intel); 183 intel->front_buffer_dirty = dirty; 184 185 /* Update Mesa state before calling _mesa_readpixels(). 186 * XXX this may not be needed since ReadPixels no longer uses the 187 * span code. 188 */ 189 190 if (ctx->NewState) 191 _mesa_update_state(ctx); 192 193 _mesa_readpixels(ctx, x, y, width, height, format, type, pack, pixels); 194 195 /* There's an intel_prepare_render() call in intelSpanRenderStart(). */ 196 intel->front_buffer_dirty = dirty; 197} 198