Home | History | Annotate | Download | only in radeon
      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     mesa_format src_mesaformat;
     54     mesa_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                 __func__, 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_B5G6R5_UNORM;
    112 		    dst_mesaformat = MESA_FORMAT_B5G6R5_UNORM;
    113 		    break;
    114 	    case 4:
    115 		    src_mesaformat = MESA_FORMAT_B8G8R8A8_UNORM;
    116 		    dst_mesaformat = MESA_FORMAT_B8G8R8A8_UNORM;
    117 		    break;
    118 	    case 1:
    119 		    src_mesaformat = MESA_FORMAT_A_UNORM8;
    120 		    dst_mesaformat = MESA_FORMAT_A_UNORM8;
    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 slice,
    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 (slice != 0 || !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, slice,
    158                                      rb, x, y, width, height);
    159     }
    160 }
    161