Subversion Repositories Kolibri OS

Rev

Go to most recent revision | 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 "nouveau/nv_m2mf.xml.h"
  31. #include "nv30_screen.h"
  32. #include "nv30_context.h"
  33. #include "nv30_resource.h"
  34. #include "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. static void *
  221. nv30_miptree_transfer_map(struct pipe_context *pipe, struct pipe_resource *pt,
  222.                           unsigned level, unsigned usage,
  223.                           const struct pipe_box *box,
  224.                           struct pipe_transfer **ptransfer)
  225. {
  226.    struct nv30_context *nv30 = nv30_context(pipe);
  227.    struct nouveau_device *dev = nv30->screen->base.device;
  228.    struct nv30_transfer *tx;
  229.    unsigned access = 0;
  230.    int ret;
  231.  
  232.    tx = CALLOC_STRUCT(nv30_transfer);
  233.    if (!tx)
  234.       return NULL;
  235.    pipe_resource_reference(&tx->base.resource, pt);
  236.    tx->base.level = level;
  237.    tx->base.usage = usage;
  238.    tx->base.box = *box;
  239.    tx->base.stride = util_format_get_nblocksx(pt->format, box->width) *
  240.                      util_format_get_blocksize(pt->format);
  241.    tx->base.layer_stride = util_format_get_nblocksy(pt->format, box->height) *
  242.                            tx->base.stride;
  243.  
  244.    tx->nblocksx = util_format_get_nblocksx(pt->format, box->width);
  245.    tx->nblocksy = util_format_get_nblocksy(pt->format, box->height);
  246.  
  247.    define_rect(pt, level, box->z, box->x, box->y,
  248.                    tx->nblocksx, tx->nblocksy, &tx->img);
  249.  
  250.    ret = nouveau_bo_new(dev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 0,
  251.                         tx->base.layer_stride, NULL, &tx->tmp.bo);
  252.    if (ret) {
  253.       pipe_resource_reference(&tx->base.resource, NULL);
  254.       FREE(tx);
  255.       return NULL;
  256.    }
  257.  
  258.    tx->tmp.domain = NOUVEAU_BO_GART;
  259.    tx->tmp.offset = 0;
  260.    tx->tmp.pitch  = tx->base.stride;
  261.    tx->tmp.cpp    = tx->img.cpp;
  262.    tx->tmp.w      = tx->nblocksx;
  263.    tx->tmp.h      = tx->nblocksy;
  264.    tx->tmp.d      = 1;
  265.    tx->tmp.x0     = 0;
  266.    tx->tmp.y0     = 0;
  267.    tx->tmp.x1     = tx->tmp.w;
  268.    tx->tmp.y1     = tx->tmp.h;
  269.    tx->tmp.z      = 0;
  270.  
  271.    if (usage & PIPE_TRANSFER_READ)
  272.       nv30_transfer_rect(nv30, NEAREST, &tx->img, &tx->tmp);
  273.  
  274.    if (tx->tmp.bo->map) {
  275.       *ptransfer = &tx->base;
  276.       return tx->tmp.bo->map;
  277.    }
  278.  
  279.    if (usage & PIPE_TRANSFER_READ)
  280.       access |= NOUVEAU_BO_RD;
  281.    if (usage & PIPE_TRANSFER_WRITE)
  282.       access |= NOUVEAU_BO_WR;
  283.  
  284.    ret = nouveau_bo_map(tx->tmp.bo, access, nv30->base.client);
  285.    if (ret) {
  286.       pipe_resource_reference(&tx->base.resource, NULL);
  287.       FREE(tx);
  288.       return NULL;
  289.    }
  290.  
  291.    *ptransfer = &tx->base;
  292.    return tx->tmp.bo->map;
  293. }
  294.  
  295. static void
  296. nv30_miptree_transfer_unmap(struct pipe_context *pipe,
  297.                             struct pipe_transfer *ptx)
  298. {
  299.    struct nv30_context *nv30 = nv30_context(pipe);
  300.    struct nv30_transfer *tx = nv30_transfer(ptx);
  301.  
  302.    if (ptx->usage & PIPE_TRANSFER_WRITE)
  303.       nv30_transfer_rect(nv30, NEAREST, &tx->tmp, &tx->img);
  304.  
  305.    nouveau_bo_ref(NULL, &tx->tmp.bo);
  306.    pipe_resource_reference(&ptx->resource, NULL);
  307.    FREE(tx);
  308. }
  309.  
  310. const struct u_resource_vtbl nv30_miptree_vtbl = {
  311.    nv30_miptree_get_handle,
  312.    nv30_miptree_destroy,
  313.    nv30_miptree_transfer_map,
  314.    u_default_transfer_flush_region,
  315.    nv30_miptree_transfer_unmap,
  316.    u_default_transfer_inline_write
  317. };
  318.  
  319. struct pipe_resource *
  320. nv30_miptree_create(struct pipe_screen *pscreen,
  321.                     const struct pipe_resource *tmpl)
  322. {
  323.    struct nouveau_device *dev = nouveau_screen(pscreen)->device;
  324.    struct nv30_miptree *mt = CALLOC_STRUCT(nv30_miptree);
  325.    struct pipe_resource *pt = &mt->base.base;
  326.    unsigned blocksz, size;
  327.    unsigned w, h, d, l;
  328.    int ret;
  329.  
  330.    switch (tmpl->nr_samples) {
  331.    case 4:
  332.       mt->ms_mode = 0x00004000;
  333.       mt->ms_x = 1;
  334.       mt->ms_y = 1;
  335.       break;
  336.    case 2:
  337.       mt->ms_mode = 0x00003000;
  338.       mt->ms_x = 1;
  339.       mt->ms_y = 0;
  340.       break;
  341.    default:
  342.       mt->ms_mode = 0x00000000;
  343.       mt->ms_x = 0;
  344.       mt->ms_y = 0;
  345.       break;
  346.    }
  347.  
  348.    mt->base.vtbl = &nv30_miptree_vtbl;
  349.    *pt = *tmpl;
  350.    pipe_reference_init(&pt->reference, 1);
  351.    pt->screen = pscreen;
  352.  
  353.    w = pt->width0 << mt->ms_x;
  354.    h = pt->height0 << mt->ms_y;
  355.    d = (pt->target == PIPE_TEXTURE_3D) ? pt->depth0 : 1;
  356.    blocksz = util_format_get_blocksize(pt->format);
  357.  
  358.    if ((pt->target == PIPE_TEXTURE_RECT) ||
  359.        !util_is_power_of_two(pt->width0) ||
  360.        !util_is_power_of_two(pt->height0) ||
  361.        !util_is_power_of_two(pt->depth0) ||
  362.        util_format_is_compressed(pt->format) ||
  363.        util_format_is_float(pt->format) || mt->ms_mode) {
  364.       mt->uniform_pitch = util_format_get_nblocksx(pt->format, w) * blocksz;
  365.       mt->uniform_pitch = align(mt->uniform_pitch, 64);
  366.    }
  367.  
  368.    if (!mt->uniform_pitch)
  369.       mt->swizzled = TRUE;
  370.  
  371.    size = 0;
  372.    for (l = 0; l <= pt->last_level; l++) {
  373.       struct nv30_miptree_level *lvl = &mt->level[l];
  374.       unsigned nbx = util_format_get_nblocksx(pt->format, w);
  375.       unsigned nby = util_format_get_nblocksx(pt->format, h);
  376.  
  377.       lvl->offset = size;
  378.       lvl->pitch  = mt->uniform_pitch;
  379.       if (!lvl->pitch)
  380.          lvl->pitch = nbx * blocksz;
  381.  
  382.       lvl->zslice_size = lvl->pitch * nby;
  383.       size += lvl->zslice_size * d;
  384.  
  385.       w = u_minify(w, 1);
  386.       h = u_minify(h, 1);
  387.       d = u_minify(d, 1);
  388.    }
  389.  
  390.    mt->layer_size = size;
  391.    if (pt->target == PIPE_TEXTURE_CUBE) {
  392.       if (!mt->uniform_pitch)
  393.          mt->layer_size = align(mt->layer_size, 128);
  394.       size = mt->layer_size * 6;
  395.    }
  396.  
  397.    ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 256, size, NULL, &mt->base.bo);
  398.    if (ret) {
  399.       FREE(mt);
  400.       return NULL;
  401.    }
  402.  
  403.    mt->base.domain = NOUVEAU_BO_VRAM;
  404.    return &mt->base.base;
  405. }
  406.  
  407. struct pipe_resource *
  408. nv30_miptree_from_handle(struct pipe_screen *pscreen,
  409.                          const struct pipe_resource *tmpl,
  410.                          struct winsys_handle *handle)
  411. {
  412.    struct nv30_miptree *mt;
  413.    unsigned stride;
  414.  
  415.    /* only supports 2D, non-mipmapped textures for the moment */
  416.    if ((tmpl->target != PIPE_TEXTURE_2D &&
  417.         tmpl->target != PIPE_TEXTURE_RECT) ||
  418.        tmpl->last_level != 0 ||
  419.        tmpl->depth0 != 1 ||
  420.        tmpl->array_size > 1)
  421.       return NULL;
  422.  
  423.    mt = CALLOC_STRUCT(nv30_miptree);
  424.    if (!mt)
  425.       return NULL;
  426.  
  427.    mt->base.bo = nouveau_screen_bo_from_handle(pscreen, handle, &stride);
  428.    if (mt->base.bo == NULL) {
  429.       FREE(mt);
  430.       return NULL;
  431.    }
  432.  
  433.    mt->base.base = *tmpl;
  434.    mt->base.vtbl = &nv30_miptree_vtbl;
  435.    pipe_reference_init(&mt->base.base.reference, 1);
  436.    mt->base.base.screen = pscreen;
  437.    mt->uniform_pitch = stride;
  438.    mt->level[0].pitch = mt->uniform_pitch;
  439.    mt->level[0].offset = 0;
  440.  
  441.    /* no need to adjust bo reference count */
  442.    return &mt->base.base;
  443. }
  444.  
  445. struct pipe_surface *
  446. nv30_miptree_surface_new(struct pipe_context *pipe,
  447.                          struct pipe_resource *pt,
  448.                          const struct pipe_surface *tmpl)
  449. {
  450.    struct nv30_miptree *mt = nv30_miptree(pt); /* guaranteed */
  451.    struct nv30_surface *ns;
  452.    struct pipe_surface *ps;
  453.    struct nv30_miptree_level *lvl = &mt->level[tmpl->u.tex.level];
  454.  
  455.    ns = CALLOC_STRUCT(nv30_surface);
  456.    if (!ns)
  457.       return NULL;
  458.    ps = &ns->base;
  459.  
  460.    pipe_reference_init(&ps->reference, 1);
  461.    pipe_resource_reference(&ps->texture, pt);
  462.    ps->context = pipe;
  463.    ps->format = tmpl->format;
  464.    ps->u.tex.level = tmpl->u.tex.level;
  465.    ps->u.tex.first_layer = tmpl->u.tex.first_layer;
  466.    ps->u.tex.last_layer = tmpl->u.tex.last_layer;
  467.  
  468.    ns->width = u_minify(pt->width0, ps->u.tex.level);
  469.    ns->height = u_minify(pt->height0, ps->u.tex.level);
  470.    ns->depth = ps->u.tex.last_layer - ps->u.tex.first_layer + 1;
  471.    ns->offset = layer_offset(pt, ps->u.tex.level, ps->u.tex.first_layer);
  472.    if (mt->swizzled)
  473.       ns->pitch = 4096; /* random, just something the hw won't reject.. */
  474.    else
  475.       ns->pitch = lvl->pitch;
  476.  
  477.    /* comment says there are going to be removed, but they're used by the st */
  478.    ps->width = ns->width;
  479.    ps->height = ns->height;
  480.    return ps;
  481. }
  482.  
  483. void
  484. nv30_miptree_surface_del(struct pipe_context *pipe, struct pipe_surface *ps)
  485. {
  486.    struct nv30_surface *ns = nv30_surface(ps);
  487.  
  488.    pipe_resource_reference(&ps->texture, NULL);
  489.    FREE(ns);
  490. }
  491.