intel_tex_copy.c revision d1fc920f613aa349e6721963e22e12c6eb49e3f9
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/mtypes.h"
29#include "main/enums.h"
30#include "main/image.h"
31#include "main/teximage.h"
32#include "main/texstate.h"
33
34#include "drivers/common/meta.h"
35
36#include "intel_screen.h"
37#include "intel_context.h"
38#include "intel_mipmap_tree.h"
39#include "intel_regions.h"
40#include "intel_fbo.h"
41#include "intel_tex.h"
42#include "intel_blit.h"
43
44#define FILE_DEBUG_FLAG DEBUG_TEXTURE
45
46/**
47 * Get the intel_region which is the source for any glCopyTex[Sub]Image call.
48 *
49 * Do the best we can using the blitter.  A future project is to use
50 * the texture engine and fragment programs for these copies.
51 */
52static struct intel_renderbuffer *
53get_teximage_readbuffer(struct intel_context *intel, GLenum internalFormat)
54{
55   DBG("%s %s\n", __FUNCTION__,
56       _mesa_lookup_enum_by_nr(internalFormat));
57
58   switch (internalFormat) {
59   case GL_DEPTH_COMPONENT:
60   case GL_DEPTH_COMPONENT16:
61   case GL_DEPTH24_STENCIL8_EXT:
62   case GL_DEPTH_STENCIL_EXT:
63      return intel_get_renderbuffer(intel->ctx.ReadBuffer, BUFFER_DEPTH);
64   default:
65      return intel_renderbuffer(intel->ctx.ReadBuffer->_ColorReadBuffer);
66   }
67}
68
69
70GLboolean
71intel_copy_texsubimage(struct intel_context *intel,
72                       GLenum target,
73                       struct intel_texture_image *intelImage,
74                       GLenum internalFormat,
75                       GLint dstx, GLint dsty,
76                       GLint x, GLint y, GLsizei width, GLsizei height)
77{
78   struct gl_context *ctx = &intel->ctx;
79   struct intel_renderbuffer *irb;
80   bool copy_supported = false;
81   bool copy_supported_with_alpha_override = false;
82
83   intel_prepare_render(intel);
84
85   irb = get_teximage_readbuffer(intel, internalFormat);
86   if (!intelImage->mt || !irb || !irb->region) {
87      if (unlikely(INTEL_DEBUG & DEBUG_FALLBACKS))
88	 fprintf(stderr, "%s fail %p %p (0x%08x)\n",
89		 __FUNCTION__, intelImage->mt, irb, internalFormat);
90      return GL_FALSE;
91   }
92
93   copy_supported = intelImage->base.TexFormat == irb->Base.Format;
94
95   /* Converting ARGB8888 to XRGB8888 is trivial: ignore the alpha bits */
96   if (irb->Base.Format == MESA_FORMAT_ARGB8888 &&
97       intelImage->base.TexFormat == MESA_FORMAT_XRGB8888) {
98      copy_supported = true;
99   }
100
101   /* Converting XRGB8888 to ARGB8888 requires setting the alpha bits to 1.0 */
102   if (irb->Base.Format == MESA_FORMAT_XRGB8888 &&
103       intelImage->base.TexFormat == MESA_FORMAT_ARGB8888) {
104      copy_supported_with_alpha_override = true;
105   }
106
107   if (!copy_supported && !copy_supported_with_alpha_override) {
108      if (unlikely(INTEL_DEBUG & DEBUG_FALLBACKS))
109	 fprintf(stderr, "%s mismatched formats %s, %s\n",
110		 __FUNCTION__,
111		 _mesa_get_format_name(intelImage->base.TexFormat),
112		 _mesa_get_format_name(irb->Base.Format));
113      return GL_FALSE;
114   }
115
116   {
117      drm_intel_bo *dst_bo = intel_region_buffer(intel,
118						 intelImage->mt->region,
119						 INTEL_WRITE_PART);
120      GLuint image_x, image_y;
121      GLshort src_pitch;
122
123      /* get dest x/y in destination texture */
124      intel_miptree_get_image_offset(intelImage->mt,
125				     intelImage->level,
126				     intelImage->face,
127				     0,
128				     &image_x, &image_y);
129
130      /* The blitter can't handle Y-tiled buffers. */
131      if (intelImage->mt->region->tiling == I915_TILING_Y) {
132	 return GL_FALSE;
133      }
134
135      if (ctx->ReadBuffer->Name == 0) {
136	 /* Flip vertical orientation for system framebuffers */
137	 y = ctx->ReadBuffer->Height - (y + height);
138	 src_pitch = -irb->region->pitch;
139      } else {
140	 /* reading from a FBO, y is already oriented the way we like */
141	 src_pitch = irb->region->pitch;
142      }
143
144      /* blit from src buffer to texture */
145      if (!intelEmitCopyBlit(intel,
146			     intelImage->mt->cpp,
147			     src_pitch,
148			     irb->region->buffer,
149			     0,
150			     irb->region->tiling,
151			     intelImage->mt->region->pitch,
152			     dst_bo,
153			     0,
154			     intelImage->mt->region->tiling,
155			     irb->region->draw_x + x, irb->region->draw_y + y,
156			     image_x + dstx, image_y + dsty,
157			     width, height,
158			     GL_COPY)) {
159	 return GL_FALSE;
160      }
161   }
162
163   if (copy_supported_with_alpha_override)
164      intel_set_teximage_alpha_to_one(ctx, intelImage);
165
166   return GL_TRUE;
167}
168
169
170static void
171intelCopyTexImage1D(struct gl_context * ctx, GLenum target, GLint level,
172                    GLenum internalFormat,
173                    GLint x, GLint y, GLsizei width, GLint border)
174{
175   struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx);
176   struct gl_texture_object *texObj =
177      _mesa_select_tex_object(ctx, texUnit, target);
178   struct gl_texture_image *texImage =
179      _mesa_select_tex_image(ctx, texObj, target, level);
180   int srcx, srcy, dstx, dsty, height;
181
182   if (border)
183      goto fail;
184
185   /* Setup or redefine the texture object, mipmap tree and texture
186    * image.  Don't populate yet.
187    */
188   ctx->Driver.TexImage1D(ctx, target, level, internalFormat,
189                          width, border,
190                          GL_RGBA, CHAN_TYPE, NULL,
191                          &ctx->DefaultPacking, texObj, texImage);
192   srcx = x;
193   srcy = y;
194   dstx = 0;
195   dsty = 0;
196   height = 1;
197   if (!_mesa_clip_copytexsubimage(ctx,
198				   &dstx, &dsty,
199				   &srcx, &srcy,
200				   &width, &height))
201      return;
202
203   if (!intel_copy_texsubimage(intel_context(ctx), target,
204                               intel_texture_image(texImage),
205                               internalFormat, 0, 0, x, y, width, height))
206      goto fail;
207
208   return;
209
210 fail:
211   fallback_debug("%s - fallback to swrast\n", __FUNCTION__);
212   _mesa_meta_CopyTexImage1D(ctx, target, level, internalFormat, x, y,
213                             width, border);
214}
215
216
217static void
218intelCopyTexImage2D(struct gl_context * ctx, GLenum target, GLint level,
219                    GLenum internalFormat,
220                    GLint x, GLint y, GLsizei width, GLsizei height,
221                    GLint border)
222{
223   struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx);
224   struct gl_texture_object *texObj =
225      _mesa_select_tex_object(ctx, texUnit, target);
226   struct gl_texture_image *texImage =
227      _mesa_select_tex_image(ctx, texObj, target, level);
228   int srcx, srcy, dstx, dsty;
229
230   if (border)
231      goto fail;
232
233   /* Setup or redefine the texture object, mipmap tree and texture
234    * image.  Don't populate yet.
235    */
236   ctx->Driver.TexImage2D(ctx, target, level, internalFormat,
237                          width, height, border,
238                          GL_RGBA, GL_UNSIGNED_BYTE, NULL,
239                          &ctx->DefaultPacking, texObj, texImage);
240
241   srcx = x;
242   srcy = y;
243   dstx = 0;
244   dsty = 0;
245   if (!_mesa_clip_copytexsubimage(ctx,
246				   &dstx, &dsty,
247				   &srcx, &srcy,
248				   &width, &height))
249      return;
250
251   if (!intel_copy_texsubimage(intel_context(ctx), target,
252                               intel_texture_image(texImage),
253                               internalFormat, 0, 0, x, y, width, height))
254      goto fail;
255
256   return;
257
258 fail:
259   fallback_debug("%s - fallback to swrast\n", __FUNCTION__);
260   _mesa_meta_CopyTexImage2D(ctx, target, level, internalFormat, x, y,
261                             width, height, border);
262}
263
264
265static void
266intelCopyTexSubImage1D(struct gl_context * ctx, GLenum target, GLint level,
267                       GLint xoffset, GLint x, GLint y, GLsizei width)
268{
269   struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx);
270   struct gl_texture_object *texObj =
271      _mesa_select_tex_object(ctx, texUnit, target);
272   struct gl_texture_image *texImage =
273      _mesa_select_tex_image(ctx, texObj, target, level);
274   GLenum internalFormat = texImage->InternalFormat;
275
276   /* XXX need to check <border> as in above function? */
277
278   /* Need to check texture is compatible with source format.
279    */
280
281   if (!intel_copy_texsubimage(intel_context(ctx), target,
282                               intel_texture_image(texImage),
283                               internalFormat, xoffset, 0, x, y, width, 1)) {
284      fallback_debug("%s - fallback to swrast\n", __FUNCTION__);
285      _mesa_meta_CopyTexSubImage1D(ctx, target, level, xoffset, x, y, width);
286   }
287}
288
289
290static void
291intelCopyTexSubImage2D(struct gl_context * ctx, GLenum target, GLint level,
292                       GLint xoffset, GLint yoffset,
293                       GLint x, GLint y, GLsizei width, GLsizei height)
294{
295   struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx);
296   struct gl_texture_object *texObj =
297      _mesa_select_tex_object(ctx, texUnit, target);
298   struct gl_texture_image *texImage =
299      _mesa_select_tex_image(ctx, texObj, target, level);
300   GLenum internalFormat = texImage->InternalFormat;
301
302   /* Need to check texture is compatible with source format.
303    */
304
305   if (!intel_copy_texsubimage(intel_context(ctx), target,
306                               intel_texture_image(texImage),
307                               internalFormat,
308                               xoffset, yoffset, x, y, width, height)) {
309      fallback_debug("%s - fallback to swrast\n", __FUNCTION__);
310      _mesa_meta_CopyTexSubImage2D(ctx, target, level,
311                                   xoffset, yoffset, x, y, width, height);
312   }
313}
314
315
316void
317intelInitTextureCopyImageFuncs(struct dd_function_table *functions)
318{
319   functions->CopyTexImage1D = intelCopyTexImage1D;
320   functions->CopyTexImage2D = intelCopyTexImage2D;
321   functions->CopyTexSubImage1D = intelCopyTexSubImage1D;
322   functions->CopyTexSubImage2D = intelCopyTexSubImage2D;
323}
324