1bf215546Sopenharmony_ci/********************************************************** 2bf215546Sopenharmony_ci * Copyright 2008-2009 VMware, Inc. All rights reserved. 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person 5bf215546Sopenharmony_ci * obtaining a copy of this software and associated documentation 6bf215546Sopenharmony_ci * files (the "Software"), to deal in the Software without 7bf215546Sopenharmony_ci * restriction, including without limitation the rights to use, copy, 8bf215546Sopenharmony_ci * modify, merge, publish, distribute, sublicense, and/or sell copies 9bf215546Sopenharmony_ci * of the Software, and to permit persons to whom the Software is 10bf215546Sopenharmony_ci * furnished to do so, subject to the following conditions: 11bf215546Sopenharmony_ci * 12bf215546Sopenharmony_ci * The above copyright notice and this permission notice shall be 13bf215546Sopenharmony_ci * included in all copies or substantial portions of the Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16bf215546Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18bf215546Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19bf215546Sopenharmony_ci * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20bf215546Sopenharmony_ci * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21bf215546Sopenharmony_ci * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22bf215546Sopenharmony_ci * SOFTWARE. 23bf215546Sopenharmony_ci * 24bf215546Sopenharmony_ci **********************************************************/ 25bf215546Sopenharmony_ci 26bf215546Sopenharmony_ci#include "svga3d_reg.h" 27bf215546Sopenharmony_ci#include "svga3d_surfacedefs.h" 28bf215546Sopenharmony_ci 29bf215546Sopenharmony_ci#include "pipe/p_state.h" 30bf215546Sopenharmony_ci#include "pipe/p_defines.h" 31bf215546Sopenharmony_ci#include "os/os_thread.h" 32bf215546Sopenharmony_ci#include "util/format/u_format.h" 33bf215546Sopenharmony_ci#include "util/u_inlines.h" 34bf215546Sopenharmony_ci#include "util/u_math.h" 35bf215546Sopenharmony_ci#include "util/u_memory.h" 36bf215546Sopenharmony_ci#include "util/u_resource.h" 37bf215546Sopenharmony_ci#include "util/u_upload_mgr.h" 38bf215546Sopenharmony_ci 39bf215546Sopenharmony_ci#include "svga_cmd.h" 40bf215546Sopenharmony_ci#include "svga_format.h" 41bf215546Sopenharmony_ci#include "svga_screen.h" 42bf215546Sopenharmony_ci#include "svga_context.h" 43bf215546Sopenharmony_ci#include "svga_resource_texture.h" 44bf215546Sopenharmony_ci#include "svga_resource_buffer.h" 45bf215546Sopenharmony_ci#include "svga_sampler_view.h" 46bf215546Sopenharmony_ci#include "svga_winsys.h" 47bf215546Sopenharmony_ci#include "svga_debug.h" 48bf215546Sopenharmony_ci 49bf215546Sopenharmony_ci 50bf215546Sopenharmony_cistatic void 51bf215546Sopenharmony_cisvga_transfer_dma_band(struct svga_context *svga, 52bf215546Sopenharmony_ci struct svga_transfer *st, 53bf215546Sopenharmony_ci SVGA3dTransferType transfer, 54bf215546Sopenharmony_ci unsigned x, unsigned y, unsigned z, 55bf215546Sopenharmony_ci unsigned w, unsigned h, unsigned d, 56bf215546Sopenharmony_ci unsigned srcx, unsigned srcy, unsigned srcz, 57bf215546Sopenharmony_ci SVGA3dSurfaceDMAFlags flags) 58bf215546Sopenharmony_ci{ 59bf215546Sopenharmony_ci struct svga_texture *texture = svga_texture(st->base.resource); 60bf215546Sopenharmony_ci SVGA3dCopyBox box; 61bf215546Sopenharmony_ci 62bf215546Sopenharmony_ci assert(!st->use_direct_map); 63bf215546Sopenharmony_ci 64bf215546Sopenharmony_ci box.x = x; 65bf215546Sopenharmony_ci box.y = y; 66bf215546Sopenharmony_ci box.z = z; 67bf215546Sopenharmony_ci box.w = w; 68bf215546Sopenharmony_ci box.h = h; 69bf215546Sopenharmony_ci box.d = d; 70bf215546Sopenharmony_ci box.srcx = srcx; 71bf215546Sopenharmony_ci box.srcy = srcy; 72bf215546Sopenharmony_ci box.srcz = srcz; 73bf215546Sopenharmony_ci 74bf215546Sopenharmony_ci SVGA_DBG(DEBUG_DMA, "dma %s sid %p, face %u, (%u, %u, %u) - " 75bf215546Sopenharmony_ci "(%u, %u, %u), %ubpp\n", 76bf215546Sopenharmony_ci transfer == SVGA3D_WRITE_HOST_VRAM ? "to" : "from", 77bf215546Sopenharmony_ci texture->handle, 78bf215546Sopenharmony_ci st->slice, 79bf215546Sopenharmony_ci x, 80bf215546Sopenharmony_ci y, 81bf215546Sopenharmony_ci z, 82bf215546Sopenharmony_ci x + w, 83bf215546Sopenharmony_ci y + h, 84bf215546Sopenharmony_ci z + 1, 85bf215546Sopenharmony_ci util_format_get_blocksize(texture->b.format) * 8 / 86bf215546Sopenharmony_ci (util_format_get_blockwidth(texture->b.format) 87bf215546Sopenharmony_ci * util_format_get_blockheight(texture->b.format))); 88bf215546Sopenharmony_ci 89bf215546Sopenharmony_ci SVGA_RETRY(svga, SVGA3D_SurfaceDMA(svga->swc, st, transfer, &box, 1, flags)); 90bf215546Sopenharmony_ci} 91bf215546Sopenharmony_ci 92bf215546Sopenharmony_ci 93bf215546Sopenharmony_cistatic void 94bf215546Sopenharmony_cisvga_transfer_dma(struct svga_context *svga, 95bf215546Sopenharmony_ci struct svga_transfer *st, 96bf215546Sopenharmony_ci SVGA3dTransferType transfer, 97bf215546Sopenharmony_ci SVGA3dSurfaceDMAFlags flags) 98bf215546Sopenharmony_ci{ 99bf215546Sopenharmony_ci struct svga_texture *texture = svga_texture(st->base.resource); 100bf215546Sopenharmony_ci struct svga_screen *screen = svga_screen(texture->b.screen); 101bf215546Sopenharmony_ci struct svga_winsys_screen *sws = screen->sws; 102bf215546Sopenharmony_ci struct pipe_fence_handle *fence = NULL; 103bf215546Sopenharmony_ci 104bf215546Sopenharmony_ci assert(!st->use_direct_map); 105bf215546Sopenharmony_ci 106bf215546Sopenharmony_ci if (transfer == SVGA3D_READ_HOST_VRAM) { 107bf215546Sopenharmony_ci SVGA_DBG(DEBUG_PERF, "%s: readback transfer\n", __FUNCTION__); 108bf215546Sopenharmony_ci } 109bf215546Sopenharmony_ci 110bf215546Sopenharmony_ci /* Ensure any pending operations on host surfaces are queued on the command 111bf215546Sopenharmony_ci * buffer first. 112bf215546Sopenharmony_ci */ 113bf215546Sopenharmony_ci svga_surfaces_flush(svga); 114bf215546Sopenharmony_ci 115bf215546Sopenharmony_ci if (!st->swbuf) { 116bf215546Sopenharmony_ci /* Do the DMA transfer in a single go */ 117bf215546Sopenharmony_ci svga_transfer_dma_band(svga, st, transfer, 118bf215546Sopenharmony_ci st->box.x, st->box.y, st->box.z, 119bf215546Sopenharmony_ci st->box.w, st->box.h, st->box.d, 120bf215546Sopenharmony_ci 0, 0, 0, 121bf215546Sopenharmony_ci flags); 122bf215546Sopenharmony_ci 123bf215546Sopenharmony_ci if (transfer == SVGA3D_READ_HOST_VRAM) { 124bf215546Sopenharmony_ci svga_context_flush(svga, &fence); 125bf215546Sopenharmony_ci sws->fence_finish(sws, fence, PIPE_TIMEOUT_INFINITE, 0); 126bf215546Sopenharmony_ci sws->fence_reference(sws, &fence, NULL); 127bf215546Sopenharmony_ci } 128bf215546Sopenharmony_ci } 129bf215546Sopenharmony_ci else { 130bf215546Sopenharmony_ci int y, h, srcy; 131bf215546Sopenharmony_ci unsigned blockheight = 132bf215546Sopenharmony_ci util_format_get_blockheight(st->base.resource->format); 133bf215546Sopenharmony_ci 134bf215546Sopenharmony_ci h = st->hw_nblocksy * blockheight; 135bf215546Sopenharmony_ci srcy = 0; 136bf215546Sopenharmony_ci 137bf215546Sopenharmony_ci for (y = 0; y < st->box.h; y += h) { 138bf215546Sopenharmony_ci unsigned offset, length; 139bf215546Sopenharmony_ci void *hw, *sw; 140bf215546Sopenharmony_ci 141bf215546Sopenharmony_ci if (y + h > st->box.h) 142bf215546Sopenharmony_ci h = st->box.h - y; 143bf215546Sopenharmony_ci 144bf215546Sopenharmony_ci /* Transfer band must be aligned to pixel block boundaries */ 145bf215546Sopenharmony_ci assert(y % blockheight == 0); 146bf215546Sopenharmony_ci assert(h % blockheight == 0); 147bf215546Sopenharmony_ci 148bf215546Sopenharmony_ci offset = y * st->base.stride / blockheight; 149bf215546Sopenharmony_ci length = h * st->base.stride / blockheight; 150bf215546Sopenharmony_ci 151bf215546Sopenharmony_ci sw = (uint8_t *) st->swbuf + offset; 152bf215546Sopenharmony_ci 153bf215546Sopenharmony_ci if (transfer == SVGA3D_WRITE_HOST_VRAM) { 154bf215546Sopenharmony_ci unsigned usage = PIPE_MAP_WRITE; 155bf215546Sopenharmony_ci 156bf215546Sopenharmony_ci /* Wait for the previous DMAs to complete */ 157bf215546Sopenharmony_ci /* TODO: keep one DMA (at half the size) in the background */ 158bf215546Sopenharmony_ci if (y) { 159bf215546Sopenharmony_ci svga_context_flush(svga, NULL); 160bf215546Sopenharmony_ci usage |= PIPE_MAP_DISCARD_WHOLE_RESOURCE; 161bf215546Sopenharmony_ci } 162bf215546Sopenharmony_ci 163bf215546Sopenharmony_ci hw = sws->buffer_map(sws, st->hwbuf, usage); 164bf215546Sopenharmony_ci assert(hw); 165bf215546Sopenharmony_ci if (hw) { 166bf215546Sopenharmony_ci memcpy(hw, sw, length); 167bf215546Sopenharmony_ci sws->buffer_unmap(sws, st->hwbuf); 168bf215546Sopenharmony_ci } 169bf215546Sopenharmony_ci } 170bf215546Sopenharmony_ci 171bf215546Sopenharmony_ci svga_transfer_dma_band(svga, st, transfer, 172bf215546Sopenharmony_ci st->box.x, y, st->box.z, 173bf215546Sopenharmony_ci st->box.w, h, st->box.d, 174bf215546Sopenharmony_ci 0, srcy, 0, flags); 175bf215546Sopenharmony_ci 176bf215546Sopenharmony_ci /* 177bf215546Sopenharmony_ci * Prevent the texture contents to be discarded on the next band 178bf215546Sopenharmony_ci * upload. 179bf215546Sopenharmony_ci */ 180bf215546Sopenharmony_ci flags.discard = FALSE; 181bf215546Sopenharmony_ci 182bf215546Sopenharmony_ci if (transfer == SVGA3D_READ_HOST_VRAM) { 183bf215546Sopenharmony_ci svga_context_flush(svga, &fence); 184bf215546Sopenharmony_ci sws->fence_finish(sws, fence, PIPE_TIMEOUT_INFINITE, 0); 185bf215546Sopenharmony_ci 186bf215546Sopenharmony_ci hw = sws->buffer_map(sws, st->hwbuf, PIPE_MAP_READ); 187bf215546Sopenharmony_ci assert(hw); 188bf215546Sopenharmony_ci if (hw) { 189bf215546Sopenharmony_ci memcpy(sw, hw, length); 190bf215546Sopenharmony_ci sws->buffer_unmap(sws, st->hwbuf); 191bf215546Sopenharmony_ci } 192bf215546Sopenharmony_ci } 193bf215546Sopenharmony_ci } 194bf215546Sopenharmony_ci } 195bf215546Sopenharmony_ci} 196bf215546Sopenharmony_ci 197bf215546Sopenharmony_ci 198bf215546Sopenharmony_ci 199bf215546Sopenharmony_cibool 200bf215546Sopenharmony_cisvga_resource_get_handle(struct pipe_screen *screen, 201bf215546Sopenharmony_ci struct pipe_context *context, 202bf215546Sopenharmony_ci struct pipe_resource *texture, 203bf215546Sopenharmony_ci struct winsys_handle *whandle, 204bf215546Sopenharmony_ci unsigned usage) 205bf215546Sopenharmony_ci{ 206bf215546Sopenharmony_ci struct svga_winsys_screen *sws = svga_winsys_screen(texture->screen); 207bf215546Sopenharmony_ci unsigned stride; 208bf215546Sopenharmony_ci 209bf215546Sopenharmony_ci if (texture->target == PIPE_BUFFER) 210bf215546Sopenharmony_ci return false; 211bf215546Sopenharmony_ci 212bf215546Sopenharmony_ci assert(svga_texture(texture)->key.cachable == 0); 213bf215546Sopenharmony_ci svga_texture(texture)->key.cachable = 0; 214bf215546Sopenharmony_ci 215bf215546Sopenharmony_ci stride = util_format_get_nblocksx(texture->format, texture->width0) * 216bf215546Sopenharmony_ci util_format_get_blocksize(texture->format); 217bf215546Sopenharmony_ci 218bf215546Sopenharmony_ci return sws->surface_get_handle(sws, svga_texture(texture)->handle, 219bf215546Sopenharmony_ci stride, whandle); 220bf215546Sopenharmony_ci} 221bf215546Sopenharmony_ci 222bf215546Sopenharmony_ci 223bf215546Sopenharmony_ci/** 224bf215546Sopenharmony_ci * Determine if we need to read back a texture image before mapping it. 225bf215546Sopenharmony_ci */ 226bf215546Sopenharmony_cistatic inline boolean 227bf215546Sopenharmony_cineed_tex_readback(struct svga_transfer *st) 228bf215546Sopenharmony_ci{ 229bf215546Sopenharmony_ci if (st->base.usage & PIPE_MAP_READ) 230bf215546Sopenharmony_ci return TRUE; 231bf215546Sopenharmony_ci 232bf215546Sopenharmony_ci if ((st->base.usage & PIPE_MAP_WRITE) && 233bf215546Sopenharmony_ci ((st->base.usage & PIPE_MAP_DISCARD_WHOLE_RESOURCE) == 0)) { 234bf215546Sopenharmony_ci return svga_was_texture_rendered_to(svga_texture(st->base.resource)); 235bf215546Sopenharmony_ci } 236bf215546Sopenharmony_ci 237bf215546Sopenharmony_ci return FALSE; 238bf215546Sopenharmony_ci} 239bf215546Sopenharmony_ci 240bf215546Sopenharmony_ci 241bf215546Sopenharmony_cistatic void 242bf215546Sopenharmony_cireadback_texture_surface(struct svga_context *svga, 243bf215546Sopenharmony_ci struct svga_texture *tex, 244bf215546Sopenharmony_ci struct svga_winsys_surface *surf) 245bf215546Sopenharmony_ci{ 246bf215546Sopenharmony_ci SVGA_RETRY(svga, SVGA3D_ReadbackGBSurface(svga->swc, surf)); 247bf215546Sopenharmony_ci 248bf215546Sopenharmony_ci /* Mark the texture surface as UPDATED */ 249bf215546Sopenharmony_ci tex->surface_state = SVGA_SURFACE_STATE_UPDATED; 250bf215546Sopenharmony_ci 251bf215546Sopenharmony_ci svga->hud.num_readbacks++; 252bf215546Sopenharmony_ci SVGA_STATS_COUNT_INC(svga_sws(svga), SVGA_STATS_COUNT_TEXREADBACK); 253bf215546Sopenharmony_ci} 254bf215546Sopenharmony_ci 255bf215546Sopenharmony_ci/** 256bf215546Sopenharmony_ci * Use DMA for the transfer request 257bf215546Sopenharmony_ci */ 258bf215546Sopenharmony_cistatic void * 259bf215546Sopenharmony_cisvga_texture_transfer_map_dma(struct svga_context *svga, 260bf215546Sopenharmony_ci struct svga_transfer *st) 261bf215546Sopenharmony_ci{ 262bf215546Sopenharmony_ci struct svga_winsys_screen *sws = svga_screen(svga->pipe.screen)->sws; 263bf215546Sopenharmony_ci struct pipe_resource *texture = st->base.resource; 264bf215546Sopenharmony_ci unsigned nblocksx, nblocksy; 265bf215546Sopenharmony_ci unsigned d; 266bf215546Sopenharmony_ci unsigned usage = st->base.usage; 267bf215546Sopenharmony_ci 268bf215546Sopenharmony_ci /* we'll put the data into a tightly packed buffer */ 269bf215546Sopenharmony_ci nblocksx = util_format_get_nblocksx(texture->format, st->box.w); 270bf215546Sopenharmony_ci nblocksy = util_format_get_nblocksy(texture->format, st->box.h); 271bf215546Sopenharmony_ci d = st->box.d; 272bf215546Sopenharmony_ci 273bf215546Sopenharmony_ci st->base.stride = nblocksx*util_format_get_blocksize(texture->format); 274bf215546Sopenharmony_ci st->base.layer_stride = st->base.stride * nblocksy; 275bf215546Sopenharmony_ci st->hw_nblocksy = nblocksy; 276bf215546Sopenharmony_ci 277bf215546Sopenharmony_ci st->hwbuf = svga_winsys_buffer_create(svga, 1, 0, 278bf215546Sopenharmony_ci st->hw_nblocksy * st->base.stride * d); 279bf215546Sopenharmony_ci 280bf215546Sopenharmony_ci while (!st->hwbuf && (st->hw_nblocksy /= 2)) { 281bf215546Sopenharmony_ci st->hwbuf = 282bf215546Sopenharmony_ci svga_winsys_buffer_create(svga, 1, 0, 283bf215546Sopenharmony_ci st->hw_nblocksy * st->base.stride * d); 284bf215546Sopenharmony_ci } 285bf215546Sopenharmony_ci 286bf215546Sopenharmony_ci if (!st->hwbuf) 287bf215546Sopenharmony_ci return NULL; 288bf215546Sopenharmony_ci 289bf215546Sopenharmony_ci if (st->hw_nblocksy < nblocksy) { 290bf215546Sopenharmony_ci /* We couldn't allocate a hardware buffer big enough for the transfer, 291bf215546Sopenharmony_ci * so allocate regular malloc memory instead 292bf215546Sopenharmony_ci */ 293bf215546Sopenharmony_ci if (0) { 294bf215546Sopenharmony_ci debug_printf("%s: failed to allocate %u KB of DMA, " 295bf215546Sopenharmony_ci "splitting into %u x %u KB DMA transfers\n", 296bf215546Sopenharmony_ci __FUNCTION__, 297bf215546Sopenharmony_ci (nblocksy * st->base.stride + 1023) / 1024, 298bf215546Sopenharmony_ci (nblocksy + st->hw_nblocksy - 1) / st->hw_nblocksy, 299bf215546Sopenharmony_ci (st->hw_nblocksy * st->base.stride + 1023) / 1024); 300bf215546Sopenharmony_ci } 301bf215546Sopenharmony_ci 302bf215546Sopenharmony_ci st->swbuf = MALLOC(nblocksy * st->base.stride * d); 303bf215546Sopenharmony_ci if (!st->swbuf) { 304bf215546Sopenharmony_ci sws->buffer_destroy(sws, st->hwbuf); 305bf215546Sopenharmony_ci return NULL; 306bf215546Sopenharmony_ci } 307bf215546Sopenharmony_ci } 308bf215546Sopenharmony_ci 309bf215546Sopenharmony_ci if (usage & PIPE_MAP_READ) { 310bf215546Sopenharmony_ci SVGA3dSurfaceDMAFlags flags; 311bf215546Sopenharmony_ci memset(&flags, 0, sizeof flags); 312bf215546Sopenharmony_ci svga_transfer_dma(svga, st, SVGA3D_READ_HOST_VRAM, flags); 313bf215546Sopenharmony_ci } 314bf215546Sopenharmony_ci 315bf215546Sopenharmony_ci if (st->swbuf) { 316bf215546Sopenharmony_ci return st->swbuf; 317bf215546Sopenharmony_ci } 318bf215546Sopenharmony_ci else { 319bf215546Sopenharmony_ci return sws->buffer_map(sws, st->hwbuf, usage); 320bf215546Sopenharmony_ci } 321bf215546Sopenharmony_ci} 322bf215546Sopenharmony_ci 323bf215546Sopenharmony_ci 324bf215546Sopenharmony_ci/** 325bf215546Sopenharmony_ci * Use direct map for the transfer request 326bf215546Sopenharmony_ci */ 327bf215546Sopenharmony_cistatic void * 328bf215546Sopenharmony_cisvga_texture_transfer_map_direct(struct svga_context *svga, 329bf215546Sopenharmony_ci struct svga_transfer *st) 330bf215546Sopenharmony_ci{ 331bf215546Sopenharmony_ci struct svga_winsys_screen *sws = svga_screen(svga->pipe.screen)->sws; 332bf215546Sopenharmony_ci struct pipe_transfer *transfer = &st->base; 333bf215546Sopenharmony_ci struct pipe_resource *texture = transfer->resource; 334bf215546Sopenharmony_ci struct svga_texture *tex = svga_texture(texture); 335bf215546Sopenharmony_ci struct svga_winsys_surface *surf = tex->handle; 336bf215546Sopenharmony_ci unsigned level = st->base.level; 337bf215546Sopenharmony_ci unsigned w, h, nblocksx, nblocksy; 338bf215546Sopenharmony_ci unsigned usage = st->base.usage; 339bf215546Sopenharmony_ci 340bf215546Sopenharmony_ci if (need_tex_readback(st)) { 341bf215546Sopenharmony_ci svga_surfaces_flush(svga); 342bf215546Sopenharmony_ci 343bf215546Sopenharmony_ci if (!svga->swc->force_coherent || tex->imported) { 344bf215546Sopenharmony_ci /* Readback the whole surface */ 345bf215546Sopenharmony_ci readback_texture_surface(svga, tex, surf); 346bf215546Sopenharmony_ci 347bf215546Sopenharmony_ci svga_context_finish(svga); 348bf215546Sopenharmony_ci } 349bf215546Sopenharmony_ci /* 350bf215546Sopenharmony_ci * Note: if PIPE_MAP_DISCARD_WHOLE_RESOURCE were specified 351bf215546Sopenharmony_ci * we could potentially clear the flag for all faces/layers/mips. 352bf215546Sopenharmony_ci */ 353bf215546Sopenharmony_ci svga_clear_texture_rendered_to(tex); 354bf215546Sopenharmony_ci } 355bf215546Sopenharmony_ci else { 356bf215546Sopenharmony_ci assert(usage & PIPE_MAP_WRITE); 357bf215546Sopenharmony_ci if ((usage & PIPE_MAP_UNSYNCHRONIZED) == 0) { 358bf215546Sopenharmony_ci if (svga_is_texture_dirty(tex, st->slice, level)) { 359bf215546Sopenharmony_ci /* 360bf215546Sopenharmony_ci * do a surface flush if the subresource has been modified 361bf215546Sopenharmony_ci * in this command buffer. 362bf215546Sopenharmony_ci */ 363bf215546Sopenharmony_ci svga_surfaces_flush(svga); 364bf215546Sopenharmony_ci if (!sws->surface_is_flushed(sws, surf)) { 365bf215546Sopenharmony_ci svga->hud.surface_write_flushes++; 366bf215546Sopenharmony_ci SVGA_STATS_COUNT_INC(sws, SVGA_STATS_COUNT_SURFACEWRITEFLUSH); 367bf215546Sopenharmony_ci svga_context_flush(svga, NULL); 368bf215546Sopenharmony_ci } 369bf215546Sopenharmony_ci } 370bf215546Sopenharmony_ci } 371bf215546Sopenharmony_ci } 372bf215546Sopenharmony_ci 373bf215546Sopenharmony_ci /* we'll directly access the guest-backed surface */ 374bf215546Sopenharmony_ci w = u_minify(texture->width0, level); 375bf215546Sopenharmony_ci h = u_minify(texture->height0, level); 376bf215546Sopenharmony_ci nblocksx = util_format_get_nblocksx(texture->format, w); 377bf215546Sopenharmony_ci nblocksy = util_format_get_nblocksy(texture->format, h); 378bf215546Sopenharmony_ci st->hw_nblocksy = nblocksy; 379bf215546Sopenharmony_ci st->base.stride = nblocksx*util_format_get_blocksize(texture->format); 380bf215546Sopenharmony_ci st->base.layer_stride = st->base.stride * nblocksy; 381bf215546Sopenharmony_ci 382bf215546Sopenharmony_ci /* 383bf215546Sopenharmony_ci * Begin mapping code 384bf215546Sopenharmony_ci */ 385bf215546Sopenharmony_ci { 386bf215546Sopenharmony_ci SVGA3dSize baseLevelSize; 387bf215546Sopenharmony_ci uint8_t *map; 388bf215546Sopenharmony_ci boolean retry, rebind; 389bf215546Sopenharmony_ci unsigned offset, mip_width, mip_height; 390bf215546Sopenharmony_ci struct svga_winsys_context *swc = svga->swc; 391bf215546Sopenharmony_ci 392bf215546Sopenharmony_ci if (swc->force_coherent) { 393bf215546Sopenharmony_ci usage |= PIPE_MAP_PERSISTENT | PIPE_MAP_COHERENT; 394bf215546Sopenharmony_ci } 395bf215546Sopenharmony_ci 396bf215546Sopenharmony_ci map = SVGA_TRY_MAP(svga->swc->surface_map 397bf215546Sopenharmony_ci (svga->swc, surf, usage, &retry, &rebind), retry); 398bf215546Sopenharmony_ci 399bf215546Sopenharmony_ci if (map == NULL && retry) { 400bf215546Sopenharmony_ci /* 401bf215546Sopenharmony_ci * At this point, the svga_surfaces_flush() should already have 402bf215546Sopenharmony_ci * called in svga_texture_get_transfer(). 403bf215546Sopenharmony_ci */ 404bf215546Sopenharmony_ci svga->hud.surface_write_flushes++; 405bf215546Sopenharmony_ci svga_retry_enter(svga); 406bf215546Sopenharmony_ci svga_context_flush(svga, NULL); 407bf215546Sopenharmony_ci map = svga->swc->surface_map(svga->swc, surf, usage, &retry, &rebind); 408bf215546Sopenharmony_ci svga_retry_exit(svga); 409bf215546Sopenharmony_ci } 410bf215546Sopenharmony_ci if (map && rebind) { 411bf215546Sopenharmony_ci enum pipe_error ret; 412bf215546Sopenharmony_ci 413bf215546Sopenharmony_ci ret = SVGA3D_BindGBSurface(swc, surf); 414bf215546Sopenharmony_ci if (ret != PIPE_OK) { 415bf215546Sopenharmony_ci svga_context_flush(svga, NULL); 416bf215546Sopenharmony_ci ret = SVGA3D_BindGBSurface(swc, surf); 417bf215546Sopenharmony_ci assert(ret == PIPE_OK); 418bf215546Sopenharmony_ci } 419bf215546Sopenharmony_ci svga_context_flush(svga, NULL); 420bf215546Sopenharmony_ci } 421bf215546Sopenharmony_ci 422bf215546Sopenharmony_ci /* 423bf215546Sopenharmony_ci * Make sure we return NULL if the map fails 424bf215546Sopenharmony_ci */ 425bf215546Sopenharmony_ci if (!map) { 426bf215546Sopenharmony_ci return NULL; 427bf215546Sopenharmony_ci } 428bf215546Sopenharmony_ci 429bf215546Sopenharmony_ci /** 430bf215546Sopenharmony_ci * Compute the offset to the specific texture slice in the buffer. 431bf215546Sopenharmony_ci */ 432bf215546Sopenharmony_ci baseLevelSize.width = tex->b.width0; 433bf215546Sopenharmony_ci baseLevelSize.height = tex->b.height0; 434bf215546Sopenharmony_ci baseLevelSize.depth = tex->b.depth0; 435bf215546Sopenharmony_ci 436bf215546Sopenharmony_ci if ((tex->b.target == PIPE_TEXTURE_1D_ARRAY) || 437bf215546Sopenharmony_ci (tex->b.target == PIPE_TEXTURE_2D_ARRAY) || 438bf215546Sopenharmony_ci (tex->b.target == PIPE_TEXTURE_CUBE_ARRAY)) { 439bf215546Sopenharmony_ci st->base.layer_stride = 440bf215546Sopenharmony_ci svga3dsurface_get_image_offset(tex->key.format, baseLevelSize, 441bf215546Sopenharmony_ci tex->b.last_level + 1, 1, 0); 442bf215546Sopenharmony_ci } 443bf215546Sopenharmony_ci 444bf215546Sopenharmony_ci offset = svga3dsurface_get_image_offset(tex->key.format, baseLevelSize, 445bf215546Sopenharmony_ci tex->b.last_level + 1, /* numMips */ 446bf215546Sopenharmony_ci st->slice, level); 447bf215546Sopenharmony_ci if (level > 0) { 448bf215546Sopenharmony_ci assert(offset > 0); 449bf215546Sopenharmony_ci } 450bf215546Sopenharmony_ci 451bf215546Sopenharmony_ci mip_width = u_minify(tex->b.width0, level); 452bf215546Sopenharmony_ci mip_height = u_minify(tex->b.height0, level); 453bf215546Sopenharmony_ci 454bf215546Sopenharmony_ci offset += svga3dsurface_get_pixel_offset(tex->key.format, 455bf215546Sopenharmony_ci mip_width, mip_height, 456bf215546Sopenharmony_ci st->box.x, 457bf215546Sopenharmony_ci st->box.y, 458bf215546Sopenharmony_ci st->box.z); 459bf215546Sopenharmony_ci 460bf215546Sopenharmony_ci return (void *) (map + offset); 461bf215546Sopenharmony_ci } 462bf215546Sopenharmony_ci} 463bf215546Sopenharmony_ci 464bf215546Sopenharmony_ci 465bf215546Sopenharmony_ci/** 466bf215546Sopenharmony_ci * Request a transfer map to the texture resource 467bf215546Sopenharmony_ci */ 468bf215546Sopenharmony_civoid * 469bf215546Sopenharmony_cisvga_texture_transfer_map(struct pipe_context *pipe, 470bf215546Sopenharmony_ci struct pipe_resource *texture, 471bf215546Sopenharmony_ci unsigned level, 472bf215546Sopenharmony_ci unsigned usage, 473bf215546Sopenharmony_ci const struct pipe_box *box, 474bf215546Sopenharmony_ci struct pipe_transfer **ptransfer) 475bf215546Sopenharmony_ci{ 476bf215546Sopenharmony_ci struct svga_context *svga = svga_context(pipe); 477bf215546Sopenharmony_ci struct svga_winsys_screen *sws = svga_screen(pipe->screen)->sws; 478bf215546Sopenharmony_ci struct svga_texture *tex = svga_texture(texture); 479bf215546Sopenharmony_ci struct svga_transfer *st; 480bf215546Sopenharmony_ci struct svga_winsys_surface *surf = tex->handle; 481bf215546Sopenharmony_ci boolean use_direct_map = svga_have_gb_objects(svga) && 482bf215546Sopenharmony_ci (!svga_have_gb_dma(svga) || (usage & PIPE_MAP_WRITE)); 483bf215546Sopenharmony_ci void *map = NULL; 484bf215546Sopenharmony_ci int64_t begin = svga_get_time(svga); 485bf215546Sopenharmony_ci 486bf215546Sopenharmony_ci SVGA_STATS_TIME_PUSH(sws, SVGA_STATS_TIME_TEXTRANSFERMAP); 487bf215546Sopenharmony_ci 488bf215546Sopenharmony_ci if (!surf) 489bf215546Sopenharmony_ci goto done; 490bf215546Sopenharmony_ci 491bf215546Sopenharmony_ci /* We can't map texture storage directly unless we have GB objects */ 492bf215546Sopenharmony_ci if (usage & PIPE_MAP_DIRECTLY) { 493bf215546Sopenharmony_ci if (svga_have_gb_objects(svga)) 494bf215546Sopenharmony_ci use_direct_map = TRUE; 495bf215546Sopenharmony_ci else 496bf215546Sopenharmony_ci goto done; 497bf215546Sopenharmony_ci } 498bf215546Sopenharmony_ci 499bf215546Sopenharmony_ci st = CALLOC_STRUCT(svga_transfer); 500bf215546Sopenharmony_ci if (!st) 501bf215546Sopenharmony_ci goto done; 502bf215546Sopenharmony_ci 503bf215546Sopenharmony_ci st->base.level = level; 504bf215546Sopenharmony_ci st->base.usage = usage; 505bf215546Sopenharmony_ci st->base.box = *box; 506bf215546Sopenharmony_ci 507bf215546Sopenharmony_ci /* The modified transfer map box with the array index removed from z. 508bf215546Sopenharmony_ci * The array index is specified in slice. 509bf215546Sopenharmony_ci */ 510bf215546Sopenharmony_ci st->box.x = box->x; 511bf215546Sopenharmony_ci st->box.y = box->y; 512bf215546Sopenharmony_ci st->box.z = box->z; 513bf215546Sopenharmony_ci st->box.w = box->width; 514bf215546Sopenharmony_ci st->box.h = box->height; 515bf215546Sopenharmony_ci st->box.d = box->depth; 516bf215546Sopenharmony_ci 517bf215546Sopenharmony_ci switch (tex->b.target) { 518bf215546Sopenharmony_ci case PIPE_TEXTURE_CUBE: 519bf215546Sopenharmony_ci st->slice = st->base.box.z; 520bf215546Sopenharmony_ci st->box.z = 0; /* so we don't apply double offsets below */ 521bf215546Sopenharmony_ci break; 522bf215546Sopenharmony_ci case PIPE_TEXTURE_1D_ARRAY: 523bf215546Sopenharmony_ci case PIPE_TEXTURE_2D_ARRAY: 524bf215546Sopenharmony_ci case PIPE_TEXTURE_CUBE_ARRAY: 525bf215546Sopenharmony_ci st->slice = st->base.box.z; 526bf215546Sopenharmony_ci st->box.z = 0; /* so we don't apply double offsets below */ 527bf215546Sopenharmony_ci 528bf215546Sopenharmony_ci /* Force direct map for transfering multiple slices */ 529bf215546Sopenharmony_ci if (st->base.box.depth > 1) 530bf215546Sopenharmony_ci use_direct_map = svga_have_gb_objects(svga); 531bf215546Sopenharmony_ci 532bf215546Sopenharmony_ci break; 533bf215546Sopenharmony_ci default: 534bf215546Sopenharmony_ci st->slice = 0; 535bf215546Sopenharmony_ci break; 536bf215546Sopenharmony_ci } 537bf215546Sopenharmony_ci 538bf215546Sopenharmony_ci /* We never want to use DMA transfers on systems with GBObjects because 539bf215546Sopenharmony_ci * it causes serialization issues and in SVGAv3 vram is gone which 540bf215546Sopenharmony_ci * makes it impossible to support both at the same time. 541bf215546Sopenharmony_ci */ 542bf215546Sopenharmony_ci if (svga_have_gb_objects(svga)) { 543bf215546Sopenharmony_ci use_direct_map = TRUE; 544bf215546Sopenharmony_ci } 545bf215546Sopenharmony_ci 546bf215546Sopenharmony_ci st->use_direct_map = use_direct_map; 547bf215546Sopenharmony_ci pipe_resource_reference(&st->base.resource, texture); 548bf215546Sopenharmony_ci 549bf215546Sopenharmony_ci /* If this is the first time mapping to the surface in this 550bf215546Sopenharmony_ci * command buffer and there is no pending primitives, clear 551bf215546Sopenharmony_ci * the dirty masks of this surface. 552bf215546Sopenharmony_ci */ 553bf215546Sopenharmony_ci if (sws->surface_is_flushed(sws, surf) && 554bf215546Sopenharmony_ci (svga_have_vgpu10(svga) || 555bf215546Sopenharmony_ci !svga_hwtnl_has_pending_prim(svga->hwtnl))) { 556bf215546Sopenharmony_ci svga_clear_texture_dirty(tex); 557bf215546Sopenharmony_ci } 558bf215546Sopenharmony_ci 559bf215546Sopenharmony_ci if (!use_direct_map) { 560bf215546Sopenharmony_ci /* upload to the DMA buffer */ 561bf215546Sopenharmony_ci map = svga_texture_transfer_map_dma(svga, st); 562bf215546Sopenharmony_ci } 563bf215546Sopenharmony_ci else { 564bf215546Sopenharmony_ci boolean can_use_upload = tex->can_use_upload && 565bf215546Sopenharmony_ci !(st->base.usage & PIPE_MAP_READ); 566bf215546Sopenharmony_ci boolean was_rendered_to = 567bf215546Sopenharmony_ci svga_was_texture_rendered_to(svga_texture(texture)); 568bf215546Sopenharmony_ci 569bf215546Sopenharmony_ci /* If the texture was already rendered to and upload buffer 570bf215546Sopenharmony_ci * is supported, then we will use upload buffer to 571bf215546Sopenharmony_ci * avoid the need to read back the texture content; otherwise, 572bf215546Sopenharmony_ci * we'll first try to map directly to the GB surface, if it is blocked, 573bf215546Sopenharmony_ci * then we'll try the upload buffer. 574bf215546Sopenharmony_ci */ 575bf215546Sopenharmony_ci if (was_rendered_to && can_use_upload) { 576bf215546Sopenharmony_ci map = svga_texture_transfer_map_upload(svga, st); 577bf215546Sopenharmony_ci } 578bf215546Sopenharmony_ci else { 579bf215546Sopenharmony_ci unsigned orig_usage = st->base.usage; 580bf215546Sopenharmony_ci 581bf215546Sopenharmony_ci /* First try directly map to the GB surface */ 582bf215546Sopenharmony_ci if (can_use_upload) 583bf215546Sopenharmony_ci st->base.usage |= PIPE_MAP_DONTBLOCK; 584bf215546Sopenharmony_ci map = svga_texture_transfer_map_direct(svga, st); 585bf215546Sopenharmony_ci st->base.usage = orig_usage; 586bf215546Sopenharmony_ci 587bf215546Sopenharmony_ci if (!map && can_use_upload) { 588bf215546Sopenharmony_ci /* if direct map with DONTBLOCK fails, then try upload to the 589bf215546Sopenharmony_ci * texture upload buffer. 590bf215546Sopenharmony_ci */ 591bf215546Sopenharmony_ci map = svga_texture_transfer_map_upload(svga, st); 592bf215546Sopenharmony_ci } 593bf215546Sopenharmony_ci } 594bf215546Sopenharmony_ci 595bf215546Sopenharmony_ci /* If upload fails, then try direct map again without forcing it 596bf215546Sopenharmony_ci * to DONTBLOCK. 597bf215546Sopenharmony_ci */ 598bf215546Sopenharmony_ci if (!map) { 599bf215546Sopenharmony_ci map = svga_texture_transfer_map_direct(svga, st); 600bf215546Sopenharmony_ci } 601bf215546Sopenharmony_ci } 602bf215546Sopenharmony_ci 603bf215546Sopenharmony_ci if (!map) { 604bf215546Sopenharmony_ci FREE(st); 605bf215546Sopenharmony_ci } 606bf215546Sopenharmony_ci else { 607bf215546Sopenharmony_ci *ptransfer = &st->base; 608bf215546Sopenharmony_ci svga->hud.num_textures_mapped++; 609bf215546Sopenharmony_ci if (usage & PIPE_MAP_WRITE) { 610bf215546Sopenharmony_ci /* record texture upload for HUD */ 611bf215546Sopenharmony_ci svga->hud.num_bytes_uploaded += 612bf215546Sopenharmony_ci st->base.layer_stride * st->box.d; 613bf215546Sopenharmony_ci 614bf215546Sopenharmony_ci /* mark this texture level as dirty */ 615bf215546Sopenharmony_ci svga_set_texture_dirty(tex, st->slice, level); 616bf215546Sopenharmony_ci } 617bf215546Sopenharmony_ci } 618bf215546Sopenharmony_ci 619bf215546Sopenharmony_cidone: 620bf215546Sopenharmony_ci svga->hud.map_buffer_time += (svga_get_time(svga) - begin); 621bf215546Sopenharmony_ci SVGA_STATS_TIME_POP(sws); 622bf215546Sopenharmony_ci (void) sws; 623bf215546Sopenharmony_ci 624bf215546Sopenharmony_ci return map; 625bf215546Sopenharmony_ci} 626bf215546Sopenharmony_ci 627bf215546Sopenharmony_ci/** 628bf215546Sopenharmony_ci * Unmap a GB texture surface. 629bf215546Sopenharmony_ci */ 630bf215546Sopenharmony_cistatic void 631bf215546Sopenharmony_cisvga_texture_surface_unmap(struct svga_context *svga, 632bf215546Sopenharmony_ci struct pipe_transfer *transfer) 633bf215546Sopenharmony_ci{ 634bf215546Sopenharmony_ci struct svga_winsys_surface *surf = svga_texture(transfer->resource)->handle; 635bf215546Sopenharmony_ci struct svga_winsys_context *swc = svga->swc; 636bf215546Sopenharmony_ci boolean rebind; 637bf215546Sopenharmony_ci 638bf215546Sopenharmony_ci assert(surf); 639bf215546Sopenharmony_ci 640bf215546Sopenharmony_ci swc->surface_unmap(swc, surf, &rebind); 641bf215546Sopenharmony_ci if (rebind) { 642bf215546Sopenharmony_ci SVGA_RETRY(svga, SVGA3D_BindGBSurface(swc, surf)); 643bf215546Sopenharmony_ci } 644bf215546Sopenharmony_ci} 645bf215546Sopenharmony_ci 646bf215546Sopenharmony_ci 647bf215546Sopenharmony_cistatic void 648bf215546Sopenharmony_ciupdate_image_vgpu9(struct svga_context *svga, 649bf215546Sopenharmony_ci struct svga_winsys_surface *surf, 650bf215546Sopenharmony_ci const SVGA3dBox *box, 651bf215546Sopenharmony_ci unsigned slice, 652bf215546Sopenharmony_ci unsigned level) 653bf215546Sopenharmony_ci{ 654bf215546Sopenharmony_ci SVGA_RETRY(svga, SVGA3D_UpdateGBImage(svga->swc, surf, box, slice, level)); 655bf215546Sopenharmony_ci} 656bf215546Sopenharmony_ci 657bf215546Sopenharmony_ci 658bf215546Sopenharmony_cistatic void 659bf215546Sopenharmony_ciupdate_image_vgpu10(struct svga_context *svga, 660bf215546Sopenharmony_ci struct svga_winsys_surface *surf, 661bf215546Sopenharmony_ci const SVGA3dBox *box, 662bf215546Sopenharmony_ci unsigned slice, 663bf215546Sopenharmony_ci unsigned level, 664bf215546Sopenharmony_ci unsigned numMipLevels) 665bf215546Sopenharmony_ci{ 666bf215546Sopenharmony_ci unsigned subResource; 667bf215546Sopenharmony_ci 668bf215546Sopenharmony_ci subResource = slice * numMipLevels + level; 669bf215546Sopenharmony_ci 670bf215546Sopenharmony_ci SVGA_RETRY(svga, SVGA3D_vgpu10_UpdateSubResource(svga->swc, surf, box, 671bf215546Sopenharmony_ci subResource)); 672bf215546Sopenharmony_ci} 673bf215546Sopenharmony_ci 674bf215546Sopenharmony_ci 675bf215546Sopenharmony_ci/** 676bf215546Sopenharmony_ci * unmap DMA transfer request 677bf215546Sopenharmony_ci */ 678bf215546Sopenharmony_cistatic void 679bf215546Sopenharmony_cisvga_texture_transfer_unmap_dma(struct svga_context *svga, 680bf215546Sopenharmony_ci struct svga_transfer *st) 681bf215546Sopenharmony_ci{ 682bf215546Sopenharmony_ci struct svga_winsys_screen *sws = svga_screen(svga->pipe.screen)->sws; 683bf215546Sopenharmony_ci 684bf215546Sopenharmony_ci if (!st->swbuf) 685bf215546Sopenharmony_ci sws->buffer_unmap(sws, st->hwbuf); 686bf215546Sopenharmony_ci 687bf215546Sopenharmony_ci if (st->base.usage & PIPE_MAP_WRITE) { 688bf215546Sopenharmony_ci /* Use DMA to transfer texture data */ 689bf215546Sopenharmony_ci SVGA3dSurfaceDMAFlags flags; 690bf215546Sopenharmony_ci struct pipe_resource *texture = st->base.resource; 691bf215546Sopenharmony_ci struct svga_texture *tex = svga_texture(texture); 692bf215546Sopenharmony_ci 693bf215546Sopenharmony_ci 694bf215546Sopenharmony_ci memset(&flags, 0, sizeof flags); 695bf215546Sopenharmony_ci if (st->base.usage & PIPE_MAP_DISCARD_WHOLE_RESOURCE) { 696bf215546Sopenharmony_ci flags.discard = TRUE; 697bf215546Sopenharmony_ci } 698bf215546Sopenharmony_ci if (st->base.usage & PIPE_MAP_UNSYNCHRONIZED) { 699bf215546Sopenharmony_ci flags.unsynchronized = TRUE; 700bf215546Sopenharmony_ci } 701bf215546Sopenharmony_ci 702bf215546Sopenharmony_ci svga_transfer_dma(svga, st, SVGA3D_WRITE_HOST_VRAM, flags); 703bf215546Sopenharmony_ci svga_set_texture_rendered_to(tex); 704bf215546Sopenharmony_ci } 705bf215546Sopenharmony_ci 706bf215546Sopenharmony_ci FREE(st->swbuf); 707bf215546Sopenharmony_ci sws->buffer_destroy(sws, st->hwbuf); 708bf215546Sopenharmony_ci} 709bf215546Sopenharmony_ci 710bf215546Sopenharmony_ci 711bf215546Sopenharmony_ci/** 712bf215546Sopenharmony_ci * unmap direct map transfer request 713bf215546Sopenharmony_ci */ 714bf215546Sopenharmony_cistatic void 715bf215546Sopenharmony_cisvga_texture_transfer_unmap_direct(struct svga_context *svga, 716bf215546Sopenharmony_ci struct svga_transfer *st) 717bf215546Sopenharmony_ci{ 718bf215546Sopenharmony_ci struct pipe_transfer *transfer = &st->base; 719bf215546Sopenharmony_ci struct svga_texture *tex = svga_texture(transfer->resource); 720bf215546Sopenharmony_ci 721bf215546Sopenharmony_ci svga_texture_surface_unmap(svga, transfer); 722bf215546Sopenharmony_ci 723bf215546Sopenharmony_ci /* Now send an update command to update the content in the backend. */ 724bf215546Sopenharmony_ci if (st->base.usage & PIPE_MAP_WRITE) { 725bf215546Sopenharmony_ci struct svga_winsys_surface *surf = tex->handle; 726bf215546Sopenharmony_ci 727bf215546Sopenharmony_ci assert(svga_have_gb_objects(svga)); 728bf215546Sopenharmony_ci 729bf215546Sopenharmony_ci /* update the effected region */ 730bf215546Sopenharmony_ci SVGA3dBox box = st->box; 731bf215546Sopenharmony_ci unsigned nlayers; 732bf215546Sopenharmony_ci 733bf215546Sopenharmony_ci switch (tex->b.target) { 734bf215546Sopenharmony_ci case PIPE_TEXTURE_2D_ARRAY: 735bf215546Sopenharmony_ci case PIPE_TEXTURE_CUBE_ARRAY: 736bf215546Sopenharmony_ci case PIPE_TEXTURE_1D_ARRAY: 737bf215546Sopenharmony_ci nlayers = box.d; 738bf215546Sopenharmony_ci box.d = 1; 739bf215546Sopenharmony_ci break; 740bf215546Sopenharmony_ci default: 741bf215546Sopenharmony_ci nlayers = 1; 742bf215546Sopenharmony_ci break; 743bf215546Sopenharmony_ci } 744bf215546Sopenharmony_ci 745bf215546Sopenharmony_ci 746bf215546Sopenharmony_ci if (0) 747bf215546Sopenharmony_ci debug_printf("%s %d, %d, %d %d x %d x %d\n", 748bf215546Sopenharmony_ci __FUNCTION__, 749bf215546Sopenharmony_ci box.x, box.y, box.z, 750bf215546Sopenharmony_ci box.w, box.h, box.d); 751bf215546Sopenharmony_ci 752bf215546Sopenharmony_ci if (!svga->swc->force_coherent || tex->imported) { 753bf215546Sopenharmony_ci if (svga_have_vgpu10(svga)) { 754bf215546Sopenharmony_ci unsigned i; 755bf215546Sopenharmony_ci 756bf215546Sopenharmony_ci for (i = 0; i < nlayers; i++) { 757bf215546Sopenharmony_ci update_image_vgpu10(svga, surf, &box, 758bf215546Sopenharmony_ci st->slice + i, transfer->level, 759bf215546Sopenharmony_ci tex->b.last_level + 1); 760bf215546Sopenharmony_ci } 761bf215546Sopenharmony_ci } else { 762bf215546Sopenharmony_ci assert(nlayers == 1); 763bf215546Sopenharmony_ci update_image_vgpu9(svga, surf, &box, st->slice, 764bf215546Sopenharmony_ci transfer->level); 765bf215546Sopenharmony_ci } 766bf215546Sopenharmony_ci } 767bf215546Sopenharmony_ci 768bf215546Sopenharmony_ci /* Mark the texture surface state as UPDATED */ 769bf215546Sopenharmony_ci tex->surface_state = SVGA_SURFACE_STATE_UPDATED; 770bf215546Sopenharmony_ci } 771bf215546Sopenharmony_ci} 772bf215546Sopenharmony_ci 773bf215546Sopenharmony_ci 774bf215546Sopenharmony_civoid 775bf215546Sopenharmony_cisvga_texture_transfer_unmap(struct pipe_context *pipe, 776bf215546Sopenharmony_ci struct pipe_transfer *transfer) 777bf215546Sopenharmony_ci{ 778bf215546Sopenharmony_ci struct svga_context *svga = svga_context(pipe); 779bf215546Sopenharmony_ci struct svga_screen *ss = svga_screen(pipe->screen); 780bf215546Sopenharmony_ci struct svga_winsys_screen *sws = ss->sws; 781bf215546Sopenharmony_ci struct svga_transfer *st = svga_transfer(transfer); 782bf215546Sopenharmony_ci struct svga_texture *tex = svga_texture(transfer->resource); 783bf215546Sopenharmony_ci 784bf215546Sopenharmony_ci SVGA_STATS_TIME_PUSH(sws, SVGA_STATS_TIME_TEXTRANSFERUNMAP); 785bf215546Sopenharmony_ci 786bf215546Sopenharmony_ci if (!st->use_direct_map) { 787bf215546Sopenharmony_ci svga_texture_transfer_unmap_dma(svga, st); 788bf215546Sopenharmony_ci } 789bf215546Sopenharmony_ci else if (st->upload.buf) { 790bf215546Sopenharmony_ci svga_texture_transfer_unmap_upload(svga, st); 791bf215546Sopenharmony_ci } 792bf215546Sopenharmony_ci else { 793bf215546Sopenharmony_ci svga_texture_transfer_unmap_direct(svga, st); 794bf215546Sopenharmony_ci } 795bf215546Sopenharmony_ci 796bf215546Sopenharmony_ci if (st->base.usage & PIPE_MAP_WRITE) { 797bf215546Sopenharmony_ci svga->hud.num_resource_updates++; 798bf215546Sopenharmony_ci 799bf215546Sopenharmony_ci /* Mark the texture level as dirty */ 800bf215546Sopenharmony_ci ss->texture_timestamp++; 801bf215546Sopenharmony_ci svga_age_texture_view(tex, transfer->level); 802bf215546Sopenharmony_ci if (transfer->resource->target == PIPE_TEXTURE_CUBE) 803bf215546Sopenharmony_ci svga_define_texture_level(tex, st->slice, transfer->level); 804bf215546Sopenharmony_ci else 805bf215546Sopenharmony_ci svga_define_texture_level(tex, 0, transfer->level); 806bf215546Sopenharmony_ci } 807bf215546Sopenharmony_ci 808bf215546Sopenharmony_ci pipe_resource_reference(&st->base.resource, NULL); 809bf215546Sopenharmony_ci FREE(st); 810bf215546Sopenharmony_ci SVGA_STATS_TIME_POP(sws); 811bf215546Sopenharmony_ci (void) sws; 812bf215546Sopenharmony_ci} 813bf215546Sopenharmony_ci 814bf215546Sopenharmony_ci 815bf215546Sopenharmony_ci/** 816bf215546Sopenharmony_ci * Does format store depth values? 817bf215546Sopenharmony_ci */ 818bf215546Sopenharmony_cistatic inline boolean 819bf215546Sopenharmony_ciformat_has_depth(enum pipe_format format) 820bf215546Sopenharmony_ci{ 821bf215546Sopenharmony_ci const struct util_format_description *desc = util_format_description(format); 822bf215546Sopenharmony_ci return util_format_has_depth(desc); 823bf215546Sopenharmony_ci} 824bf215546Sopenharmony_ci 825bf215546Sopenharmony_cistruct pipe_resource * 826bf215546Sopenharmony_cisvga_texture_create(struct pipe_screen *screen, 827bf215546Sopenharmony_ci const struct pipe_resource *template) 828bf215546Sopenharmony_ci{ 829bf215546Sopenharmony_ci struct svga_screen *svgascreen = svga_screen(screen); 830bf215546Sopenharmony_ci struct svga_texture *tex; 831bf215546Sopenharmony_ci unsigned bindings = template->bind; 832bf215546Sopenharmony_ci 833bf215546Sopenharmony_ci SVGA_STATS_TIME_PUSH(svgascreen->sws, 834bf215546Sopenharmony_ci SVGA_STATS_TIME_CREATETEXTURE); 835bf215546Sopenharmony_ci 836bf215546Sopenharmony_ci assert(template->last_level < SVGA_MAX_TEXTURE_LEVELS); 837bf215546Sopenharmony_ci if (template->last_level >= SVGA_MAX_TEXTURE_LEVELS) { 838bf215546Sopenharmony_ci goto fail_notex; 839bf215546Sopenharmony_ci } 840bf215546Sopenharmony_ci 841bf215546Sopenharmony_ci /* Verify the number of mipmap levels isn't impossibly large. For example, 842bf215546Sopenharmony_ci * if the base 2D image is 16x16, we can't have 8 mipmap levels. 843bf215546Sopenharmony_ci * the gallium frontend should never ask us to create a resource with invalid 844bf215546Sopenharmony_ci * parameters. 845bf215546Sopenharmony_ci */ 846bf215546Sopenharmony_ci { 847bf215546Sopenharmony_ci unsigned max_dim = template->width0; 848bf215546Sopenharmony_ci 849bf215546Sopenharmony_ci switch (template->target) { 850bf215546Sopenharmony_ci case PIPE_TEXTURE_1D: 851bf215546Sopenharmony_ci case PIPE_TEXTURE_1D_ARRAY: 852bf215546Sopenharmony_ci // nothing 853bf215546Sopenharmony_ci break; 854bf215546Sopenharmony_ci case PIPE_TEXTURE_2D: 855bf215546Sopenharmony_ci case PIPE_TEXTURE_CUBE: 856bf215546Sopenharmony_ci case PIPE_TEXTURE_CUBE_ARRAY: 857bf215546Sopenharmony_ci case PIPE_TEXTURE_2D_ARRAY: 858bf215546Sopenharmony_ci max_dim = MAX2(max_dim, template->height0); 859bf215546Sopenharmony_ci break; 860bf215546Sopenharmony_ci case PIPE_TEXTURE_3D: 861bf215546Sopenharmony_ci max_dim = MAX3(max_dim, template->height0, template->depth0); 862bf215546Sopenharmony_ci break; 863bf215546Sopenharmony_ci case PIPE_TEXTURE_RECT: 864bf215546Sopenharmony_ci case PIPE_BUFFER: 865bf215546Sopenharmony_ci assert(template->last_level == 0); 866bf215546Sopenharmony_ci /* the assertion below should always pass */ 867bf215546Sopenharmony_ci break; 868bf215546Sopenharmony_ci default: 869bf215546Sopenharmony_ci debug_printf("Unexpected texture target type\n"); 870bf215546Sopenharmony_ci } 871bf215546Sopenharmony_ci assert(1 << template->last_level <= max_dim); 872bf215546Sopenharmony_ci } 873bf215546Sopenharmony_ci 874bf215546Sopenharmony_ci tex = CALLOC_STRUCT(svga_texture); 875bf215546Sopenharmony_ci if (!tex) { 876bf215546Sopenharmony_ci goto fail_notex; 877bf215546Sopenharmony_ci } 878bf215546Sopenharmony_ci 879bf215546Sopenharmony_ci tex->defined = CALLOC(template->depth0 * template->array_size, 880bf215546Sopenharmony_ci sizeof(tex->defined[0])); 881bf215546Sopenharmony_ci if (!tex->defined) { 882bf215546Sopenharmony_ci FREE(tex); 883bf215546Sopenharmony_ci goto fail_notex; 884bf215546Sopenharmony_ci } 885bf215546Sopenharmony_ci 886bf215546Sopenharmony_ci tex->dirty = CALLOC(template->depth0 * template->array_size, 887bf215546Sopenharmony_ci sizeof(tex->dirty[0])); 888bf215546Sopenharmony_ci if (!tex->dirty) { 889bf215546Sopenharmony_ci goto fail; 890bf215546Sopenharmony_ci } 891bf215546Sopenharmony_ci 892bf215546Sopenharmony_ci tex->b = *template; 893bf215546Sopenharmony_ci pipe_reference_init(&tex->b.reference, 1); 894bf215546Sopenharmony_ci tex->b.screen = screen; 895bf215546Sopenharmony_ci 896bf215546Sopenharmony_ci tex->key.flags = 0; 897bf215546Sopenharmony_ci tex->key.size.width = template->width0; 898bf215546Sopenharmony_ci tex->key.size.height = template->height0; 899bf215546Sopenharmony_ci tex->key.size.depth = template->depth0; 900bf215546Sopenharmony_ci tex->key.arraySize = 1; 901bf215546Sopenharmony_ci tex->key.numFaces = 1; 902bf215546Sopenharmony_ci 903bf215546Sopenharmony_ci /* nr_samples=1 must be treated as a non-multisample texture */ 904bf215546Sopenharmony_ci if (tex->b.nr_samples == 1) { 905bf215546Sopenharmony_ci tex->b.nr_samples = 0; 906bf215546Sopenharmony_ci } 907bf215546Sopenharmony_ci else if (tex->b.nr_samples > 1) { 908bf215546Sopenharmony_ci assert(svgascreen->sws->have_sm4_1); 909bf215546Sopenharmony_ci tex->key.flags |= SVGA3D_SURFACE_MULTISAMPLE; 910bf215546Sopenharmony_ci } 911bf215546Sopenharmony_ci 912bf215546Sopenharmony_ci tex->key.sampleCount = tex->b.nr_samples; 913bf215546Sopenharmony_ci 914bf215546Sopenharmony_ci if (svgascreen->sws->have_vgpu10) { 915bf215546Sopenharmony_ci switch (template->target) { 916bf215546Sopenharmony_ci case PIPE_TEXTURE_1D: 917bf215546Sopenharmony_ci tex->key.flags |= SVGA3D_SURFACE_1D; 918bf215546Sopenharmony_ci break; 919bf215546Sopenharmony_ci case PIPE_TEXTURE_1D_ARRAY: 920bf215546Sopenharmony_ci tex->key.flags |= SVGA3D_SURFACE_1D; 921bf215546Sopenharmony_ci FALLTHROUGH; 922bf215546Sopenharmony_ci case PIPE_TEXTURE_2D_ARRAY: 923bf215546Sopenharmony_ci tex->key.flags |= SVGA3D_SURFACE_ARRAY; 924bf215546Sopenharmony_ci tex->key.arraySize = template->array_size; 925bf215546Sopenharmony_ci break; 926bf215546Sopenharmony_ci case PIPE_TEXTURE_3D: 927bf215546Sopenharmony_ci tex->key.flags |= SVGA3D_SURFACE_VOLUME; 928bf215546Sopenharmony_ci break; 929bf215546Sopenharmony_ci case PIPE_TEXTURE_CUBE: 930bf215546Sopenharmony_ci tex->key.flags |= (SVGA3D_SURFACE_CUBEMAP | SVGA3D_SURFACE_ARRAY); 931bf215546Sopenharmony_ci tex->key.numFaces = 6; 932bf215546Sopenharmony_ci break; 933bf215546Sopenharmony_ci case PIPE_TEXTURE_CUBE_ARRAY: 934bf215546Sopenharmony_ci assert(svgascreen->sws->have_sm4_1); 935bf215546Sopenharmony_ci tex->key.flags |= (SVGA3D_SURFACE_CUBEMAP | SVGA3D_SURFACE_ARRAY); 936bf215546Sopenharmony_ci tex->key.numFaces = 1; // arraySize already includes the 6 faces 937bf215546Sopenharmony_ci tex->key.arraySize = template->array_size; 938bf215546Sopenharmony_ci break; 939bf215546Sopenharmony_ci default: 940bf215546Sopenharmony_ci break; 941bf215546Sopenharmony_ci } 942bf215546Sopenharmony_ci } 943bf215546Sopenharmony_ci else { 944bf215546Sopenharmony_ci switch (template->target) { 945bf215546Sopenharmony_ci case PIPE_TEXTURE_3D: 946bf215546Sopenharmony_ci tex->key.flags |= SVGA3D_SURFACE_VOLUME; 947bf215546Sopenharmony_ci break; 948bf215546Sopenharmony_ci case PIPE_TEXTURE_CUBE: 949bf215546Sopenharmony_ci tex->key.flags |= SVGA3D_SURFACE_CUBEMAP; 950bf215546Sopenharmony_ci tex->key.numFaces = 6; 951bf215546Sopenharmony_ci break; 952bf215546Sopenharmony_ci default: 953bf215546Sopenharmony_ci break; 954bf215546Sopenharmony_ci } 955bf215546Sopenharmony_ci } 956bf215546Sopenharmony_ci 957bf215546Sopenharmony_ci tex->key.cachable = 1; 958bf215546Sopenharmony_ci 959bf215546Sopenharmony_ci if ((bindings & (PIPE_BIND_RENDER_TARGET | PIPE_BIND_DEPTH_STENCIL)) && 960bf215546Sopenharmony_ci !(bindings & PIPE_BIND_SAMPLER_VIEW)) { 961bf215546Sopenharmony_ci /* Also check if the format can be sampled from */ 962bf215546Sopenharmony_ci if (screen->is_format_supported(screen, template->format, 963bf215546Sopenharmony_ci template->target, 964bf215546Sopenharmony_ci template->nr_samples, 965bf215546Sopenharmony_ci template->nr_storage_samples, 966bf215546Sopenharmony_ci PIPE_BIND_SAMPLER_VIEW)) { 967bf215546Sopenharmony_ci bindings |= PIPE_BIND_SAMPLER_VIEW; 968bf215546Sopenharmony_ci } 969bf215546Sopenharmony_ci } 970bf215546Sopenharmony_ci 971bf215546Sopenharmony_ci if (bindings & PIPE_BIND_SAMPLER_VIEW) { 972bf215546Sopenharmony_ci tex->key.flags |= SVGA3D_SURFACE_HINT_TEXTURE; 973bf215546Sopenharmony_ci tex->key.flags |= SVGA3D_SURFACE_BIND_SHADER_RESOURCE; 974bf215546Sopenharmony_ci 975bf215546Sopenharmony_ci if (!(bindings & PIPE_BIND_RENDER_TARGET)) { 976bf215546Sopenharmony_ci /* Also check if the format is color renderable */ 977bf215546Sopenharmony_ci if (screen->is_format_supported(screen, template->format, 978bf215546Sopenharmony_ci template->target, 979bf215546Sopenharmony_ci template->nr_samples, 980bf215546Sopenharmony_ci template->nr_storage_samples, 981bf215546Sopenharmony_ci PIPE_BIND_RENDER_TARGET)) { 982bf215546Sopenharmony_ci bindings |= PIPE_BIND_RENDER_TARGET; 983bf215546Sopenharmony_ci } 984bf215546Sopenharmony_ci } 985bf215546Sopenharmony_ci 986bf215546Sopenharmony_ci if (!(bindings & PIPE_BIND_DEPTH_STENCIL)) { 987bf215546Sopenharmony_ci /* Also check if the format is depth/stencil renderable */ 988bf215546Sopenharmony_ci if (screen->is_format_supported(screen, template->format, 989bf215546Sopenharmony_ci template->target, 990bf215546Sopenharmony_ci template->nr_samples, 991bf215546Sopenharmony_ci template->nr_storage_samples, 992bf215546Sopenharmony_ci PIPE_BIND_DEPTH_STENCIL)) { 993bf215546Sopenharmony_ci bindings |= PIPE_BIND_DEPTH_STENCIL; 994bf215546Sopenharmony_ci } 995bf215546Sopenharmony_ci } 996bf215546Sopenharmony_ci } 997bf215546Sopenharmony_ci 998bf215546Sopenharmony_ci if (bindings & PIPE_BIND_DISPLAY_TARGET) { 999bf215546Sopenharmony_ci tex->key.cachable = 0; 1000bf215546Sopenharmony_ci } 1001bf215546Sopenharmony_ci 1002bf215546Sopenharmony_ci if (bindings & PIPE_BIND_SHARED) { 1003bf215546Sopenharmony_ci tex->key.cachable = 0; 1004bf215546Sopenharmony_ci } 1005bf215546Sopenharmony_ci 1006bf215546Sopenharmony_ci if (bindings & (PIPE_BIND_SCANOUT | PIPE_BIND_CURSOR)) { 1007bf215546Sopenharmony_ci tex->key.scanout = 1; 1008bf215546Sopenharmony_ci tex->key.cachable = 0; 1009bf215546Sopenharmony_ci } 1010bf215546Sopenharmony_ci 1011bf215546Sopenharmony_ci /* 1012bf215546Sopenharmony_ci * Note: Previously we never passed the 1013bf215546Sopenharmony_ci * SVGA3D_SURFACE_HINT_RENDERTARGET hint. Mesa cannot 1014bf215546Sopenharmony_ci * know beforehand whether a texture will be used as a rendertarget or not 1015bf215546Sopenharmony_ci * and it always requests PIPE_BIND_RENDER_TARGET, therefore 1016bf215546Sopenharmony_ci * passing the SVGA3D_SURFACE_HINT_RENDERTARGET here defeats its purpose. 1017bf215546Sopenharmony_ci * 1018bf215546Sopenharmony_ci * However, this was changed since other gallium frontends 1019bf215546Sopenharmony_ci * (XA for example) uses it accurately and certain device versions 1020bf215546Sopenharmony_ci * relies on it in certain situations to render correctly. 1021bf215546Sopenharmony_ci */ 1022bf215546Sopenharmony_ci if ((bindings & PIPE_BIND_RENDER_TARGET) && 1023bf215546Sopenharmony_ci !util_format_is_s3tc(template->format)) { 1024bf215546Sopenharmony_ci tex->key.flags |= SVGA3D_SURFACE_HINT_RENDERTARGET; 1025bf215546Sopenharmony_ci tex->key.flags |= SVGA3D_SURFACE_BIND_RENDER_TARGET; 1026bf215546Sopenharmony_ci } 1027bf215546Sopenharmony_ci 1028bf215546Sopenharmony_ci if (bindings & PIPE_BIND_DEPTH_STENCIL) { 1029bf215546Sopenharmony_ci tex->key.flags |= SVGA3D_SURFACE_HINT_DEPTHSTENCIL; 1030bf215546Sopenharmony_ci tex->key.flags |= SVGA3D_SURFACE_BIND_DEPTH_STENCIL; 1031bf215546Sopenharmony_ci } 1032bf215546Sopenharmony_ci 1033bf215546Sopenharmony_ci tex->key.numMipLevels = template->last_level + 1; 1034bf215546Sopenharmony_ci 1035bf215546Sopenharmony_ci tex->key.format = svga_translate_format(svgascreen, template->format, 1036bf215546Sopenharmony_ci bindings); 1037bf215546Sopenharmony_ci if (tex->key.format == SVGA3D_FORMAT_INVALID) { 1038bf215546Sopenharmony_ci goto fail; 1039bf215546Sopenharmony_ci } 1040bf215546Sopenharmony_ci 1041bf215546Sopenharmony_ci bool use_typeless = FALSE; 1042bf215546Sopenharmony_ci if (svgascreen->sws->have_gl43) { 1043bf215546Sopenharmony_ci /* Do not use typeless for SHARED, SCANOUT or DISPLAY_TARGET surfaces. */ 1044bf215546Sopenharmony_ci use_typeless = !(bindings & (PIPE_BIND_SHARED | PIPE_BIND_SCANOUT | 1045bf215546Sopenharmony_ci PIPE_BIND_DISPLAY_TARGET)); 1046bf215546Sopenharmony_ci } else if (svgascreen->sws->have_vgpu10) { 1047bf215546Sopenharmony_ci /* For VGPU10 device, use typeless formats only for sRGB and depth resources 1048bf215546Sopenharmony_ci * if they do not have SHARED, SCANOUT or DISPLAY_TARGET bind flags 1049bf215546Sopenharmony_ci */ 1050bf215546Sopenharmony_ci use_typeless = (util_format_is_srgb(template->format) || 1051bf215546Sopenharmony_ci format_has_depth(template->format)) && 1052bf215546Sopenharmony_ci !(bindings & (PIPE_BIND_SHARED | PIPE_BIND_SCANOUT | 1053bf215546Sopenharmony_ci PIPE_BIND_DISPLAY_TARGET)); 1054bf215546Sopenharmony_ci } 1055bf215546Sopenharmony_ci 1056bf215546Sopenharmony_ci if (use_typeless) { 1057bf215546Sopenharmony_ci SVGA3dSurfaceFormat typeless = svga_typeless_format(tex->key.format); 1058bf215546Sopenharmony_ci if (0) { 1059bf215546Sopenharmony_ci debug_printf("Convert resource type %s -> %s (bind 0x%x)\n", 1060bf215546Sopenharmony_ci svga_format_name(tex->key.format), 1061bf215546Sopenharmony_ci svga_format_name(typeless), 1062bf215546Sopenharmony_ci bindings); 1063bf215546Sopenharmony_ci } 1064bf215546Sopenharmony_ci 1065bf215546Sopenharmony_ci if (svga_format_is_uncompressed_snorm(tex->key.format)) { 1066bf215546Sopenharmony_ci /* We can't normally render to snorm surfaces, but once we 1067bf215546Sopenharmony_ci * substitute a typeless format, we can if the rendertarget view 1068bf215546Sopenharmony_ci * is unorm. This can happen with GL_ARB_copy_image. 1069bf215546Sopenharmony_ci */ 1070bf215546Sopenharmony_ci tex->key.flags |= SVGA3D_SURFACE_HINT_RENDERTARGET; 1071bf215546Sopenharmony_ci tex->key.flags |= SVGA3D_SURFACE_BIND_RENDER_TARGET; 1072bf215546Sopenharmony_ci } 1073bf215546Sopenharmony_ci 1074bf215546Sopenharmony_ci tex->key.format = typeless; 1075bf215546Sopenharmony_ci } 1076bf215546Sopenharmony_ci 1077bf215546Sopenharmony_ci if (svgascreen->sws->have_sm5 && 1078bf215546Sopenharmony_ci bindings & (PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET)) { 1079bf215546Sopenharmony_ci if (template->nr_samples < 2 && 1080bf215546Sopenharmony_ci screen->is_format_supported(screen, template->format, 1081bf215546Sopenharmony_ci template->target, 1082bf215546Sopenharmony_ci template->nr_samples, 1083bf215546Sopenharmony_ci template->nr_storage_samples, 1084bf215546Sopenharmony_ci PIPE_BIND_SHADER_IMAGE)) { 1085bf215546Sopenharmony_ci /* Any non multi-samples texture that can be used as a render target 1086bf215546Sopenharmony_ci * or sampler view can be bound to an image unit. 1087bf215546Sopenharmony_ci * So make sure to set the UAV flag here. 1088bf215546Sopenharmony_ci */ 1089bf215546Sopenharmony_ci tex->key.flags |= SVGA3D_SURFACE_BIND_UAVIEW; 1090bf215546Sopenharmony_ci } 1091bf215546Sopenharmony_ci } 1092bf215546Sopenharmony_ci 1093bf215546Sopenharmony_ci SVGA_DBG(DEBUG_DMA, "surface_create for texture\n"); 1094bf215546Sopenharmony_ci boolean invalidated; 1095bf215546Sopenharmony_ci tex->handle = svga_screen_surface_create(svgascreen, bindings, 1096bf215546Sopenharmony_ci tex->b.usage, 1097bf215546Sopenharmony_ci &invalidated, &tex->key); 1098bf215546Sopenharmony_ci if (!tex->handle) { 1099bf215546Sopenharmony_ci goto fail; 1100bf215546Sopenharmony_ci } 1101bf215546Sopenharmony_ci if (invalidated) { 1102bf215546Sopenharmony_ci tex->surface_state = SVGA_SURFACE_STATE_INVALIDATED; 1103bf215546Sopenharmony_ci } else { 1104bf215546Sopenharmony_ci tex->surface_state = SVGA_SURFACE_STATE_CREATED; 1105bf215546Sopenharmony_ci } 1106bf215546Sopenharmony_ci 1107bf215546Sopenharmony_ci SVGA_DBG(DEBUG_DMA, " --> got sid %p (texture)\n", tex->handle); 1108bf215546Sopenharmony_ci 1109bf215546Sopenharmony_ci debug_reference(&tex->b.reference, 1110bf215546Sopenharmony_ci (debug_reference_descriptor)debug_describe_resource, 0); 1111bf215546Sopenharmony_ci 1112bf215546Sopenharmony_ci tex->size = util_resource_size(template); 1113bf215546Sopenharmony_ci 1114bf215546Sopenharmony_ci /* Determine if texture upload buffer can be used to upload this texture */ 1115bf215546Sopenharmony_ci tex->can_use_upload = svga_texture_transfer_map_can_upload(svgascreen, 1116bf215546Sopenharmony_ci &tex->b); 1117bf215546Sopenharmony_ci 1118bf215546Sopenharmony_ci /* Initialize the backing resource cache */ 1119bf215546Sopenharmony_ci tex->backed_handle = NULL; 1120bf215546Sopenharmony_ci 1121bf215546Sopenharmony_ci svgascreen->hud.total_resource_bytes += tex->size; 1122bf215546Sopenharmony_ci svgascreen->hud.num_resources++; 1123bf215546Sopenharmony_ci 1124bf215546Sopenharmony_ci SVGA_STATS_TIME_POP(svgascreen->sws); 1125bf215546Sopenharmony_ci 1126bf215546Sopenharmony_ci return &tex->b; 1127bf215546Sopenharmony_ci 1128bf215546Sopenharmony_cifail: 1129bf215546Sopenharmony_ci if (tex->dirty) 1130bf215546Sopenharmony_ci FREE(tex->dirty); 1131bf215546Sopenharmony_ci if (tex->defined) 1132bf215546Sopenharmony_ci FREE(tex->defined); 1133bf215546Sopenharmony_ci FREE(tex); 1134bf215546Sopenharmony_cifail_notex: 1135bf215546Sopenharmony_ci SVGA_STATS_TIME_POP(svgascreen->sws); 1136bf215546Sopenharmony_ci return NULL; 1137bf215546Sopenharmony_ci} 1138bf215546Sopenharmony_ci 1139bf215546Sopenharmony_ci 1140bf215546Sopenharmony_cistruct pipe_resource * 1141bf215546Sopenharmony_cisvga_texture_from_handle(struct pipe_screen *screen, 1142bf215546Sopenharmony_ci const struct pipe_resource *template, 1143bf215546Sopenharmony_ci struct winsys_handle *whandle) 1144bf215546Sopenharmony_ci{ 1145bf215546Sopenharmony_ci struct svga_winsys_screen *sws = svga_winsys_screen(screen); 1146bf215546Sopenharmony_ci struct svga_screen *ss = svga_screen(screen); 1147bf215546Sopenharmony_ci struct svga_winsys_surface *srf; 1148bf215546Sopenharmony_ci struct svga_texture *tex; 1149bf215546Sopenharmony_ci enum SVGA3dSurfaceFormat format = 0; 1150bf215546Sopenharmony_ci assert(screen); 1151bf215546Sopenharmony_ci 1152bf215546Sopenharmony_ci /* Only supports one type */ 1153bf215546Sopenharmony_ci if ((template->target != PIPE_TEXTURE_2D && 1154bf215546Sopenharmony_ci template->target != PIPE_TEXTURE_RECT) || 1155bf215546Sopenharmony_ci template->last_level != 0 || 1156bf215546Sopenharmony_ci template->depth0 != 1) { 1157bf215546Sopenharmony_ci return NULL; 1158bf215546Sopenharmony_ci } 1159bf215546Sopenharmony_ci 1160bf215546Sopenharmony_ci srf = sws->surface_from_handle(sws, whandle, &format); 1161bf215546Sopenharmony_ci 1162bf215546Sopenharmony_ci if (!srf) 1163bf215546Sopenharmony_ci return NULL; 1164bf215546Sopenharmony_ci 1165bf215546Sopenharmony_ci if (!svga_format_is_shareable(ss, template->format, format, 1166bf215546Sopenharmony_ci template->bind, true)) 1167bf215546Sopenharmony_ci goto out_unref; 1168bf215546Sopenharmony_ci 1169bf215546Sopenharmony_ci tex = CALLOC_STRUCT(svga_texture); 1170bf215546Sopenharmony_ci if (!tex) 1171bf215546Sopenharmony_ci goto out_unref; 1172bf215546Sopenharmony_ci 1173bf215546Sopenharmony_ci tex->defined = CALLOC(template->depth0 * template->array_size, 1174bf215546Sopenharmony_ci sizeof(tex->defined[0])); 1175bf215546Sopenharmony_ci if (!tex->defined) 1176bf215546Sopenharmony_ci goto out_no_defined; 1177bf215546Sopenharmony_ci 1178bf215546Sopenharmony_ci tex->b = *template; 1179bf215546Sopenharmony_ci pipe_reference_init(&tex->b.reference, 1); 1180bf215546Sopenharmony_ci tex->b.screen = screen; 1181bf215546Sopenharmony_ci 1182bf215546Sopenharmony_ci SVGA_DBG(DEBUG_DMA, "wrap surface sid %p\n", srf); 1183bf215546Sopenharmony_ci 1184bf215546Sopenharmony_ci tex->key.cachable = 0; 1185bf215546Sopenharmony_ci tex->key.format = format; 1186bf215546Sopenharmony_ci tex->handle = srf; 1187bf215546Sopenharmony_ci 1188bf215546Sopenharmony_ci 1189bf215546Sopenharmony_ci /* set bind flags for the imported texture handle according to the bind 1190bf215546Sopenharmony_ci * flags in the template 1191bf215546Sopenharmony_ci */ 1192bf215546Sopenharmony_ci if (template->bind & PIPE_BIND_RENDER_TARGET){ 1193bf215546Sopenharmony_ci tex->key.flags |= SVGA3D_SURFACE_HINT_RENDERTARGET; 1194bf215546Sopenharmony_ci tex->key.flags |= SVGA3D_SURFACE_BIND_RENDER_TARGET; 1195bf215546Sopenharmony_ci } 1196bf215546Sopenharmony_ci 1197bf215546Sopenharmony_ci if (template->bind & PIPE_BIND_DEPTH_STENCIL) { 1198bf215546Sopenharmony_ci tex->key.flags |= SVGA3D_SURFACE_HINT_DEPTHSTENCIL; 1199bf215546Sopenharmony_ci tex->key.flags |= SVGA3D_SURFACE_BIND_DEPTH_STENCIL; 1200bf215546Sopenharmony_ci } 1201bf215546Sopenharmony_ci 1202bf215546Sopenharmony_ci if (template->bind & PIPE_BIND_SAMPLER_VIEW) { 1203bf215546Sopenharmony_ci tex->key.flags |= SVGA3D_SURFACE_HINT_TEXTURE; 1204bf215546Sopenharmony_ci tex->key.flags |= SVGA3D_SURFACE_BIND_SHADER_RESOURCE; 1205bf215546Sopenharmony_ci } 1206bf215546Sopenharmony_ci 1207bf215546Sopenharmony_ci tex->dirty = CALLOC(1, sizeof(tex->dirty[0])); 1208bf215546Sopenharmony_ci if (!tex->dirty) 1209bf215546Sopenharmony_ci goto out_no_dirty; 1210bf215546Sopenharmony_ci 1211bf215546Sopenharmony_ci tex->imported = TRUE; 1212bf215546Sopenharmony_ci 1213bf215546Sopenharmony_ci ss->hud.num_resources++; 1214bf215546Sopenharmony_ci 1215bf215546Sopenharmony_ci return &tex->b; 1216bf215546Sopenharmony_ci 1217bf215546Sopenharmony_ciout_no_dirty: 1218bf215546Sopenharmony_ci FREE(tex->defined); 1219bf215546Sopenharmony_ciout_no_defined: 1220bf215546Sopenharmony_ci FREE(tex); 1221bf215546Sopenharmony_ciout_unref: 1222bf215546Sopenharmony_ci sws->surface_reference(sws, &srf, NULL); 1223bf215546Sopenharmony_ci return NULL; 1224bf215546Sopenharmony_ci} 1225bf215546Sopenharmony_ci 1226bf215546Sopenharmony_cibool 1227bf215546Sopenharmony_cisvga_texture_generate_mipmap(struct pipe_context *pipe, 1228bf215546Sopenharmony_ci struct pipe_resource *pt, 1229bf215546Sopenharmony_ci enum pipe_format format, 1230bf215546Sopenharmony_ci unsigned base_level, 1231bf215546Sopenharmony_ci unsigned last_level, 1232bf215546Sopenharmony_ci unsigned first_layer, 1233bf215546Sopenharmony_ci unsigned last_layer) 1234bf215546Sopenharmony_ci{ 1235bf215546Sopenharmony_ci struct pipe_sampler_view templ, *psv; 1236bf215546Sopenharmony_ci struct svga_pipe_sampler_view *sv; 1237bf215546Sopenharmony_ci struct svga_context *svga = svga_context(pipe); 1238bf215546Sopenharmony_ci struct svga_texture *tex = svga_texture(pt); 1239bf215546Sopenharmony_ci 1240bf215546Sopenharmony_ci assert(svga_have_vgpu10(svga)); 1241bf215546Sopenharmony_ci 1242bf215546Sopenharmony_ci /* Fallback to the mipmap generation utility for those formats that 1243bf215546Sopenharmony_ci * do not support hw generate mipmap 1244bf215546Sopenharmony_ci */ 1245bf215546Sopenharmony_ci if (!svga_format_support_gen_mips(format)) 1246bf215546Sopenharmony_ci return false; 1247bf215546Sopenharmony_ci 1248bf215546Sopenharmony_ci /* Make sure the texture surface was created with 1249bf215546Sopenharmony_ci * SVGA3D_SURFACE_BIND_RENDER_TARGET 1250bf215546Sopenharmony_ci */ 1251bf215546Sopenharmony_ci if (!tex->handle || !(tex->key.flags & SVGA3D_SURFACE_BIND_RENDER_TARGET)) 1252bf215546Sopenharmony_ci return false; 1253bf215546Sopenharmony_ci 1254bf215546Sopenharmony_ci templ.format = format; 1255bf215546Sopenharmony_ci templ.target = pt->target; 1256bf215546Sopenharmony_ci templ.u.tex.first_layer = first_layer; 1257bf215546Sopenharmony_ci templ.u.tex.last_layer = last_layer; 1258bf215546Sopenharmony_ci templ.u.tex.first_level = base_level; 1259bf215546Sopenharmony_ci templ.u.tex.last_level = last_level; 1260bf215546Sopenharmony_ci 1261bf215546Sopenharmony_ci if (pt->target == PIPE_TEXTURE_CUBE) { 1262bf215546Sopenharmony_ci /** 1263bf215546Sopenharmony_ci * state tracker generates mipmap one face at a time. 1264bf215546Sopenharmony_ci * But SVGA generates mipmap for the entire cubemap. 1265bf215546Sopenharmony_ci */ 1266bf215546Sopenharmony_ci templ.u.tex.first_layer = 0; 1267bf215546Sopenharmony_ci templ.u.tex.last_layer = 5; 1268bf215546Sopenharmony_ci } 1269bf215546Sopenharmony_ci 1270bf215546Sopenharmony_ci psv = pipe->create_sampler_view(pipe, pt, &templ); 1271bf215546Sopenharmony_ci if (psv == NULL) 1272bf215546Sopenharmony_ci return false; 1273bf215546Sopenharmony_ci 1274bf215546Sopenharmony_ci sv = svga_pipe_sampler_view(psv); 1275bf215546Sopenharmony_ci SVGA_RETRY(svga, svga_validate_pipe_sampler_view(svga, sv)); 1276bf215546Sopenharmony_ci 1277bf215546Sopenharmony_ci SVGA_RETRY(svga, SVGA3D_vgpu10_GenMips(svga->swc, sv->id, tex->handle)); 1278bf215546Sopenharmony_ci pipe_sampler_view_reference(&psv, NULL); 1279bf215546Sopenharmony_ci 1280bf215546Sopenharmony_ci /* Mark the texture surface as RENDERED */ 1281bf215546Sopenharmony_ci svga_set_texture_rendered_to(tex); 1282bf215546Sopenharmony_ci 1283bf215546Sopenharmony_ci svga->hud.num_generate_mipmap++; 1284bf215546Sopenharmony_ci 1285bf215546Sopenharmony_ci return true; 1286bf215546Sopenharmony_ci} 1287bf215546Sopenharmony_ci 1288bf215546Sopenharmony_ci 1289bf215546Sopenharmony_ci/* texture upload buffer default size in bytes */ 1290bf215546Sopenharmony_ci#define TEX_UPLOAD_DEFAULT_SIZE (1024 * 1024) 1291bf215546Sopenharmony_ci 1292bf215546Sopenharmony_ci/** 1293bf215546Sopenharmony_ci * Create a texture upload buffer 1294bf215546Sopenharmony_ci */ 1295bf215546Sopenharmony_ciboolean 1296bf215546Sopenharmony_cisvga_texture_transfer_map_upload_create(struct svga_context *svga) 1297bf215546Sopenharmony_ci{ 1298bf215546Sopenharmony_ci svga->tex_upload = u_upload_create(&svga->pipe, TEX_UPLOAD_DEFAULT_SIZE, 1299bf215546Sopenharmony_ci PIPE_BIND_CUSTOM, PIPE_USAGE_STAGING, 0); 1300bf215546Sopenharmony_ci if (svga->tex_upload) 1301bf215546Sopenharmony_ci u_upload_disable_persistent(svga->tex_upload); 1302bf215546Sopenharmony_ci 1303bf215546Sopenharmony_ci return svga->tex_upload != NULL; 1304bf215546Sopenharmony_ci} 1305bf215546Sopenharmony_ci 1306bf215546Sopenharmony_ci 1307bf215546Sopenharmony_ci/** 1308bf215546Sopenharmony_ci * Destroy the texture upload buffer 1309bf215546Sopenharmony_ci */ 1310bf215546Sopenharmony_civoid 1311bf215546Sopenharmony_cisvga_texture_transfer_map_upload_destroy(struct svga_context *svga) 1312bf215546Sopenharmony_ci{ 1313bf215546Sopenharmony_ci u_upload_destroy(svga->tex_upload); 1314bf215546Sopenharmony_ci} 1315bf215546Sopenharmony_ci 1316bf215546Sopenharmony_ci 1317bf215546Sopenharmony_ci/** 1318bf215546Sopenharmony_ci * Returns true if this transfer map request can use the upload buffer. 1319bf215546Sopenharmony_ci */ 1320bf215546Sopenharmony_ciboolean 1321bf215546Sopenharmony_cisvga_texture_transfer_map_can_upload(const struct svga_screen *svgascreen, 1322bf215546Sopenharmony_ci const struct pipe_resource *texture) 1323bf215546Sopenharmony_ci{ 1324bf215546Sopenharmony_ci if (svgascreen->sws->have_transfer_from_buffer_cmd == FALSE) 1325bf215546Sopenharmony_ci return FALSE; 1326bf215546Sopenharmony_ci 1327bf215546Sopenharmony_ci /* TransferFromBuffer command is not well supported with multi-samples surface */ 1328bf215546Sopenharmony_ci if (texture->nr_samples > 1) 1329bf215546Sopenharmony_ci return FALSE; 1330bf215546Sopenharmony_ci 1331bf215546Sopenharmony_ci if (util_format_is_compressed(texture->format)) { 1332bf215546Sopenharmony_ci /* XXX Need to take a closer look to see why texture upload 1333bf215546Sopenharmony_ci * with 3D texture with compressed format fails 1334bf215546Sopenharmony_ci */ 1335bf215546Sopenharmony_ci if (texture->target == PIPE_TEXTURE_3D) 1336bf215546Sopenharmony_ci return FALSE; 1337bf215546Sopenharmony_ci } 1338bf215546Sopenharmony_ci else if (texture->format == PIPE_FORMAT_R9G9B9E5_FLOAT) { 1339bf215546Sopenharmony_ci return FALSE; 1340bf215546Sopenharmony_ci } 1341bf215546Sopenharmony_ci 1342bf215546Sopenharmony_ci return TRUE; 1343bf215546Sopenharmony_ci} 1344bf215546Sopenharmony_ci 1345bf215546Sopenharmony_ci 1346bf215546Sopenharmony_ci/** 1347bf215546Sopenharmony_ci * Use upload buffer for the transfer map request. 1348bf215546Sopenharmony_ci */ 1349bf215546Sopenharmony_civoid * 1350bf215546Sopenharmony_cisvga_texture_transfer_map_upload(struct svga_context *svga, 1351bf215546Sopenharmony_ci struct svga_transfer *st) 1352bf215546Sopenharmony_ci{ 1353bf215546Sopenharmony_ci struct pipe_resource *texture = st->base.resource; 1354bf215546Sopenharmony_ci struct pipe_resource *tex_buffer = NULL; 1355bf215546Sopenharmony_ci void *tex_map; 1356bf215546Sopenharmony_ci unsigned nblocksx, nblocksy; 1357bf215546Sopenharmony_ci unsigned offset; 1358bf215546Sopenharmony_ci unsigned upload_size; 1359bf215546Sopenharmony_ci 1360bf215546Sopenharmony_ci assert(svga->tex_upload); 1361bf215546Sopenharmony_ci 1362bf215546Sopenharmony_ci st->upload.box.x = st->base.box.x; 1363bf215546Sopenharmony_ci st->upload.box.y = st->base.box.y; 1364bf215546Sopenharmony_ci st->upload.box.z = st->base.box.z; 1365bf215546Sopenharmony_ci st->upload.box.w = st->base.box.width; 1366bf215546Sopenharmony_ci st->upload.box.h = st->base.box.height; 1367bf215546Sopenharmony_ci st->upload.box.d = st->base.box.depth; 1368bf215546Sopenharmony_ci st->upload.nlayers = 1; 1369bf215546Sopenharmony_ci 1370bf215546Sopenharmony_ci switch (texture->target) { 1371bf215546Sopenharmony_ci case PIPE_TEXTURE_CUBE: 1372bf215546Sopenharmony_ci st->upload.box.z = 0; 1373bf215546Sopenharmony_ci break; 1374bf215546Sopenharmony_ci case PIPE_TEXTURE_2D_ARRAY: 1375bf215546Sopenharmony_ci case PIPE_TEXTURE_CUBE_ARRAY: 1376bf215546Sopenharmony_ci st->upload.nlayers = st->base.box.depth; 1377bf215546Sopenharmony_ci st->upload.box.z = 0; 1378bf215546Sopenharmony_ci st->upload.box.d = 1; 1379bf215546Sopenharmony_ci break; 1380bf215546Sopenharmony_ci case PIPE_TEXTURE_1D_ARRAY: 1381bf215546Sopenharmony_ci st->upload.nlayers = st->base.box.depth; 1382bf215546Sopenharmony_ci st->upload.box.y = st->upload.box.z = 0; 1383bf215546Sopenharmony_ci st->upload.box.d = 1; 1384bf215546Sopenharmony_ci break; 1385bf215546Sopenharmony_ci default: 1386bf215546Sopenharmony_ci break; 1387bf215546Sopenharmony_ci } 1388bf215546Sopenharmony_ci 1389bf215546Sopenharmony_ci nblocksx = util_format_get_nblocksx(texture->format, st->base.box.width); 1390bf215546Sopenharmony_ci nblocksy = util_format_get_nblocksy(texture->format, st->base.box.height); 1391bf215546Sopenharmony_ci 1392bf215546Sopenharmony_ci st->base.stride = nblocksx * util_format_get_blocksize(texture->format); 1393bf215546Sopenharmony_ci st->base.layer_stride = st->base.stride * nblocksy; 1394bf215546Sopenharmony_ci 1395bf215546Sopenharmony_ci /* In order to use the TransferFromBuffer command to update the 1396bf215546Sopenharmony_ci * texture content from the buffer, the layer stride for a multi-layers 1397bf215546Sopenharmony_ci * surface needs to be in multiples of 16 bytes. 1398bf215546Sopenharmony_ci */ 1399bf215546Sopenharmony_ci if (st->upload.nlayers > 1 && st->base.layer_stride & 15) 1400bf215546Sopenharmony_ci return NULL; 1401bf215546Sopenharmony_ci 1402bf215546Sopenharmony_ci upload_size = st->base.layer_stride * st->base.box.depth; 1403bf215546Sopenharmony_ci upload_size = align(upload_size, 16); 1404bf215546Sopenharmony_ci 1405bf215546Sopenharmony_ci#ifdef DEBUG 1406bf215546Sopenharmony_ci if (util_format_is_compressed(texture->format)) { 1407bf215546Sopenharmony_ci struct svga_texture *tex = svga_texture(texture); 1408bf215546Sopenharmony_ci unsigned blockw, blockh, bytesPerBlock; 1409bf215546Sopenharmony_ci 1410bf215546Sopenharmony_ci svga_format_size(tex->key.format, &blockw, &blockh, &bytesPerBlock); 1411bf215546Sopenharmony_ci 1412bf215546Sopenharmony_ci /* dest box must start on block boundary */ 1413bf215546Sopenharmony_ci assert((st->base.box.x % blockw) == 0); 1414bf215546Sopenharmony_ci assert((st->base.box.y % blockh) == 0); 1415bf215546Sopenharmony_ci } 1416bf215546Sopenharmony_ci#endif 1417bf215546Sopenharmony_ci 1418bf215546Sopenharmony_ci /* If the upload size exceeds the default buffer size, the 1419bf215546Sopenharmony_ci * upload buffer manager code will try to allocate a new buffer 1420bf215546Sopenharmony_ci * with the new buffer size. 1421bf215546Sopenharmony_ci */ 1422bf215546Sopenharmony_ci u_upload_alloc(svga->tex_upload, 0, upload_size, 16, 1423bf215546Sopenharmony_ci &offset, &tex_buffer, &tex_map); 1424bf215546Sopenharmony_ci 1425bf215546Sopenharmony_ci if (!tex_map) { 1426bf215546Sopenharmony_ci return NULL; 1427bf215546Sopenharmony_ci } 1428bf215546Sopenharmony_ci 1429bf215546Sopenharmony_ci st->upload.buf = tex_buffer; 1430bf215546Sopenharmony_ci st->upload.map = tex_map; 1431bf215546Sopenharmony_ci st->upload.offset = offset; 1432bf215546Sopenharmony_ci 1433bf215546Sopenharmony_ci return tex_map; 1434bf215546Sopenharmony_ci} 1435bf215546Sopenharmony_ci 1436bf215546Sopenharmony_ci 1437bf215546Sopenharmony_ci/** 1438bf215546Sopenharmony_ci * Unmap upload map transfer request 1439bf215546Sopenharmony_ci */ 1440bf215546Sopenharmony_civoid 1441bf215546Sopenharmony_cisvga_texture_transfer_unmap_upload(struct svga_context *svga, 1442bf215546Sopenharmony_ci struct svga_transfer *st) 1443bf215546Sopenharmony_ci{ 1444bf215546Sopenharmony_ci struct svga_winsys_surface *srcsurf; 1445bf215546Sopenharmony_ci struct svga_winsys_surface *dstsurf; 1446bf215546Sopenharmony_ci struct pipe_resource *texture = st->base.resource; 1447bf215546Sopenharmony_ci struct svga_texture *tex = svga_texture(texture); 1448bf215546Sopenharmony_ci unsigned subResource; 1449bf215546Sopenharmony_ci unsigned numMipLevels; 1450bf215546Sopenharmony_ci unsigned i, layer; 1451bf215546Sopenharmony_ci unsigned offset = st->upload.offset; 1452bf215546Sopenharmony_ci 1453bf215546Sopenharmony_ci assert(svga->tex_upload); 1454bf215546Sopenharmony_ci assert(st->upload.buf); 1455bf215546Sopenharmony_ci 1456bf215546Sopenharmony_ci /* unmap the texture upload buffer */ 1457bf215546Sopenharmony_ci u_upload_unmap(svga->tex_upload); 1458bf215546Sopenharmony_ci 1459bf215546Sopenharmony_ci srcsurf = svga_buffer_handle(svga, st->upload.buf, 0); 1460bf215546Sopenharmony_ci dstsurf = svga_texture(texture)->handle; 1461bf215546Sopenharmony_ci assert(dstsurf); 1462bf215546Sopenharmony_ci 1463bf215546Sopenharmony_ci numMipLevels = texture->last_level + 1; 1464bf215546Sopenharmony_ci 1465bf215546Sopenharmony_ci for (i = 0, layer = st->slice; i < st->upload.nlayers; i++, layer++) { 1466bf215546Sopenharmony_ci subResource = layer * numMipLevels + st->base.level; 1467bf215546Sopenharmony_ci 1468bf215546Sopenharmony_ci /* send a transferFromBuffer command to update the host texture surface */ 1469bf215546Sopenharmony_ci assert((offset & 15) == 0); 1470bf215546Sopenharmony_ci 1471bf215546Sopenharmony_ci SVGA_RETRY(svga, SVGA3D_vgpu10_TransferFromBuffer(svga->swc, srcsurf, 1472bf215546Sopenharmony_ci offset, 1473bf215546Sopenharmony_ci st->base.stride, 1474bf215546Sopenharmony_ci st->base.layer_stride, 1475bf215546Sopenharmony_ci dstsurf, subResource, 1476bf215546Sopenharmony_ci &st->upload.box)); 1477bf215546Sopenharmony_ci offset += st->base.layer_stride; 1478bf215546Sopenharmony_ci } 1479bf215546Sopenharmony_ci 1480bf215546Sopenharmony_ci /* Mark the texture surface state as RENDERED */ 1481bf215546Sopenharmony_ci svga_set_texture_rendered_to(tex); 1482bf215546Sopenharmony_ci 1483bf215546Sopenharmony_ci pipe_resource_reference(&st->upload.buf, NULL); 1484bf215546Sopenharmony_ci} 1485bf215546Sopenharmony_ci 1486bf215546Sopenharmony_ci/** 1487bf215546Sopenharmony_ci * Does the device format backing this surface have an 1488bf215546Sopenharmony_ci * alpha channel? 1489bf215546Sopenharmony_ci * 1490bf215546Sopenharmony_ci * \param texture[in] The texture whose format we're querying 1491bf215546Sopenharmony_ci * \return TRUE if the format has an alpha channel, FALSE otherwise 1492bf215546Sopenharmony_ci * 1493bf215546Sopenharmony_ci * For locally created textures, the device (svga) format is typically 1494bf215546Sopenharmony_ci * identical to svga_format(texture->format), and we can use the gallium 1495bf215546Sopenharmony_ci * format tests to determine whether the device format has an alpha channel 1496bf215546Sopenharmony_ci * or not. However, for textures backed by imported svga surfaces that is 1497bf215546Sopenharmony_ci * not always true, and we have to look at the SVGA3D utilities. 1498bf215546Sopenharmony_ci */ 1499bf215546Sopenharmony_ciboolean 1500bf215546Sopenharmony_cisvga_texture_device_format_has_alpha(struct pipe_resource *texture) 1501bf215546Sopenharmony_ci{ 1502bf215546Sopenharmony_ci /* the svga_texture() call below is invalid for PIPE_BUFFER resources */ 1503bf215546Sopenharmony_ci assert(texture->target != PIPE_BUFFER); 1504bf215546Sopenharmony_ci 1505bf215546Sopenharmony_ci const struct svga3d_surface_desc *surf_desc = 1506bf215546Sopenharmony_ci svga3dsurface_get_desc(svga_texture(texture)->key.format); 1507bf215546Sopenharmony_ci 1508bf215546Sopenharmony_ci enum svga3d_block_desc block_desc = surf_desc->block_desc; 1509bf215546Sopenharmony_ci 1510bf215546Sopenharmony_ci return !!((block_desc & SVGA3DBLOCKDESC_ALPHA) || 1511bf215546Sopenharmony_ci ((block_desc == SVGA3DBLOCKDESC_TYPELESS) && 1512bf215546Sopenharmony_ci (surf_desc->bitDepth.alpha > 0))); 1513bf215546Sopenharmony_ci} 1514