Subversion Repositories Kolibri OS

Rev

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

  1. /**************************************************************************
  2.  *
  3.  * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
  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 TUNGSTEN GRAPHICS 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 <keith@tungstengraphics.com>
  30.   *   Michel Dänzer <michel@tungstengraphics.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/u_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.  * Just compute row strides here.  Storage is allocated on demand later.
  66.  */
  67. static boolean
  68. llvmpipe_texture_layout(struct llvmpipe_screen *screen,
  69.                         struct llvmpipe_resource *lpr)
  70. {
  71.    struct pipe_resource *pt = &lpr->base;
  72.    unsigned level;
  73.    unsigned width = pt->width0;
  74.    unsigned height = pt->height0;
  75.    unsigned depth = pt->depth0;
  76.    uint64_t total_size = 0;
  77.    unsigned layers = pt->array_size;
  78.  
  79.    assert(LP_MAX_TEXTURE_2D_LEVELS <= LP_MAX_TEXTURE_LEVELS);
  80.    assert(LP_MAX_TEXTURE_3D_LEVELS <= LP_MAX_TEXTURE_LEVELS);
  81.  
  82.    for (level = 0; level <= pt->last_level; level++) {
  83.  
  84.       /* Row stride and image stride */
  85.       {
  86.          unsigned align_x, align_y, nblocksx, nblocksy, block_size;
  87.  
  88.          /* For non-compressed formats we need 4x4 pixel alignment
  89.           * so we can read/write LP_RASTER_BLOCK_SIZE when rendering to them.
  90.           * We also want cache line size in x direction,
  91.           * otherwise same cache line could end up in multiple threads.
  92.           * For explicit 1d resources however we reduce this to 4x1 and
  93.           * handle specially in render output code (as we need to do special
  94.           * handling there for buffers in any case).
  95.           */
  96.          if (util_format_is_compressed(pt->format))
  97.             align_x = align_y = 1;
  98.          else {
  99.             align_x = LP_RASTER_BLOCK_SIZE;
  100.             if (llvmpipe_resource_is_1d(&lpr->base))
  101.                align_y = 1;
  102.             else
  103.                align_y = LP_RASTER_BLOCK_SIZE;
  104.          }
  105.  
  106.          nblocksx = util_format_get_nblocksx(pt->format,
  107.                                              align(width, align_x));
  108.          nblocksy = util_format_get_nblocksy(pt->format,
  109.                                              align(height, align_y));
  110.          block_size = util_format_get_blocksize(pt->format);
  111.  
  112.          if (util_format_is_compressed(pt->format))
  113.             lpr->row_stride[level] = nblocksx * block_size;
  114.          else
  115.             lpr->row_stride[level] = align(nblocksx * block_size, util_cpu_caps.cacheline);
  116.  
  117.          /* if row_stride * height > LP_MAX_TEXTURE_SIZE */
  118.          if (lpr->row_stride[level] > LP_MAX_TEXTURE_SIZE / nblocksy) {
  119.             /* image too large */
  120.             goto fail;
  121.          }
  122.  
  123.          lpr->img_stride[level] = lpr->row_stride[level] * nblocksy;
  124.       }
  125.  
  126.       /* Number of 3D image slices, cube faces or texture array layers */
  127.       {
  128.          unsigned num_slices;
  129.  
  130.          if (lpr->base.target == PIPE_TEXTURE_CUBE)
  131.             num_slices = 6;
  132.          else if (lpr->base.target == PIPE_TEXTURE_3D)
  133.             num_slices = depth;
  134.          else if (lpr->base.target == PIPE_TEXTURE_1D_ARRAY ||
  135.                   lpr->base.target == PIPE_TEXTURE_2D_ARRAY)
  136.             num_slices = layers;
  137.          else
  138.             num_slices = 1;
  139.  
  140.          lpr->num_slices_faces[level] = num_slices;
  141.       }
  142.  
  143.       /* if img_stride * num_slices_faces > LP_MAX_TEXTURE_SIZE */
  144.       if (lpr->img_stride[level] >
  145.           LP_MAX_TEXTURE_SIZE / lpr->num_slices_faces[level]) {
  146.          /* volume too large */
  147.          goto fail;
  148.       }
  149.  
  150.       total_size += (uint64_t) lpr->num_slices_faces[level]
  151.                   * (uint64_t) lpr->img_stride[level];
  152.       if (total_size > LP_MAX_TEXTURE_SIZE) {
  153.          goto fail;
  154.       }
  155.  
  156.       /* Compute size of next mipmap level */
  157.       width = u_minify(width, 1);
  158.       height = u_minify(height, 1);
  159.       depth = u_minify(depth, 1);
  160.    }
  161.  
  162.    return TRUE;
  163.  
  164. fail:
  165.    return FALSE;
  166. }
  167.  
  168.  
  169. /**
  170.  * Check the size of the texture specified by 'res'.
  171.  * \return TRUE if OK, FALSE if too large.
  172.  */
  173. static boolean
  174. llvmpipe_can_create_resource(struct pipe_screen *screen,
  175.                              const struct pipe_resource *res)
  176. {
  177.    struct llvmpipe_resource lpr;
  178.    memset(&lpr, 0, sizeof(lpr));
  179.    lpr.base = *res;
  180.    return llvmpipe_texture_layout(llvmpipe_screen(screen), &lpr);
  181. }
  182.  
  183.  
  184. static boolean
  185. llvmpipe_displaytarget_layout(struct llvmpipe_screen *screen,
  186.                               struct llvmpipe_resource *lpr)
  187. {
  188.    struct sw_winsys *winsys = screen->winsys;
  189.  
  190.    /* Round up the surface size to a multiple of the tile size to
  191.     * avoid tile clipping.
  192.     */
  193.    const unsigned width = MAX2(1, align(lpr->base.width0, TILE_SIZE));
  194.    const unsigned height = MAX2(1, align(lpr->base.height0, TILE_SIZE));
  195.  
  196.    lpr->num_slices_faces[0] = 1;
  197.    lpr->img_stride[0] = 0;
  198.  
  199.    lpr->dt = winsys->displaytarget_create(winsys,
  200.                                           lpr->base.bind,
  201.                                           lpr->base.format,
  202.                                           width, height,
  203.                                           16,
  204.                                           &lpr->row_stride[0] );
  205.  
  206.    if (lpr->dt == NULL)
  207.       return FALSE;
  208.  
  209.    {
  210.       void *map = winsys->displaytarget_map(winsys, lpr->dt,
  211.                                             PIPE_TRANSFER_WRITE);
  212.  
  213.       if (map)
  214.          memset(map, 0, height * lpr->row_stride[0]);
  215.  
  216.       winsys->displaytarget_unmap(winsys, lpr->dt);
  217.    }
  218.  
  219.    return TRUE;
  220. }
  221.  
  222.  
  223. static struct pipe_resource *
  224. llvmpipe_resource_create(struct pipe_screen *_screen,
  225.                          const struct pipe_resource *templat)
  226. {
  227.    struct llvmpipe_screen *screen = llvmpipe_screen(_screen);
  228.    struct llvmpipe_resource *lpr = CALLOC_STRUCT(llvmpipe_resource);
  229.    if (!lpr)
  230.       return NULL;
  231.  
  232.    lpr->base = *templat;
  233.    pipe_reference_init(&lpr->base.reference, 1);
  234.    lpr->base.screen = &screen->base;
  235.  
  236.    /* assert(lpr->base.bind); */
  237.  
  238.    if (llvmpipe_resource_is_texture(&lpr->base)) {
  239.       if (lpr->base.bind & (PIPE_BIND_DISPLAY_TARGET |
  240.                             PIPE_BIND_SCANOUT |
  241.                             PIPE_BIND_SHARED)) {
  242.          /* displayable surface */
  243.          if (!llvmpipe_displaytarget_layout(screen, lpr))
  244.             goto fail;
  245.       }
  246.       else {
  247.          /* texture map */
  248.          if (!llvmpipe_texture_layout(screen, lpr))
  249.             goto fail;
  250.       }
  251.    }
  252.    else {
  253.       /* other data (vertex buffer, const buffer, etc) */
  254.       const uint bytes = templat->width0;
  255.       assert(util_format_get_blocksize(templat->format) == 1);
  256.       assert(templat->height0 == 1);
  257.       assert(templat->depth0 == 1);
  258.       assert(templat->last_level == 0);
  259.       /*
  260.        * Reserve some extra storage since if we'd render to a buffer we
  261.        * read/write always LP_RASTER_BLOCK_SIZE pixels, but the element
  262.        * offset doesn't need to be aligned to LP_RASTER_BLOCK_SIZE.
  263.        */
  264.       lpr->data = align_malloc(bytes + (LP_RASTER_BLOCK_SIZE - 1) * 4 * sizeof(float), 16);
  265.       /*
  266.        * buffers don't really have stride but it's probably safer
  267.        * (for code doing same calculations for buffers and textures)
  268.        * to put something sane in there.
  269.        */
  270.       lpr->row_stride[0] = bytes;
  271.       if (!lpr->data)
  272.          goto fail;
  273.       memset(lpr->data, 0, bytes);
  274.    }
  275.  
  276.    lpr->id = id_counter++;
  277.  
  278. #ifdef DEBUG
  279.    insert_at_tail(&resource_list, lpr);
  280. #endif
  281.  
  282.    return &lpr->base;
  283.  
  284.  fail:
  285.    FREE(lpr);
  286.    return NULL;
  287. }
  288.  
  289.  
  290. static void
  291. llvmpipe_resource_destroy(struct pipe_screen *pscreen,
  292.                           struct pipe_resource *pt)
  293. {
  294.    struct llvmpipe_screen *screen = llvmpipe_screen(pscreen);
  295.    struct llvmpipe_resource *lpr = llvmpipe_resource(pt);
  296.  
  297.    if (lpr->dt) {
  298.       /* display target */
  299.       struct sw_winsys *winsys = screen->winsys;
  300.       winsys->displaytarget_destroy(winsys, lpr->dt);
  301.    }
  302.    else if (llvmpipe_resource_is_texture(pt)) {
  303.       /* free linear image data */
  304.       if (lpr->linear_img.data) {
  305.          align_free(lpr->linear_img.data);
  306.          lpr->linear_img.data = NULL;
  307.       }
  308.    }
  309.    else if (!lpr->userBuffer) {
  310.       assert(lpr->data);
  311.       align_free(lpr->data);
  312.    }
  313.  
  314. #ifdef DEBUG
  315.    if (lpr->next)
  316.       remove_from_list(lpr);
  317. #endif
  318.  
  319.    FREE(lpr);
  320. }
  321.  
  322.  
  323. /**
  324.  * Map a resource for read/write.
  325.  */
  326. void *
  327. llvmpipe_resource_map(struct pipe_resource *resource,
  328.                       unsigned level,
  329.                       unsigned layer,
  330.                       enum lp_texture_usage tex_usage)
  331. {
  332.    struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
  333.    uint8_t *map;
  334.  
  335.    assert(level < LP_MAX_TEXTURE_LEVELS);
  336.    assert(layer < (u_minify(resource->depth0, level) + resource->array_size - 1));
  337.  
  338.    assert(tex_usage == LP_TEX_USAGE_READ ||
  339.           tex_usage == LP_TEX_USAGE_READ_WRITE ||
  340.           tex_usage == LP_TEX_USAGE_WRITE_ALL);
  341.  
  342.    if (lpr->dt) {
  343.       /* display target */
  344.       struct llvmpipe_screen *screen = llvmpipe_screen(resource->screen);
  345.       struct sw_winsys *winsys = screen->winsys;
  346.       unsigned dt_usage;
  347.  
  348.       if (tex_usage == LP_TEX_USAGE_READ) {
  349.          dt_usage = PIPE_TRANSFER_READ;
  350.       }
  351.       else {
  352.          dt_usage = PIPE_TRANSFER_READ_WRITE;
  353.       }
  354.  
  355.       assert(level == 0);
  356.       assert(layer == 0);
  357.  
  358.       /* FIXME: keep map count? */
  359.       map = winsys->displaytarget_map(winsys, lpr->dt, dt_usage);
  360.  
  361.       /* install this linear image in texture data structure */
  362.       lpr->linear_img.data = map;
  363.  
  364.       return map;
  365.    }
  366.    else if (llvmpipe_resource_is_texture(resource)) {
  367.  
  368.       map = llvmpipe_get_texture_image(lpr, layer, level, tex_usage);
  369.       return map;
  370.    }
  371.    else {
  372.       return lpr->data;
  373.    }
  374. }
  375.  
  376.  
  377. /**
  378.  * Unmap a resource.
  379.  */
  380. void
  381. llvmpipe_resource_unmap(struct pipe_resource *resource,
  382.                        unsigned level,
  383.                        unsigned layer)
  384. {
  385.    struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
  386.  
  387.    if (lpr->dt) {
  388.       /* display target */
  389.       struct llvmpipe_screen *lp_screen = llvmpipe_screen(resource->screen);
  390.       struct sw_winsys *winsys = lp_screen->winsys;
  391.  
  392.       assert(level == 0);
  393.       assert(layer == 0);
  394.  
  395.       winsys->displaytarget_unmap(winsys, lpr->dt);
  396.    }
  397. }
  398.  
  399.  
  400. void *
  401. llvmpipe_resource_data(struct pipe_resource *resource)
  402. {
  403.    struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
  404.  
  405.    assert(!llvmpipe_resource_is_texture(resource));
  406.  
  407.    return lpr->data;
  408. }
  409.  
  410.  
  411. static struct pipe_resource *
  412. llvmpipe_resource_from_handle(struct pipe_screen *screen,
  413.                               const struct pipe_resource *template,
  414.                               struct winsys_handle *whandle)
  415. {
  416.    struct sw_winsys *winsys = llvmpipe_screen(screen)->winsys;
  417.    struct llvmpipe_resource *lpr;
  418.  
  419.    /* XXX Seems like from_handled depth textures doesn't work that well */
  420.  
  421.    lpr = CALLOC_STRUCT(llvmpipe_resource);
  422.    if (!lpr) {
  423.       goto no_lpr;
  424.    }
  425.  
  426.    lpr->base = *template;
  427.    pipe_reference_init(&lpr->base.reference, 1);
  428.    lpr->base.screen = screen;
  429.  
  430.    /*
  431.     * Looks like unaligned displaytargets work just fine,
  432.     * at least sampler/render ones.
  433.     */
  434. #if 0
  435.    assert(lpr->base.width0 == width);
  436.    assert(lpr->base.height0 == height);
  437. #endif
  438.  
  439.    lpr->num_slices_faces[0] = 1;
  440.    lpr->img_stride[0] = 0;
  441.  
  442.    lpr->dt = winsys->displaytarget_from_handle(winsys,
  443.                                                template,
  444.                                                whandle,
  445.                                                &lpr->row_stride[0]);
  446.    if (!lpr->dt) {
  447.       goto no_dt;
  448.    }
  449.  
  450.    lpr->id = id_counter++;
  451.  
  452. #ifdef DEBUG
  453.    insert_at_tail(&resource_list, lpr);
  454. #endif
  455.  
  456.    return &lpr->base;
  457.  
  458. no_dt:
  459.    FREE(lpr);
  460. no_lpr:
  461.    return NULL;
  462. }
  463.  
  464.  
  465. static boolean
  466. llvmpipe_resource_get_handle(struct pipe_screen *screen,
  467.                             struct pipe_resource *pt,
  468.                             struct winsys_handle *whandle)
  469. {
  470.    struct sw_winsys *winsys = llvmpipe_screen(screen)->winsys;
  471.    struct llvmpipe_resource *lpr = llvmpipe_resource(pt);
  472.  
  473.    assert(lpr->dt);
  474.    if (!lpr->dt)
  475.       return FALSE;
  476.  
  477.    return winsys->displaytarget_get_handle(winsys, lpr->dt, whandle);
  478. }
  479.  
  480.  
  481. static void *
  482. llvmpipe_transfer_map( struct pipe_context *pipe,
  483.                        struct pipe_resource *resource,
  484.                        unsigned level,
  485.                        unsigned usage,
  486.                        const struct pipe_box *box,
  487.                        struct pipe_transfer **transfer )
  488. {
  489.    struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
  490.    struct llvmpipe_screen *screen = llvmpipe_screen(pipe->screen);
  491.    struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
  492.    struct llvmpipe_transfer *lpt;
  493.    struct pipe_transfer *pt;
  494.    ubyte *map;
  495.    enum pipe_format format;
  496.    enum lp_texture_usage tex_usage;
  497.    const char *mode;
  498.  
  499.    assert(resource);
  500.    assert(level <= resource->last_level);
  501.  
  502.    /*
  503.     * Transfers, like other pipe operations, must happen in order, so flush the
  504.     * context if necessary.
  505.     */
  506.    if (!(usage & PIPE_TRANSFER_UNSYNCHRONIZED)) {
  507.       boolean read_only = !(usage & PIPE_TRANSFER_WRITE);
  508.       boolean do_not_block = !!(usage & PIPE_TRANSFER_DONTBLOCK);
  509.       if (!llvmpipe_flush_resource(pipe, resource,
  510.                                    level,
  511.                                    read_only,
  512.                                    TRUE, /* cpu_access */
  513.                                    do_not_block,
  514.                                    __FUNCTION__)) {
  515.          /*
  516.           * It would have blocked, but state tracker requested no to.
  517.           */
  518.          assert(do_not_block);
  519.          return NULL;
  520.       }
  521.    }
  522.  
  523.    /* Check if we're mapping the current constant buffer */
  524.    if ((usage & PIPE_TRANSFER_WRITE) &&
  525.        (resource->bind & PIPE_BIND_CONSTANT_BUFFER)) {
  526.       unsigned i;
  527.       for (i = 0; i < Elements(llvmpipe->constants[PIPE_SHADER_FRAGMENT]); ++i) {
  528.          if (resource == llvmpipe->constants[PIPE_SHADER_FRAGMENT][i].buffer) {
  529.             /* constants may have changed */
  530.             llvmpipe->dirty |= LP_NEW_CONSTANTS;
  531.             break;
  532.          }
  533.       }
  534.    }
  535.  
  536.    lpt = CALLOC_STRUCT(llvmpipe_transfer);
  537.    if (!lpt)
  538.       return NULL;
  539.    pt = &lpt->base;
  540.    pipe_resource_reference(&pt->resource, resource);
  541.    pt->box = *box;
  542.    pt->level = level;
  543.    pt->stride = lpr->row_stride[level];
  544.    pt->layer_stride = lpr->img_stride[level];
  545.    pt->usage = usage;
  546.    *transfer = pt;
  547.  
  548.    assert(level < LP_MAX_TEXTURE_LEVELS);
  549.  
  550.    /*
  551.    printf("tex_transfer_map(%d, %d  %d x %d of %d x %d,  usage %d )\n",
  552.           transfer->x, transfer->y, transfer->width, transfer->height,
  553.           transfer->texture->width0,
  554.           transfer->texture->height0,
  555.           transfer->usage);
  556.    */
  557.  
  558.    if (usage == PIPE_TRANSFER_READ) {
  559.       tex_usage = LP_TEX_USAGE_READ;
  560.       mode = "read";
  561.    }
  562.    else {
  563.       tex_usage = LP_TEX_USAGE_READ_WRITE;
  564.       mode = "read/write";
  565.    }
  566.  
  567.    if (0) {
  568.       printf("transfer map tex %u  mode %s\n", lpr->id, mode);
  569.    }
  570.  
  571.    format = lpr->base.format;
  572.  
  573.    map = llvmpipe_resource_map(resource,
  574.                                level,
  575.                                box->z,
  576.                                tex_usage);
  577.  
  578.  
  579.    /* May want to do different things here depending on read/write nature
  580.     * of the map:
  581.     */
  582.    if (usage & PIPE_TRANSFER_WRITE) {
  583.       /* Do something to notify sharing contexts of a texture change.
  584.        */
  585.       screen->timestamp++;
  586.    }
  587.  
  588.    map +=
  589.       box->y / util_format_get_blockheight(format) * pt->stride +
  590.       box->x / util_format_get_blockwidth(format) * util_format_get_blocksize(format);
  591.  
  592.    return map;
  593. }
  594.  
  595.  
  596. static void
  597. llvmpipe_transfer_unmap(struct pipe_context *pipe,
  598.                         struct pipe_transfer *transfer)
  599. {
  600.    assert(transfer->resource);
  601.  
  602.    llvmpipe_resource_unmap(transfer->resource,
  603.                            transfer->level,
  604.                            transfer->box.z);
  605.  
  606.    /* Effectively do the texture_update work here - if texture images
  607.     * needed post-processing to put them into hardware layout, this is
  608.     * where it would happen.  For llvmpipe, nothing to do.
  609.     */
  610.    assert (transfer->resource);
  611.    pipe_resource_reference(&transfer->resource, NULL);
  612.    FREE(transfer);
  613. }
  614.  
  615. unsigned int
  616. llvmpipe_is_resource_referenced( struct pipe_context *pipe,
  617.                                  struct pipe_resource *presource,
  618.                                  unsigned level)
  619. {
  620.    struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe );
  621.  
  622.    /*
  623.     * XXX checking only resources with the right bind flags
  624.     * is unsafe since with opengl state tracker we can end up
  625.     * with resources bound to places they weren't supposed to be
  626.     * (buffers bound as sampler views is one possibility here).
  627.     */
  628.    if (!(presource->bind & (PIPE_BIND_DEPTH_STENCIL |
  629.                             PIPE_BIND_RENDER_TARGET |
  630.                             PIPE_BIND_SAMPLER_VIEW)))
  631.       return LP_UNREFERENCED;
  632.  
  633.    return lp_setup_is_resource_referenced(llvmpipe->setup, presource);
  634. }
  635.  
  636.  
  637. /**
  638.  * Returns the largest possible alignment for a format in llvmpipe
  639.  */
  640. unsigned
  641. llvmpipe_get_format_alignment( enum pipe_format format )
  642. {
  643.    const struct util_format_description *desc = util_format_description(format);
  644.    unsigned size = 0;
  645.    unsigned bytes;
  646.    unsigned i;
  647.  
  648.    for (i = 0; i < desc->nr_channels; ++i) {
  649.       size += desc->channel[i].size;
  650.    }
  651.  
  652.    bytes = size / 8;
  653.  
  654.    if (!util_is_power_of_two(bytes)) {
  655.       bytes /= desc->nr_channels;
  656.    }
  657.  
  658.    if (bytes % 2 || bytes < 1) {
  659.       return 1;
  660.    } else {
  661.       return bytes;
  662.    }
  663. }
  664.  
  665.  
  666. /**
  667.  * Create buffer which wraps user-space data.
  668.  */
  669. struct pipe_resource *
  670. llvmpipe_user_buffer_create(struct pipe_screen *screen,
  671.                             void *ptr,
  672.                             unsigned bytes,
  673.                             unsigned bind_flags)
  674. {
  675.    struct llvmpipe_resource *buffer;
  676.  
  677.    buffer = CALLOC_STRUCT(llvmpipe_resource);
  678.    if(!buffer)
  679.       return NULL;
  680.  
  681.    pipe_reference_init(&buffer->base.reference, 1);
  682.    buffer->base.screen = screen;
  683.    buffer->base.format = PIPE_FORMAT_R8_UNORM; /* ?? */
  684.    buffer->base.bind = bind_flags;
  685.    buffer->base.usage = PIPE_USAGE_IMMUTABLE;
  686.    buffer->base.flags = 0;
  687.    buffer->base.width0 = bytes;
  688.    buffer->base.height0 = 1;
  689.    buffer->base.depth0 = 1;
  690.    buffer->base.array_size = 1;
  691.    buffer->userBuffer = TRUE;
  692.    buffer->data = ptr;
  693.  
  694.    return &buffer->base;
  695. }
  696.  
  697.  
  698. /**
  699.  * Compute size (in bytes) need to store a texture image / mipmap level,
  700.  * for just one cube face, one array layer or one 3D texture slice
  701.  */
  702. static unsigned
  703. tex_image_face_size(const struct llvmpipe_resource *lpr, unsigned level)
  704. {
  705.    return lpr->img_stride[level];
  706. }
  707.  
  708.  
  709. /**
  710.  * Compute size (in bytes) need to store a texture image / mipmap level,
  711.  * including all cube faces or 3D image slices
  712.  */
  713. static unsigned
  714. tex_image_size(const struct llvmpipe_resource *lpr, unsigned level)
  715. {
  716.    const unsigned buf_size = tex_image_face_size(lpr, level);
  717.    return buf_size * lpr->num_slices_faces[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.    struct llvmpipe_texture_image *img;
  730.    unsigned offset;
  731.  
  732.    img = &lpr->linear_img;
  733.    offset = lpr->linear_mip_offsets[level];
  734.  
  735.    if (face_slice > 0)
  736.       offset += face_slice * tex_image_face_size(lpr, level);
  737.  
  738.    return (ubyte *) img->data + offset;
  739. }
  740.  
  741.  
  742. /**
  743.  * Allocate storage for a linear image
  744.  * (all cube faces and all 3D slices, all levels).
  745.  */
  746. static void
  747. alloc_image_data(struct llvmpipe_resource *lpr)
  748. {
  749.    uint alignment = MAX2(16, util_cpu_caps.cacheline);
  750.    uint level;
  751.    uint offset = 0;
  752.  
  753.    if (lpr->dt) {
  754.       /* we get the linear memory from the winsys, and it has
  755.        * already been zeroed
  756.        */
  757.       struct llvmpipe_screen *screen = llvmpipe_screen(lpr->base.screen);
  758.       struct sw_winsys *winsys = screen->winsys;
  759.  
  760.       assert(lpr->base.last_level == 0);
  761.  
  762.       lpr->linear_img.data =
  763.          winsys->displaytarget_map(winsys, lpr->dt,
  764.                                    PIPE_TRANSFER_READ_WRITE);
  765.    }
  766.    else {
  767.       /* not a display target - allocate regular memory */
  768.       /*
  769.        * Offset calculation for start of a specific mip/layer is always
  770.        * offset = lpr->linear_mip_offsets[level] + lpr->img_stride[level] * layer
  771.        */
  772.       for (level = 0; level <= lpr->base.last_level; level++) {
  773.          uint buffer_size = tex_image_size(lpr, level);
  774.          lpr->linear_mip_offsets[level] = offset;
  775.          offset += align(buffer_size, alignment);
  776.       }
  777.       lpr->linear_img.data = align_malloc(offset, alignment);
  778.       if (lpr->linear_img.data) {
  779.          memset(lpr->linear_img.data, 0, offset);
  780.       }
  781.    }
  782. }
  783.  
  784.  
  785.  
  786. /**
  787.  * Return pointer to texture image data
  788.  * for a particular cube face or 3D texture slice.
  789.  *
  790.  * \param face_slice  the cube face or 3D slice of interest
  791.  * \param usage  one of LP_TEX_USAGE_READ/WRITE_ALL/READ_WRITE
  792.  */
  793. void *
  794. llvmpipe_get_texture_image(struct llvmpipe_resource *lpr,
  795.                            unsigned face_slice, unsigned level,
  796.                            enum lp_texture_usage usage)
  797. {
  798.    struct llvmpipe_texture_image *target_img;
  799.    void *target_data;
  800.    unsigned target_offset;
  801.    unsigned *target_off_ptr;
  802.  
  803.    assert(usage == LP_TEX_USAGE_READ ||
  804.           usage == LP_TEX_USAGE_READ_WRITE ||
  805.           usage == LP_TEX_USAGE_WRITE_ALL);
  806.  
  807.    if (lpr->dt) {
  808.       assert(lpr->linear_img.data);
  809.    }
  810.  
  811.    target_img = &lpr->linear_img;
  812.    target_off_ptr = lpr->linear_mip_offsets;
  813.    target_data = target_img->data;
  814.  
  815.    if (!target_data) {
  816.       /* allocate memory for the target image now */
  817.       alloc_image_data(lpr);
  818.       target_data = target_img->data;
  819.    }
  820.  
  821.    target_offset = target_off_ptr[level];
  822.  
  823.    if (face_slice > 0) {
  824.       target_offset += face_slice * tex_image_face_size(lpr, level);
  825.    }
  826.  
  827.    if (target_data) {
  828.       target_data = (uint8_t *) target_data + target_offset;
  829.    }
  830.  
  831.    return target_data;
  832. }
  833.  
  834.  
  835. /**
  836.  * Return pointer to start of a texture image (1D, 2D, 3D, CUBE).
  837.  * This is typically used when we're about to sample from a texture.
  838.  */
  839. void *
  840. llvmpipe_get_texture_image_all(struct llvmpipe_resource *lpr,
  841.                                unsigned level,
  842.                                enum lp_texture_usage usage)
  843. {
  844.    const int slices = lpr->num_slices_faces[level];
  845.    int slice;
  846.    void *map = NULL;
  847.  
  848.    assert(slices > 0);
  849.  
  850.    for (slice = slices - 1; slice >= 0; slice--) {
  851.       map = llvmpipe_get_texture_image(lpr, slice, level, usage);
  852.    }
  853.  
  854.    return map;
  855. }
  856.  
  857.  
  858. /**
  859.  * Get pointer to a linear image (not the tile!) at tile (x,y).
  860.  * \return pointer to start of image/face (not the tile)
  861.  */
  862. ubyte *
  863. llvmpipe_get_texture_tile_linear(struct llvmpipe_resource *lpr,
  864.                                  unsigned face_slice, unsigned level,
  865.                                  enum lp_texture_usage usage,
  866.                                  unsigned x, unsigned y)
  867. {
  868.    struct llvmpipe_texture_image *linear_img = &lpr->linear_img;
  869.    uint8_t *linear_image;
  870.  
  871.    assert(llvmpipe_resource_is_texture(&lpr->base));
  872.    assert(x % TILE_SIZE == 0);
  873.    assert(y % TILE_SIZE == 0);
  874.  
  875.    if (!linear_img->data) {
  876.       /* allocate memory for the linear image now */
  877.       /* XXX should probably not do that here? */
  878.       alloc_image_data(lpr);
  879.    }
  880.    assert(linear_img->data);
  881.  
  882.    /* compute address of the slice/face of the image that contains the tile */
  883.    linear_image = llvmpipe_get_texture_image_address(lpr, face_slice, level);
  884.  
  885.    return linear_image;
  886. }
  887.  
  888.  
  889. /**
  890.  * Return size of resource in bytes
  891.  */
  892. unsigned
  893. llvmpipe_resource_size(const struct pipe_resource *resource)
  894. {
  895.    const struct llvmpipe_resource *lpr = llvmpipe_resource_const(resource);
  896.    unsigned lvl, size = 0;
  897.  
  898.    if (llvmpipe_resource_is_texture(resource)) {
  899.       for (lvl = 0; lvl <= lpr->base.last_level; lvl++) {
  900.          if (lpr->linear_img.data)
  901.             size += tex_image_size(lpr, lvl);
  902.       }
  903.    }
  904.    else {
  905.       size = resource->width0;
  906.    }
  907.  
  908.    return size;
  909. }
  910.  
  911.  
  912. #ifdef DEBUG
  913. void
  914. llvmpipe_print_resources(void)
  915. {
  916.    struct llvmpipe_resource *lpr;
  917.    unsigned n = 0, total = 0;
  918.  
  919.    debug_printf("LLVMPIPE: current resources:\n");
  920.    foreach(lpr, &resource_list) {
  921.       unsigned size = llvmpipe_resource_size(&lpr->base);
  922.       debug_printf("resource %u at %p, size %ux%ux%u: %u bytes, refcount %u\n",
  923.                    lpr->id, (void *) lpr,
  924.                    lpr->base.width0, lpr->base.height0, lpr->base.depth0,
  925.                    size, lpr->base.reference.count);
  926.       total += size;
  927.       n++;
  928.    }
  929.    debug_printf("LLVMPIPE: total size of %u resources: %u\n", n, total);
  930. }
  931. #endif
  932.  
  933.  
  934. void
  935. llvmpipe_init_screen_resource_funcs(struct pipe_screen *screen)
  936. {
  937. #ifdef DEBUG
  938.    /* init linked list for tracking resources */
  939.    {
  940.       static boolean first_call = TRUE;
  941.       if (first_call) {
  942.          memset(&resource_list, 0, sizeof(resource_list));
  943.          make_empty_list(&resource_list);
  944.          first_call = FALSE;
  945.       }
  946.    }
  947. #endif
  948.  
  949.    screen->resource_create = llvmpipe_resource_create;
  950.    screen->resource_destroy = llvmpipe_resource_destroy;
  951.    screen->resource_from_handle = llvmpipe_resource_from_handle;
  952.    screen->resource_get_handle = llvmpipe_resource_get_handle;
  953.    screen->can_create_resource = llvmpipe_can_create_resource;
  954. }
  955.  
  956.  
  957. void
  958. llvmpipe_init_context_resource_funcs(struct pipe_context *pipe)
  959. {
  960.    pipe->transfer_map = llvmpipe_transfer_map;
  961.    pipe->transfer_unmap = llvmpipe_transfer_unmap;
  962.  
  963.    pipe->transfer_flush_region = u_default_transfer_flush_region;
  964.    pipe->transfer_inline_write = u_default_transfer_inline_write;
  965. }
  966.