Subversion Repositories Kolibri OS

Rev

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

  1. /**************************************************************************
  2.  *
  3.  * Copyright 2006 VMware, Inc.
  4.  * All Rights Reserved.
  5.  *
  6.  * Permission is hereby granted, free of charge, to any person obtaining a
  7.  * copy of this software and associated documentation files (the
  8.  * "Software"), to deal in the Software without restriction, including
  9.  * without limitation the rights to use, copy, modify, merge, publish,
  10.  * distribute, sub license, and/or sell copies of the Software, and to
  11.  * permit persons to whom the Software is furnished to do so, subject to
  12.  * the following conditions:
  13.  *
  14.  * The above copyright notice and this permission notice (including the
  15.  * next paragraph) shall be included in all copies or substantial portions
  16.  * of the Software.
  17.  *
  18.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  19.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  20.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
  21.  * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
  22.  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  23.  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  24.  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25.  *
  26.  **************************************************************************/
  27.  /*
  28.   * Authors:
  29.   *   Keith Whitwell <keithw@vmware.com>
  30.   *   Michel Dänzer <daenzer@vmware.com>
  31.   */
  32.  
  33. #include <stdio.h>
  34.  
  35. #include "pipe/p_context.h"
  36. #include "pipe/p_defines.h"
  37.  
  38. #include "util/u_inlines.h"
  39. #include "util/u_cpu_detect.h"
  40. #include "util/u_format.h"
  41. #include "util/u_math.h"
  42. #include "util/u_memory.h"
  43. #include "util/simple_list.h"
  44. #include "util/u_transfer.h"
  45.  
  46. #include "lp_context.h"
  47. #include "lp_flush.h"
  48. #include "lp_screen.h"
  49. #include "lp_texture.h"
  50. #include "lp_setup.h"
  51. #include "lp_state.h"
  52. #include "lp_rast.h"
  53.  
  54. #include "state_tracker/sw_winsys.h"
  55.  
  56.  
  57. #ifdef DEBUG
  58. static struct llvmpipe_resource resource_list;
  59. #endif
  60. static unsigned id_counter = 0;
  61.  
  62.  
  63. /**
  64.  * Conventional allocation path for non-display textures:
  65.  * Compute strides and allocate data (unless asked not to).
  66.  */
  67. static boolean
  68. llvmpipe_texture_layout(struct llvmpipe_screen *screen,
  69.                         struct llvmpipe_resource *lpr,
  70.                         boolean allocate)
  71. {
  72.    struct pipe_resource *pt = &lpr->base;
  73.    unsigned level;
  74.    unsigned width = pt->width0;
  75.    unsigned height = pt->height0;
  76.    unsigned depth = pt->depth0;
  77.    uint64_t total_size = 0;
  78.    unsigned layers = pt->array_size;
  79.    /* XXX:
  80.     * This alignment here (same for displaytarget) was added for the purpose of
  81.     * ARB_map_buffer_alignment. I am not convinced it's needed for non-buffer
  82.     * resources. Otherwise we'd want the max of cacheline size and 16 (max size
  83.     * of a block for all formats) though this should not be strictly necessary
  84.     * neither. In any case it can only affect compressed or 1d textures.
  85.     */
  86.    unsigned mip_align = MAX2(64, util_cpu_caps.cacheline);
  87.  
  88.    assert(LP_MAX_TEXTURE_2D_LEVELS <= LP_MAX_TEXTURE_LEVELS);
  89.    assert(LP_MAX_TEXTURE_3D_LEVELS <= LP_MAX_TEXTURE_LEVELS);
  90.  
  91.    for (level = 0; level <= pt->last_level; level++) {
  92.       uint64_t mipsize;
  93.       unsigned align_x, align_y, nblocksx, nblocksy, block_size, num_slices;
  94.  
  95.       /* Row stride and image stride */
  96.  
  97.       /* For non-compressed formats we need 4x4 pixel alignment
  98.        * so we can read/write LP_RASTER_BLOCK_SIZE when rendering to them.
  99.        * We also want cache line size in x direction,
  100.        * otherwise same cache line could end up in multiple threads.
  101.        * For explicit 1d resources however we reduce this to 4x1 and
  102.        * handle specially in render output code (as we need to do special
  103.        * handling there for buffers in any case).
  104.        */
  105.       if (util_format_is_compressed(pt->format))
  106.          align_x = align_y = 1;
  107.       else {
  108.          align_x = LP_RASTER_BLOCK_SIZE;
  109.          if (llvmpipe_resource_is_1d(&lpr->base))
  110.             align_y = 1;
  111.          else
  112.             align_y = LP_RASTER_BLOCK_SIZE;
  113.       }
  114.  
  115.       nblocksx = util_format_get_nblocksx(pt->format,
  116.                                           align(width, align_x));
  117.       nblocksy = util_format_get_nblocksy(pt->format,
  118.                                           align(height, align_y));
  119.       block_size = util_format_get_blocksize(pt->format);
  120.  
  121.       if (util_format_is_compressed(pt->format))
  122.          lpr->row_stride[level] = nblocksx * block_size;
  123.       else
  124.          lpr->row_stride[level] = align(nblocksx * block_size, util_cpu_caps.cacheline);
  125.  
  126.       /* if row_stride * height > LP_MAX_TEXTURE_SIZE */
  127.       if ((uint64_t)lpr->row_stride[level] * nblocksy > LP_MAX_TEXTURE_SIZE) {
  128.          /* image too large */
  129.          goto fail;
  130.       }
  131.  
  132.       lpr->img_stride[level] = lpr->row_stride[level] * nblocksy;
  133.  
  134.       /* Number of 3D image slices, cube faces or texture array layers */
  135.       if (lpr->base.target == PIPE_TEXTURE_CUBE) {
  136.          assert(layers == 6);
  137.       }
  138.  
  139.       if (lpr->base.target == PIPE_TEXTURE_3D)
  140.          num_slices = depth;
  141.       else if (lpr->base.target == PIPE_TEXTURE_1D_ARRAY ||
  142.                lpr->base.target == PIPE_TEXTURE_2D_ARRAY ||
  143.                lpr->base.target == PIPE_TEXTURE_CUBE ||
  144.                lpr->base.target == PIPE_TEXTURE_CUBE_ARRAY)
  145.          num_slices = layers;
  146.       else
  147.          num_slices = 1;
  148.  
  149.       /* if img_stride * num_slices_faces > LP_MAX_TEXTURE_SIZE */
  150.       mipsize = (uint64_t)lpr->img_stride[level] * num_slices;
  151.       if (mipsize > LP_MAX_TEXTURE_SIZE) {
  152.          /* volume too large */
  153.          goto fail;
  154.       }
  155.  
  156.       lpr->mip_offsets[level] = total_size;
  157.  
  158.       total_size += align((unsigned)mipsize, mip_align);
  159.       if (total_size > LP_MAX_TEXTURE_SIZE) {
  160.          goto fail;
  161.       }
  162.  
  163.       /* Compute size of next mipmap level */
  164.       width = u_minify(width, 1);
  165.       height = u_minify(height, 1);
  166.       depth = u_minify(depth, 1);
  167.    }
  168.  
  169.    if (allocate) {
  170.       lpr->tex_data = align_malloc(total_size, mip_align);
  171.       if (!lpr->tex_data) {
  172.          return FALSE;
  173.       }
  174.       else {
  175.          memset(lpr->tex_data, 0, total_size);
  176.       }
  177.    }
  178.  
  179.    return TRUE;
  180.  
  181. fail:
  182.    return FALSE;
  183. }
  184.  
  185.  
  186. /**
  187.  * Check the size of the texture specified by 'res'.
  188.  * \return TRUE if OK, FALSE if too large.
  189.  */
  190. static boolean
  191. llvmpipe_can_create_resource(struct pipe_screen *screen,
  192.                              const struct pipe_resource *res)
  193. {
  194.    struct llvmpipe_resource lpr;
  195.    memset(&lpr, 0, sizeof(lpr));
  196.    lpr.base = *res;
  197.    return llvmpipe_texture_layout(llvmpipe_screen(screen), &lpr, false);
  198. }
  199.  
  200.  
  201. static boolean
  202. llvmpipe_displaytarget_layout(struct llvmpipe_screen *screen,
  203.                               struct llvmpipe_resource *lpr)
  204. {
  205.    struct sw_winsys *winsys = screen->winsys;
  206.  
  207.    /* Round up the surface size to a multiple of the tile size to
  208.     * avoid tile clipping.
  209.     */
  210.    const unsigned width = MAX2(1, align(lpr->base.width0, TILE_SIZE));
  211.    const unsigned height = MAX2(1, align(lpr->base.height0, TILE_SIZE));
  212.  
  213.    lpr->dt = winsys->displaytarget_create(winsys,
  214.                                           lpr->base.bind,
  215.                                           lpr->base.format,
  216.                                           width, height,
  217.                                           64,
  218.                                           &lpr->row_stride[0] );
  219.  
  220.    if (lpr->dt == NULL)
  221.       return FALSE;
  222.  
  223.    {
  224.       void *map = winsys->displaytarget_map(winsys, lpr->dt,
  225.                                             PIPE_TRANSFER_WRITE);
  226.  
  227.       if (map)
  228.          memset(map, 0, height * lpr->row_stride[0]);
  229.  
  230.       winsys->displaytarget_unmap(winsys, lpr->dt);
  231.    }
  232.  
  233.    return TRUE;
  234. }
  235.  
  236.  
  237. static struct pipe_resource *
  238. llvmpipe_resource_create(struct pipe_screen *_screen,
  239.                          const struct pipe_resource *templat)
  240. {
  241.    struct llvmpipe_screen *screen = llvmpipe_screen(_screen);
  242.    struct llvmpipe_resource *lpr = CALLOC_STRUCT(llvmpipe_resource);
  243.    if (!lpr)
  244.       return NULL;
  245.  
  246.    lpr->base = *templat;
  247.    pipe_reference_init(&lpr->base.reference, 1);
  248.    lpr->base.screen = &screen->base;
  249.  
  250.    /* assert(lpr->base.bind); */
  251.  
  252.    if (llvmpipe_resource_is_texture(&lpr->base)) {
  253.       if (lpr->base.bind & (PIPE_BIND_DISPLAY_TARGET |
  254.                             PIPE_BIND_SCANOUT |
  255.                             PIPE_BIND_SHARED)) {
  256.          /* displayable surface */
  257.          if (!llvmpipe_displaytarget_layout(screen, lpr))
  258.             goto fail;
  259.       }
  260.       else {
  261.          /* texture map */
  262.          if (!llvmpipe_texture_layout(screen, lpr, true))
  263.             goto fail;
  264.       }
  265.    }
  266.    else {
  267.       /* other data (vertex buffer, const buffer, etc) */
  268.       const uint bytes = templat->width0;
  269.       assert(util_format_get_blocksize(templat->format) == 1);
  270.       assert(templat->height0 == 1);
  271.       assert(templat->depth0 == 1);
  272.       assert(templat->last_level == 0);
  273.       /*
  274.        * Reserve some extra storage since if we'd render to a buffer we
  275.        * read/write always LP_RASTER_BLOCK_SIZE pixels, but the element
  276.        * offset doesn't need to be aligned to LP_RASTER_BLOCK_SIZE.
  277.        */
  278.       lpr->data = align_malloc(bytes + (LP_RASTER_BLOCK_SIZE - 1) * 4 * sizeof(float), 64);
  279.  
  280.       /*
  281.        * buffers don't really have stride but it's probably safer
  282.        * (for code doing same calculations for buffers and textures)
  283.        * to put something sane in there.
  284.        */
  285.       lpr->row_stride[0] = bytes;
  286.       if (!lpr->data)
  287.          goto fail;
  288.       memset(lpr->data, 0, bytes);
  289.    }
  290.  
  291.    lpr->id = id_counter++;
  292.  
  293. #ifdef DEBUG
  294.    insert_at_tail(&resource_list, lpr);
  295. #endif
  296.  
  297.    return &lpr->base;
  298.  
  299.  fail:
  300.    FREE(lpr);
  301.    return NULL;
  302. }
  303.  
  304.  
  305. static void
  306. llvmpipe_resource_destroy(struct pipe_screen *pscreen,
  307.                           struct pipe_resource *pt)
  308. {
  309.    struct llvmpipe_screen *screen = llvmpipe_screen(pscreen);
  310.    struct llvmpipe_resource *lpr = llvmpipe_resource(pt);
  311.  
  312.    if (lpr->dt) {
  313.       /* display target */
  314.       struct sw_winsys *winsys = screen->winsys;
  315.       winsys->displaytarget_destroy(winsys, lpr->dt);
  316.    }
  317.    else if (llvmpipe_resource_is_texture(pt)) {
  318.       /* free linear image data */
  319.       if (lpr->tex_data) {
  320.          align_free(lpr->tex_data);
  321.          lpr->tex_data = NULL;
  322.       }
  323.    }
  324.    else if (!lpr->userBuffer) {
  325.       assert(lpr->data);
  326.       align_free(lpr->data);
  327.    }
  328.  
  329. #ifdef DEBUG
  330.    if (lpr->next)
  331.       remove_from_list(lpr);
  332. #endif
  333.  
  334.    FREE(lpr);
  335. }
  336.  
  337.  
  338. /**
  339.  * Map a resource for read/write.
  340.  */
  341. void *
  342. llvmpipe_resource_map(struct pipe_resource *resource,
  343.                       unsigned level,
  344.                       unsigned layer,
  345.                       enum lp_texture_usage tex_usage)
  346. {
  347.    struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
  348.    uint8_t *map;
  349.  
  350.    assert(level < LP_MAX_TEXTURE_LEVELS);
  351.    assert(layer < (u_minify(resource->depth0, level) + resource->array_size - 1));
  352.  
  353.    assert(tex_usage == LP_TEX_USAGE_READ ||
  354.           tex_usage == LP_TEX_USAGE_READ_WRITE ||
  355.           tex_usage == LP_TEX_USAGE_WRITE_ALL);
  356.  
  357.    if (lpr->dt) {
  358.       /* display target */
  359.       struct llvmpipe_screen *screen = llvmpipe_screen(resource->screen);
  360.       struct sw_winsys *winsys = screen->winsys;
  361.       unsigned dt_usage;
  362.  
  363.       if (tex_usage == LP_TEX_USAGE_READ) {
  364.          dt_usage = PIPE_TRANSFER_READ;
  365.       }
  366.       else {
  367.          dt_usage = PIPE_TRANSFER_READ_WRITE;
  368.       }
  369.  
  370.       assert(level == 0);
  371.       assert(layer == 0);
  372.  
  373.       /* FIXME: keep map count? */
  374.       map = winsys->displaytarget_map(winsys, lpr->dt, dt_usage);
  375.  
  376.       /* install this linear image in texture data structure */
  377.       lpr->tex_data = map;
  378.  
  379.       return map;
  380.    }
  381.    else if (llvmpipe_resource_is_texture(resource)) {
  382.  
  383.       map = llvmpipe_get_texture_image_address(lpr, layer, level);
  384.       return map;
  385.    }
  386.    else {
  387.       return lpr->data;
  388.    }
  389. }
  390.  
  391.  
  392. /**
  393.  * Unmap a resource.
  394.  */
  395. void
  396. llvmpipe_resource_unmap(struct pipe_resource *resource,
  397.                        unsigned level,
  398.                        unsigned layer)
  399. {
  400.    struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
  401.  
  402.    if (lpr->dt) {
  403.       /* display target */
  404.       struct llvmpipe_screen *lp_screen = llvmpipe_screen(resource->screen);
  405.       struct sw_winsys *winsys = lp_screen->winsys;
  406.  
  407.       assert(level == 0);
  408.       assert(layer == 0);
  409.  
  410.       winsys->displaytarget_unmap(winsys, lpr->dt);
  411.    }
  412. }
  413.  
  414.  
  415. void *
  416. llvmpipe_resource_data(struct pipe_resource *resource)
  417. {
  418.    struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
  419.  
  420.    assert(!llvmpipe_resource_is_texture(resource));
  421.  
  422.    return lpr->data;
  423. }
  424.  
  425.  
  426. static struct pipe_resource *
  427. llvmpipe_resource_from_handle(struct pipe_screen *screen,
  428.                               const struct pipe_resource *template,
  429.                               struct winsys_handle *whandle)
  430. {
  431.    struct sw_winsys *winsys = llvmpipe_screen(screen)->winsys;
  432.    struct llvmpipe_resource *lpr;
  433.  
  434.    /* XXX Seems like from_handled depth textures doesn't work that well */
  435.  
  436.    lpr = CALLOC_STRUCT(llvmpipe_resource);
  437.    if (!lpr) {
  438.       goto no_lpr;
  439.    }
  440.  
  441.    lpr->base = *template;
  442.    pipe_reference_init(&lpr->base.reference, 1);
  443.    lpr->base.screen = screen;
  444.  
  445.    /*
  446.     * Looks like unaligned displaytargets work just fine,
  447.     * at least sampler/render ones.
  448.     */
  449. #if 0
  450.    assert(lpr->base.width0 == width);
  451.    assert(lpr->base.height0 == height);
  452. #endif
  453.  
  454.    lpr->dt = winsys->displaytarget_from_handle(winsys,
  455.                                                template,
  456.                                                whandle,
  457.                                                &lpr->row_stride[0]);
  458.    if (!lpr->dt) {
  459.       goto no_dt;
  460.    }
  461.  
  462.    lpr->id = id_counter++;
  463.  
  464. #ifdef DEBUG
  465.    insert_at_tail(&resource_list, lpr);
  466. #endif
  467.  
  468.    return &lpr->base;
  469.  
  470. no_dt:
  471.    FREE(lpr);
  472. no_lpr:
  473.    return NULL;
  474. }
  475.  
  476.  
  477. static boolean
  478. llvmpipe_resource_get_handle(struct pipe_screen *screen,
  479.                             struct pipe_resource *pt,
  480.                             struct winsys_handle *whandle)
  481. {
  482.    struct sw_winsys *winsys = llvmpipe_screen(screen)->winsys;
  483.    struct llvmpipe_resource *lpr = llvmpipe_resource(pt);
  484.  
  485.    assert(lpr->dt);
  486.    if (!lpr->dt)
  487.       return FALSE;
  488.  
  489.    return winsys->displaytarget_get_handle(winsys, lpr->dt, whandle);
  490. }
  491.  
  492.  
  493. static void *
  494. llvmpipe_transfer_map( struct pipe_context *pipe,
  495.                        struct pipe_resource *resource,
  496.                        unsigned level,
  497.                        unsigned usage,
  498.                        const struct pipe_box *box,
  499.                        struct pipe_transfer **transfer )
  500. {
  501.    struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
  502.    struct llvmpipe_screen *screen = llvmpipe_screen(pipe->screen);
  503.    struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
  504.    struct llvmpipe_transfer *lpt;
  505.    struct pipe_transfer *pt;
  506.    ubyte *map;
  507.    enum pipe_format format;
  508.    enum lp_texture_usage tex_usage;
  509.    const char *mode;
  510.  
  511.    assert(resource);
  512.    assert(level <= resource->last_level);
  513.  
  514.    /*
  515.     * Transfers, like other pipe operations, must happen in order, so flush the
  516.     * context if necessary.
  517.     */
  518.    if (!(usage & PIPE_TRANSFER_UNSYNCHRONIZED)) {
  519.       boolean read_only = !(usage & PIPE_TRANSFER_WRITE);
  520.       boolean do_not_block = !!(usage & PIPE_TRANSFER_DONTBLOCK);
  521.       if (!llvmpipe_flush_resource(pipe, resource,
  522.                                    level,
  523.                                    read_only,
  524.                                    TRUE, /* cpu_access */
  525.                                    do_not_block,
  526.                                    __FUNCTION__)) {
  527.          /*
  528.           * It would have blocked, but state tracker requested no to.
  529.           */
  530.          assert(do_not_block);
  531.          return NULL;
  532.       }
  533.    }
  534.  
  535.    /* Check if we're mapping the current constant buffer */
  536.    if ((usage & PIPE_TRANSFER_WRITE) &&
  537.        (resource->bind & PIPE_BIND_CONSTANT_BUFFER)) {
  538.       unsigned i;
  539.       for (i = 0; i < Elements(llvmpipe->constants[PIPE_SHADER_FRAGMENT]); ++i) {
  540.          if (resource == llvmpipe->constants[PIPE_SHADER_FRAGMENT][i].buffer) {
  541.             /* constants may have changed */
  542.             llvmpipe->dirty |= LP_NEW_CONSTANTS;
  543.             break;
  544.          }
  545.       }
  546.    }
  547.  
  548.    lpt = CALLOC_STRUCT(llvmpipe_transfer);
  549.    if (!lpt)
  550.       return NULL;
  551.    pt = &lpt->base;
  552.    pipe_resource_reference(&pt->resource, resource);
  553.    pt->box = *box;
  554.    pt->level = level;
  555.    pt->stride = lpr->row_stride[level];
  556.    pt->layer_stride = lpr->img_stride[level];
  557.    pt->usage = usage;
  558.    *transfer = pt;
  559.  
  560.    assert(level < LP_MAX_TEXTURE_LEVELS);
  561.  
  562.    /*
  563.    printf("tex_transfer_map(%d, %d  %d x %d of %d x %d,  usage %d )\n",
  564.           transfer->x, transfer->y, transfer->width, transfer->height,
  565.           transfer->texture->width0,
  566.           transfer->texture->height0,
  567.           transfer->usage);
  568.    */
  569.  
  570.    if (usage == PIPE_TRANSFER_READ) {
  571.       tex_usage = LP_TEX_USAGE_READ;
  572.       mode = "read";
  573.    }
  574.    else {
  575.       tex_usage = LP_TEX_USAGE_READ_WRITE;
  576.       mode = "read/write";
  577.    }
  578.  
  579.    if (0) {
  580.       printf("transfer map tex %u  mode %s\n", lpr->id, mode);
  581.    }
  582.  
  583.    format = lpr->base.format;
  584.  
  585.    map = llvmpipe_resource_map(resource,
  586.                                level,
  587.                                box->z,
  588.                                tex_usage);
  589.  
  590.  
  591.    /* May want to do different things here depending on read/write nature
  592.     * of the map:
  593.     */
  594.    if (usage & PIPE_TRANSFER_WRITE) {
  595.       /* Do something to notify sharing contexts of a texture change.
  596.        */
  597.       screen->timestamp++;
  598.    }
  599.  
  600.    map +=
  601.       box->y / util_format_get_blockheight(format) * pt->stride +
  602.       box->x / util_format_get_blockwidth(format) * util_format_get_blocksize(format);
  603.  
  604.    return map;
  605. }
  606.  
  607.  
  608. static void
  609. llvmpipe_transfer_unmap(struct pipe_context *pipe,
  610.                         struct pipe_transfer *transfer)
  611. {
  612.    assert(transfer->resource);
  613.  
  614.    llvmpipe_resource_unmap(transfer->resource,
  615.                            transfer->level,
  616.                            transfer->box.z);
  617.  
  618.    /* Effectively do the texture_update work here - if texture images
  619.     * needed post-processing to put them into hardware layout, this is
  620.     * where it would happen.  For llvmpipe, nothing to do.
  621.     */
  622.    assert (transfer->resource);
  623.    pipe_resource_reference(&transfer->resource, NULL);
  624.    FREE(transfer);
  625. }
  626.  
  627. unsigned int
  628. llvmpipe_is_resource_referenced( struct pipe_context *pipe,
  629.                                  struct pipe_resource *presource,
  630.                                  unsigned level)
  631. {
  632.    struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe );
  633.  
  634.    /*
  635.     * XXX checking only resources with the right bind flags
  636.     * is unsafe since with opengl state tracker we can end up
  637.     * with resources bound to places they weren't supposed to be
  638.     * (buffers bound as sampler views is one possibility here).
  639.     */
  640.    if (!(presource->bind & (PIPE_BIND_DEPTH_STENCIL |
  641.                             PIPE_BIND_RENDER_TARGET |
  642.                             PIPE_BIND_SAMPLER_VIEW)))
  643.       return LP_UNREFERENCED;
  644.  
  645.    return lp_setup_is_resource_referenced(llvmpipe->setup, presource);
  646. }
  647.  
  648.  
  649. /**
  650.  * Returns the largest possible alignment for a format in llvmpipe
  651.  */
  652. unsigned
  653. llvmpipe_get_format_alignment( enum pipe_format format )
  654. {
  655.    const struct util_format_description *desc = util_format_description(format);
  656.    unsigned size = 0;
  657.    unsigned bytes;
  658.    unsigned i;
  659.  
  660.    for (i = 0; i < desc->nr_channels; ++i) {
  661.       size += desc->channel[i].size;
  662.    }
  663.  
  664.    bytes = size / 8;
  665.  
  666.    if (!util_is_power_of_two(bytes)) {
  667.       bytes /= desc->nr_channels;
  668.    }
  669.  
  670.    if (bytes % 2 || bytes < 1) {
  671.       return 1;
  672.    } else {
  673.       return bytes;
  674.    }
  675. }
  676.  
  677.  
  678. /**
  679.  * Create buffer which wraps user-space data.
  680.  */
  681. struct pipe_resource *
  682. llvmpipe_user_buffer_create(struct pipe_screen *screen,
  683.                             void *ptr,
  684.                             unsigned bytes,
  685.                             unsigned bind_flags)
  686. {
  687.    struct llvmpipe_resource *buffer;
  688.  
  689.    buffer = CALLOC_STRUCT(llvmpipe_resource);
  690.    if(!buffer)
  691.       return NULL;
  692.  
  693.    pipe_reference_init(&buffer->base.reference, 1);
  694.    buffer->base.screen = screen;
  695.    buffer->base.format = PIPE_FORMAT_R8_UNORM; /* ?? */
  696.    buffer->base.bind = bind_flags;
  697.    buffer->base.usage = PIPE_USAGE_IMMUTABLE;
  698.    buffer->base.flags = 0;
  699.    buffer->base.width0 = bytes;
  700.    buffer->base.height0 = 1;
  701.    buffer->base.depth0 = 1;
  702.    buffer->base.array_size = 1;
  703.    buffer->userBuffer = TRUE;
  704.    buffer->data = ptr;
  705.  
  706.    return &buffer->base;
  707. }
  708.  
  709.  
  710. /**
  711.  * Compute size (in bytes) need to store a texture image / mipmap level,
  712.  * for just one cube face, one array layer or one 3D texture slice
  713.  */
  714. static unsigned
  715. tex_image_face_size(const struct llvmpipe_resource *lpr, unsigned level)
  716. {
  717.    return lpr->img_stride[level];
  718. }
  719.  
  720.  
  721. /**
  722.  * Return pointer to a 2D texture image/face/slice.
  723.  * No tiled/linear conversion is done.
  724.  */
  725. ubyte *
  726. llvmpipe_get_texture_image_address(struct llvmpipe_resource *lpr,
  727.                                    unsigned face_slice, unsigned level)
  728. {
  729.    unsigned offset;
  730.  
  731.    assert(llvmpipe_resource_is_texture(&lpr->base));
  732.  
  733.    offset = lpr->mip_offsets[level];
  734.  
  735.    if (face_slice > 0)
  736.       offset += face_slice * tex_image_face_size(lpr, level);
  737.  
  738.    return (ubyte *) lpr->tex_data + offset;
  739. }
  740.  
  741.  
  742. /**
  743.  * Return size of resource in bytes
  744.  */
  745. unsigned
  746. llvmpipe_resource_size(const struct pipe_resource *resource)
  747. {
  748.    const struct llvmpipe_resource *lpr = llvmpipe_resource_const(resource);
  749.    unsigned size = 0;
  750.  
  751.    if (llvmpipe_resource_is_texture(resource)) {
  752.       /* Note this will always return 0 for displaytarget resources */
  753.       size = lpr->total_alloc_size;
  754.    }
  755.    else {
  756.       size = resource->width0;
  757.    }
  758.    return size;
  759. }
  760.  
  761.  
  762. #ifdef DEBUG
  763. void
  764. llvmpipe_print_resources(void)
  765. {
  766.    struct llvmpipe_resource *lpr;
  767.    unsigned n = 0, total = 0;
  768.  
  769.    debug_printf("LLVMPIPE: current resources:\n");
  770.    foreach(lpr, &resource_list) {
  771.       unsigned size = llvmpipe_resource_size(&lpr->base);
  772.       debug_printf("resource %u at %p, size %ux%ux%u: %u bytes, refcount %u\n",
  773.                    lpr->id, (void *) lpr,
  774.                    lpr->base.width0, lpr->base.height0, lpr->base.depth0,
  775.                    size, lpr->base.reference.count);
  776.       total += size;
  777.       n++;
  778.    }
  779.    debug_printf("LLVMPIPE: total size of %u resources: %u\n", n, total);
  780. }
  781. #endif
  782.  
  783.  
  784. void
  785. llvmpipe_init_screen_resource_funcs(struct pipe_screen *screen)
  786. {
  787. #ifdef DEBUG
  788.    /* init linked list for tracking resources */
  789.    {
  790.       static boolean first_call = TRUE;
  791.       if (first_call) {
  792.          memset(&resource_list, 0, sizeof(resource_list));
  793.          make_empty_list(&resource_list);
  794.          first_call = FALSE;
  795.       }
  796.    }
  797. #endif
  798.  
  799.    screen->resource_create = llvmpipe_resource_create;
  800.    screen->resource_destroy = llvmpipe_resource_destroy;
  801.    screen->resource_from_handle = llvmpipe_resource_from_handle;
  802.    screen->resource_get_handle = llvmpipe_resource_get_handle;
  803.    screen->can_create_resource = llvmpipe_can_create_resource;
  804. }
  805.  
  806.  
  807. void
  808. llvmpipe_init_context_resource_funcs(struct pipe_context *pipe)
  809. {
  810.    pipe->transfer_map = llvmpipe_transfer_map;
  811.    pipe->transfer_unmap = llvmpipe_transfer_unmap;
  812.  
  813.    pipe->transfer_flush_region = u_default_transfer_flush_region;
  814.    pipe->transfer_inline_write = u_default_transfer_inline_write;
  815. }
  816.