intel_tex_copy.c revision 8fda97afb8b7a03415dbca6d83691d2d6461126c
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/mipmap.h" 33 34#include "drivers/common/meta.h" 35 36#include "intel_screen.h" 37#include "intel_context.h" 38#include "intel_batchbuffer.h" 39#include "intel_buffers.h" 40#include "intel_mipmap_tree.h" 41#include "intel_regions.h" 42#include "intel_fbo.h" 43#include "intel_tex.h" 44#include "intel_blit.h" 45 46#define FILE_DEBUG_FLAG DEBUG_TEXTURE 47 48/** 49 * Get the intel_region which is the source for any glCopyTex[Sub]Image call. 50 * 51 * Do the best we can using the blitter. A future project is to use 52 * the texture engine and fragment programs for these copies. 53 */ 54static const struct intel_region * 55get_teximage_source(struct intel_context *intel, GLenum internalFormat) 56{ 57 struct intel_renderbuffer *irb; 58 59 DBG("%s %s\n", __FUNCTION__, 60 _mesa_lookup_enum_by_nr(internalFormat)); 61 62 switch (internalFormat) { 63 case GL_DEPTH_COMPONENT: 64 case GL_DEPTH_COMPONENT16: 65 irb = intel_get_renderbuffer(intel->ctx.ReadBuffer, BUFFER_DEPTH); 66 if (irb && irb->region && irb->region->cpp == 2) 67 return irb->region; 68 return NULL; 69 case GL_DEPTH24_STENCIL8_EXT: 70 case GL_DEPTH_STENCIL_EXT: 71 irb = intel_get_renderbuffer(intel->ctx.ReadBuffer, BUFFER_DEPTH); 72 if (irb && irb->region && irb->region->cpp == 4) 73 return irb->region; 74 return NULL; 75 case GL_RGBA: 76 case GL_RGBA8: 77 case GL_RGB: 78 case GL_RGB8: 79 return intel_readbuf_region(intel); 80 default: 81 return NULL; 82 } 83} 84 85 86static GLboolean 87do_copy_texsubimage(struct intel_context *intel, 88 GLenum target, 89 struct intel_texture_image *intelImage, 90 GLenum internalFormat, 91 GLint dstx, GLint dsty, 92 GLint x, GLint y, GLsizei width, GLsizei height) 93{ 94 GLcontext *ctx = &intel->ctx; 95 const struct intel_region *src = 96 get_teximage_source(intel, internalFormat); 97 98 if (!intelImage->mt || !src) { 99 if (INTEL_DEBUG & DEBUG_FALLBACKS) 100 fprintf(stderr, "%s fail %p %p (0x%08x)\n", 101 __FUNCTION__, intelImage->mt, src, internalFormat); 102 return GL_FALSE; 103 } 104 105 if (intelImage->mt->cpp != src->cpp) { 106 if (INTEL_DEBUG & DEBUG_FALLBACKS) 107 fprintf(stderr, "%s fail %d vs %d cpp\n", 108 __FUNCTION__, intelImage->mt->cpp, src->cpp); 109 return GL_FALSE; 110 } 111 112 intelFlush(ctx); 113 LOCK_HARDWARE(intel); 114 { 115 drm_intel_bo *dst_bo = intel_region_buffer(intel, 116 intelImage->mt->region, 117 INTEL_WRITE_PART); 118 GLuint image_offset = intel_miptree_image_offset(intelImage->mt, 119 intelImage->face, 120 intelImage->level); 121 const GLint orig_x = x; 122 const GLint orig_y = y; 123 GLshort src_pitch; 124 125 /* Update dst for clipped src. Need to also clip the source rect. */ 126 dstx += x - orig_x; 127 dsty += y - orig_y; 128 129 /* Can't blit to tiled buffers with non-tile-aligned offset. */ 130 if (intelImage->mt->region->tiling != I915_TILING_NONE && 131 (image_offset & 4095) != 0) { 132 UNLOCK_HARDWARE(intel); 133 return GL_FALSE; 134 } 135 136 if (ctx->ReadBuffer->Name == 0) { 137 /* reading from a window, adjust x, y */ 138 __DRIdrawablePrivate *dPriv = intel->driDrawable; 139 y = dPriv->y + (dPriv->h - (y + height)); 140 x += dPriv->x; 141 142 /* Invert the data coming from the source rectangle due to GL 143 * and hardware disagreeing on where y=0 is. 144 * 145 * It appears that our offsets and pitches get mangled 146 * appropriately by the hardware, and we don't need to adjust them 147 * on our own. 148 */ 149 src_pitch = -src->pitch; 150 } else { 151 /* reading from a FBO, y is already oriented the way we like */ 152 src_pitch = src->pitch; 153 } 154 155 if (!intelEmitCopyBlit(intel, 156 intelImage->mt->cpp, 157 src_pitch, 158 src->buffer, 159 0, 160 src->tiling, 161 intelImage->mt->pitch, 162 dst_bo, 163 image_offset, 164 intelImage->mt->region->tiling, 165 x, y, dstx, dsty, width, height, 166 GL_COPY)) { 167 UNLOCK_HARDWARE(intel); 168 return GL_FALSE; 169 } 170 } 171 172 UNLOCK_HARDWARE(intel); 173 174 return GL_TRUE; 175} 176 177 178static void 179intelCopyTexImage1D(GLcontext * ctx, GLenum target, GLint level, 180 GLenum internalFormat, 181 GLint x, GLint y, GLsizei width, GLint border) 182{ 183 struct gl_texture_unit *texUnit = 184 &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 185 struct gl_texture_object *texObj = 186 _mesa_select_tex_object(ctx, texUnit, target); 187 struct gl_texture_image *texImage = 188 _mesa_select_tex_image(ctx, texObj, target, level); 189 int srcx, srcy, dstx, dsty, height; 190 191 if (border) 192 goto fail; 193 194 /* Setup or redefine the texture object, mipmap tree and texture 195 * image. Don't populate yet. 196 */ 197 ctx->Driver.TexImage1D(ctx, target, level, internalFormat, 198 width, border, 199 GL_RGBA, CHAN_TYPE, NULL, 200 &ctx->DefaultPacking, texObj, texImage); 201 srcx = x; 202 srcy = y; 203 dstx = 0; 204 dsty = 0; 205 height = 1; 206 if (!_mesa_clip_copytexsubimage(ctx, 207 &dstx, &dsty, 208 &srcx, &srcy, 209 &width, &height)) 210 return; 211 212 if (!do_copy_texsubimage(intel_context(ctx), target, 213 intel_texture_image(texImage), 214 internalFormat, 0, 0, x, y, width, height)) 215 goto fail; 216 217 return; 218 219 fail: 220 _mesa_meta_CopyTexImage1D(ctx, target, level, internalFormat, x, y, 221 width, border); 222} 223 224 225static void 226intelCopyTexImage2D(GLcontext * ctx, GLenum target, GLint level, 227 GLenum internalFormat, 228 GLint x, GLint y, GLsizei width, GLsizei height, 229 GLint border) 230{ 231 struct gl_texture_unit *texUnit = 232 &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 233 struct gl_texture_object *texObj = 234 _mesa_select_tex_object(ctx, texUnit, target); 235 struct gl_texture_image *texImage = 236 _mesa_select_tex_image(ctx, texObj, target, level); 237 int srcx, srcy, dstx, dsty; 238 239 if (border) 240 goto fail; 241 242 /* Setup or redefine the texture object, mipmap tree and texture 243 * image. Don't populate yet. 244 */ 245 ctx->Driver.TexImage2D(ctx, target, level, internalFormat, 246 width, height, border, 247 GL_RGBA, CHAN_TYPE, NULL, 248 &ctx->DefaultPacking, texObj, texImage); 249 250 srcx = x; 251 srcy = y; 252 dstx = 0; 253 dsty = 0; 254 if (!_mesa_clip_copytexsubimage(ctx, 255 &dstx, &dsty, 256 &srcx, &srcy, 257 &width, &height)) 258 return; 259 260 if (!do_copy_texsubimage(intel_context(ctx), target, 261 intel_texture_image(texImage), 262 internalFormat, 0, 0, x, y, width, height)) 263 goto fail; 264 265 return; 266 267 fail: 268 _mesa_meta_CopyTexImage2D(ctx, target, level, internalFormat, x, y, 269 width, height, border); 270} 271 272 273static void 274intelCopyTexSubImage1D(GLcontext * ctx, GLenum target, GLint level, 275 GLint xoffset, GLint x, GLint y, GLsizei width) 276{ 277 struct gl_texture_unit *texUnit = 278 &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 279 struct gl_texture_object *texObj = 280 _mesa_select_tex_object(ctx, texUnit, target); 281 struct gl_texture_image *texImage = 282 _mesa_select_tex_image(ctx, texObj, target, level); 283 GLenum internalFormat = texImage->InternalFormat; 284 285 /* XXX need to check <border> as in above function? */ 286 287 /* Need to check texture is compatible with source format. 288 */ 289 290 if (!do_copy_texsubimage(intel_context(ctx), target, 291 intel_texture_image(texImage), 292 internalFormat, xoffset, 0, x, y, width, 1)) { 293 _mesa_meta_CopyTexSubImage1D(ctx, target, level, xoffset, x, y, width); 294 } 295} 296 297 298static void 299intelCopyTexSubImage2D(GLcontext * ctx, GLenum target, GLint level, 300 GLint xoffset, GLint yoffset, 301 GLint x, GLint y, GLsizei width, GLsizei height) 302{ 303 struct gl_texture_unit *texUnit = 304 &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 305 struct gl_texture_object *texObj = 306 _mesa_select_tex_object(ctx, texUnit, target); 307 struct gl_texture_image *texImage = 308 _mesa_select_tex_image(ctx, texObj, target, level); 309 GLenum internalFormat = texImage->InternalFormat; 310 311 /* Need to check texture is compatible with source format. 312 */ 313 314 if (!do_copy_texsubimage(intel_context(ctx), target, 315 intel_texture_image(texImage), 316 internalFormat, 317 xoffset, yoffset, x, y, width, height)) { 318 319 DBG("%s - fallback to _mesa_meta_CopyTexSubImage2D\n", __FUNCTION__); 320 321 _mesa_meta_CopyTexSubImage2D(ctx, target, level, 322 xoffset, yoffset, x, y, width, height); 323 } 324} 325 326 327void 328intelInitTextureCopyImageFuncs(struct dd_function_table *functions) 329{ 330 functions->CopyTexImage1D = intelCopyTexImage1D; 331 functions->CopyTexImage2D = intelCopyTexImage2D; 332 functions->CopyTexSubImage1D = intelCopyTexSubImage1D; 333 functions->CopyTexSubImage2D = intelCopyTexSubImage2D; 334} 335