1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright 2012 Red Hat Inc. 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice shall be included in 12bf215546Sopenharmony_ci * all copies or substantial portions of the Software. 13bf215546Sopenharmony_ci * 14bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 18bf215546Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19bf215546Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20bf215546Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE. 21bf215546Sopenharmony_ci * 22bf215546Sopenharmony_ci * Authors: Ben Skeggs 23bf215546Sopenharmony_ci * 24bf215546Sopenharmony_ci */ 25bf215546Sopenharmony_ci 26bf215546Sopenharmony_ci#include "util/format/u_format.h" 27bf215546Sopenharmony_ci#include "util/u_inlines.h" 28bf215546Sopenharmony_ci#include "util/u_surface.h" 29bf215546Sopenharmony_ci 30bf215546Sopenharmony_ci#include "nv_m2mf.xml.h" 31bf215546Sopenharmony_ci#include "nv_object.xml.h" 32bf215546Sopenharmony_ci#include "nv30/nv30_screen.h" 33bf215546Sopenharmony_ci#include "nv30/nv30_context.h" 34bf215546Sopenharmony_ci#include "nv30/nv30_resource.h" 35bf215546Sopenharmony_ci#include "nv30/nv30_transfer.h" 36bf215546Sopenharmony_ci 37bf215546Sopenharmony_cistatic inline unsigned 38bf215546Sopenharmony_cilayer_offset(struct pipe_resource *pt, unsigned level, unsigned layer) 39bf215546Sopenharmony_ci{ 40bf215546Sopenharmony_ci struct nv30_miptree *mt = nv30_miptree(pt); 41bf215546Sopenharmony_ci struct nv30_miptree_level *lvl = &mt->level[level]; 42bf215546Sopenharmony_ci 43bf215546Sopenharmony_ci if (pt->target == PIPE_TEXTURE_CUBE) 44bf215546Sopenharmony_ci return (layer * mt->layer_size) + lvl->offset; 45bf215546Sopenharmony_ci 46bf215546Sopenharmony_ci return lvl->offset + (layer * lvl->zslice_size); 47bf215546Sopenharmony_ci} 48bf215546Sopenharmony_ci 49bf215546Sopenharmony_cibool 50bf215546Sopenharmony_cinv30_miptree_get_handle(struct pipe_screen *pscreen, 51bf215546Sopenharmony_ci struct pipe_context *context, 52bf215546Sopenharmony_ci struct pipe_resource *pt, 53bf215546Sopenharmony_ci struct winsys_handle *handle, 54bf215546Sopenharmony_ci unsigned usage) 55bf215546Sopenharmony_ci{ 56bf215546Sopenharmony_ci if (pt->target == PIPE_BUFFER) 57bf215546Sopenharmony_ci return false; 58bf215546Sopenharmony_ci 59bf215546Sopenharmony_ci struct nv30_miptree *mt = nv30_miptree(pt); 60bf215546Sopenharmony_ci unsigned stride; 61bf215546Sopenharmony_ci 62bf215546Sopenharmony_ci if (!mt || !mt->base.bo) 63bf215546Sopenharmony_ci return false; 64bf215546Sopenharmony_ci 65bf215546Sopenharmony_ci stride = mt->level[0].pitch; 66bf215546Sopenharmony_ci 67bf215546Sopenharmony_ci return nouveau_screen_bo_get_handle(pscreen, mt->base.bo, stride, handle); 68bf215546Sopenharmony_ci} 69bf215546Sopenharmony_ci 70bf215546Sopenharmony_civoid 71bf215546Sopenharmony_cinv30_miptree_destroy(struct pipe_screen *pscreen, struct pipe_resource *pt) 72bf215546Sopenharmony_ci{ 73bf215546Sopenharmony_ci struct nv30_miptree *mt = nv30_miptree(pt); 74bf215546Sopenharmony_ci 75bf215546Sopenharmony_ci nouveau_bo_ref(NULL, &mt->base.bo); 76bf215546Sopenharmony_ci FREE(mt); 77bf215546Sopenharmony_ci} 78bf215546Sopenharmony_ci 79bf215546Sopenharmony_cistruct nv30_transfer { 80bf215546Sopenharmony_ci struct pipe_transfer base; 81bf215546Sopenharmony_ci struct nv30_rect img; 82bf215546Sopenharmony_ci struct nv30_rect tmp; 83bf215546Sopenharmony_ci unsigned nblocksx; 84bf215546Sopenharmony_ci unsigned nblocksy; 85bf215546Sopenharmony_ci}; 86bf215546Sopenharmony_ci 87bf215546Sopenharmony_cistatic inline struct nv30_transfer * 88bf215546Sopenharmony_cinv30_transfer(struct pipe_transfer *ptx) 89bf215546Sopenharmony_ci{ 90bf215546Sopenharmony_ci return (struct nv30_transfer *)ptx; 91bf215546Sopenharmony_ci} 92bf215546Sopenharmony_ci 93bf215546Sopenharmony_cistatic inline void 94bf215546Sopenharmony_cidefine_rect(struct pipe_resource *pt, unsigned level, unsigned z, 95bf215546Sopenharmony_ci unsigned x, unsigned y, unsigned w, unsigned h, 96bf215546Sopenharmony_ci struct nv30_rect *rect) 97bf215546Sopenharmony_ci{ 98bf215546Sopenharmony_ci struct nv30_miptree *mt = nv30_miptree(pt); 99bf215546Sopenharmony_ci struct nv30_miptree_level *lvl = &mt->level[level]; 100bf215546Sopenharmony_ci 101bf215546Sopenharmony_ci rect->w = u_minify(pt->width0, level) << mt->ms_x; 102bf215546Sopenharmony_ci rect->w = util_format_get_nblocksx(pt->format, rect->w); 103bf215546Sopenharmony_ci rect->h = u_minify(pt->height0, level) << mt->ms_y; 104bf215546Sopenharmony_ci rect->h = util_format_get_nblocksy(pt->format, rect->h); 105bf215546Sopenharmony_ci rect->d = 1; 106bf215546Sopenharmony_ci rect->z = 0; 107bf215546Sopenharmony_ci if (mt->swizzled) { 108bf215546Sopenharmony_ci if (pt->target == PIPE_TEXTURE_3D) { 109bf215546Sopenharmony_ci rect->d = u_minify(pt->depth0, level); 110bf215546Sopenharmony_ci rect->z = z; z = 0; 111bf215546Sopenharmony_ci } 112bf215546Sopenharmony_ci rect->pitch = 0; 113bf215546Sopenharmony_ci } else { 114bf215546Sopenharmony_ci rect->pitch = lvl->pitch; 115bf215546Sopenharmony_ci } 116bf215546Sopenharmony_ci 117bf215546Sopenharmony_ci rect->bo = mt->base.bo; 118bf215546Sopenharmony_ci rect->domain = NOUVEAU_BO_VRAM; 119bf215546Sopenharmony_ci rect->offset = layer_offset(pt, level, z); 120bf215546Sopenharmony_ci rect->cpp = util_format_get_blocksize(pt->format); 121bf215546Sopenharmony_ci 122bf215546Sopenharmony_ci rect->x0 = util_format_get_nblocksx(pt->format, x) << mt->ms_x; 123bf215546Sopenharmony_ci rect->y0 = util_format_get_nblocksy(pt->format, y) << mt->ms_y; 124bf215546Sopenharmony_ci rect->x1 = rect->x0 + (util_format_get_nblocksx(pt->format, w) << mt->ms_x); 125bf215546Sopenharmony_ci rect->y1 = rect->y0 + (util_format_get_nblocksy(pt->format, h) << mt->ms_y); 126bf215546Sopenharmony_ci 127bf215546Sopenharmony_ci /* XXX There's some indication that swizzled formats > 4 bytes are treated 128bf215546Sopenharmony_ci * differently. However that only applies to RGBA16_FLOAT, RGBA32_FLOAT, 129bf215546Sopenharmony_ci * and the DXT* formats. The former aren't properly supported yet, and the 130bf215546Sopenharmony_ci * latter avoid swizzled layouts. 131bf215546Sopenharmony_ci 132bf215546Sopenharmony_ci if (mt->swizzled && rect->cpp > 4) { 133bf215546Sopenharmony_ci unsigned scale = rect->cpp / 4; 134bf215546Sopenharmony_ci rect->w *= scale; 135bf215546Sopenharmony_ci rect->x0 *= scale; 136bf215546Sopenharmony_ci rect->x1 *= scale; 137bf215546Sopenharmony_ci rect->cpp = 4; 138bf215546Sopenharmony_ci } 139bf215546Sopenharmony_ci */ 140bf215546Sopenharmony_ci} 141bf215546Sopenharmony_ci 142bf215546Sopenharmony_civoid 143bf215546Sopenharmony_cinv30_resource_copy_region(struct pipe_context *pipe, 144bf215546Sopenharmony_ci struct pipe_resource *dstres, unsigned dst_level, 145bf215546Sopenharmony_ci unsigned dstx, unsigned dsty, unsigned dstz, 146bf215546Sopenharmony_ci struct pipe_resource *srcres, unsigned src_level, 147bf215546Sopenharmony_ci const struct pipe_box *src_box) 148bf215546Sopenharmony_ci{ 149bf215546Sopenharmony_ci struct nv30_context *nv30 = nv30_context(pipe); 150bf215546Sopenharmony_ci struct nv30_rect src, dst; 151bf215546Sopenharmony_ci 152bf215546Sopenharmony_ci if (dstres->target == PIPE_BUFFER && srcres->target == PIPE_BUFFER) { 153bf215546Sopenharmony_ci nouveau_copy_buffer(&nv30->base, 154bf215546Sopenharmony_ci nv04_resource(dstres), dstx, 155bf215546Sopenharmony_ci nv04_resource(srcres), src_box->x, src_box->width); 156bf215546Sopenharmony_ci return; 157bf215546Sopenharmony_ci } 158bf215546Sopenharmony_ci 159bf215546Sopenharmony_ci define_rect(srcres, src_level, src_box->z, src_box->x, src_box->y, 160bf215546Sopenharmony_ci src_box->width, src_box->height, &src); 161bf215546Sopenharmony_ci define_rect(dstres, dst_level, dstz, dstx, dsty, 162bf215546Sopenharmony_ci src_box->width, src_box->height, &dst); 163bf215546Sopenharmony_ci 164bf215546Sopenharmony_ci nv30_transfer_rect(nv30, NEAREST, &src, &dst); 165bf215546Sopenharmony_ci} 166bf215546Sopenharmony_ci 167bf215546Sopenharmony_cistatic void 168bf215546Sopenharmony_cinv30_resource_resolve(struct nv30_context *nv30, 169bf215546Sopenharmony_ci const struct pipe_blit_info *info) 170bf215546Sopenharmony_ci{ 171bf215546Sopenharmony_ci struct nv30_miptree *src_mt = nv30_miptree(info->src.resource); 172bf215546Sopenharmony_ci struct nv30_rect src, dst; 173bf215546Sopenharmony_ci unsigned x, x0, x1, y, y1, w, h; 174bf215546Sopenharmony_ci 175bf215546Sopenharmony_ci define_rect(info->src.resource, 0, info->src.box.z, info->src.box.x, 176bf215546Sopenharmony_ci info->src.box.y, info->src.box.width, info->src.box.height, &src); 177bf215546Sopenharmony_ci define_rect(info->dst.resource, 0, info->dst.box.z, info->dst.box.x, 178bf215546Sopenharmony_ci info->dst.box.y, info->dst.box.width, info->dst.box.height, &dst); 179bf215546Sopenharmony_ci 180bf215546Sopenharmony_ci x0 = src.x0; 181bf215546Sopenharmony_ci x1 = src.x1; 182bf215546Sopenharmony_ci y1 = src.y1; 183bf215546Sopenharmony_ci 184bf215546Sopenharmony_ci /* On nv3x we must use sifm which is restricted to 1024x1024 tiles */ 185bf215546Sopenharmony_ci for (y = src.y0; y < y1; y += h) { 186bf215546Sopenharmony_ci h = y1 - y; 187bf215546Sopenharmony_ci if (h > 1024) 188bf215546Sopenharmony_ci h = 1024; 189bf215546Sopenharmony_ci 190bf215546Sopenharmony_ci src.y0 = 0; 191bf215546Sopenharmony_ci src.y1 = h; 192bf215546Sopenharmony_ci src.h = h; 193bf215546Sopenharmony_ci 194bf215546Sopenharmony_ci dst.y1 = dst.y0 + (h >> src_mt->ms_y); 195bf215546Sopenharmony_ci dst.h = h >> src_mt->ms_y; 196bf215546Sopenharmony_ci 197bf215546Sopenharmony_ci for (x = x0; x < x1; x += w) { 198bf215546Sopenharmony_ci w = x1 - x; 199bf215546Sopenharmony_ci if (w > 1024) 200bf215546Sopenharmony_ci w = 1024; 201bf215546Sopenharmony_ci 202bf215546Sopenharmony_ci src.offset = y * src.pitch + x * src.cpp; 203bf215546Sopenharmony_ci src.x0 = 0; 204bf215546Sopenharmony_ci src.x1 = w; 205bf215546Sopenharmony_ci src.w = w; 206bf215546Sopenharmony_ci 207bf215546Sopenharmony_ci dst.offset = (y >> src_mt->ms_y) * dst.pitch + 208bf215546Sopenharmony_ci (x >> src_mt->ms_x) * dst.cpp; 209bf215546Sopenharmony_ci dst.x1 = dst.x0 + (w >> src_mt->ms_x); 210bf215546Sopenharmony_ci dst.w = w >> src_mt->ms_x; 211bf215546Sopenharmony_ci 212bf215546Sopenharmony_ci nv30_transfer_rect(nv30, BILINEAR, &src, &dst); 213bf215546Sopenharmony_ci } 214bf215546Sopenharmony_ci } 215bf215546Sopenharmony_ci} 216bf215546Sopenharmony_ci 217bf215546Sopenharmony_civoid 218bf215546Sopenharmony_cinv30_blit(struct pipe_context *pipe, 219bf215546Sopenharmony_ci const struct pipe_blit_info *blit_info) 220bf215546Sopenharmony_ci{ 221bf215546Sopenharmony_ci struct nv30_context *nv30 = nv30_context(pipe); 222bf215546Sopenharmony_ci struct pipe_blit_info info = *blit_info; 223bf215546Sopenharmony_ci 224bf215546Sopenharmony_ci if (info.src.resource->nr_samples > 1 && 225bf215546Sopenharmony_ci info.dst.resource->nr_samples <= 1 && 226bf215546Sopenharmony_ci !util_format_is_depth_or_stencil(info.src.resource->format) && 227bf215546Sopenharmony_ci !util_format_is_pure_integer(info.src.resource->format)) { 228bf215546Sopenharmony_ci nv30_resource_resolve(nv30, blit_info); 229bf215546Sopenharmony_ci return; 230bf215546Sopenharmony_ci } 231bf215546Sopenharmony_ci 232bf215546Sopenharmony_ci if (util_try_blit_via_copy_region(pipe, &info, nv30->render_cond_query != NULL)) { 233bf215546Sopenharmony_ci return; /* done */ 234bf215546Sopenharmony_ci } 235bf215546Sopenharmony_ci 236bf215546Sopenharmony_ci if (info.mask & PIPE_MASK_S) { 237bf215546Sopenharmony_ci debug_printf("nv30: cannot blit stencil, skipping\n"); 238bf215546Sopenharmony_ci info.mask &= ~PIPE_MASK_S; 239bf215546Sopenharmony_ci } 240bf215546Sopenharmony_ci 241bf215546Sopenharmony_ci if (!util_blitter_is_blit_supported(nv30->blitter, &info)) { 242bf215546Sopenharmony_ci debug_printf("nv30: blit unsupported %s -> %s\n", 243bf215546Sopenharmony_ci util_format_short_name(info.src.resource->format), 244bf215546Sopenharmony_ci util_format_short_name(info.dst.resource->format)); 245bf215546Sopenharmony_ci return; 246bf215546Sopenharmony_ci } 247bf215546Sopenharmony_ci 248bf215546Sopenharmony_ci /* XXX turn off occlusion queries */ 249bf215546Sopenharmony_ci 250bf215546Sopenharmony_ci util_blitter_save_vertex_buffer_slot(nv30->blitter, nv30->vtxbuf); 251bf215546Sopenharmony_ci util_blitter_save_vertex_elements(nv30->blitter, nv30->vertex); 252bf215546Sopenharmony_ci util_blitter_save_vertex_shader(nv30->blitter, nv30->vertprog.program); 253bf215546Sopenharmony_ci util_blitter_save_rasterizer(nv30->blitter, nv30->rast); 254bf215546Sopenharmony_ci util_blitter_save_viewport(nv30->blitter, &nv30->viewport); 255bf215546Sopenharmony_ci util_blitter_save_scissor(nv30->blitter, &nv30->scissor); 256bf215546Sopenharmony_ci util_blitter_save_fragment_shader(nv30->blitter, nv30->fragprog.program); 257bf215546Sopenharmony_ci util_blitter_save_blend(nv30->blitter, nv30->blend); 258bf215546Sopenharmony_ci util_blitter_save_depth_stencil_alpha(nv30->blitter, 259bf215546Sopenharmony_ci nv30->zsa); 260bf215546Sopenharmony_ci util_blitter_save_stencil_ref(nv30->blitter, &nv30->stencil_ref); 261bf215546Sopenharmony_ci util_blitter_save_sample_mask(nv30->blitter, nv30->sample_mask, 0); 262bf215546Sopenharmony_ci util_blitter_save_framebuffer(nv30->blitter, &nv30->framebuffer); 263bf215546Sopenharmony_ci util_blitter_save_fragment_sampler_states(nv30->blitter, 264bf215546Sopenharmony_ci nv30->fragprog.num_samplers, 265bf215546Sopenharmony_ci (void**)nv30->fragprog.samplers); 266bf215546Sopenharmony_ci util_blitter_save_fragment_sampler_views(nv30->blitter, 267bf215546Sopenharmony_ci nv30->fragprog.num_textures, nv30->fragprog.textures); 268bf215546Sopenharmony_ci util_blitter_save_render_condition(nv30->blitter, nv30->render_cond_query, 269bf215546Sopenharmony_ci nv30->render_cond_cond, nv30->render_cond_mode); 270bf215546Sopenharmony_ci util_blitter_blit(nv30->blitter, &info); 271bf215546Sopenharmony_ci} 272bf215546Sopenharmony_ci 273bf215546Sopenharmony_civoid 274bf215546Sopenharmony_cinv30_flush_resource(struct pipe_context *pipe, 275bf215546Sopenharmony_ci struct pipe_resource *resource) 276bf215546Sopenharmony_ci{ 277bf215546Sopenharmony_ci} 278bf215546Sopenharmony_ci 279bf215546Sopenharmony_civoid * 280bf215546Sopenharmony_cinv30_miptree_transfer_map(struct pipe_context *pipe, struct pipe_resource *pt, 281bf215546Sopenharmony_ci unsigned level, unsigned usage, 282bf215546Sopenharmony_ci const struct pipe_box *box, 283bf215546Sopenharmony_ci struct pipe_transfer **ptransfer) 284bf215546Sopenharmony_ci{ 285bf215546Sopenharmony_ci struct nv30_context *nv30 = nv30_context(pipe); 286bf215546Sopenharmony_ci struct nouveau_device *dev = nv30->screen->base.device; 287bf215546Sopenharmony_ci struct nv30_miptree *mt = nv30_miptree(pt); 288bf215546Sopenharmony_ci struct nv30_transfer *tx; 289bf215546Sopenharmony_ci unsigned access = 0; 290bf215546Sopenharmony_ci int ret; 291bf215546Sopenharmony_ci 292bf215546Sopenharmony_ci tx = CALLOC_STRUCT(nv30_transfer); 293bf215546Sopenharmony_ci if (!tx) 294bf215546Sopenharmony_ci return NULL; 295bf215546Sopenharmony_ci pipe_resource_reference(&tx->base.resource, pt); 296bf215546Sopenharmony_ci tx->base.level = level; 297bf215546Sopenharmony_ci tx->base.usage = usage; 298bf215546Sopenharmony_ci tx->base.box = *box; 299bf215546Sopenharmony_ci tx->base.stride = align(util_format_get_nblocksx(pt->format, box->width) * 300bf215546Sopenharmony_ci util_format_get_blocksize(pt->format), 64); 301bf215546Sopenharmony_ci tx->base.layer_stride = util_format_get_nblocksy(pt->format, box->height) * 302bf215546Sopenharmony_ci tx->base.stride; 303bf215546Sopenharmony_ci 304bf215546Sopenharmony_ci tx->nblocksx = util_format_get_nblocksx(pt->format, box->width); 305bf215546Sopenharmony_ci tx->nblocksy = util_format_get_nblocksy(pt->format, box->height); 306bf215546Sopenharmony_ci 307bf215546Sopenharmony_ci define_rect(pt, level, box->z, box->x, box->y, 308bf215546Sopenharmony_ci box->width, box->height, &tx->img); 309bf215546Sopenharmony_ci 310bf215546Sopenharmony_ci ret = nouveau_bo_new(dev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 0, 311bf215546Sopenharmony_ci tx->base.layer_stride * tx->base.box.depth, NULL, 312bf215546Sopenharmony_ci &tx->tmp.bo); 313bf215546Sopenharmony_ci if (ret) { 314bf215546Sopenharmony_ci pipe_resource_reference(&tx->base.resource, NULL); 315bf215546Sopenharmony_ci FREE(tx); 316bf215546Sopenharmony_ci return NULL; 317bf215546Sopenharmony_ci } 318bf215546Sopenharmony_ci 319bf215546Sopenharmony_ci tx->tmp.domain = NOUVEAU_BO_GART; 320bf215546Sopenharmony_ci tx->tmp.offset = 0; 321bf215546Sopenharmony_ci tx->tmp.pitch = tx->base.stride; 322bf215546Sopenharmony_ci tx->tmp.cpp = tx->img.cpp; 323bf215546Sopenharmony_ci tx->tmp.w = tx->nblocksx; 324bf215546Sopenharmony_ci tx->tmp.h = tx->nblocksy; 325bf215546Sopenharmony_ci tx->tmp.d = 1; 326bf215546Sopenharmony_ci tx->tmp.x0 = 0; 327bf215546Sopenharmony_ci tx->tmp.y0 = 0; 328bf215546Sopenharmony_ci tx->tmp.x1 = tx->tmp.w; 329bf215546Sopenharmony_ci tx->tmp.y1 = tx->tmp.h; 330bf215546Sopenharmony_ci tx->tmp.z = 0; 331bf215546Sopenharmony_ci 332bf215546Sopenharmony_ci if (usage & PIPE_MAP_READ) { 333bf215546Sopenharmony_ci bool is_3d = mt->base.base.target == PIPE_TEXTURE_3D; 334bf215546Sopenharmony_ci unsigned offset = tx->img.offset; 335bf215546Sopenharmony_ci unsigned z = tx->img.z; 336bf215546Sopenharmony_ci unsigned i; 337bf215546Sopenharmony_ci for (i = 0; i < box->depth; ++i) { 338bf215546Sopenharmony_ci nv30_transfer_rect(nv30, NEAREST, &tx->img, &tx->tmp); 339bf215546Sopenharmony_ci if (is_3d && mt->swizzled) 340bf215546Sopenharmony_ci tx->img.z++; 341bf215546Sopenharmony_ci else if (is_3d) 342bf215546Sopenharmony_ci tx->img.offset += mt->level[level].zslice_size; 343bf215546Sopenharmony_ci else 344bf215546Sopenharmony_ci tx->img.offset += mt->layer_size; 345bf215546Sopenharmony_ci tx->tmp.offset += tx->base.layer_stride; 346bf215546Sopenharmony_ci } 347bf215546Sopenharmony_ci tx->img.z = z; 348bf215546Sopenharmony_ci tx->img.offset = offset; 349bf215546Sopenharmony_ci tx->tmp.offset = 0; 350bf215546Sopenharmony_ci } 351bf215546Sopenharmony_ci 352bf215546Sopenharmony_ci if (tx->tmp.bo->map) { 353bf215546Sopenharmony_ci *ptransfer = &tx->base; 354bf215546Sopenharmony_ci return tx->tmp.bo->map; 355bf215546Sopenharmony_ci } 356bf215546Sopenharmony_ci 357bf215546Sopenharmony_ci if (usage & PIPE_MAP_READ) 358bf215546Sopenharmony_ci access |= NOUVEAU_BO_RD; 359bf215546Sopenharmony_ci if (usage & PIPE_MAP_WRITE) 360bf215546Sopenharmony_ci access |= NOUVEAU_BO_WR; 361bf215546Sopenharmony_ci 362bf215546Sopenharmony_ci ret = nouveau_bo_map(tx->tmp.bo, access, nv30->base.client); 363bf215546Sopenharmony_ci if (ret) { 364bf215546Sopenharmony_ci pipe_resource_reference(&tx->base.resource, NULL); 365bf215546Sopenharmony_ci FREE(tx); 366bf215546Sopenharmony_ci return NULL; 367bf215546Sopenharmony_ci } 368bf215546Sopenharmony_ci 369bf215546Sopenharmony_ci *ptransfer = &tx->base; 370bf215546Sopenharmony_ci return tx->tmp.bo->map; 371bf215546Sopenharmony_ci} 372bf215546Sopenharmony_ci 373bf215546Sopenharmony_civoid 374bf215546Sopenharmony_cinv30_miptree_transfer_unmap(struct pipe_context *pipe, 375bf215546Sopenharmony_ci struct pipe_transfer *ptx) 376bf215546Sopenharmony_ci{ 377bf215546Sopenharmony_ci struct nv30_context *nv30 = nv30_context(pipe); 378bf215546Sopenharmony_ci struct nv30_transfer *tx = nv30_transfer(ptx); 379bf215546Sopenharmony_ci struct nv30_miptree *mt = nv30_miptree(tx->base.resource); 380bf215546Sopenharmony_ci unsigned i; 381bf215546Sopenharmony_ci 382bf215546Sopenharmony_ci if (ptx->usage & PIPE_MAP_WRITE) { 383bf215546Sopenharmony_ci bool is_3d = mt->base.base.target == PIPE_TEXTURE_3D; 384bf215546Sopenharmony_ci for (i = 0; i < tx->base.box.depth; ++i) { 385bf215546Sopenharmony_ci nv30_transfer_rect(nv30, NEAREST, &tx->tmp, &tx->img); 386bf215546Sopenharmony_ci if (is_3d && mt->swizzled) 387bf215546Sopenharmony_ci tx->img.z++; 388bf215546Sopenharmony_ci else if (is_3d) 389bf215546Sopenharmony_ci tx->img.offset += mt->level[tx->base.level].zslice_size; 390bf215546Sopenharmony_ci else 391bf215546Sopenharmony_ci tx->img.offset += mt->layer_size; 392bf215546Sopenharmony_ci tx->tmp.offset += tx->base.layer_stride; 393bf215546Sopenharmony_ci } 394bf215546Sopenharmony_ci 395bf215546Sopenharmony_ci /* Allow the copies above to finish executing before freeing the source */ 396bf215546Sopenharmony_ci nouveau_fence_work(nv30->screen->base.fence.current, 397bf215546Sopenharmony_ci nouveau_fence_unref_bo, tx->tmp.bo); 398bf215546Sopenharmony_ci } else { 399bf215546Sopenharmony_ci nouveau_bo_ref(NULL, &tx->tmp.bo); 400bf215546Sopenharmony_ci } 401bf215546Sopenharmony_ci pipe_resource_reference(&ptx->resource, NULL); 402bf215546Sopenharmony_ci FREE(tx); 403bf215546Sopenharmony_ci} 404bf215546Sopenharmony_ci 405bf215546Sopenharmony_cistruct pipe_resource * 406bf215546Sopenharmony_cinv30_miptree_create(struct pipe_screen *pscreen, 407bf215546Sopenharmony_ci const struct pipe_resource *tmpl) 408bf215546Sopenharmony_ci{ 409bf215546Sopenharmony_ci struct nouveau_device *dev = nouveau_screen(pscreen)->device; 410bf215546Sopenharmony_ci struct nv30_miptree *mt = CALLOC_STRUCT(nv30_miptree); 411bf215546Sopenharmony_ci struct pipe_resource *pt = &mt->base.base; 412bf215546Sopenharmony_ci unsigned blocksz, size; 413bf215546Sopenharmony_ci unsigned w, h, d, l; 414bf215546Sopenharmony_ci int ret; 415bf215546Sopenharmony_ci 416bf215546Sopenharmony_ci switch (tmpl->nr_samples) { 417bf215546Sopenharmony_ci case 4: 418bf215546Sopenharmony_ci mt->ms_mode = 0x00004000; 419bf215546Sopenharmony_ci mt->ms_x = 1; 420bf215546Sopenharmony_ci mt->ms_y = 1; 421bf215546Sopenharmony_ci break; 422bf215546Sopenharmony_ci case 2: 423bf215546Sopenharmony_ci mt->ms_mode = 0x00003000; 424bf215546Sopenharmony_ci mt->ms_x = 1; 425bf215546Sopenharmony_ci mt->ms_y = 0; 426bf215546Sopenharmony_ci break; 427bf215546Sopenharmony_ci default: 428bf215546Sopenharmony_ci mt->ms_mode = 0x00000000; 429bf215546Sopenharmony_ci mt->ms_x = 0; 430bf215546Sopenharmony_ci mt->ms_y = 0; 431bf215546Sopenharmony_ci break; 432bf215546Sopenharmony_ci } 433bf215546Sopenharmony_ci 434bf215546Sopenharmony_ci *pt = *tmpl; 435bf215546Sopenharmony_ci pipe_reference_init(&pt->reference, 1); 436bf215546Sopenharmony_ci pt->screen = pscreen; 437bf215546Sopenharmony_ci 438bf215546Sopenharmony_ci w = pt->width0 << mt->ms_x; 439bf215546Sopenharmony_ci h = pt->height0 << mt->ms_y; 440bf215546Sopenharmony_ci d = (pt->target == PIPE_TEXTURE_3D) ? pt->depth0 : 1; 441bf215546Sopenharmony_ci blocksz = util_format_get_blocksize(pt->format); 442bf215546Sopenharmony_ci 443bf215546Sopenharmony_ci if ((pt->target == PIPE_TEXTURE_RECT) || 444bf215546Sopenharmony_ci (pt->bind & PIPE_BIND_SCANOUT) || 445bf215546Sopenharmony_ci !util_is_power_of_two_or_zero(pt->width0) || 446bf215546Sopenharmony_ci !util_is_power_of_two_or_zero(pt->height0) || 447bf215546Sopenharmony_ci !util_is_power_of_two_or_zero(pt->depth0) || 448bf215546Sopenharmony_ci mt->ms_mode) { 449bf215546Sopenharmony_ci mt->uniform_pitch = util_format_get_nblocksx(pt->format, w) * blocksz; 450bf215546Sopenharmony_ci mt->uniform_pitch = align(mt->uniform_pitch, 64); 451bf215546Sopenharmony_ci if (pt->bind & PIPE_BIND_SCANOUT) { 452bf215546Sopenharmony_ci struct nv30_screen *screen = nv30_screen(pscreen); 453bf215546Sopenharmony_ci int pitch_align = MAX2( 454bf215546Sopenharmony_ci screen->eng3d->oclass >= NV40_3D_CLASS ? 1024 : 256, 455bf215546Sopenharmony_ci /* round_down_pow2(mt->uniform_pitch / 4) */ 456bf215546Sopenharmony_ci 1 << (util_last_bit(mt->uniform_pitch / 4) - 1)); 457bf215546Sopenharmony_ci mt->uniform_pitch = align(mt->uniform_pitch, pitch_align); 458bf215546Sopenharmony_ci } 459bf215546Sopenharmony_ci } 460bf215546Sopenharmony_ci 461bf215546Sopenharmony_ci if (util_format_is_compressed(pt->format)) { 462bf215546Sopenharmony_ci // Compressed (DXT) formats are packed tightly. We don't mark them as 463bf215546Sopenharmony_ci // swizzled, since their layout is largely linear. However we do end up 464bf215546Sopenharmony_ci // omitting the LINEAR flag when texturing them, as the levels are not 465bf215546Sopenharmony_ci // uniformly sized (for POT sizes). 466bf215546Sopenharmony_ci } else if (!mt->uniform_pitch) { 467bf215546Sopenharmony_ci mt->swizzled = true; 468bf215546Sopenharmony_ci } 469bf215546Sopenharmony_ci 470bf215546Sopenharmony_ci size = 0; 471bf215546Sopenharmony_ci for (l = 0; l <= pt->last_level; l++) { 472bf215546Sopenharmony_ci struct nv30_miptree_level *lvl = &mt->level[l]; 473bf215546Sopenharmony_ci unsigned nbx = util_format_get_nblocksx(pt->format, w); 474bf215546Sopenharmony_ci unsigned nby = util_format_get_nblocksy(pt->format, h); 475bf215546Sopenharmony_ci 476bf215546Sopenharmony_ci lvl->offset = size; 477bf215546Sopenharmony_ci lvl->pitch = mt->uniform_pitch; 478bf215546Sopenharmony_ci if (!lvl->pitch) 479bf215546Sopenharmony_ci lvl->pitch = nbx * blocksz; 480bf215546Sopenharmony_ci 481bf215546Sopenharmony_ci lvl->zslice_size = lvl->pitch * nby; 482bf215546Sopenharmony_ci size += lvl->zslice_size * d; 483bf215546Sopenharmony_ci 484bf215546Sopenharmony_ci w = u_minify(w, 1); 485bf215546Sopenharmony_ci h = u_minify(h, 1); 486bf215546Sopenharmony_ci d = u_minify(d, 1); 487bf215546Sopenharmony_ci } 488bf215546Sopenharmony_ci 489bf215546Sopenharmony_ci mt->layer_size = size; 490bf215546Sopenharmony_ci if (pt->target == PIPE_TEXTURE_CUBE) { 491bf215546Sopenharmony_ci if (!mt->uniform_pitch) 492bf215546Sopenharmony_ci mt->layer_size = align(mt->layer_size, 128); 493bf215546Sopenharmony_ci size = mt->layer_size * 6; 494bf215546Sopenharmony_ci } 495bf215546Sopenharmony_ci 496bf215546Sopenharmony_ci ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 256, size, NULL, &mt->base.bo); 497bf215546Sopenharmony_ci if (ret) { 498bf215546Sopenharmony_ci FREE(mt); 499bf215546Sopenharmony_ci return NULL; 500bf215546Sopenharmony_ci } 501bf215546Sopenharmony_ci 502bf215546Sopenharmony_ci mt->base.domain = NOUVEAU_BO_VRAM; 503bf215546Sopenharmony_ci return &mt->base.base; 504bf215546Sopenharmony_ci} 505bf215546Sopenharmony_ci 506bf215546Sopenharmony_cistruct pipe_resource * 507bf215546Sopenharmony_cinv30_miptree_from_handle(struct pipe_screen *pscreen, 508bf215546Sopenharmony_ci const struct pipe_resource *tmpl, 509bf215546Sopenharmony_ci struct winsys_handle *handle) 510bf215546Sopenharmony_ci{ 511bf215546Sopenharmony_ci struct nv30_miptree *mt; 512bf215546Sopenharmony_ci unsigned stride; 513bf215546Sopenharmony_ci 514bf215546Sopenharmony_ci /* only supports 2D, non-mipmapped textures for the moment */ 515bf215546Sopenharmony_ci if ((tmpl->target != PIPE_TEXTURE_2D && 516bf215546Sopenharmony_ci tmpl->target != PIPE_TEXTURE_RECT) || 517bf215546Sopenharmony_ci tmpl->last_level != 0 || 518bf215546Sopenharmony_ci tmpl->depth0 != 1 || 519bf215546Sopenharmony_ci tmpl->array_size > 1) 520bf215546Sopenharmony_ci return NULL; 521bf215546Sopenharmony_ci 522bf215546Sopenharmony_ci mt = CALLOC_STRUCT(nv30_miptree); 523bf215546Sopenharmony_ci if (!mt) 524bf215546Sopenharmony_ci return NULL; 525bf215546Sopenharmony_ci 526bf215546Sopenharmony_ci mt->base.bo = nouveau_screen_bo_from_handle(pscreen, handle, &stride); 527bf215546Sopenharmony_ci if (mt->base.bo == NULL) { 528bf215546Sopenharmony_ci FREE(mt); 529bf215546Sopenharmony_ci return NULL; 530bf215546Sopenharmony_ci } 531bf215546Sopenharmony_ci 532bf215546Sopenharmony_ci mt->base.base = *tmpl; 533bf215546Sopenharmony_ci pipe_reference_init(&mt->base.base.reference, 1); 534bf215546Sopenharmony_ci mt->base.base.screen = pscreen; 535bf215546Sopenharmony_ci mt->uniform_pitch = stride; 536bf215546Sopenharmony_ci mt->level[0].pitch = mt->uniform_pitch; 537bf215546Sopenharmony_ci mt->level[0].offset = 0; 538bf215546Sopenharmony_ci 539bf215546Sopenharmony_ci /* no need to adjust bo reference count */ 540bf215546Sopenharmony_ci return &mt->base.base; 541bf215546Sopenharmony_ci} 542bf215546Sopenharmony_ci 543bf215546Sopenharmony_cistruct pipe_surface * 544bf215546Sopenharmony_cinv30_miptree_surface_new(struct pipe_context *pipe, 545bf215546Sopenharmony_ci struct pipe_resource *pt, 546bf215546Sopenharmony_ci const struct pipe_surface *tmpl) 547bf215546Sopenharmony_ci{ 548bf215546Sopenharmony_ci struct nv30_miptree *mt = nv30_miptree(pt); /* guaranteed */ 549bf215546Sopenharmony_ci struct nv30_surface *ns; 550bf215546Sopenharmony_ci struct pipe_surface *ps; 551bf215546Sopenharmony_ci struct nv30_miptree_level *lvl = &mt->level[tmpl->u.tex.level]; 552bf215546Sopenharmony_ci 553bf215546Sopenharmony_ci ns = CALLOC_STRUCT(nv30_surface); 554bf215546Sopenharmony_ci if (!ns) 555bf215546Sopenharmony_ci return NULL; 556bf215546Sopenharmony_ci ps = &ns->base; 557bf215546Sopenharmony_ci 558bf215546Sopenharmony_ci pipe_reference_init(&ps->reference, 1); 559bf215546Sopenharmony_ci pipe_resource_reference(&ps->texture, pt); 560bf215546Sopenharmony_ci ps->context = pipe; 561bf215546Sopenharmony_ci ps->format = tmpl->format; 562bf215546Sopenharmony_ci ps->u.tex.level = tmpl->u.tex.level; 563bf215546Sopenharmony_ci ps->u.tex.first_layer = tmpl->u.tex.first_layer; 564bf215546Sopenharmony_ci ps->u.tex.last_layer = tmpl->u.tex.last_layer; 565bf215546Sopenharmony_ci 566bf215546Sopenharmony_ci ns->width = u_minify(pt->width0, ps->u.tex.level); 567bf215546Sopenharmony_ci ns->height = u_minify(pt->height0, ps->u.tex.level); 568bf215546Sopenharmony_ci ns->depth = ps->u.tex.last_layer - ps->u.tex.first_layer + 1; 569bf215546Sopenharmony_ci ns->offset = layer_offset(pt, ps->u.tex.level, ps->u.tex.first_layer); 570bf215546Sopenharmony_ci if (mt->swizzled) 571bf215546Sopenharmony_ci ns->pitch = 4096; /* random, just something the hw won't reject.. */ 572bf215546Sopenharmony_ci else 573bf215546Sopenharmony_ci ns->pitch = lvl->pitch; 574bf215546Sopenharmony_ci 575bf215546Sopenharmony_ci /* comment says there are going to be removed, but they're used by the st */ 576bf215546Sopenharmony_ci ps->width = ns->width; 577bf215546Sopenharmony_ci ps->height = ns->height; 578bf215546Sopenharmony_ci return ps; 579bf215546Sopenharmony_ci} 580bf215546Sopenharmony_ci 581bf215546Sopenharmony_civoid 582bf215546Sopenharmony_cinv30_miptree_surface_del(struct pipe_context *pipe, struct pipe_surface *ps) 583bf215546Sopenharmony_ci{ 584bf215546Sopenharmony_ci struct nv30_surface *ns = nv30_surface(ps); 585bf215546Sopenharmony_ci 586bf215546Sopenharmony_ci pipe_resource_reference(&ps->texture, NULL); 587bf215546Sopenharmony_ci FREE(ns); 588bf215546Sopenharmony_ci} 589