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