intel_pixel_read.c revision 8d68a90e225d831a395ba788e425cb717eec1f9a
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#define FILE_DEBUG_FLAG DEBUG_PIXEL
46
47/* For many applications, the new ability to pull the source buffers
48 * back out of the GTT and then do the packing/conversion operations
49 * in software will be as much of an improvement as trying to get the
50 * blitter and/or texture engine to do the work.
51 *
52 * This step is gated on private backbuffers.
53 *
54 * Obviously the frontbuffer can't be pulled back, so that is either
55 * an argument for blit/texture readpixels, or for blitting to a
56 * temporary and then pulling that back.
57 *
58 * When the destination is a pbo, however, it's not clear if it is
59 * ever going to be pulled to main memory (though the access param
60 * will be a good hint).  So it sounds like we do want to be able to
61 * choose between blit/texture implementation on the gpu and pullback
62 * and cpu-based copying.
63 *
64 * Unless you can magically turn client memory into a PBO for the
65 * duration of this call, there will be a cpu-based copying step in
66 * any case.
67 */
68
69static GLboolean
70do_blit_readpixels(struct gl_context * ctx,
71                   GLint x, GLint y, GLsizei width, GLsizei height,
72                   GLenum format, GLenum type,
73                   const struct gl_pixelstore_attrib *pack, GLvoid * pixels)
74{
75   struct intel_context *intel = intel_context(ctx);
76   struct intel_region *src = intel_readbuf_region(intel);
77   struct intel_buffer_object *dst = intel_buffer_object(pack->BufferObj);
78   GLuint dst_offset;
79   GLuint rowLength;
80   drm_intel_bo *dst_buffer;
81   GLboolean all;
82   GLint dst_x, dst_y;
83
84   DBG("%s\n", __FUNCTION__);
85
86   if (!src)
87      return GL_FALSE;
88
89   if (!_mesa_is_bufferobj(pack->BufferObj)) {
90      /* PBO only for now:
91       */
92      DBG("%s - not PBO\n", __FUNCTION__);
93      return GL_FALSE;
94   }
95
96
97   if (ctx->_ImageTransferState ||
98       !intel_check_blit_format(src, format, type)) {
99      DBG("%s - bad format for blit\n", __FUNCTION__);
100      return GL_FALSE;
101   }
102
103   if (pack->Alignment != 1 || pack->SwapBytes || pack->LsbFirst) {
104      DBG("%s: bad packing params\n", __FUNCTION__);
105      return GL_FALSE;
106   }
107
108   if (pack->RowLength > 0)
109      rowLength = pack->RowLength;
110   else
111      rowLength = width;
112
113   if (pack->Invert) {
114      DBG("%s: MESA_PACK_INVERT not done yet\n", __FUNCTION__);
115      return GL_FALSE;
116   }
117   else {
118      if (ctx->ReadBuffer->Name == 0)
119	 rowLength = -rowLength;
120   }
121
122   dst_offset = (GLintptr) _mesa_image_address(2, pack, pixels, width, height,
123					       format, type, 0, 0, 0);
124
125   if (!_mesa_clip_copytexsubimage(ctx,
126				   &dst_x, &dst_y,
127				   &x, &y,
128				   &width, &height)) {
129      return GL_TRUE;
130   }
131
132   intel_prepare_render(intel);
133
134   all = (width * height * src->cpp == dst->Base.Size &&
135	  x == 0 && dst_offset == 0);
136
137   dst_x = 0;
138   dst_y = 0;
139
140   dst_buffer = intel_bufferobj_buffer(intel, dst,
141				       all ? INTEL_WRITE_FULL :
142				       INTEL_WRITE_PART);
143
144   if (ctx->ReadBuffer->Name == 0)
145      y = ctx->ReadBuffer->Height - (y + height);
146
147   if (!intelEmitCopyBlit(intel,
148			  src->cpp,
149			  src->pitch, src->buffer, 0, src->tiling,
150			  rowLength, dst_buffer, dst_offset, GL_FALSE,
151			  x, y,
152			  dst_x, dst_y,
153			  width, height,
154			  GL_COPY)) {
155      return GL_FALSE;
156   }
157
158   DBG("%s - DONE\n", __FUNCTION__);
159
160   return GL_TRUE;
161}
162
163void
164intelReadPixels(struct gl_context * ctx,
165                GLint x, GLint y, GLsizei width, GLsizei height,
166                GLenum format, GLenum type,
167                const struct gl_pixelstore_attrib *pack, GLvoid * pixels)
168{
169   struct intel_context *intel = intel_context(ctx);
170   GLboolean dirty;
171
172   DBG("%s\n", __FUNCTION__);
173
174   intel_flush(ctx);
175
176   /* glReadPixels() wont dirty the front buffer, so reset the dirty
177    * flag after calling intel_prepare_render(). */
178   dirty = intel->front_buffer_dirty;
179   intel_prepare_render(intel);
180   intel->front_buffer_dirty = dirty;
181
182   if (do_blit_readpixels
183       (ctx, x, y, width, height, format, type, pack, pixels))
184      return;
185
186   fallback_debug("%s: fallback to swrast\n", __FUNCTION__);
187
188   /* Update Mesa state before calling down into _swrast_ReadPixels, as
189    * the spans code requires the computed buffer states to be up to date,
190    * but _swrast_ReadPixels only updates Mesa state after setting up
191    * the spans code.
192    */
193
194   if (ctx->NewState)
195      _mesa_update_state(ctx);
196
197   _swrast_ReadPixels(ctx, x, y, width, height, format, type, pack, pixels);
198
199   /* There's an intel_prepare_render() call in intelSpanRenderStart(). */
200   intel->front_buffer_dirty = dirty;
201}
202