Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright 2012 Red Hat Inc.
  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.  * Authors: Ben Skeggs
  23.  *
  24.  */
  25.  
  26. #include "util/u_format.h"
  27. #include "util/u_inlines.h"
  28. #include "util/u_surface.h"
  29.  
  30. #include "nv_m2mf.xml.h"
  31. #include "nv30/nv30_screen.h"
  32. #include "nv30/nv30_context.h"
  33. #include "nv30/nv30_resource.h"
  34. #include "nv30/nv30_transfer.h"
  35.  
  36. static INLINE unsigned
  37. layer_offset(struct pipe_resource *pt, unsigned level, unsigned layer)
  38. {
  39.    struct nv30_miptree *mt = nv30_miptree(pt);
  40.    struct nv30_miptree_level *lvl = &mt->level[level];
  41.  
  42.    if (pt->target == PIPE_TEXTURE_CUBE)
  43.       return (layer * mt->layer_size) + lvl->offset;
  44.  
  45.    return lvl->offset + (layer * lvl->zslice_size);
  46. }
  47.  
  48. static boolean
  49. nv30_miptree_get_handle(struct pipe_screen *pscreen,
  50.                         struct pipe_resource *pt,
  51.                         struct winsys_handle *handle)
  52. {
  53.    struct nv30_miptree *mt = nv30_miptree(pt);
  54.    unsigned stride;
  55.  
  56.    if (!mt || !mt->base.bo)
  57.       return FALSE;
  58.  
  59.    stride = mt->level[0].pitch;
  60.  
  61.    return nouveau_screen_bo_get_handle(pscreen, mt->base.bo, stride, handle);
  62. }
  63.  
  64. static void
  65. nv30_miptree_destroy(struct pipe_screen *pscreen, struct pipe_resource *pt)
  66. {
  67.    struct nv30_miptree *mt = nv30_miptree(pt);
  68.  
  69.    nouveau_bo_ref(NULL, &mt->base.bo);
  70.    FREE(mt);
  71. }
  72.  
  73. struct nv30_transfer {
  74.    struct pipe_transfer base;
  75.    struct nv30_rect img;
  76.    struct nv30_rect tmp;
  77.    unsigned nblocksx;
  78.    unsigned nblocksy;
  79. };
  80.  
  81. static INLINE struct nv30_transfer *
  82. nv30_transfer(struct pipe_transfer *ptx)
  83. {
  84.    return (struct nv30_transfer *)ptx;
  85. }
  86.  
  87. static INLINE void
  88. define_rect(struct pipe_resource *pt, unsigned level, unsigned z,
  89.             unsigned x, unsigned y, unsigned w, unsigned h,
  90.             struct nv30_rect *rect)
  91. {
  92.    struct nv30_miptree *mt = nv30_miptree(pt);
  93.    struct nv30_miptree_level *lvl = &mt->level[level];
  94.  
  95.    rect->w = u_minify(pt->width0, level) << mt->ms_x;
  96.    rect->w = util_format_get_nblocksx(pt->format, rect->w);
  97.    rect->h = u_minify(pt->height0, level) << mt->ms_y;
  98.    rect->h = util_format_get_nblocksy(pt->format, rect->h);
  99.    rect->d = 1;
  100.    rect->z = 0;
  101.    if (mt->swizzled) {
  102.       if (pt->target == PIPE_TEXTURE_3D) {
  103.          rect->d = u_minify(pt->depth0, level);
  104.          rect->z = z; z = 0;
  105.       }
  106.       rect->pitch = 0;
  107.    } else {
  108.       rect->pitch = lvl->pitch;
  109.    }
  110.  
  111.    rect->bo     = mt->base.bo;
  112.    rect->domain = NOUVEAU_BO_VRAM;
  113.    rect->offset = layer_offset(pt, level, z);
  114.    rect->cpp    = util_format_get_blocksize(pt->format);
  115.  
  116.    rect->x0     = util_format_get_nblocksx(pt->format, x) << mt->ms_x;
  117.    rect->y0     = util_format_get_nblocksy(pt->format, y) << mt->ms_y;
  118.    rect->x1     = rect->x0 + (w << mt->ms_x);
  119.    rect->y1     = rect->y0 + (h << mt->ms_y);
  120. }
  121.  
  122. void
  123. nv30_resource_copy_region(struct pipe_context *pipe,
  124.                           struct pipe_resource *dstres, unsigned dst_level,
  125.                           unsigned dstx, unsigned dsty, unsigned dstz,
  126.                           struct pipe_resource *srcres, unsigned src_level,
  127.                           const struct pipe_box *src_box)
  128. {
  129.    struct nv30_context *nv30 = nv30_context(pipe);
  130.    struct nv30_rect src, dst;
  131.  
  132.    if (dstres->target == PIPE_BUFFER && srcres->target == PIPE_BUFFER) {
  133.       nouveau_copy_buffer(&nv30->base,
  134.                           nv04_resource(dstres), dstx,
  135.                           nv04_resource(srcres), src_box->x, src_box->width);
  136.       return;
  137.    }
  138.  
  139.    define_rect(srcres, src_level, src_box->z, src_box->x, src_box->y,
  140.                        src_box->width, src_box->height, &src);
  141.    define_rect(dstres, dst_level, dstz, dstx, dsty,
  142.                        src_box->width, src_box->height, &dst);
  143.  
  144.    nv30_transfer_rect(nv30, NEAREST, &src, &dst);
  145. }
  146.  
  147. void
  148. nv30_resource_resolve(struct pipe_context *pipe,
  149.                       const struct pipe_resolve_info *info)
  150. {
  151. #if 0
  152.    struct nv30_context *nv30 = nv30_context(pipe);
  153.    struct nv30_rect src, dst;
  154.  
  155.    define_rect(info->src.res, 0, 0, info->src.x0, info->src.y0,
  156.                info->src.x1 - info->src.x0, info->src.y1 - info->src.y0, &src);
  157.    define_rect(info->dst.res, info->dst.level, 0, info->dst.x0, info->dst.y0,
  158.                info->dst.x1 - info->dst.x0, info->dst.y1 - info->dst.y0, &dst);
  159.  
  160.    nv30_transfer_rect(nv30, BILINEAR, &src, &dst);
  161. #endif
  162. }
  163.  
  164. void
  165. nv30_blit(struct pipe_context *pipe,
  166.           const struct pipe_blit_info *blit_info)
  167. {
  168.    struct nv30_context *nv30 = nv30_context(pipe);
  169.    struct pipe_blit_info info = *blit_info;
  170.  
  171.    if (info.src.resource->nr_samples > 1 &&
  172.        info.dst.resource->nr_samples <= 1 &&
  173.        !util_format_is_depth_or_stencil(info.src.resource->format) &&
  174.        !util_format_is_pure_integer(info.src.resource->format)) {
  175.       debug_printf("nv30: color resolve unimplemented\n");
  176.       return;
  177.    }
  178.  
  179.    if (util_try_blit_via_copy_region(pipe, &info)) {
  180.       return; /* done */
  181.    }
  182.  
  183.    if (info.mask & PIPE_MASK_S) {
  184.       debug_printf("nv30: cannot blit stencil, skipping\n");
  185.       info.mask &= ~PIPE_MASK_S;
  186.    }
  187.  
  188.    if (!util_blitter_is_blit_supported(nv30->blitter, &info)) {
  189.       debug_printf("nv30: blit unsupported %s -> %s\n",
  190.                    util_format_short_name(info.src.resource->format),
  191.                    util_format_short_name(info.dst.resource->format));
  192.       return;
  193.    }
  194.  
  195.    /* XXX turn off occlusion queries */
  196.  
  197.    util_blitter_save_vertex_buffer_slot(nv30->blitter, nv30->vtxbuf);
  198.    util_blitter_save_vertex_elements(nv30->blitter, nv30->vertex);
  199.    util_blitter_save_vertex_shader(nv30->blitter, nv30->vertprog.program);
  200.    util_blitter_save_rasterizer(nv30->blitter, nv30->rast);
  201.    util_blitter_save_viewport(nv30->blitter, &nv30->viewport);
  202.    util_blitter_save_scissor(nv30->blitter, &nv30->scissor);
  203.    util_blitter_save_fragment_shader(nv30->blitter, nv30->fragprog.program);
  204.    util_blitter_save_blend(nv30->blitter, nv30->blend);
  205.    util_blitter_save_depth_stencil_alpha(nv30->blitter,
  206.                                          nv30->zsa);
  207.    util_blitter_save_stencil_ref(nv30->blitter, &nv30->stencil_ref);
  208.    util_blitter_save_sample_mask(nv30->blitter, nv30->sample_mask);
  209.    util_blitter_save_framebuffer(nv30->blitter, &nv30->framebuffer);
  210.    util_blitter_save_fragment_sampler_states(nv30->blitter,
  211.                      nv30->fragprog.num_samplers,
  212.                      (void**)nv30->fragprog.samplers);
  213.    util_blitter_save_fragment_sampler_views(nv30->blitter,
  214.                      nv30->fragprog.num_textures, nv30->fragprog.textures);
  215.    util_blitter_save_render_condition(nv30->blitter, nv30->render_cond_query,
  216.                                       nv30->render_cond_cond, nv30->render_cond_mode);
  217.    util_blitter_blit(nv30->blitter, &info);
  218. }
  219.  
  220. void
  221. nv30_flush_resource(struct pipe_context *pipe,
  222.                     struct pipe_resource *resource)
  223. {
  224. }
  225.  
  226. static void *
  227. nv30_miptree_transfer_map(struct pipe_context *pipe, struct pipe_resource *pt,
  228.                           unsigned level, unsigned usage,
  229.                           const struct pipe_box *box,
  230.                           struct pipe_transfer **ptransfer)
  231. {
  232.    struct nv30_context *nv30 = nv30_context(pipe);
  233.    struct nouveau_device *dev = nv30->screen->base.device;
  234.    struct nv30_transfer *tx;
  235.    unsigned access = 0;
  236.    int ret;
  237.  
  238.    tx = CALLOC_STRUCT(nv30_transfer);
  239.    if (!tx)
  240.       return NULL;
  241.    pipe_resource_reference(&tx->base.resource, pt);
  242.    tx->base.level = level;
  243.    tx->base.usage = usage;
  244.    tx->base.box = *box;
  245.    tx->base.stride = util_format_get_nblocksx(pt->format, box->width) *
  246.                      util_format_get_blocksize(pt->format);
  247.    tx->base.layer_stride = util_format_get_nblocksy(pt->format, box->height) *
  248.                            tx->base.stride;
  249.  
  250.    tx->nblocksx = util_format_get_nblocksx(pt->format, box->width);
  251.    tx->nblocksy = util_format_get_nblocksy(pt->format, box->height);
  252.  
  253.    define_rect(pt, level, box->z, box->x, box->y,
  254.                    tx->nblocksx, tx->nblocksy, &tx->img);
  255.  
  256.    ret = nouveau_bo_new(dev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 0,
  257.                         tx->base.layer_stride, NULL, &tx->tmp.bo);
  258.    if (ret) {
  259.       pipe_resource_reference(&tx->base.resource, NULL);
  260.       FREE(tx);
  261.       return NULL;
  262.    }
  263.  
  264.    tx->tmp.domain = NOUVEAU_BO_GART;
  265.    tx->tmp.offset = 0;
  266.    tx->tmp.pitch  = tx->base.stride;
  267.    tx->tmp.cpp    = tx->img.cpp;
  268.    tx->tmp.w      = tx->nblocksx;
  269.    tx->tmp.h      = tx->nblocksy;
  270.    tx->tmp.d      = 1;
  271.    tx->tmp.x0     = 0;
  272.    tx->tmp.y0     = 0;
  273.    tx->tmp.x1     = tx->tmp.w;
  274.    tx->tmp.y1     = tx->tmp.h;
  275.    tx->tmp.z      = 0;
  276.  
  277.    if (usage & PIPE_TRANSFER_READ)
  278.       nv30_transfer_rect(nv30, NEAREST, &tx->img, &tx->tmp);
  279.  
  280.    if (tx->tmp.bo->map) {
  281.       *ptransfer = &tx->base;
  282.       return tx->tmp.bo->map;
  283.    }
  284.  
  285.    if (usage & PIPE_TRANSFER_READ)
  286.       access |= NOUVEAU_BO_RD;
  287.    if (usage & PIPE_TRANSFER_WRITE)
  288.       access |= NOUVEAU_BO_WR;
  289.  
  290.    ret = nouveau_bo_map(tx->tmp.bo, access, nv30->base.client);
  291.    if (ret) {
  292.       pipe_resource_reference(&tx->base.resource, NULL);
  293.       FREE(tx);
  294.       return NULL;
  295.    }
  296.  
  297.    *ptransfer = &tx->base;
  298.    return tx->tmp.bo->map;
  299. }
  300.  
  301. static void
  302. nv30_miptree_transfer_unmap(struct pipe_context *pipe,
  303.                             struct pipe_transfer *ptx)
  304. {
  305.    struct nv30_context *nv30 = nv30_context(pipe);
  306.    struct nv30_transfer *tx = nv30_transfer(ptx);
  307.  
  308.    if (ptx->usage & PIPE_TRANSFER_WRITE)
  309.       nv30_transfer_rect(nv30, NEAREST, &tx->tmp, &tx->img);
  310.  
  311.    nouveau_bo_ref(NULL, &tx->tmp.bo);
  312.    pipe_resource_reference(&ptx->resource, NULL);
  313.    FREE(tx);
  314. }
  315.  
  316. const struct u_resource_vtbl nv30_miptree_vtbl = {
  317.    nv30_miptree_get_handle,
  318.    nv30_miptree_destroy,
  319.    nv30_miptree_transfer_map,
  320.    u_default_transfer_flush_region,
  321.    nv30_miptree_transfer_unmap,
  322.    u_default_transfer_inline_write
  323. };
  324.  
  325. struct pipe_resource *
  326. nv30_miptree_create(struct pipe_screen *pscreen,
  327.                     const struct pipe_resource *tmpl)
  328. {
  329.    struct nouveau_device *dev = nouveau_screen(pscreen)->device;
  330.    struct nv30_miptree *mt = CALLOC_STRUCT(nv30_miptree);
  331.    struct pipe_resource *pt = &mt->base.base;
  332.    unsigned blocksz, size;
  333.    unsigned w, h, d, l;
  334.    int ret;
  335.  
  336.    switch (tmpl->nr_samples) {
  337.    case 4:
  338.       mt->ms_mode = 0x00004000;
  339.       mt->ms_x = 1;
  340.       mt->ms_y = 1;
  341.       break;
  342.    case 2:
  343.       mt->ms_mode = 0x00003000;
  344.       mt->ms_x = 1;
  345.       mt->ms_y = 0;
  346.       break;
  347.    default:
  348.       mt->ms_mode = 0x00000000;
  349.       mt->ms_x = 0;
  350.       mt->ms_y = 0;
  351.       break;
  352.    }
  353.  
  354.    mt->base.vtbl = &nv30_miptree_vtbl;
  355.    *pt = *tmpl;
  356.    pipe_reference_init(&pt->reference, 1);
  357.    pt->screen = pscreen;
  358.  
  359.    w = pt->width0 << mt->ms_x;
  360.    h = pt->height0 << mt->ms_y;
  361.    d = (pt->target == PIPE_TEXTURE_3D) ? pt->depth0 : 1;
  362.    blocksz = util_format_get_blocksize(pt->format);
  363.  
  364.    if ((pt->target == PIPE_TEXTURE_RECT) ||
  365.        !util_is_power_of_two(pt->width0) ||
  366.        !util_is_power_of_two(pt->height0) ||
  367.        !util_is_power_of_two(pt->depth0) ||
  368.        util_format_is_compressed(pt->format) ||
  369.        util_format_is_float(pt->format) || mt->ms_mode) {
  370.       mt->uniform_pitch = util_format_get_nblocksx(pt->format, w) * blocksz;
  371.       mt->uniform_pitch = align(mt->uniform_pitch, 64);
  372.    }
  373.  
  374.    if (!mt->uniform_pitch)
  375.       mt->swizzled = TRUE;
  376.  
  377.    size = 0;
  378.    for (l = 0; l <= pt->last_level; l++) {
  379.       struct nv30_miptree_level *lvl = &mt->level[l];
  380.       unsigned nbx = util_format_get_nblocksx(pt->format, w);
  381.       unsigned nby = util_format_get_nblocksx(pt->format, h);
  382.  
  383.       lvl->offset = size;
  384.       lvl->pitch  = mt->uniform_pitch;
  385.       if (!lvl->pitch)
  386.          lvl->pitch = nbx * blocksz;
  387.  
  388.       lvl->zslice_size = lvl->pitch * nby;
  389.       size += lvl->zslice_size * d;
  390.  
  391.       w = u_minify(w, 1);
  392.       h = u_minify(h, 1);
  393.       d = u_minify(d, 1);
  394.    }
  395.  
  396.    mt->layer_size = size;
  397.    if (pt->target == PIPE_TEXTURE_CUBE) {
  398.       if (!mt->uniform_pitch)
  399.          mt->layer_size = align(mt->layer_size, 128);
  400.       size = mt->layer_size * 6;
  401.    }
  402.  
  403.    ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 256, size, NULL, &mt->base.bo);
  404.    if (ret) {
  405.       FREE(mt);
  406.       return NULL;
  407.    }
  408.  
  409.    mt->base.domain = NOUVEAU_BO_VRAM;
  410.    return &mt->base.base;
  411. }
  412.  
  413. struct pipe_resource *
  414. nv30_miptree_from_handle(struct pipe_screen *pscreen,
  415.                          const struct pipe_resource *tmpl,
  416.                          struct winsys_handle *handle)
  417. {
  418.    struct nv30_miptree *mt;
  419.    unsigned stride;
  420.  
  421.    /* only supports 2D, non-mipmapped textures for the moment */
  422.    if ((tmpl->target != PIPE_TEXTURE_2D &&
  423.         tmpl->target != PIPE_TEXTURE_RECT) ||
  424.        tmpl->last_level != 0 ||
  425.        tmpl->depth0 != 1 ||
  426.        tmpl->array_size > 1)
  427.       return NULL;
  428.  
  429.    mt = CALLOC_STRUCT(nv30_miptree);
  430.    if (!mt)
  431.       return NULL;
  432.  
  433.    mt->base.bo = nouveau_screen_bo_from_handle(pscreen, handle, &stride);
  434.    if (mt->base.bo == NULL) {
  435.       FREE(mt);
  436.       return NULL;
  437.    }
  438.  
  439.    mt->base.base = *tmpl;
  440.    mt->base.vtbl = &nv30_miptree_vtbl;
  441.    pipe_reference_init(&mt->base.base.reference, 1);
  442.    mt->base.base.screen = pscreen;
  443.    mt->uniform_pitch = stride;
  444.    mt->level[0].pitch = mt->uniform_pitch;
  445.    mt->level[0].offset = 0;
  446.  
  447.    /* no need to adjust bo reference count */
  448.    return &mt->base.base;
  449. }
  450.  
  451. struct pipe_surface *
  452. nv30_miptree_surface_new(struct pipe_context *pipe,
  453.                          struct pipe_resource *pt,
  454.                          const struct pipe_surface *tmpl)
  455. {
  456.    struct nv30_miptree *mt = nv30_miptree(pt); /* guaranteed */
  457.    struct nv30_surface *ns;
  458.    struct pipe_surface *ps;
  459.    struct nv30_miptree_level *lvl = &mt->level[tmpl->u.tex.level];
  460.  
  461.    ns = CALLOC_STRUCT(nv30_surface);
  462.    if (!ns)
  463.       return NULL;
  464.    ps = &ns->base;
  465.  
  466.    pipe_reference_init(&ps->reference, 1);
  467.    pipe_resource_reference(&ps->texture, pt);
  468.    ps->context = pipe;
  469.    ps->format = tmpl->format;
  470.    ps->u.tex.level = tmpl->u.tex.level;
  471.    ps->u.tex.first_layer = tmpl->u.tex.first_layer;
  472.    ps->u.tex.last_layer = tmpl->u.tex.last_layer;
  473.  
  474.    ns->width = u_minify(pt->width0, ps->u.tex.level);
  475.    ns->height = u_minify(pt->height0, ps->u.tex.level);
  476.    ns->depth = ps->u.tex.last_layer - ps->u.tex.first_layer + 1;
  477.    ns->offset = layer_offset(pt, ps->u.tex.level, ps->u.tex.first_layer);
  478.    if (mt->swizzled)
  479.       ns->pitch = 4096; /* random, just something the hw won't reject.. */
  480.    else
  481.       ns->pitch = lvl->pitch;
  482.  
  483.    /* comment says there are going to be removed, but they're used by the st */
  484.    ps->width = ns->width;
  485.    ps->height = ns->height;
  486.    return ps;
  487. }
  488.  
  489. void
  490. nv30_miptree_surface_del(struct pipe_context *pipe, struct pipe_surface *ps)
  491. {
  492.    struct nv30_surface *ns = nv30_surface(ps);
  493.  
  494.    pipe_resource_reference(&ps->texture, NULL);
  495.    FREE(ns);
  496. }
  497.