Subversion Repositories Kolibri OS

Rev

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

  1. /*
  2.  * Copyright 2008 Ben Skeggs
  3.  *
  4.  * Permission is hereby granted, free of charge, to any person obtaining a
  5.  * copy of this software and associated documentation files (the "Software"),
  6.  * to deal in the Software without restriction, including without limitation
  7.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8.  * and/or sell copies of the Software, and to permit persons to whom the
  9.  * Software is furnished to do so, subject to the following conditions:
  10.  *
  11.  * The above copyright notice and this permission notice shall be included in
  12.  * all copies or substantial portions of the Software.
  13.  *
  14.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  17.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  18.  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  19.  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  20.  * OTHER DEALINGS IN THE SOFTWARE.
  21.  */
  22.  
  23. #include "pipe/p_state.h"
  24. #include "pipe/p_defines.h"
  25. #include "util/u_inlines.h"
  26. #include "util/u_format.h"
  27.  
  28. #include "nvc0_context.h"
  29. #include "nvc0_resource.h"
  30.  
  31. static uint32_t
  32. nvc0_tex_choose_tile_dims(unsigned nx, unsigned ny, unsigned nz)
  33. {
  34.    return nv50_tex_choose_tile_dims_helper(nx, ny, nz);
  35. }
  36.  
  37. static uint32_t
  38. nvc0_mt_choose_storage_type(struct nv50_miptree *mt, boolean compressed)
  39. {
  40.    const unsigned ms = util_logbase2(mt->base.base.nr_samples);
  41.  
  42.    uint32_t tile_flags;
  43.  
  44.    if (unlikely(mt->base.base.bind & PIPE_BIND_CURSOR))
  45.       return 0;
  46.    if (unlikely(mt->base.base.flags & NOUVEAU_RESOURCE_FLAG_LINEAR))
  47.       return 0;
  48.  
  49.    switch (mt->base.base.format) {
  50.    case PIPE_FORMAT_Z16_UNORM:
  51.       if (compressed)
  52.          tile_flags = 0x02 + ms;
  53.       else
  54.          tile_flags = 0x01;
  55.       break;
  56.    case PIPE_FORMAT_S8_UINT_Z24_UNORM:
  57.       if (compressed)
  58.          tile_flags = 0x51 + ms;
  59.       else
  60.          tile_flags = 0x46;
  61.       break;
  62.    case PIPE_FORMAT_Z24X8_UNORM:
  63.    case PIPE_FORMAT_Z24_UNORM_S8_UINT:
  64.       if (compressed)
  65.          tile_flags = 0x17 + ms;
  66.       else
  67.          tile_flags = 0x11;
  68.       break;
  69.    case PIPE_FORMAT_Z32_FLOAT:
  70.       if (compressed)
  71.          tile_flags = 0x86 + ms;
  72.       else
  73.          tile_flags = 0x7b;
  74.       break;
  75.    case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
  76.       if (compressed)
  77.          tile_flags = 0xce + ms;
  78.       else
  79.          tile_flags = 0xc3;
  80.       break;
  81.    default:
  82.       switch (util_format_get_blocksizebits(mt->base.base.format)) {
  83.       case 128:
  84.          if (compressed)
  85.             tile_flags = 0xf4 + ms * 2;
  86.          else
  87.             tile_flags = 0xfe;
  88.          break;
  89.       case 64:
  90.          if (compressed) {
  91.             switch (ms) {
  92.             case 0: tile_flags = 0xe6; break;
  93.             case 1: tile_flags = 0xeb; break;
  94.             case 2: tile_flags = 0xed; break;
  95.             case 3: tile_flags = 0xf2; break;
  96.             default:
  97.                return 0;
  98.             }
  99.          } else {
  100.             tile_flags = 0xfe;
  101.          }
  102.          break;
  103.       case 32:
  104.          if (compressed && ms) {
  105.             switch (ms) {
  106.                /* This one makes things blurry:
  107.             case 0: tile_flags = 0xdb; break;
  108.                */
  109.             case 1: tile_flags = 0xdd; break;
  110.             case 2: tile_flags = 0xdf; break;
  111.             case 3: tile_flags = 0xe4; break;
  112.             default:
  113.                return 0;
  114.             }
  115.          } else {
  116.             tile_flags = 0xfe;
  117.          }
  118.          break;
  119.       case 16:
  120.       case 8:
  121.          tile_flags = 0xfe;
  122.          break;
  123.       default:
  124.          return 0;
  125.       }
  126.       break;
  127.    }
  128.  
  129.    return tile_flags;
  130. }
  131.  
  132. static INLINE boolean
  133. nvc0_miptree_init_ms_mode(struct nv50_miptree *mt)
  134. {
  135.    switch (mt->base.base.nr_samples) {
  136.    case 8:
  137.       mt->ms_mode = NVC0_3D_MULTISAMPLE_MODE_MS8;
  138.       mt->ms_x = 2;
  139.       mt->ms_y = 1;
  140.       break;
  141.    case 4:
  142.       mt->ms_mode = NVC0_3D_MULTISAMPLE_MODE_MS4;
  143.       mt->ms_x = 1;
  144.       mt->ms_y = 1;
  145.       break;
  146.    case 2:
  147.       mt->ms_mode = NVC0_3D_MULTISAMPLE_MODE_MS2;
  148.       mt->ms_x = 1;
  149.       break;
  150.    case 1:
  151.    case 0:
  152.       mt->ms_mode = NVC0_3D_MULTISAMPLE_MODE_MS1;
  153.       break;
  154.    default:
  155.       NOUVEAU_ERR("invalid nr_samples: %u\n", mt->base.base.nr_samples);
  156.       return FALSE;
  157.    }
  158.    return TRUE;
  159. }
  160.  
  161. static void
  162. nvc0_miptree_init_layout_video(struct nv50_miptree *mt)
  163. {
  164.    const struct pipe_resource *pt = &mt->base.base;
  165.    const unsigned blocksize = util_format_get_blocksize(pt->format);
  166.  
  167.    assert(pt->last_level == 0);
  168.    assert(mt->ms_x == 0 && mt->ms_y == 0);
  169.    assert(!util_format_is_compressed(pt->format));
  170.  
  171.    mt->layout_3d = pt->target == PIPE_TEXTURE_3D;
  172.  
  173.    mt->level[0].tile_mode = 0x10;
  174.    mt->level[0].pitch = align(pt->width0 * blocksize, 64);
  175.    mt->total_size = align(pt->height0, 16) * mt->level[0].pitch * (mt->layout_3d ? pt->depth0 : 1);
  176.  
  177.    if (pt->array_size > 1) {
  178.       mt->layer_stride = align(mt->total_size, NVC0_TILE_SIZE(0x10));
  179.       mt->total_size = mt->layer_stride * pt->array_size;
  180.    }
  181. }
  182.  
  183. static void
  184. nvc0_miptree_init_layout_tiled(struct nv50_miptree *mt)
  185. {
  186.    struct pipe_resource *pt = &mt->base.base;
  187.    unsigned w, h, d, l;
  188.    const unsigned blocksize = util_format_get_blocksize(pt->format);
  189.  
  190.    mt->layout_3d = pt->target == PIPE_TEXTURE_3D;
  191.  
  192.    w = pt->width0 << mt->ms_x;
  193.    h = pt->height0 << mt->ms_y;
  194.  
  195.    /* For 3D textures, a mipmap is spanned by all the layers, for array
  196.     * textures and cube maps, each layer contains its own mipmaps.
  197.     */
  198.    d = mt->layout_3d ? pt->depth0 : 1;
  199.  
  200.    assert(!mt->ms_mode || !pt->last_level);
  201.  
  202.    for (l = 0; l <= pt->last_level; ++l) {
  203.       struct nv50_miptree_level *lvl = &mt->level[l];
  204.       unsigned tsx, tsy, tsz;
  205.       unsigned nbx = util_format_get_nblocksx(pt->format, w);
  206.       unsigned nby = util_format_get_nblocksy(pt->format, h);
  207.  
  208.       lvl->offset = mt->total_size;
  209.  
  210.       lvl->tile_mode = nvc0_tex_choose_tile_dims(nbx, nby, d);
  211.  
  212.       tsx = NVC0_TILE_SIZE_X(lvl->tile_mode); /* x is tile row pitch in bytes */
  213.       tsy = NVC0_TILE_SIZE_Y(lvl->tile_mode);
  214.       tsz = NVC0_TILE_SIZE_Z(lvl->tile_mode);
  215.  
  216.       lvl->pitch = align(nbx * blocksize, tsx);
  217.  
  218.       mt->total_size += lvl->pitch * align(nby, tsy) * align(d, tsz);
  219.  
  220.       w = u_minify(w, 1);
  221.       h = u_minify(h, 1);
  222.       d = u_minify(d, 1);
  223.    }
  224.  
  225.    if (pt->array_size > 1) {
  226.       mt->layer_stride = align(mt->total_size,
  227.                                NVC0_TILE_SIZE(mt->level[0].tile_mode));
  228.       mt->total_size = mt->layer_stride * pt->array_size;
  229.    }
  230. }
  231.  
  232. const struct u_resource_vtbl nvc0_miptree_vtbl =
  233. {
  234.    nv50_miptree_get_handle,         /* get_handle */
  235.    nv50_miptree_destroy,            /* resource_destroy */
  236.    nvc0_miptree_transfer_map,       /* transfer_map */
  237.    u_default_transfer_flush_region, /* transfer_flush_region */
  238.    nvc0_miptree_transfer_unmap,     /* transfer_unmap */
  239.    u_default_transfer_inline_write  /* transfer_inline_write */
  240. };
  241.  
  242. struct pipe_resource *
  243. nvc0_miptree_create(struct pipe_screen *pscreen,
  244.                     const struct pipe_resource *templ)
  245. {
  246.    struct nouveau_device *dev = nouveau_screen(pscreen)->device;
  247.    struct nv50_miptree *mt = CALLOC_STRUCT(nv50_miptree);
  248.    struct pipe_resource *pt = &mt->base.base;
  249.    boolean compressed = dev->drm_version >= 0x01000101;
  250.    int ret;
  251.    union nouveau_bo_config bo_config;
  252.    uint32_t bo_flags;
  253.  
  254.    if (!mt)
  255.       return NULL;
  256.  
  257.    mt->base.vtbl = &nvc0_miptree_vtbl;
  258.    *pt = *templ;
  259.    pipe_reference_init(&pt->reference, 1);
  260.    pt->screen = pscreen;
  261.  
  262.    if (pt->usage == PIPE_USAGE_STAGING) {
  263.       switch (pt->target) {
  264.       case PIPE_TEXTURE_1D:
  265.       case PIPE_TEXTURE_2D:
  266.       case PIPE_TEXTURE_RECT:
  267.          if (pt->last_level == 0 &&
  268.              !util_format_is_depth_or_stencil(pt->format) &&
  269.              pt->nr_samples <= 1)
  270.             pt->flags |= NOUVEAU_RESOURCE_FLAG_LINEAR;
  271.          break;
  272.       default:
  273.          break;
  274.       }
  275.    }
  276.  
  277.    bo_config.nvc0.memtype = nvc0_mt_choose_storage_type(mt, compressed);
  278.  
  279.    if (!nvc0_miptree_init_ms_mode(mt)) {
  280.       FREE(mt);
  281.       return NULL;
  282.    }
  283.  
  284.    if (unlikely(pt->flags & NVC0_RESOURCE_FLAG_VIDEO)) {
  285.       nvc0_miptree_init_layout_video(mt);
  286.    } else
  287.    if (likely(bo_config.nvc0.memtype)) {
  288.       nvc0_miptree_init_layout_tiled(mt);
  289.    } else
  290.    if (!nv50_miptree_init_layout_linear(mt, 128)) {
  291.       FREE(mt);
  292.       return NULL;
  293.    }
  294.    bo_config.nvc0.tile_mode = mt->level[0].tile_mode;
  295.  
  296.    if (!bo_config.nvc0.memtype && pt->usage == PIPE_USAGE_STAGING)
  297.       mt->base.domain = NOUVEAU_BO_GART;
  298.    else
  299.       mt->base.domain = NOUVEAU_BO_VRAM;
  300.  
  301.    bo_flags = mt->base.domain | NOUVEAU_BO_NOSNOOP;
  302.  
  303.    if (mt->base.base.bind & (PIPE_BIND_CURSOR | PIPE_BIND_DISPLAY_TARGET))
  304.       bo_flags |= NOUVEAU_BO_CONTIG;
  305.  
  306.    ret = nouveau_bo_new(dev, bo_flags, 4096, mt->total_size, &bo_config,
  307.                         &mt->base.bo);
  308.    if (ret) {
  309.       FREE(mt);
  310.       return NULL;
  311.    }
  312.    mt->base.address = mt->base.bo->offset;
  313.  
  314.    NOUVEAU_DRV_STAT(nouveau_screen(pscreen), tex_obj_current_count, 1);
  315.    NOUVEAU_DRV_STAT(nouveau_screen(pscreen), tex_obj_current_bytes,
  316.                     mt->total_size);
  317.  
  318.    return pt;
  319. }
  320.  
  321. /* Offset of zslice @z from start of level @l. */
  322. INLINE unsigned
  323. nvc0_mt_zslice_offset(const struct nv50_miptree *mt, unsigned l, unsigned z)
  324. {
  325.    const struct pipe_resource *pt = &mt->base.base;
  326.  
  327.    unsigned tds = NVC0_TILE_SHIFT_Z(mt->level[l].tile_mode);
  328.    unsigned ths = NVC0_TILE_SHIFT_Y(mt->level[l].tile_mode);
  329.  
  330.    unsigned nby = util_format_get_nblocksy(pt->format,
  331.                                            u_minify(pt->height0, l));
  332.  
  333.    /* to next 2D tile slice within a 3D tile */
  334.    unsigned stride_2d = NVC0_TILE_SIZE_2D(mt->level[l].tile_mode);
  335.  
  336.    /* to slice in the next (in z direction) 3D tile */
  337.    unsigned stride_3d = (align(nby, (1 << ths)) * mt->level[l].pitch) << tds;
  338.  
  339.    return (z & (1 << (tds - 1))) * stride_2d + (z >> tds) * stride_3d;
  340. }
  341.  
  342. /* Surface functions.
  343.  */
  344.  
  345. struct pipe_surface *
  346. nvc0_miptree_surface_new(struct pipe_context *pipe,
  347.                          struct pipe_resource *pt,
  348.                          const struct pipe_surface *templ)
  349. {
  350.    struct nv50_surface *ns = nv50_surface_from_miptree(nv50_miptree(pt), templ);
  351.    if (!ns)
  352.       return NULL;
  353.    ns->base.context = pipe;
  354.    return &ns->base;
  355. }
  356.