static void setup_hierz_buffer(struct gl_context *ctx) { struct nouveau_channel *chan = context_chan(ctx); struct nouveau_grobj *celsius = context_eng3d(ctx); struct nouveau_bo_context *bctx = context_bctx(ctx, HIERZ); struct gl_framebuffer *fb = ctx->DrawBuffer; struct nouveau_framebuffer *nfb = to_nouveau_framebuffer(fb); unsigned pitch = align(fb->Width, 128), height = align(fb->Height, 2), size = pitch * height; if (!nfb->hierz.bo || nfb->hierz.bo->size != size) { nouveau_bo_ref(NULL, &nfb->hierz.bo); nouveau_bo_new_tile(context_dev(ctx), NOUVEAU_BO_VRAM, 0, size, 0, NOUVEAU_BO_TILE_ZETA, &nfb->hierz.bo); } nouveau_bo_markl(bctx, celsius, NV17_3D_HIERZ_OFFSET, nfb->hierz.bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR); WAIT_RING(chan, 9); BEGIN_RING(chan, celsius, NV17_3D_HIERZ_WINDOW_X, 4); OUT_RINGf(chan, - 1792); OUT_RINGf(chan, - 2304 + fb->Height); OUT_RINGf(chan, fb->_DepthMaxF / 2); OUT_RINGf(chan, 0); BEGIN_RING(chan, celsius, NV17_3D_HIERZ_PITCH, 1); OUT_RING(chan, pitch); BEGIN_RING(chan, celsius, NV17_3D_HIERZ_ENABLE, 1); OUT_RING(chan, 1); }
struct nouveau_bo * nouveau_screen_bo_new(struct pipe_screen *pscreen, unsigned alignment, unsigned usage, unsigned bind, unsigned size) { struct nouveau_device *dev = nouveau_screen(pscreen)->device; struct nouveau_bo *bo = NULL; uint32_t flags = NOUVEAU_BO_MAP, tile_mode = 0, tile_flags = 0; int ret; if (bind & PIPE_BIND_VERTEX_BUFFER) flags |= nouveau_screen(pscreen)->vertex_buffer_flags; else if (bind & PIPE_BIND_INDEX_BUFFER) flags |= nouveau_screen(pscreen)->index_buffer_flags; if (bind & (PIPE_BIND_RENDER_TARGET | PIPE_BIND_DEPTH_STENCIL | PIPE_BIND_SCANOUT | PIPE_BIND_DISPLAY_TARGET | PIPE_BIND_SAMPLER_VIEW)) { /* TODO: this may be incorrect or suboptimal */ if (!(bind & PIPE_BIND_SCANOUT)) flags |= NOUVEAU_BO_GART; if (usage != PIPE_USAGE_DYNAMIC) flags |= NOUVEAU_BO_VRAM; if (dev->chipset == 0x50 || dev->chipset >= 0x80) { if (bind & PIPE_BIND_DEPTH_STENCIL) tile_flags = 0x2800; else tile_flags = 0x7000; } } ret = nouveau_bo_new_tile(dev, flags, alignment, size, tile_mode, tile_flags, &bo); if (ret) return NULL; return bo; }
Bool nouveau_allocate_surface(ScrnInfoPtr scrn, int width, int height, int bpp, int usage_hint, int *pitch, struct nouveau_bo **bo) { NVPtr pNv = NVPTR(scrn); Bool scanout = (usage_hint & NOUVEAU_CREATE_PIXMAP_SCANOUT); Bool tiled = (usage_hint & NOUVEAU_CREATE_PIXMAP_TILED); int tile_mode = 0, tile_flags = 0; int flags = NOUVEAU_BO_MAP | (bpp >= 8 ? NOUVEAU_BO_VRAM : 0); int cpp = bpp / 8, ret; if (pNv->Architecture >= NV_ARCH_50) { if (scanout) { if (pNv->tiled_scanout) { tiled = TRUE; *pitch = NOUVEAU_ALIGN(width * cpp, 64); } else { *pitch = NOUVEAU_ALIGN(width * cpp, 256); } } else { if (bpp >= 8) tiled = TRUE; *pitch = NOUVEAU_ALIGN(width * cpp, 64); } } else { if (scanout && pNv->tiled_scanout) tiled = TRUE; *pitch = NOUVEAU_ALIGN(width * cpp, 64); } if (tiled) { if (pNv->Architecture >= NV_ARCH_C0) { if (height > 64) tile_mode = 0x40; else if (height > 32) tile_mode = 0x30; else if (height > 16) tile_mode = 0x20; else if (height > 8) tile_mode = 0x10; else tile_mode = 0x00; if (usage_hint & NOUVEAU_CREATE_PIXMAP_ZETA) tile_flags = (bpp == 16) ? 0x0100 : 0x1100; /* Z16 : Z24S8 */ else tile_flags = 0xfe00; height = NOUVEAU_ALIGN( height, NVC0_TILE_HEIGHT(tile_mode)); } else if (pNv->Architecture >= NV_ARCH_50) { if (height > 32) tile_mode = 4; else if (height > 16) tile_mode = 3; else if (height > 8) tile_mode = 2; else if (height > 4) tile_mode = 1; else tile_mode = 0; if (usage_hint & NOUVEAU_CREATE_PIXMAP_ZETA) tile_flags = (bpp == 16) ? 0x26c00 : 0x22800; else if (usage_hint & NOUVEAU_CREATE_PIXMAP_SCANOUT) tile_flags = (bpp == 16 ? 0x7000 : 0x7a00); else tile_flags = 0x7000; height = NOUVEAU_ALIGN(height, 1 << (tile_mode + 2)); } else { int pitch_align = max( pNv->dev->chipset >= 0x40 ? 1024 : 256, round_down_pow2(*pitch / 4)); tile_mode = *pitch = NOUVEAU_ALIGN(*pitch, pitch_align); } } if (bpp == 32) tile_flags |= NOUVEAU_BO_TILE_32BPP; else if (bpp == 16) tile_flags |= NOUVEAU_BO_TILE_16BPP; if (usage_hint & NOUVEAU_CREATE_PIXMAP_ZETA) tile_flags |= NOUVEAU_BO_TILE_ZETA; if (usage_hint & NOUVEAU_CREATE_PIXMAP_SCANOUT) tile_flags |= NOUVEAU_BO_TILE_SCANOUT; ret = nouveau_bo_new_tile(pNv->dev, flags, 0, *pitch * height, tile_mode, tile_flags, bo); if (ret) return FALSE; return TRUE; }
static struct pipe_texture * nv50_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *tmp) { struct nouveau_device *dev = nouveau_screen(pscreen)->device; struct nv50_miptree *mt = CALLOC_STRUCT(nv50_miptree); struct pipe_texture *pt = &mt->base.base; unsigned width = tmp->width0, height = tmp->height0; unsigned depth = tmp->depth0, image_alignment; uint32_t tile_flags; int ret, i, l; *pt = *tmp; pipe_reference_init(&pt->reference, 1); pt->screen = pscreen; switch (pt->format) { case PIPE_FORMAT_Z32_FLOAT: tile_flags = 0x4800; break; case PIPE_FORMAT_S8Z24_UNORM: tile_flags = 0x1800; break; case PIPE_FORMAT_Z16_UNORM: tile_flags = 0x6c00; break; case PIPE_FORMAT_Z24X8_UNORM: case PIPE_FORMAT_Z24S8_UNORM: tile_flags = 0x2800; break; case PIPE_FORMAT_R32G32B32A32_FLOAT: case PIPE_FORMAT_R32G32B32_FLOAT: tile_flags = 0x7400; break; default: if ((pt->tex_usage & PIPE_TEXTURE_USAGE_PRIMARY) && util_format_get_blocksizebits(pt->format) == 32) tile_flags = 0x7a00; else tile_flags = 0x7000; break; } /* XXX: texture arrays */ mt->image_nr = (pt->target == PIPE_TEXTURE_CUBE) ? 6 : 1; for (l = 0; l <= pt->last_level; l++) { struct nv50_miptree_level *lvl = &mt->level[l]; unsigned nblocksy = util_format_get_nblocksy(pt->format, height); lvl->image_offset = CALLOC(mt->image_nr, sizeof(int)); lvl->pitch = align(util_format_get_stride(pt->format, width), 64); lvl->tile_mode = get_tile_mode(nblocksy, depth); width = u_minify(width, 1); height = u_minify(height, 1); depth = u_minify(depth, 1); } image_alignment = get_tile_height(mt->level[0].tile_mode) * 64; image_alignment *= get_tile_depth(mt->level[0].tile_mode); /* NOTE the distinction between arrays of mip-mapped 2D textures and * mip-mapped 3D textures. We can't use image_nr == depth for 3D mip. */ for (i = 0; i < mt->image_nr; i++) { for (l = 0; l <= pt->last_level; l++) { struct nv50_miptree_level *lvl = &mt->level[l]; int size; unsigned tile_h = get_tile_height(lvl->tile_mode); unsigned tile_d = get_tile_depth(lvl->tile_mode); size = lvl->pitch; size *= align(util_format_get_nblocksy(pt->format, u_minify(pt->height0, l)), tile_h); size *= align(u_minify(pt->depth0, l), tile_d); lvl->image_offset[i] = mt->total_size; mt->total_size += size; } mt->total_size = align(mt->total_size, image_alignment); } ret = nouveau_bo_new_tile(dev, NOUVEAU_BO_VRAM, 256, mt->total_size, mt->level[0].tile_mode, tile_flags, &mt->base.bo); if (ret) { for (l = 0; l <= pt->last_level; ++l) FREE(mt->level[l].image_offset); FREE(mt); return NULL; } return pt; }