1 /* 2 * Copyright (C) 2009 Maciej Cencora <m.cencora (at) gmail.com> 3 * 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining 7 * a 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, sublicense, 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 16 * portions of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE 22 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 24 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 */ 27 28 #include "radeon_common.h" 29 #include "radeon_texture.h" 30 31 #include "main/enums.h" 32 #include "main/image.h" 33 #include "main/teximage.h" 34 #include "main/texstate.h" 35 #include "drivers/common/meta.h" 36 37 #include "radeon_mipmap_tree.h" 38 39 static GLboolean 40 do_copy_texsubimage(struct gl_context *ctx, 41 struct radeon_tex_obj *tobj, 42 radeon_texture_image *timg, 43 GLint dstx, GLint dsty, 44 struct radeon_renderbuffer *rrb, 45 GLint x, GLint y, 46 GLsizei width, GLsizei height) 47 { 48 radeonContextPtr radeon = RADEON_CONTEXT(ctx); 49 const GLuint face = timg->base.Base.Face; 50 const GLuint level = timg->base.Base.Level; 51 unsigned src_bpp; 52 unsigned dst_bpp; 53 gl_format src_mesaformat; 54 gl_format dst_mesaformat; 55 unsigned flip_y; 56 57 if (!radeon->vtbl.blit) { 58 return GL_FALSE; 59 } 60 61 // This is software renderbuffer, fallback to swrast 62 if (!rrb) { 63 return GL_FALSE; 64 } 65 66 if (_mesa_get_format_bits(timg->base.Base.TexFormat, GL_DEPTH_BITS) > 0) { 67 /* copying depth values */ 68 flip_y = ctx->ReadBuffer->Attachment[BUFFER_DEPTH].Type == GL_NONE; 69 } else { 70 /* copying color */ 71 flip_y = ctx->ReadBuffer->Attachment[BUFFER_COLOR0].Type == GL_NONE; 72 } 73 74 if (!timg->mt) { 75 radeon_validate_texture_miptree(ctx, &tobj->base.Sampler, &tobj->base); 76 } 77 78 assert(rrb->bo); 79 assert(timg->mt); 80 assert(timg->mt->bo); 81 assert(timg->base.Base.Width >= dstx + width); 82 assert(timg->base.Base.Height >= dsty + height); 83 84 intptr_t src_offset = rrb->draw_offset; 85 intptr_t dst_offset = radeon_miptree_image_offset(timg->mt, face, level); 86 87 if (0) { 88 fprintf(stderr, "%s: copying to face %d, level %d\n", 89 __FUNCTION__, face, level); 90 fprintf(stderr, "to: x %d, y %d, offset %d\n", dstx, dsty, (uint32_t) dst_offset); 91 fprintf(stderr, "from (%dx%d) width %d, height %d, offset %d, pitch %d\n", 92 x, y, rrb->base.Base.Width, rrb->base.Base.Height, (uint32_t) src_offset, rrb->pitch/rrb->cpp); 93 fprintf(stderr, "src size %d, dst size %d\n", rrb->bo->size, timg->mt->bo->size); 94 95 } 96 97 src_mesaformat = rrb->base.Base.Format; 98 dst_mesaformat = timg->base.Base.TexFormat; 99 src_bpp = _mesa_get_format_bytes(src_mesaformat); 100 dst_bpp = _mesa_get_format_bytes(dst_mesaformat); 101 if (!radeon->vtbl.check_blit(dst_mesaformat, rrb->pitch / rrb->cpp)) { 102 /* depth formats tend to be special */ 103 if (_mesa_get_format_bits(dst_mesaformat, GL_DEPTH_BITS) > 0) 104 return GL_FALSE; 105 106 if (src_bpp != dst_bpp) 107 return GL_FALSE; 108 109 switch (dst_bpp) { 110 case 2: 111 src_mesaformat = MESA_FORMAT_RGB565; 112 dst_mesaformat = MESA_FORMAT_RGB565; 113 break; 114 case 4: 115 src_mesaformat = MESA_FORMAT_ARGB8888; 116 dst_mesaformat = MESA_FORMAT_ARGB8888; 117 break; 118 case 1: 119 src_mesaformat = MESA_FORMAT_A8; 120 dst_mesaformat = MESA_FORMAT_A8; 121 break; 122 default: 123 return GL_FALSE; 124 } 125 } 126 127 /* blit from src buffer to texture */ 128 return radeon->vtbl.blit(ctx, rrb->bo, src_offset, src_mesaformat, rrb->pitch/rrb->cpp, 129 rrb->base.Base.Width, rrb->base.Base.Height, x, y, 130 timg->mt->bo, dst_offset, dst_mesaformat, 131 timg->mt->levels[level].rowstride / dst_bpp, 132 timg->base.Base.Width, timg->base.Base.Height, 133 dstx, dsty, width, height, flip_y); 134 } 135 136 void 137 radeonCopyTexSubImage(struct gl_context *ctx, GLuint dims, 138 struct gl_texture_image *texImage, 139 GLint xoffset, GLint yoffset, GLint zoffset, 140 struct gl_renderbuffer *rb, 141 GLint x, GLint y, 142 GLsizei width, GLsizei height) 143 { 144 radeonContextPtr radeon = RADEON_CONTEXT(ctx); 145 radeon_prepare_render(radeon); 146 147 if (dims != 2 || !do_copy_texsubimage(ctx, 148 radeon_tex_obj(texImage->TexObject), 149 (radeon_texture_image *)texImage, 150 xoffset, yoffset, 151 radeon_renderbuffer(rb), x, y, width, height)) { 152 153 radeon_print(RADEON_FALLBACKS, RADEON_NORMAL, 154 "Falling back to sw for glCopyTexSubImage2D\n"); 155 156 _mesa_meta_CopyTexSubImage(ctx, dims, texImage, 157 xoffset, yoffset, zoffset, 158 rb, x, y, width, height); 159 } 160 } 161