Home | History | Annotate | Download | only in radeon
      1 /*
      2  * Copyright (C) 2010 Advanced Micro Devices, Inc.
      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_context.h"
     30 #include "radeon_blit.h"
     31 
     32 static inline uint32_t cmdpacket0(struct radeon_screen *rscrn,
     33                                   int reg, int count)
     34 {
     35     if (count)
     36 	    return CP_PACKET0(reg, count - 1);
     37     return CP_PACKET2;
     38 }
     39 
     40 /* common formats supported as both textures and render targets */
     41 unsigned r100_check_blit(gl_format mesa_format, uint32_t dst_pitch)
     42 {
     43     /* XXX others?  BE/LE? */
     44     switch (mesa_format) {
     45     case MESA_FORMAT_ARGB8888:
     46     case MESA_FORMAT_XRGB8888:
     47     case MESA_FORMAT_RGB565:
     48     case MESA_FORMAT_ARGB4444:
     49     case MESA_FORMAT_ARGB1555:
     50     case MESA_FORMAT_A8:
     51     case MESA_FORMAT_L8:
     52     case MESA_FORMAT_I8:
     53 	    break;
     54     default:
     55 	    return 0;
     56     }
     57 
     58     /* Rendering to small buffer doesn't work.
     59      * Looks like a hw limitation.
     60      */
     61     if (dst_pitch < 32)
     62         return 0;
     63 
     64     /* ??? */
     65     if (_mesa_get_format_bits(mesa_format, GL_DEPTH_BITS) > 0)
     66 	    return 0;
     67 
     68     return 1;
     69 }
     70 
     71 static inline void emit_vtx_state(struct r100_context *r100)
     72 {
     73     BATCH_LOCALS(&r100->radeon);
     74 
     75     BEGIN_BATCH(8);
     76     if (r100->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL) {
     77 	    OUT_BATCH_REGVAL(RADEON_SE_CNTL_STATUS, 0);
     78     } else {
     79 	    OUT_BATCH_REGVAL(RADEON_SE_CNTL_STATUS, RADEON_TCL_BYPASS);
     80 
     81     }
     82     OUT_BATCH_REGVAL(RADEON_SE_COORD_FMT, (RADEON_VTX_XY_PRE_MULT_1_OVER_W0 |
     83 					   RADEON_TEX1_W_ROUTING_USE_W0));
     84     OUT_BATCH_REGVAL(RADEON_SE_VTX_FMT, RADEON_SE_VTX_FMT_XY | RADEON_SE_VTX_FMT_ST0);
     85     OUT_BATCH_REGVAL(RADEON_SE_CNTL, (RADEON_DIFFUSE_SHADE_GOURAUD |
     86 				      RADEON_BFACE_SOLID |
     87 				      RADEON_FFACE_SOLID |
     88 				      RADEON_VTX_PIX_CENTER_OGL |
     89 				      RADEON_ROUND_MODE_ROUND |
     90 				      RADEON_ROUND_PREC_4TH_PIX));
     91     END_BATCH();
     92 }
     93 
     94 static void inline emit_tx_setup(struct r100_context *r100,
     95 				 gl_format mesa_format,
     96 				 struct radeon_bo *bo,
     97 				 intptr_t offset,
     98 				 unsigned width,
     99 				 unsigned height,
    100 				 unsigned pitch)
    101 {
    102     uint32_t txformat = RADEON_TXFORMAT_NON_POWER2;
    103     BATCH_LOCALS(&r100->radeon);
    104 
    105     assert(width <= 2048);
    106     assert(height <= 2048);
    107     assert(offset % 32 == 0);
    108 
    109     /* XXX others?  BE/LE? */
    110     switch (mesa_format) {
    111     case MESA_FORMAT_ARGB8888:
    112 	    txformat |= RADEON_TXFORMAT_ARGB8888 | RADEON_TXFORMAT_ALPHA_IN_MAP;
    113 	    break;
    114     case MESA_FORMAT_RGBA8888:
    115             txformat |= RADEON_TXFORMAT_RGBA8888 | RADEON_TXFORMAT_ALPHA_IN_MAP;
    116             break;
    117     case MESA_FORMAT_XRGB8888:
    118 	    txformat |= RADEON_TXFORMAT_ARGB8888;
    119 	    break;
    120     case MESA_FORMAT_RGB565:
    121 	    txformat |= RADEON_TXFORMAT_RGB565;
    122 	    break;
    123     case MESA_FORMAT_ARGB4444:
    124 	    txformat |= RADEON_TXFORMAT_ARGB4444 | RADEON_TXFORMAT_ALPHA_IN_MAP;
    125 	    break;
    126     case MESA_FORMAT_ARGB1555:
    127 	    txformat |= RADEON_TXFORMAT_ARGB1555 | RADEON_TXFORMAT_ALPHA_IN_MAP;
    128 	    break;
    129     case MESA_FORMAT_A8:
    130     case MESA_FORMAT_I8:
    131 	    txformat |= RADEON_TXFORMAT_I8 | RADEON_TXFORMAT_ALPHA_IN_MAP;
    132 	    break;
    133     case MESA_FORMAT_L8:
    134             txformat |= RADEON_TXFORMAT_I8;
    135             break;
    136     case MESA_FORMAT_AL88:
    137             txformat |= RADEON_TXFORMAT_AI88 | RADEON_TXFORMAT_ALPHA_IN_MAP;
    138             break;
    139     default:
    140 	    break;
    141     }
    142 
    143     if (bo->flags & RADEON_BO_FLAGS_MACRO_TILE)
    144        offset |= RADEON_TXO_MACRO_TILE;
    145     if (bo->flags & RADEON_BO_FLAGS_MICRO_TILE)
    146        offset |= RADEON_TXO_MICRO_TILE_X2;
    147 
    148     BEGIN_BATCH(18);
    149     OUT_BATCH_REGVAL(RADEON_PP_CNTL, RADEON_TEX_0_ENABLE | RADEON_TEX_BLEND_0_ENABLE);
    150     OUT_BATCH_REGVAL(RADEON_PP_TXCBLEND_0, (RADEON_COLOR_ARG_A_ZERO |
    151 					    RADEON_COLOR_ARG_B_ZERO |
    152 					    RADEON_COLOR_ARG_C_T0_COLOR |
    153 					    RADEON_BLEND_CTL_ADD |
    154 					    RADEON_CLAMP_TX));
    155     OUT_BATCH_REGVAL(RADEON_PP_TXABLEND_0, (RADEON_ALPHA_ARG_A_ZERO |
    156 					    RADEON_ALPHA_ARG_B_ZERO |
    157 					    RADEON_ALPHA_ARG_C_T0_ALPHA |
    158 					    RADEON_BLEND_CTL_ADD |
    159 					    RADEON_CLAMP_TX));
    160     OUT_BATCH_REGVAL(RADEON_PP_TXFILTER_0, (RADEON_CLAMP_S_CLAMP_LAST |
    161 					    RADEON_CLAMP_T_CLAMP_LAST |
    162 					    RADEON_MAG_FILTER_NEAREST |
    163 					    RADEON_MIN_FILTER_NEAREST));
    164     OUT_BATCH_REGVAL(RADEON_PP_TXFORMAT_0, txformat);
    165     OUT_BATCH_REGVAL(RADEON_PP_TEX_SIZE_0, ((width - 1) |
    166 					    ((height - 1) << RADEON_TEX_VSIZE_SHIFT)));
    167     OUT_BATCH_REGVAL(RADEON_PP_TEX_PITCH_0, pitch * _mesa_get_format_bytes(mesa_format) - 32);
    168 
    169     OUT_BATCH_REGSEQ(RADEON_PP_TXOFFSET_0, 1);
    170     OUT_BATCH_RELOC(offset, bo, offset, RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0);
    171 
    172     END_BATCH();
    173 }
    174 
    175 static inline void emit_cb_setup(struct r100_context *r100,
    176 				 struct radeon_bo *bo,
    177 				 intptr_t offset,
    178 				 gl_format mesa_format,
    179 				 unsigned pitch,
    180 				 unsigned width,
    181 				 unsigned height)
    182 {
    183     uint32_t dst_pitch = pitch;
    184     uint32_t dst_format = 0;
    185     BATCH_LOCALS(&r100->radeon);
    186 
    187     /* XXX others?  BE/LE? */
    188     switch (mesa_format) {
    189     case MESA_FORMAT_ARGB8888:
    190     case MESA_FORMAT_XRGB8888:
    191 	    dst_format = RADEON_COLOR_FORMAT_ARGB8888;
    192 	    break;
    193     case MESA_FORMAT_RGB565:
    194 	    dst_format = RADEON_COLOR_FORMAT_RGB565;
    195 	    break;
    196     case MESA_FORMAT_ARGB4444:
    197 	    dst_format = RADEON_COLOR_FORMAT_ARGB4444;
    198 	    break;
    199     case MESA_FORMAT_ARGB1555:
    200 	    dst_format = RADEON_COLOR_FORMAT_ARGB1555;
    201 	    break;
    202     case MESA_FORMAT_A8:
    203     case MESA_FORMAT_L8:
    204     case MESA_FORMAT_I8:
    205 	    dst_format = RADEON_COLOR_FORMAT_RGB8;
    206 	    break;
    207     default:
    208 	    break;
    209     }
    210 
    211     if (bo->flags & RADEON_BO_FLAGS_MACRO_TILE)
    212         dst_pitch |= RADEON_COLOR_TILE_ENABLE;
    213 
    214     if (bo->flags & RADEON_BO_FLAGS_MICRO_TILE)
    215         dst_pitch |= RADEON_COLOR_MICROTILE_ENABLE;
    216 
    217     BEGIN_BATCH_NO_AUTOSTATE(18);
    218     OUT_BATCH_REGVAL(RADEON_RE_TOP_LEFT, 0);
    219     OUT_BATCH_REGVAL(RADEON_RE_WIDTH_HEIGHT, (((width - 1) << RADEON_RE_WIDTH_SHIFT) |
    220 					      ((height - 1) << RADEON_RE_HEIGHT_SHIFT)));
    221     OUT_BATCH_REGVAL(RADEON_RB3D_PLANEMASK, 0xffffffff);
    222     OUT_BATCH_REGVAL(RADEON_RB3D_BLENDCNTL, RADEON_SRC_BLEND_GL_ONE | RADEON_DST_BLEND_GL_ZERO);
    223     OUT_BATCH_REGVAL(RADEON_RB3D_CNTL, dst_format);
    224 
    225     OUT_BATCH_REGSEQ(RADEON_RB3D_COLOROFFSET, 1);
    226     OUT_BATCH_RELOC(offset, bo, offset, 0, RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0);
    227     OUT_BATCH_REGSEQ(RADEON_RB3D_COLORPITCH, 1);
    228     OUT_BATCH_RELOC(dst_pitch, bo, dst_pitch, 0, RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0);
    229 
    230     END_BATCH();
    231 }
    232 
    233 static GLboolean validate_buffers(struct r100_context *r100,
    234                                   struct radeon_bo *src_bo,
    235                                   struct radeon_bo *dst_bo)
    236 {
    237     int ret;
    238 
    239     radeon_cs_space_reset_bos(r100->radeon.cmdbuf.cs);
    240 
    241     ret = radeon_cs_space_check_with_bo(r100->radeon.cmdbuf.cs,
    242                                         src_bo, RADEON_GEM_DOMAIN_VRAM | RADEON_GEM_DOMAIN_GTT, 0);
    243     if (ret)
    244         return GL_FALSE;
    245 
    246     ret = radeon_cs_space_check_with_bo(r100->radeon.cmdbuf.cs,
    247                                         dst_bo, 0, RADEON_GEM_DOMAIN_VRAM | RADEON_GEM_DOMAIN_GTT);
    248     if (ret)
    249         return GL_FALSE;
    250 
    251     return GL_TRUE;
    252 }
    253 
    254 /**
    255  * Calculate texcoords for given image region.
    256  * Output values are [minx, maxx, miny, maxy]
    257  */
    258 static inline void calc_tex_coords(float img_width, float img_height,
    259 				   float x, float y,
    260 				   float reg_width, float reg_height,
    261 				   unsigned flip_y, float *buf)
    262 {
    263     buf[0] = x / img_width;
    264     buf[1] = buf[0] + reg_width / img_width;
    265     buf[2] = y / img_height;
    266     buf[3] = buf[2] + reg_height / img_height;
    267     if (flip_y)
    268     {
    269         buf[2] = 1.0 - buf[2];
    270         buf[3] = 1.0 - buf[3];
    271     }
    272 }
    273 
    274 static inline void emit_draw_packet(struct r100_context *r100,
    275 				    unsigned src_width, unsigned src_height,
    276 				    unsigned src_x_offset, unsigned src_y_offset,
    277 				    unsigned dst_x_offset, unsigned dst_y_offset,
    278 				    unsigned reg_width, unsigned reg_height,
    279 				    unsigned flip_y)
    280 {
    281     float texcoords[4];
    282     float verts[12];
    283     BATCH_LOCALS(&r100->radeon);
    284 
    285     calc_tex_coords(src_width, src_height,
    286                     src_x_offset, src_y_offset,
    287                     reg_width, reg_height,
    288                     flip_y, texcoords);
    289 
    290     verts[0] = dst_x_offset;
    291     verts[1] = dst_y_offset + reg_height;
    292     verts[2] = texcoords[0];
    293     verts[3] = texcoords[3];
    294 
    295     verts[4] = dst_x_offset + reg_width;
    296     verts[5] = dst_y_offset + reg_height;
    297     verts[6] = texcoords[1];
    298     verts[7] = texcoords[3];
    299 
    300     verts[8] = dst_x_offset + reg_width;
    301     verts[9] = dst_y_offset;
    302     verts[10] = texcoords[1];
    303     verts[11] = texcoords[2];
    304 
    305     BEGIN_BATCH(15);
    306     OUT_BATCH(RADEON_CP_PACKET3_3D_DRAW_IMMD | (13 << 16));
    307     OUT_BATCH(RADEON_CP_VC_FRMT_XY | RADEON_CP_VC_FRMT_ST0);
    308     OUT_BATCH(RADEON_CP_VC_CNTL_PRIM_WALK_RING |
    309 	      RADEON_CP_VC_CNTL_PRIM_TYPE_RECT_LIST |
    310 	      RADEON_CP_VC_CNTL_MAOS_ENABLE |
    311 	      RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE |
    312               (3 << 16));
    313     OUT_BATCH_TABLE(verts, 12);
    314     END_BATCH();
    315 }
    316 
    317 /**
    318  * Copy a region of [@a width x @a height] pixels from source buffer
    319  * to destination buffer.
    320  * @param[in] r100 r100 context
    321  * @param[in] src_bo source radeon buffer object
    322  * @param[in] src_offset offset of the source image in the @a src_bo
    323  * @param[in] src_mesaformat source image format
    324  * @param[in] src_pitch aligned source image width
    325  * @param[in] src_width source image width
    326  * @param[in] src_height source image height
    327  * @param[in] src_x_offset x offset in the source image
    328  * @param[in] src_y_offset y offset in the source image
    329  * @param[in] dst_bo destination radeon buffer object
    330  * @param[in] dst_offset offset of the destination image in the @a dst_bo
    331  * @param[in] dst_mesaformat destination image format
    332  * @param[in] dst_pitch aligned destination image width
    333  * @param[in] dst_width destination image width
    334  * @param[in] dst_height destination image height
    335  * @param[in] dst_x_offset x offset in the destination image
    336  * @param[in] dst_y_offset y offset in the destination image
    337  * @param[in] width region width
    338  * @param[in] height region height
    339  * @param[in] flip_y set if y coords of the source image need to be flipped
    340  */
    341 unsigned r100_blit(struct gl_context *ctx,
    342                    struct radeon_bo *src_bo,
    343                    intptr_t src_offset,
    344                    gl_format src_mesaformat,
    345                    unsigned src_pitch,
    346                    unsigned src_width,
    347                    unsigned src_height,
    348                    unsigned src_x_offset,
    349                    unsigned src_y_offset,
    350                    struct radeon_bo *dst_bo,
    351                    intptr_t dst_offset,
    352                    gl_format dst_mesaformat,
    353                    unsigned dst_pitch,
    354                    unsigned dst_width,
    355                    unsigned dst_height,
    356                    unsigned dst_x_offset,
    357                    unsigned dst_y_offset,
    358                    unsigned reg_width,
    359                    unsigned reg_height,
    360                    unsigned flip_y)
    361 {
    362     struct r100_context *r100 = R100_CONTEXT(ctx);
    363 
    364     if (!r100_check_blit(dst_mesaformat, dst_pitch))
    365         return GL_FALSE;
    366 
    367     /* Make sure that colorbuffer has even width - hw limitation */
    368     if (dst_pitch % 2 > 0)
    369         ++dst_pitch;
    370 
    371     /* Need to clamp the region size to make sure
    372      * we don't read outside of the source buffer
    373      * or write outside of the destination buffer.
    374      */
    375     if (reg_width + src_x_offset > src_width)
    376         reg_width = src_width - src_x_offset;
    377     if (reg_height + src_y_offset > src_height)
    378         reg_height = src_height - src_y_offset;
    379     if (reg_width + dst_x_offset > dst_width)
    380         reg_width = dst_width - dst_x_offset;
    381     if (reg_height + dst_y_offset > dst_height)
    382         reg_height = dst_height - dst_y_offset;
    383 
    384     if (src_bo == dst_bo) {
    385         return GL_FALSE;
    386     }
    387 
    388     if (src_offset % 32 || dst_offset % 32) {
    389         return GL_FALSE;
    390     }
    391 
    392     if (0) {
    393         fprintf(stderr, "src: size [%d x %d], pitch %d, offset %zd "
    394                 "offset [%d x %d], format %s, bo %p\n",
    395                 src_width, src_height, src_pitch, src_offset,
    396                 src_x_offset, src_y_offset,
    397                 _mesa_get_format_name(src_mesaformat),
    398                 src_bo);
    399         fprintf(stderr, "dst: pitch %d offset %zd, offset[%d x %d], format %s, bo %p\n",
    400                 dst_pitch, dst_offset,  dst_x_offset, dst_y_offset,
    401                 _mesa_get_format_name(dst_mesaformat), dst_bo);
    402         fprintf(stderr, "region: %d x %d\n", reg_width, reg_height);
    403     }
    404 
    405     /* Flush is needed to make sure that source buffer has correct data */
    406     radeonFlush(ctx);
    407 
    408     rcommonEnsureCmdBufSpace(&r100->radeon, 59, __FUNCTION__);
    409 
    410     if (!validate_buffers(r100, src_bo, dst_bo))
    411         return GL_FALSE;
    412 
    413     /* 8 */
    414     emit_vtx_state(r100);
    415     /* 18 */
    416     emit_tx_setup(r100, src_mesaformat, src_bo, src_offset, src_width, src_height, src_pitch);
    417     /* 18 */
    418     emit_cb_setup(r100, dst_bo, dst_offset, dst_mesaformat, dst_pitch, dst_width, dst_height);
    419     /* 15 */
    420     emit_draw_packet(r100, src_width, src_height,
    421                      src_x_offset, src_y_offset,
    422                      dst_x_offset, dst_y_offset,
    423                      reg_width, reg_height,
    424                      flip_y);
    425 
    426     radeonFlush(ctx);
    427 
    428     return GL_TRUE;
    429 }
    430