Subversion Repositories Kolibri OS

Rev

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/nv50_context.h"
  24. #include "nv50/nv50_resource.h"
  25. #include "nv50/nv50_texture.xml.h"
  26. #include "nv50/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 (templ->target == PIPE_TEXTURE_RECT || templ->target == PIPE_BUFFER)
  62.       flags |= NV50_TEXVIEW_SCALED_COORDS;
  63.  
  64.    return nv50_create_texture_view(pipe, res, templ, flags, templ->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.    depth = MAX2(mt->base.base.array_size, mt->base.base.depth0);
  119.  
  120.    if (mt->base.base.array_size > 1) {
  121.       /* there doesn't seem to be a base layer field in TIC */
  122.       addr += view->pipe.u.tex.first_layer * mt->layer_stride;
  123.       depth = view->pipe.u.tex.last_layer - view->pipe.u.tex.first_layer + 1;
  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.    assert(nv50->num_textures[s] <= PIPE_MAX_SAMPLERS);
  226.    for (i = 0; i < nv50->num_textures[s]; ++i) {
  227.       struct nv50_tic_entry *tic = nv50_tic_entry(nv50->textures[s][i]);
  228.       struct nv04_resource *res;
  229.  
  230.       if (!tic) {
  231.          BEGIN_NV04(push, NV50_3D(BIND_TIC(s)), 1);
  232.          PUSH_DATA (push, (i << 1) | 0);
  233.          continue;
  234.       }
  235.       res = &nv50_miptree(tic->pipe.texture)->base;
  236.  
  237.       if (tic->id < 0) {
  238.          tic->id = nv50_screen_tic_alloc(nv50->screen, tic);
  239.  
  240.          BEGIN_NV04(push, NV50_2D(DST_FORMAT), 2);
  241.          PUSH_DATA (push, NV50_SURFACE_FORMAT_R8_UNORM);
  242.          PUSH_DATA (push, 1);
  243.          BEGIN_NV04(push, NV50_2D(DST_PITCH), 5);
  244.          PUSH_DATA (push, 262144);
  245.          PUSH_DATA (push, 65536);
  246.          PUSH_DATA (push, 1);
  247.          PUSH_DATAh(push, txc->offset);
  248.          PUSH_DATA (push, txc->offset);
  249.          BEGIN_NV04(push, NV50_2D(SIFC_BITMAP_ENABLE), 2);
  250.          PUSH_DATA (push, 0);
  251.          PUSH_DATA (push, NV50_SURFACE_FORMAT_R8_UNORM);
  252.          BEGIN_NV04(push, NV50_2D(SIFC_WIDTH), 10);
  253.          PUSH_DATA (push, 32);
  254.          PUSH_DATA (push, 1);
  255.          PUSH_DATA (push, 0);
  256.          PUSH_DATA (push, 1);
  257.          PUSH_DATA (push, 0);
  258.          PUSH_DATA (push, 1);
  259.          PUSH_DATA (push, 0);
  260.          PUSH_DATA (push, tic->id * 32);
  261.          PUSH_DATA (push, 0);
  262.          PUSH_DATA (push, 0);
  263.          BEGIN_NI04(push, NV50_2D(SIFC_DATA), 8);
  264.          PUSH_DATAp(push, &tic->tic[0], 8);
  265.  
  266.          need_flush = TRUE;
  267.       } else
  268.       if (res->status & NOUVEAU_BUFFER_STATUS_GPU_WRITING) {
  269.          BEGIN_NV04(push, NV50_3D(TEX_CACHE_CTL), 1);
  270.          PUSH_DATA (push, 0x20);
  271.       }
  272.  
  273.       nv50->screen->tic.lock[tic->id / 32] |= 1 << (tic->id % 32);
  274.  
  275.       res->status &= ~NOUVEAU_BUFFER_STATUS_GPU_WRITING;
  276.       res->status |= NOUVEAU_BUFFER_STATUS_GPU_READING;
  277.  
  278.       BCTX_REFN(nv50->bufctx_3d, TEXTURES, res, RD);
  279.  
  280.       BEGIN_NV04(push, NV50_3D(BIND_TIC(s)), 1);
  281.       PUSH_DATA (push, (tic->id << 9) | (i << 1) | 1);
  282.    }
  283.    for (; i < nv50->state.num_textures[s]; ++i) {
  284.       BEGIN_NV04(push, NV50_3D(BIND_TIC(s)), 1);
  285.       PUSH_DATA (push, (i << 1) | 0);
  286.    }
  287.    if (nv50->num_textures[s]) {
  288.       BEGIN_NV04(push, NV50_3D(CB_ADDR), 1);
  289.       PUSH_DATA (push, ((NV50_CB_AUX_TEX_MS_OFFSET + 16 * s * 2 * 4) << (8 - 2)) | NV50_CB_AUX);
  290.       BEGIN_NI04(push, NV50_3D(CB_DATA(0)), nv50->num_textures[s] * 2);
  291.       for (i = 0; i < nv50->num_textures[s]; i++) {
  292.          struct nv50_tic_entry *tic = nv50_tic_entry(nv50->textures[s][i]);
  293.          struct nv50_miptree *res;
  294.  
  295.          if (!tic) {
  296.             PUSH_DATA (push, 0);
  297.             PUSH_DATA (push, 0);
  298.             continue;
  299.          }
  300.          res = nv50_miptree(tic->pipe.texture);
  301.          PUSH_DATA (push, res->ms_x);
  302.          PUSH_DATA (push, res->ms_y);
  303.       }
  304.    }
  305.    nv50->state.num_textures[s] = nv50->num_textures[s];
  306.  
  307.    return need_flush;
  308. }
  309.  
  310. void nv50_validate_textures(struct nv50_context *nv50)
  311. {
  312.    boolean need_flush;
  313.  
  314.    need_flush  = nv50_validate_tic(nv50, 0);
  315.    need_flush |= nv50_validate_tic(nv50, 1);
  316.    need_flush |= nv50_validate_tic(nv50, 2);
  317.  
  318.    if (need_flush) {
  319.       BEGIN_NV04(nv50->base.pushbuf, NV50_3D(TIC_FLUSH), 1);
  320.       PUSH_DATA (nv50->base.pushbuf, 0);
  321.    }
  322. }
  323.  
  324. static boolean
  325. nv50_validate_tsc(struct nv50_context *nv50, int s)
  326. {
  327.    struct nouveau_pushbuf *push = nv50->base.pushbuf;
  328.    unsigned i;
  329.    boolean need_flush = FALSE;
  330.  
  331.    assert(nv50->num_samplers[s] <= PIPE_MAX_SAMPLERS);
  332.    for (i = 0; i < nv50->num_samplers[s]; ++i) {
  333.       struct nv50_tsc_entry *tsc = nv50_tsc_entry(nv50->samplers[s][i]);
  334.  
  335.       if (!tsc) {
  336.          BEGIN_NV04(push, NV50_3D(BIND_TSC(s)), 1);
  337.          PUSH_DATA (push, (i << 4) | 0);
  338.          continue;
  339.       }
  340.       if (tsc->id < 0) {
  341.          tsc->id = nv50_screen_tsc_alloc(nv50->screen, tsc);
  342.  
  343.          nv50_sifc_linear_u8(&nv50->base, nv50->screen->txc,
  344.                              65536 + tsc->id * 32,
  345.                              NOUVEAU_BO_VRAM, 32, tsc->tsc);
  346.          need_flush = TRUE;
  347.       }
  348.       nv50->screen->tsc.lock[tsc->id / 32] |= 1 << (tsc->id % 32);
  349.  
  350.       BEGIN_NV04(push, NV50_3D(BIND_TSC(s)), 1);
  351.       PUSH_DATA (push, (tsc->id << 12) | (i << 4) | 1);
  352.    }
  353.    for (; i < nv50->state.num_samplers[s]; ++i) {
  354.       BEGIN_NV04(push, NV50_3D(BIND_TSC(s)), 1);
  355.       PUSH_DATA (push, (i << 4) | 0);
  356.    }
  357.    nv50->state.num_samplers[s] = nv50->num_samplers[s];
  358.  
  359.    return need_flush;
  360. }
  361.  
  362. void nv50_validate_samplers(struct nv50_context *nv50)
  363. {
  364.    boolean need_flush;
  365.  
  366.    need_flush  = nv50_validate_tsc(nv50, 0);
  367.    need_flush |= nv50_validate_tsc(nv50, 1);
  368.    need_flush |= nv50_validate_tsc(nv50, 2);
  369.  
  370.    if (need_flush) {
  371.       BEGIN_NV04(nv50->base.pushbuf, NV50_3D(TSC_FLUSH), 1);
  372.       PUSH_DATA (nv50->base.pushbuf, 0);
  373.    }
  374. }
  375.  
  376. /* There can be up to 4 different MS levels (1, 2, 4, 8). To simplify the
  377.  * shader logic, allow each one to take up 8 offsets.
  378.  */
  379. #define COMBINE(x, y) x, y
  380. #define DUMMY 0, 0
  381. static const uint32_t msaa_sample_xy_offsets[] = {
  382.    /* MS1 */
  383.    COMBINE(0, 0),
  384.    DUMMY,
  385.    DUMMY,
  386.    DUMMY,
  387.    DUMMY,
  388.    DUMMY,
  389.    DUMMY,
  390.    DUMMY,
  391.  
  392.    /* MS2 */
  393.    COMBINE(0, 0),
  394.    COMBINE(1, 0),
  395.    DUMMY,
  396.    DUMMY,
  397.    DUMMY,
  398.    DUMMY,
  399.    DUMMY,
  400.    DUMMY,
  401.  
  402.    /* MS4 */
  403.    COMBINE(0, 0),
  404.    COMBINE(1, 0),
  405.    COMBINE(0, 1),
  406.    COMBINE(1, 1),
  407.    DUMMY,
  408.    DUMMY,
  409.    DUMMY,
  410.    DUMMY,
  411.  
  412.    /* MS8 */
  413.    COMBINE(0, 0),
  414.    COMBINE(1, 0),
  415.    COMBINE(0, 1),
  416.    COMBINE(1, 1),
  417.    COMBINE(2, 0),
  418.    COMBINE(3, 0),
  419.    COMBINE(2, 1),
  420.    COMBINE(3, 1),
  421. };
  422.  
  423. void nv50_upload_ms_info(struct nouveau_pushbuf *push)
  424. {
  425.    BEGIN_NV04(push, NV50_3D(CB_ADDR), 1);
  426.    PUSH_DATA (push, (NV50_CB_AUX_MS_OFFSET << (8 - 2)) | NV50_CB_AUX);
  427.    BEGIN_NI04(push, NV50_3D(CB_DATA(0)), Elements(msaa_sample_xy_offsets));
  428.    PUSH_DATAp(push, msaa_sample_xy_offsets, Elements(msaa_sample_xy_offsets));
  429. }
  430.