}
boolean
-nv50_miptree_init_layout_linear(struct nv50_miptree *mt)
+nv50_miptree_init_layout_linear(struct nv50_miptree *mt, unsigned pitch_align)
{
struct pipe_resource *pt = &mt->base.base;
const unsigned blocksize = util_format_get_blocksize(pt->format);
if (mt->ms_x | mt->ms_y)
return FALSE;
- mt->level[0].pitch = align(pt->width0 * blocksize, 64);
+ mt->level[0].pitch = align(pt->width0 * blocksize, pitch_align);
/* Account for very generous prefetch (allocate size as if tiled). */
h = MAX2(h, 8);
if (bo_config.nv50.memtype != 0) {
nv50_miptree_init_layout_tiled(mt);
} else
- if (!nv50_miptree_init_layout_linear(mt)) {
+ if (!nv50_miptree_init_layout_linear(mt, 64)) {
FREE(mt);
return NULL;
}
/* Internal functions:
*/
boolean
-nv50_miptree_init_layout_linear(struct nv50_miptree *mt);
+nv50_miptree_init_layout_linear(struct nv50_miptree *mt, unsigned pitch_align);
struct pipe_resource *
nv50_miptree_create(struct pipe_screen *pscreen,
#define NVC0_2D_UNK258 0x00000258
-#define NVC0_2D_UNK260 0x00000260
+#define NVC0_2D_SINGLE_GPC 0x00000260
#define NVC0_2D_COND_ADDRESS_HIGH 0x00000264
return TRUE;
}
-boolean
-nv50_miptree_init_layout_linear(struct nv50_miptree *);
-
static void
nvc0_miptree_init_layout_video(struct nv50_miptree *mt)
{
pipe_reference_init(&pt->reference, 1);
pt->screen = pscreen;
+ if (pt->usage == PIPE_USAGE_STAGING) {
+ switch (pt->target) {
+ case PIPE_TEXTURE_1D:
+ case PIPE_TEXTURE_2D:
+ case PIPE_TEXTURE_RECT:
+ if (pt->last_level == 0 &&
+ !util_format_is_depth_or_stencil(pt->format) &&
+ pt->nr_samples <= 1)
+ pt->flags |= NOUVEAU_RESOURCE_FLAG_LINEAR;
+ break;
+ default:
+ break;
+ }
+ }
+
bo_config.nvc0.memtype = nvc0_mt_choose_storage_type(mt, compressed);
if (!nvc0_miptree_init_ms_mode(mt)) {
if (likely(bo_config.nvc0.memtype)) {
nvc0_miptree_init_layout_tiled(mt);
} else
- if (!nv50_miptree_init_layout_linear(mt)) {
+ if (!nv50_miptree_init_layout_linear(mt, 128)) {
FREE(mt);
return NULL;
}
bo_config.nvc0.tile_mode = mt->level[0].tile_mode;
- mt->base.domain = NOUVEAU_BO_VRAM;
+ if (!bo_config.nvc0.memtype && pt->usage == PIPE_USAGE_STAGING)
+ mt->base.domain = NOUVEAU_BO_GART;
+ else
+ mt->base.domain = NOUVEAU_BO_VRAM;
bo_flags = mt->base.domain | NOUVEAU_BO_NOSNOOP;
BEGIN_NVC0(push, SUBC_2D(NV01_SUBCHAN_OBJECT), 1);
PUSH_DATA (push, screen->eng2d->oclass);
+ BEGIN_NVC0(push, NVC0_2D(SINGLE_GPC), 1);
+ PUSH_DATA (push, 0);
BEGIN_NVC0(push, NVC0_2D(OPERATION), 1);
PUSH_DATA (push, NVC0_2D_OPERATION_SRCCOPY);
BEGIN_NVC0(push, NVC0_2D(CLIP_ENABLE), 1);
PUSH_DATA (push, srcy >> 32);
}
}
- nvc0_bufctx_fence(nvc0, nvc0->bufctx, FALSE);
+ nvc0_resource_validate(&dst->base, NOUVEAU_BO_WR);
+ nvc0_resource_validate(&src->base, NOUVEAU_BO_RD);
nouveau_bufctx_reset(nvc0->bufctx, NVC0_BIND_2D);
nouveau_bufctx_reset(bctx, 0);
}
+
+static INLINE boolean
+nvc0_mt_transfer_can_map_directly(struct nv50_miptree *mt)
+{
+ if (mt->base.domain == NOUVEAU_BO_VRAM)
+ return FALSE;
+ if (mt->base.base.usage != PIPE_USAGE_STAGING)
+ return FALSE;
+ return !nouveau_bo_memtype(mt->base.bo);
+}
+
+static INLINE boolean
+nvc0_mt_sync(struct nvc0_context *nvc0, struct nv50_miptree *mt, unsigned usage)
+{
+ if (!mt->base.mm) {
+ uint32_t access = (usage & PIPE_TRANSFER_WRITE) ?
+ NOUVEAU_BO_WR : NOUVEAU_BO_RD;
+ return !nouveau_bo_wait(mt->base.bo, access, nvc0->base.client);
+ }
+ if (usage & PIPE_TRANSFER_WRITE)
+ return !mt->base.fence || nouveau_fence_wait(mt->base.fence);
+ return !mt->base.fence_wr || nouveau_fence_wait(mt->base.fence_wr);
+}
+
void *
nvc0_miptree_transfer_map(struct pipe_context *pctx,
struct pipe_resource *res,
int ret;
unsigned flags = 0;
+ if (nvc0_mt_transfer_can_map_directly(mt)) {
+ ret = !nvc0_mt_sync(nvc0, mt, usage);
+ if (!ret)
+ ret = nouveau_bo_map(mt->base.bo, 0, NULL);
+ if (ret &&
+ (usage & PIPE_TRANSFER_MAP_DIRECTLY))
+ return NULL;
+ if (!ret)
+ usage |= PIPE_TRANSFER_MAP_DIRECTLY;
+ } else
if (usage & PIPE_TRANSFER_MAP_DIRECTLY)
return NULL;
tx->base.stride = tx->nblocksx * util_format_get_blocksize(res->format);
tx->base.layer_stride = tx->nblocksy * tx->base.stride;
+ if (usage & PIPE_TRANSFER_MAP_DIRECTLY) {
+ tx->base.stride = align(tx->base.stride, 128);
+ *ptransfer = &tx->base;
+ return mt->base.bo->map + mt->base.offset;
+ }
+
nv50_m2mf_rect_setup(&tx->rect[0], res, level, box->x, box->y, box->z);
size = tx->base.layer_stride;
struct nv50_miptree *mt = nv50_miptree(tx->base.resource);
unsigned i;
+ if (tx->base.usage & PIPE_TRANSFER_MAP_DIRECTLY) {
+ pipe_resource_reference(&transfer->resource, NULL);
+
+ FREE(tx);
+ return;
+ }
+
if (tx->base.usage & PIPE_TRANSFER_WRITE) {
for (i = 0; i < tx->nlayers; ++i) {
nvc0->m2mf_copy_rect(nvc0, &tx->rect[0], &tx->rect[1],