Subversion Repositories Kolibri OS

Rev

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

  1. /**************************************************************************
  2.  *
  3.  * Copyright 2007 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. /**
  29.  * Render target tile caching.
  30.  *
  31.  * Author:
  32.  *    Brian Paul
  33.  */
  34.  
  35. #include "util/u_inlines.h"
  36. #include "util/u_format.h"
  37. #include "util/u_memory.h"
  38. #include "util/u_tile.h"
  39. #include "sp_tile_cache.h"
  40.  
  41. static struct softpipe_cached_tile *
  42. sp_alloc_tile(struct softpipe_tile_cache *tc);
  43.  
  44.  
  45. /**
  46.  * Return the position in the cache for the tile that contains win pos (x,y).
  47.  * We currently use a direct mapped cache so this is like a hack key.
  48.  * At some point we should investige something more sophisticated, like
  49.  * a LRU replacement policy.
  50.  */
  51. #define CACHE_POS(x, y) \
  52.    (((x) + (y) * 5) % NUM_ENTRIES)
  53.  
  54.  
  55.  
  56. /**
  57.  * Is the tile at (x,y) in cleared state?
  58.  */
  59. static INLINE uint
  60. is_clear_flag_set(const uint *bitvec, union tile_address addr)
  61. {
  62.    int pos, bit;
  63.    pos = addr.bits.y * (MAX_WIDTH / TILE_SIZE) + addr.bits.x;
  64.    assert(pos / 32 < (MAX_WIDTH / TILE_SIZE) * (MAX_HEIGHT / TILE_SIZE) / 32);
  65.    bit = bitvec[pos / 32] & (1 << (pos & 31));
  66.    return bit;
  67. }
  68.    
  69.  
  70. /**
  71.  * Mark the tile at (x,y) as not cleared.
  72.  */
  73. static INLINE void
  74. clear_clear_flag(uint *bitvec, union tile_address addr)
  75. {
  76.    int pos;
  77.    pos = addr.bits.y * (MAX_WIDTH / TILE_SIZE) + addr.bits.x;
  78.    assert(pos / 32 < (MAX_WIDTH / TILE_SIZE) * (MAX_HEIGHT / TILE_SIZE) / 32);
  79.    bitvec[pos / 32] &= ~(1 << (pos & 31));
  80. }
  81.    
  82.  
  83. struct softpipe_tile_cache *
  84. sp_create_tile_cache( struct pipe_context *pipe )
  85. {
  86.    struct softpipe_tile_cache *tc;
  87.    uint pos;
  88.    int maxLevels, maxTexSize;
  89.  
  90.    /* sanity checking: max sure MAX_WIDTH/HEIGHT >= largest texture image */
  91.    maxLevels = pipe->screen->get_param(pipe->screen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS);
  92.    maxTexSize = 1 << (maxLevels - 1);
  93.    assert(MAX_WIDTH >= maxTexSize);
  94.  
  95.    assert(sizeof(union tile_address) == 4);
  96.  
  97.    assert((TILE_SIZE << TILE_ADDR_BITS) >= MAX_WIDTH);
  98.  
  99.    tc = CALLOC_STRUCT( softpipe_tile_cache );
  100.    if (tc) {
  101.       tc->pipe = pipe;
  102.       for (pos = 0; pos < Elements(tc->tile_addrs); pos++) {
  103.          tc->tile_addrs[pos].bits.invalid = 1;
  104.       }
  105.       tc->last_tile_addr.bits.invalid = 1;
  106.  
  107.       /* this allocation allows us to guarantee that allocation
  108.        * failures are never fatal later
  109.        */
  110.       tc->tile = MALLOC_STRUCT( softpipe_cached_tile );
  111.       if (!tc->tile)
  112.       {
  113.          FREE(tc);
  114.          return NULL;
  115.       }
  116.  
  117.       /* XXX this code prevents valgrind warnings about use of uninitialized
  118.        * memory in programs that don't clear the surface before rendering.
  119.        * However, it breaks clearing in other situations (such as in
  120.        * progs/tests/drawbuffers, see bug 24402).
  121.        */
  122. #if 0
  123.       /* set flags to indicate all the tiles are cleared */
  124.       memset(tc->clear_flags, 255, sizeof(tc->clear_flags));
  125. #endif
  126.    }
  127.    return tc;
  128. }
  129.  
  130.  
  131. void
  132. sp_destroy_tile_cache(struct softpipe_tile_cache *tc)
  133. {
  134.    if (tc) {
  135.       uint pos;
  136.  
  137.       for (pos = 0; pos < Elements(tc->entries); pos++) {
  138.          /*assert(tc->entries[pos].x < 0);*/
  139.          FREE( tc->entries[pos] );
  140.       }
  141.       FREE( tc->tile );
  142.  
  143.       if (tc->transfer) {
  144.          tc->pipe->transfer_unmap(tc->pipe, tc->transfer);
  145.       }
  146.  
  147.       FREE( tc );
  148.    }
  149. }
  150.  
  151.  
  152. /**
  153.  * Specify the surface to cache.
  154.  */
  155. void
  156. sp_tile_cache_set_surface(struct softpipe_tile_cache *tc,
  157.                           struct pipe_surface *ps)
  158. {
  159.    struct pipe_context *pipe = tc->pipe;
  160.  
  161.    if (tc->transfer_map) {
  162.       if (ps == tc->surface)
  163.          return;
  164.  
  165.       pipe->transfer_unmap(pipe, tc->transfer);
  166.       tc->transfer = NULL;
  167.       tc->transfer_map = NULL;
  168.    }
  169.  
  170.    tc->surface = ps;
  171.  
  172.    if (ps) {
  173.       if (ps->texture->target != PIPE_BUFFER) {
  174.          tc->transfer_map = pipe_transfer_map(pipe, ps->texture,
  175.                                               ps->u.tex.level, ps->u.tex.first_layer,
  176.                                               PIPE_TRANSFER_READ_WRITE |
  177.                                               PIPE_TRANSFER_UNSYNCHRONIZED,
  178.                                               0, 0, ps->width, ps->height,
  179.                                               &tc->transfer);
  180.       }
  181.       else {
  182.          /* can't render to buffers */
  183.          assert(0);
  184.       }
  185.  
  186.       tc->depth_stencil = util_format_is_depth_or_stencil(ps->format);
  187.    }
  188. }
  189.  
  190.  
  191. /**
  192.  * Return the transfer being cached.
  193.  */
  194. struct pipe_surface *
  195. sp_tile_cache_get_surface(struct softpipe_tile_cache *tc)
  196. {
  197.    return tc->surface;
  198. }
  199.  
  200.  
  201. /**
  202.  * Set pixels in a tile to the given clear color/value, float.
  203.  */
  204. static void
  205. clear_tile_rgba(struct softpipe_cached_tile *tile,
  206.                 enum pipe_format format,
  207.                 const union pipe_color_union *clear_value)
  208. {
  209.    if (clear_value->f[0] == 0.0 &&
  210.        clear_value->f[1] == 0.0 &&
  211.        clear_value->f[2] == 0.0 &&
  212.        clear_value->f[3] == 0.0) {
  213.       memset(tile->data.color, 0, sizeof(tile->data.color));
  214.    }
  215.    else {
  216.       uint i, j;
  217.  
  218.       if (util_format_is_pure_uint(format)) {
  219.          for (i = 0; i < TILE_SIZE; i++) {
  220.             for (j = 0; j < TILE_SIZE; j++) {
  221.                tile->data.colorui128[i][j][0] = clear_value->ui[0];
  222.                tile->data.colorui128[i][j][1] = clear_value->ui[1];
  223.                tile->data.colorui128[i][j][2] = clear_value->ui[2];
  224.                tile->data.colorui128[i][j][3] = clear_value->ui[3];
  225.             }
  226.          }
  227.       } else if (util_format_is_pure_sint(format)) {
  228.          for (i = 0; i < TILE_SIZE; i++) {
  229.             for (j = 0; j < TILE_SIZE; j++) {
  230.                tile->data.colori128[i][j][0] = clear_value->i[0];
  231.                tile->data.colori128[i][j][1] = clear_value->i[1];
  232.                tile->data.colori128[i][j][2] = clear_value->i[2];
  233.                tile->data.colori128[i][j][3] = clear_value->i[3];
  234.             }
  235.          }
  236.       } else {
  237.          for (i = 0; i < TILE_SIZE; i++) {
  238.             for (j = 0; j < TILE_SIZE; j++) {
  239.                tile->data.color[i][j][0] = clear_value->f[0];
  240.                tile->data.color[i][j][1] = clear_value->f[1];
  241.                tile->data.color[i][j][2] = clear_value->f[2];
  242.                tile->data.color[i][j][3] = clear_value->f[3];
  243.             }
  244.          }
  245.       }
  246.    }
  247. }
  248.  
  249.  
  250. /**
  251.  * Set a tile to a solid value/color.
  252.  */
  253. static void
  254. clear_tile(struct softpipe_cached_tile *tile,
  255.            enum pipe_format format,
  256.            uint64_t clear_value)
  257. {
  258.    uint i, j;
  259.  
  260.    switch (util_format_get_blocksize(format)) {
  261.    case 1:
  262.       memset(tile->data.any, (int) clear_value, TILE_SIZE * TILE_SIZE);
  263.       break;
  264.    case 2:
  265.       if (clear_value == 0) {
  266.          memset(tile->data.any, 0, 2 * TILE_SIZE * TILE_SIZE);
  267.       }
  268.       else {
  269.          for (i = 0; i < TILE_SIZE; i++) {
  270.             for (j = 0; j < TILE_SIZE; j++) {
  271.                tile->data.depth16[i][j] = (ushort) clear_value;
  272.             }
  273.          }
  274.       }
  275.       break;
  276.    case 4:
  277.       if (clear_value == 0) {
  278.          memset(tile->data.any, 0, 4 * TILE_SIZE * TILE_SIZE);
  279.       }
  280.       else {
  281.          for (i = 0; i < TILE_SIZE; i++) {
  282.             for (j = 0; j < TILE_SIZE; j++) {
  283.                tile->data.depth32[i][j] = (uint) clear_value;
  284.             }
  285.          }
  286.       }
  287.       break;
  288.    case 8:
  289.       if (clear_value == 0) {
  290.          memset(tile->data.any, 0, 8 * TILE_SIZE * TILE_SIZE);
  291.       }
  292.       else {
  293.          for (i = 0; i < TILE_SIZE; i++) {
  294.             for (j = 0; j < TILE_SIZE; j++) {
  295.                tile->data.depth64[i][j] = clear_value;
  296.             }
  297.          }
  298.       }
  299.       break;
  300.    default:
  301.       assert(0);
  302.    }
  303. }
  304.  
  305.  
  306. /**
  307.  * Actually clear the tiles which were flagged as being in a clear state.
  308.  */
  309. static void
  310. sp_tile_cache_flush_clear(struct softpipe_tile_cache *tc)
  311. {
  312.    struct pipe_transfer *pt = tc->transfer;
  313.    const uint w = tc->transfer->box.width;
  314.    const uint h = tc->transfer->box.height;
  315.    uint x, y;
  316.    uint numCleared = 0;
  317.  
  318.    assert(pt->resource);
  319.    if (!tc->tile)
  320.       tc->tile = sp_alloc_tile(tc);
  321.  
  322.    /* clear the scratch tile to the clear value */
  323.    if (tc->depth_stencil) {
  324.       clear_tile(tc->tile, pt->resource->format, tc->clear_val);
  325.    } else {
  326.       clear_tile_rgba(tc->tile, pt->resource->format, &tc->clear_color);
  327.    }
  328.  
  329.    /* push the tile to all positions marked as clear */
  330.    for (y = 0; y < h; y += TILE_SIZE) {
  331.       for (x = 0; x < w; x += TILE_SIZE) {
  332.          union tile_address addr = tile_address(x, y);
  333.  
  334.          if (is_clear_flag_set(tc->clear_flags, addr)) {
  335.             /* write the scratch tile to the surface */
  336.             if (tc->depth_stencil) {
  337.                pipe_put_tile_raw(pt, tc->transfer_map,
  338.                                  x, y, TILE_SIZE, TILE_SIZE,
  339.                                  tc->tile->data.any, 0/*STRIDE*/);
  340.             }
  341.             else {
  342.                if (util_format_is_pure_uint(tc->surface->format)) {
  343.                   pipe_put_tile_ui_format(pt, tc->transfer_map,
  344.                                           x, y, TILE_SIZE, TILE_SIZE,
  345.                                           pt->resource->format,
  346.                                           (unsigned *) tc->tile->data.colorui128);
  347.                } else if (util_format_is_pure_sint(tc->surface->format)) {
  348.                   pipe_put_tile_i_format(pt, tc->transfer_map,
  349.                                          x, y, TILE_SIZE, TILE_SIZE,
  350.                                          pt->resource->format,
  351.                                          (int *) tc->tile->data.colori128);
  352.                } else {
  353.                   pipe_put_tile_rgba(pt, tc->transfer_map,
  354.                                      x, y, TILE_SIZE, TILE_SIZE,
  355.                                      (float *) tc->tile->data.color);
  356.                }
  357.             }
  358.             numCleared++;
  359.          }
  360.       }
  361.    }
  362.  
  363.    /* reset all clear flags to zero */
  364.    memset(tc->clear_flags, 0, sizeof(tc->clear_flags));
  365.  
  366. #if 0
  367.    debug_printf("num cleared: %u\n", numCleared);
  368. #endif
  369. }
  370.  
  371. static void
  372. sp_flush_tile(struct softpipe_tile_cache* tc, unsigned pos)
  373. {
  374.    if (!tc->tile_addrs[pos].bits.invalid) {
  375.       if (tc->depth_stencil) {
  376.          pipe_put_tile_raw(tc->transfer, tc->transfer_map,
  377.                            tc->tile_addrs[pos].bits.x * TILE_SIZE,
  378.                            tc->tile_addrs[pos].bits.y * TILE_SIZE,
  379.                            TILE_SIZE, TILE_SIZE,
  380.                            tc->entries[pos]->data.depth32, 0/*STRIDE*/);
  381.       }
  382.       else {
  383.          if (util_format_is_pure_uint(tc->surface->format)) {
  384.             pipe_put_tile_ui_format(tc->transfer, tc->transfer_map,
  385.                                     tc->tile_addrs[pos].bits.x * TILE_SIZE,
  386.                                     tc->tile_addrs[pos].bits.y * TILE_SIZE,
  387.                                     TILE_SIZE, TILE_SIZE,
  388.                                     tc->surface->format,
  389.                                     (unsigned *) tc->entries[pos]->data.colorui128);
  390.          } else if (util_format_is_pure_sint(tc->surface->format)) {
  391.             pipe_put_tile_i_format(tc->transfer, tc->transfer_map,
  392.                                    tc->tile_addrs[pos].bits.x * TILE_SIZE,
  393.                                    tc->tile_addrs[pos].bits.y * TILE_SIZE,
  394.                                    TILE_SIZE, TILE_SIZE,
  395.                                    tc->surface->format,
  396.                                    (int *) tc->entries[pos]->data.colori128);
  397.          } else {
  398.             pipe_put_tile_rgba_format(tc->transfer, tc->transfer_map,
  399.                                       tc->tile_addrs[pos].bits.x * TILE_SIZE,
  400.                                       tc->tile_addrs[pos].bits.y * TILE_SIZE,
  401.                                       TILE_SIZE, TILE_SIZE,
  402.                                       tc->surface->format,
  403.                                       (float *) tc->entries[pos]->data.color);
  404.          }
  405.       }
  406.       tc->tile_addrs[pos].bits.invalid = 1;  /* mark as empty */
  407.    }
  408. }
  409.  
  410. /**
  411.  * Flush the tile cache: write all dirty tiles back to the transfer.
  412.  * any tiles "flagged" as cleared will be "really" cleared.
  413.  */
  414. void
  415. sp_flush_tile_cache(struct softpipe_tile_cache *tc)
  416. {
  417.    struct pipe_transfer *pt = tc->transfer;
  418.    int inuse = 0, pos;
  419.  
  420.    if (pt) {
  421.       /* caching a drawing transfer */
  422.       for (pos = 0; pos < Elements(tc->entries); pos++) {
  423.          struct softpipe_cached_tile *tile = tc->entries[pos];
  424.          if (!tile)
  425.          {
  426.             assert(tc->tile_addrs[pos].bits.invalid);
  427.             continue;
  428.          }
  429.  
  430.          sp_flush_tile(tc, pos);
  431.          ++inuse;
  432.       }
  433.  
  434.       sp_tile_cache_flush_clear(tc);
  435.  
  436.  
  437.       tc->last_tile_addr.bits.invalid = 1;
  438.    }
  439.  
  440. #if 0
  441.    debug_printf("flushed tiles in use: %d\n", inuse);
  442. #endif
  443. }
  444.  
  445. static struct softpipe_cached_tile *
  446. sp_alloc_tile(struct softpipe_tile_cache *tc)
  447. {
  448.    struct softpipe_cached_tile * tile = MALLOC_STRUCT(softpipe_cached_tile);
  449.    if (!tile)
  450.    {
  451.       /* in this case, steal an existing tile */
  452.       if (!tc->tile)
  453.       {
  454.          unsigned pos;
  455.          for (pos = 0; pos < Elements(tc->entries); ++pos) {
  456.             if (!tc->entries[pos])
  457.                continue;
  458.  
  459.             sp_flush_tile(tc, pos);
  460.             tc->tile = tc->entries[pos];
  461.             tc->entries[pos] = NULL;
  462.             break;
  463.          }
  464.  
  465.          /* this should never happen */
  466.          if (!tc->tile)
  467.             abort();
  468.       }
  469.  
  470.       tile = tc->tile;
  471.       tc->tile = NULL;
  472.  
  473.       tc->last_tile_addr.bits.invalid = 1;
  474.    }
  475.    return tile;
  476. }
  477.  
  478. /**
  479.  * Get a tile from the cache.
  480.  * \param x, y  position of tile, in pixels
  481.  */
  482. struct softpipe_cached_tile *
  483. sp_find_cached_tile(struct softpipe_tile_cache *tc,
  484.                     union tile_address addr )
  485. {
  486.    struct pipe_transfer *pt = tc->transfer;
  487.    /* cache pos/entry: */
  488.    const int pos = CACHE_POS(addr.bits.x,
  489.                              addr.bits.y);
  490.    struct softpipe_cached_tile *tile = tc->entries[pos];
  491.  
  492.    if (!tile) {
  493.       tile = sp_alloc_tile(tc);
  494.       tc->entries[pos] = tile;
  495.    }
  496.  
  497.    if (addr.value != tc->tile_addrs[pos].value) {
  498.  
  499.       assert(pt->resource);
  500.       if (tc->tile_addrs[pos].bits.invalid == 0) {
  501.          /* put dirty tile back in framebuffer */
  502.          if (tc->depth_stencil) {
  503.             pipe_put_tile_raw(pt, tc->transfer_map,
  504.                               tc->tile_addrs[pos].bits.x * TILE_SIZE,
  505.                               tc->tile_addrs[pos].bits.y * TILE_SIZE,
  506.                               TILE_SIZE, TILE_SIZE,
  507.                               tile->data.depth32, 0/*STRIDE*/);
  508.          }
  509.          else {
  510.             if (util_format_is_pure_uint(tc->surface->format)) {
  511.                pipe_put_tile_ui_format(pt, tc->transfer_map,
  512.                                       tc->tile_addrs[pos].bits.x * TILE_SIZE,
  513.                                       tc->tile_addrs[pos].bits.y * TILE_SIZE,
  514.                                       TILE_SIZE, TILE_SIZE,
  515.                                       tc->surface->format,
  516.                                       (unsigned *) tile->data.colorui128);
  517.             } else if (util_format_is_pure_sint(tc->surface->format)) {
  518.                pipe_put_tile_i_format(pt, tc->transfer_map,
  519.                                       tc->tile_addrs[pos].bits.x * TILE_SIZE,
  520.                                       tc->tile_addrs[pos].bits.y * TILE_SIZE,
  521.                                       TILE_SIZE, TILE_SIZE,
  522.                                       tc->surface->format,
  523.                                       (int *) tile->data.colori128);
  524.             } else {
  525.                pipe_put_tile_rgba_format(pt, tc->transfer_map,
  526.                                          tc->tile_addrs[pos].bits.x * TILE_SIZE,
  527.                                          tc->tile_addrs[pos].bits.y * TILE_SIZE,
  528.                                          TILE_SIZE, TILE_SIZE,
  529.                                          tc->surface->format,
  530.                                          (float *) tile->data.color);
  531.             }
  532.          }
  533.       }
  534.  
  535.       tc->tile_addrs[pos] = addr;
  536.  
  537.       if (is_clear_flag_set(tc->clear_flags, addr)) {
  538.          /* don't get tile from framebuffer, just clear it */
  539.          if (tc->depth_stencil) {
  540.             clear_tile(tile, pt->resource->format, tc->clear_val);
  541.          }
  542.          else {
  543.             clear_tile_rgba(tile, pt->resource->format, &tc->clear_color);
  544.          }
  545.          clear_clear_flag(tc->clear_flags, addr);
  546.       }
  547.       else {
  548.          /* get new tile data from transfer */
  549.          if (tc->depth_stencil) {
  550.             pipe_get_tile_raw(pt, tc->transfer_map,
  551.                               tc->tile_addrs[pos].bits.x * TILE_SIZE,
  552.                               tc->tile_addrs[pos].bits.y * TILE_SIZE,
  553.                               TILE_SIZE, TILE_SIZE,
  554.                               tile->data.depth32, 0/*STRIDE*/);
  555.          }
  556.          else {
  557.             if (util_format_is_pure_uint(tc->surface->format)) {
  558.                pipe_get_tile_ui_format(pt, tc->transfer_map,
  559.                                          tc->tile_addrs[pos].bits.x * TILE_SIZE,
  560.                                          tc->tile_addrs[pos].bits.y * TILE_SIZE,
  561.                                          TILE_SIZE, TILE_SIZE,
  562.                                          tc->surface->format,
  563.                                          (unsigned *) tile->data.colorui128);
  564.             } else if (util_format_is_pure_sint(tc->surface->format)) {
  565.                pipe_get_tile_i_format(pt, tc->transfer_map,
  566.                                          tc->tile_addrs[pos].bits.x * TILE_SIZE,
  567.                                          tc->tile_addrs[pos].bits.y * TILE_SIZE,
  568.                                          TILE_SIZE, TILE_SIZE,
  569.                                          tc->surface->format,
  570.                                          (int *) tile->data.colori128);
  571.             } else {
  572.                pipe_get_tile_rgba_format(pt, tc->transfer_map,
  573.                                          tc->tile_addrs[pos].bits.x * TILE_SIZE,
  574.                                          tc->tile_addrs[pos].bits.y * TILE_SIZE,
  575.                                          TILE_SIZE, TILE_SIZE,
  576.                                          tc->surface->format,
  577.                                          (float *) tile->data.color);
  578.             }
  579.          }
  580.       }
  581.    }
  582.  
  583.    tc->last_tile = tile;
  584.    tc->last_tile_addr = addr;
  585.    return tile;
  586. }
  587.  
  588.  
  589.  
  590.  
  591.  
  592. /**
  593.  * When a whole surface is being cleared to a value we can avoid
  594.  * fetching tiles above.
  595.  * Save the color and set a 'clearflag' for each tile of the screen.
  596.  */
  597. void
  598. sp_tile_cache_clear(struct softpipe_tile_cache *tc,
  599.                     const union pipe_color_union *color,
  600.                     uint64_t clearValue)
  601. {
  602.    uint pos;
  603.  
  604.    tc->clear_color = *color;
  605.  
  606.    tc->clear_val = clearValue;
  607.  
  608.    /* set flags to indicate all the tiles are cleared */
  609.    memset(tc->clear_flags, 255, sizeof(tc->clear_flags));
  610.  
  611.    for (pos = 0; pos < Elements(tc->tile_addrs); pos++) {
  612.       tc->tile_addrs[pos].bits.invalid = 1;
  613.    }
  614.    tc->last_tile_addr.bits.invalid = 1;
  615. }
  616.