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