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 "nv50_context.h"
  24. #include "nv50_resource.h"
  25. #include "nv50_texture.xml.h"
  26. #include "nv50_defs.xml.h"
  27.  
  28. #include "util/u_format.h"
  29.  
  30. #define NV50_TIC_0_SWIZZLE__MASK                      \
  31.    (NV50_TIC_0_MAPA__MASK | NV50_TIC_0_MAPB__MASK |   \
  32.     NV50_TIC_0_MAPG__MASK | NV50_TIC_0_MAPR__MASK)
  33.  
  34. static INLINE uint32_t
  35. nv50_tic_swizzle(uint32_t tc, unsigned swz, boolean tex_int)
  36. {
  37.    switch (swz) {
  38.    case PIPE_SWIZZLE_RED:
  39.       return (tc & NV50_TIC_0_MAPR__MASK) >> NV50_TIC_0_MAPR__SHIFT;
  40.    case PIPE_SWIZZLE_GREEN:
  41.       return (tc & NV50_TIC_0_MAPG__MASK) >> NV50_TIC_0_MAPG__SHIFT;
  42.    case PIPE_SWIZZLE_BLUE:
  43.       return (tc & NV50_TIC_0_MAPB__MASK) >> NV50_TIC_0_MAPB__SHIFT;
  44.    case PIPE_SWIZZLE_ALPHA:
  45.       return (tc & NV50_TIC_0_MAPA__MASK) >> NV50_TIC_0_MAPA__SHIFT;
  46.    case PIPE_SWIZZLE_ONE:
  47.       return tex_int ? NV50_TIC_MAP_ONE_INT : NV50_TIC_MAP_ONE_FLOAT;
  48.    case PIPE_SWIZZLE_ZERO:
  49.    default:
  50.       return NV50_TIC_MAP_ZERO;
  51.    }
  52. }
  53.  
  54. struct pipe_sampler_view *
  55. nv50_create_sampler_view(struct pipe_context *pipe,
  56.                          struct pipe_resource *res,
  57.                          const struct pipe_sampler_view *templ)
  58. {
  59.    uint32_t flags = 0;
  60.  
  61.    if (res->target == PIPE_TEXTURE_RECT || res->target == PIPE_BUFFER)
  62.       flags |= NV50_TEXVIEW_SCALED_COORDS;
  63.  
  64.    return nv50_create_texture_view(pipe, res, templ, flags, res->target);
  65. }
  66.  
  67. struct pipe_sampler_view *
  68. nv50_create_texture_view(struct pipe_context *pipe,
  69.                          struct pipe_resource *texture,
  70.                          const struct pipe_sampler_view *templ,
  71.                          uint32_t flags,
  72.                          enum pipe_texture_target target)
  73. {
  74.    const struct util_format_description *desc;
  75.    uint64_t addr;
  76.    uint32_t *tic;
  77.    uint32_t swz[4];
  78.    uint32_t depth;
  79.    struct nv50_tic_entry *view;
  80.    struct nv50_miptree *mt = nv50_miptree(texture);
  81.    boolean tex_int;
  82.  
  83.    view = MALLOC_STRUCT(nv50_tic_entry);
  84.    if (!view)
  85.       return NULL;
  86.  
  87.    view->pipe = *templ;
  88.    view->pipe.reference.count = 1;
  89.    view->pipe.texture = NULL;
  90.    view->pipe.context = pipe;
  91.  
  92.    view->id = -1;
  93.  
  94.    pipe_resource_reference(&view->pipe.texture, texture);
  95.  
  96.    tic = &view->tic[0];
  97.  
  98.    desc = util_format_description(view->pipe.format);
  99.  
  100.    /* TIC[0] */
  101.  
  102.    tic[0] = nv50_format_table[view->pipe.format].tic;
  103.  
  104.    tex_int = util_format_is_pure_integer(view->pipe.format);
  105.  
  106.    swz[0] = nv50_tic_swizzle(tic[0], view->pipe.swizzle_r, tex_int);
  107.    swz[1] = nv50_tic_swizzle(tic[0], view->pipe.swizzle_g, tex_int);
  108.    swz[2] = nv50_tic_swizzle(tic[0], view->pipe.swizzle_b, tex_int);
  109.    swz[3] = nv50_tic_swizzle(tic[0], view->pipe.swizzle_a, tex_int);
  110.    tic[0] = (tic[0] & ~NV50_TIC_0_SWIZZLE__MASK) |
  111.       (swz[0] << NV50_TIC_0_MAPR__SHIFT) |
  112.       (swz[1] << NV50_TIC_0_MAPG__SHIFT) |
  113.       (swz[2] << NV50_TIC_0_MAPB__SHIFT) |
  114.       (swz[3] << NV50_TIC_0_MAPA__SHIFT);
  115.  
  116.    addr = mt->base.address;
  117.  
  118.    if (mt->base.base.target == PIPE_TEXTURE_1D_ARRAY ||
  119.        mt->base.base.target == PIPE_TEXTURE_2D_ARRAY) {
  120.       addr += view->pipe.u.tex.first_layer * mt->layer_stride;
  121.       depth = view->pipe.u.tex.last_layer - view->pipe.u.tex.first_layer + 1;
  122.    } else {
  123.       depth = mt->base.base.depth0;
  124.    }
  125.  
  126.    tic[2] = 0x10001000 | NV50_TIC_2_NO_BORDER;
  127.  
  128.    if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB)
  129.       tic[2] |= NV50_TIC_2_COLORSPACE_SRGB;
  130.  
  131.    if (!(flags & NV50_TEXVIEW_SCALED_COORDS))
  132.       tic[2] |= NV50_TIC_2_NORMALIZED_COORDS;
  133.  
  134.    if (unlikely(!nouveau_bo_memtype(nv04_resource(texture)->bo))) {
  135.       if (target == PIPE_BUFFER) {
  136.          addr += view->pipe.u.buf.first_element * desc->block.bits / 8;
  137.          tic[2] |= NV50_TIC_2_LINEAR | NV50_TIC_2_TARGET_BUFFER;
  138.          tic[3] = 0;
  139.          tic[4] = /* width */
  140.             view->pipe.u.buf.last_element - view->pipe.u.buf.first_element + 1;
  141.          tic[5] = 0;
  142.       } else {
  143.          tic[2] |= NV50_TIC_2_LINEAR | NV50_TIC_2_TARGET_RECT;
  144.          tic[3] = mt->level[0].pitch;
  145.          tic[4] = mt->base.base.width0;
  146.          tic[5] = (1 << 16) | mt->base.base.height0;
  147.       }
  148.       tic[6] =
  149.       tic[7] = 0;
  150.       tic[1] = addr;
  151.       tic[2] |= addr >> 32;
  152.       return &view->pipe;
  153.    }
  154.  
  155.    tic[1] = addr;
  156.    tic[2] |= (addr >> 32) & 0xff;
  157.  
  158.    tic[2] |=
  159.       ((mt->level[0].tile_mode & 0x0f0) << (22 - 4)) |
  160.       ((mt->level[0].tile_mode & 0xf00) << (25 - 8));
  161.  
  162.    switch (target) {
  163.    case PIPE_TEXTURE_1D:
  164.       tic[2] |= NV50_TIC_2_TARGET_1D;
  165.       break;
  166.    case PIPE_TEXTURE_2D:
  167.       tic[2] |= NV50_TIC_2_TARGET_2D;
  168.       break;
  169.    case PIPE_TEXTURE_RECT:
  170.       tic[2] |= NV50_TIC_2_TARGET_RECT;
  171.       break;
  172.    case PIPE_TEXTURE_3D:
  173.       tic[2] |= NV50_TIC_2_TARGET_3D;
  174.       break;
  175.    case PIPE_TEXTURE_CUBE:
  176.       depth /= 6;
  177.       tic[2] |= NV50_TIC_2_TARGET_CUBE;
  178.       break;
  179.    case PIPE_TEXTURE_1D_ARRAY:
  180.       tic[2] |= NV50_TIC_2_TARGET_1D_ARRAY;
  181.       break;
  182.    case PIPE_TEXTURE_2D_ARRAY:
  183.       tic[2] |= NV50_TIC_2_TARGET_2D_ARRAY;
  184.       break;
  185.    case PIPE_TEXTURE_CUBE_ARRAY:
  186.       depth /= 6;
  187.       tic[2] |= NV50_TIC_2_TARGET_CUBE_ARRAY;
  188.       break;
  189.    case PIPE_BUFFER:
  190.       assert(0); /* should be linear and handled above ! */
  191.       tic[2] |= NV50_TIC_2_TARGET_BUFFER | NV50_TIC_2_LINEAR;
  192.       break;
  193.    default:
  194.       NOUVEAU_ERR("invalid texture target: %d\n", mt->base.base.target);
  195.       return FALSE;
  196.    }
  197.  
  198.    tic[3] = (flags & NV50_TEXVIEW_FILTER_MSAA8) ? 0x20000000 : 0x00300000;
  199.  
  200.    tic[4] = (1 << 31) | (mt->base.base.width0 << mt->ms_x);
  201.  
  202.    tic[5] = (mt->base.base.height0 << mt->ms_y) & 0xffff;
  203.    tic[5] |= depth << 16;
  204.    tic[5] |= mt->base.base.last_level << NV50_TIC_5_LAST_LEVEL__SHIFT;
  205.  
  206.    tic[6] = (mt->ms_x > 1) ? 0x88000000 : 0x03000000; /* sampling points */
  207.  
  208.    tic[7] = (view->pipe.u.tex.last_level << 4) | view->pipe.u.tex.first_level;
  209.  
  210.    if (unlikely(!(tic[2] & NV50_TIC_2_NORMALIZED_COORDS)))
  211.       if (mt->base.base.last_level)
  212.          tic[5] &= ~NV50_TIC_5_LAST_LEVEL__MASK;
  213.  
  214.    return &view->pipe;
  215. }
  216.  
  217. static boolean
  218. nv50_validate_tic(struct nv50_context *nv50, int s)
  219. {
  220.    struct nouveau_pushbuf *push = nv50->base.pushbuf;
  221.    struct nouveau_bo *txc = nv50->screen->txc;
  222.    unsigned i;
  223.    boolean need_flush = FALSE;
  224.  
  225.    for (i = 0; i < nv50->num_textures[s]; ++i) {
  226.       struct nv50_tic_entry *tic = nv50_tic_entry(nv50->textures[s][i]);
  227.       struct nv04_resource *res;
  228.  
  229.       if (!tic) {
  230.          BEGIN_NV04(push, NV50_3D(BIND_TIC(s)), 1);
  231.          PUSH_DATA (push, (i << 1) | 0);
  232.          continue;
  233.       }
  234.       res = &nv50_miptree(tic->pipe.texture)->base;
  235.  
  236.       if (tic->id < 0) {
  237.          tic->id = nv50_screen_tic_alloc(nv50->screen, tic);
  238.  
  239.          BEGIN_NV04(push, NV50_2D(DST_FORMAT), 2);
  240.          PUSH_DATA (push, NV50_SURFACE_FORMAT_R8_UNORM);
  241.          PUSH_DATA (push, 1);
  242.          BEGIN_NV04(push, NV50_2D(DST_PITCH), 5);
  243.          PUSH_DATA (push, 262144);
  244.          PUSH_DATA (push, 65536);
  245.          PUSH_DATA (push, 1);
  246.          PUSH_DATAh(push, txc->offset);
  247.          PUSH_DATA (push, txc->offset);
  248.          BEGIN_NV04(push, NV50_2D(SIFC_BITMAP_ENABLE), 2);
  249.          PUSH_DATA (push, 0);
  250.          PUSH_DATA (push, NV50_SURFACE_FORMAT_R8_UNORM);
  251.          BEGIN_NV04(push, NV50_2D(SIFC_WIDTH), 10);
  252.          PUSH_DATA (push, 32);
  253.          PUSH_DATA (push, 1);
  254.          PUSH_DATA (push, 0);
  255.          PUSH_DATA (push, 1);
  256.          PUSH_DATA (push, 0);
  257.          PUSH_DATA (push, 1);
  258.          PUSH_DATA (push, 0);
  259.          PUSH_DATA (push, tic->id * 32);
  260.          PUSH_DATA (push, 0);
  261.          PUSH_DATA (push, 0);
  262.          BEGIN_NI04(push, NV50_2D(SIFC_DATA), 8);
  263.          PUSH_DATAp(push, &tic->tic[0], 8);
  264.  
  265.          need_flush = TRUE;
  266.       } else
  267.       if (res->status & NOUVEAU_BUFFER_STATUS_GPU_WRITING) {
  268.          BEGIN_NV04(push, NV50_3D(TEX_CACHE_CTL), 1);
  269.          PUSH_DATA (push, 0x20);
  270.       }
  271.  
  272.       nv50->screen->tic.lock[tic->id / 32] |= 1 << (tic->id % 32);
  273.  
  274.       res->status &= NOUVEAU_BUFFER_STATUS_GPU_WRITING;
  275.       res->status |= NOUVEAU_BUFFER_STATUS_GPU_READING;
  276.  
  277.       BCTX_REFN(nv50->bufctx_3d, TEXTURES, res, RD);
  278.  
  279.       BEGIN_NV04(push, NV50_3D(BIND_TIC(s)), 1);
  280.       PUSH_DATA (push, (tic->id << 9) | (i << 1) | 1);
  281.    }
  282.    for (; i < nv50->state.num_textures[s]; ++i) {
  283.       BEGIN_NV04(push, NV50_3D(BIND_TIC(s)), 1);
  284.       PUSH_DATA (push, (i << 1) | 0);
  285.    }
  286.    nv50->state.num_textures[s] = nv50->num_textures[s];
  287.  
  288.    return need_flush;
  289. }
  290.  
  291. void nv50_validate_textures(struct nv50_context *nv50)
  292. {
  293.    boolean need_flush;
  294.  
  295.    need_flush  = nv50_validate_tic(nv50, 0);
  296.    need_flush |= nv50_validate_tic(nv50, 2);
  297.  
  298.    if (need_flush) {
  299.       BEGIN_NV04(nv50->base.pushbuf, NV50_3D(TIC_FLUSH), 1);
  300.       PUSH_DATA (nv50->base.pushbuf, 0);
  301.    }
  302. }
  303.  
  304. static boolean
  305. nv50_validate_tsc(struct nv50_context *nv50, int s)
  306. {
  307.    struct nouveau_pushbuf *push = nv50->base.pushbuf;
  308.    unsigned i;
  309.    boolean need_flush = FALSE;
  310.  
  311.    for (i = 0; i < nv50->num_samplers[s]; ++i) {
  312.       struct nv50_tsc_entry *tsc = nv50_tsc_entry(nv50->samplers[s][i]);
  313.  
  314.       if (!tsc) {
  315.          BEGIN_NV04(push, NV50_3D(BIND_TSC(s)), 1);
  316.          PUSH_DATA (push, (i << 4) | 0);
  317.          continue;
  318.       }
  319.       if (tsc->id < 0) {
  320.          tsc->id = nv50_screen_tsc_alloc(nv50->screen, tsc);
  321.  
  322.          nv50_sifc_linear_u8(&nv50->base, nv50->screen->txc,
  323.                              65536 + tsc->id * 32,
  324.                              NOUVEAU_BO_VRAM, 32, tsc->tsc);
  325.          need_flush = TRUE;
  326.       }
  327.       nv50->screen->tsc.lock[tsc->id / 32] |= 1 << (tsc->id % 32);
  328.  
  329.       BEGIN_NV04(push, NV50_3D(BIND_TSC(s)), 1);
  330.       PUSH_DATA (push, (tsc->id << 12) | (i << 4) | 1);
  331.    }
  332.    for (; i < nv50->state.num_samplers[s]; ++i) {
  333.       BEGIN_NV04(push, NV50_3D(BIND_TSC(s)), 1);
  334.       PUSH_DATA (push, (i << 4) | 0);
  335.    }
  336.    nv50->state.num_samplers[s] = nv50->num_samplers[s];
  337.  
  338.    return need_flush;
  339. }
  340.  
  341. void nv50_validate_samplers(struct nv50_context *nv50)
  342. {
  343.    boolean need_flush;
  344.  
  345.    need_flush  = nv50_validate_tsc(nv50, 0);
  346.    need_flush |= nv50_validate_tsc(nv50, 2);
  347.  
  348.    if (need_flush) {
  349.       BEGIN_NV04(nv50->base.pushbuf, NV50_3D(TSC_FLUSH), 1);
  350.       PUSH_DATA (nv50->base.pushbuf, 0);
  351.    }
  352. }
  353.