Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  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.