#include "nvc0_context.h"
#include "nvc0_screen.h"
-#include "nouveau/nv_object.xml.h"
#include "nvc0_graph_macros.h"
static boolean
static int
nvc0_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
{
+ const uint16_t class_3d = nouveau_screen(pscreen)->class_3d;
+
switch (param) {
case PIPE_CAP_MAX_COMBINED_SAMPLERS:
return 16 * PIPE_SHADER_TYPES; /* NOTE: should not count COMPUTE */
case PIPE_CAP_NPOT_TEXTURES:
case PIPE_CAP_ANISOTROPIC_FILTER:
case PIPE_CAP_SEAMLESS_CUBE_MAP:
+ case PIPE_CAP_CUBE_MAP_ARRAY:
return 1;
case PIPE_CAP_SEAMLESS_CUBE_MAP_PER_TEXTURE:
- return 0;
+ return (class_3d >= NVE4_3D_CLASS) ? 1 : 0;
case PIPE_CAP_TWO_SIDED_STENCIL:
case PIPE_CAP_DEPTH_CLIP_DISABLE:
case PIPE_CAP_DEPTHSTENCIL_CLEAR_SEPARATE:
case PIPE_CAP_VERTEX_COLOR_UNCLAMPED:
case PIPE_CAP_VERTEX_COLOR_CLAMPED:
return 1;
- case PIPE_CAP_TIMER_QUERY:
+ case PIPE_CAP_QUERY_TIMESTAMP:
+ case PIPE_CAP_QUERY_TIME_ELAPSED:
case PIPE_CAP_OCCLUSION_QUERY:
case PIPE_CAP_STREAM_OUTPUT_PAUSE_RESUME:
return 1;
case PIPE_CAP_CONDITIONAL_RENDER:
case PIPE_CAP_TEXTURE_BARRIER:
case PIPE_CAP_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION:
+ case PIPE_CAP_START_INSTANCE:
return 1;
case PIPE_CAP_TGSI_CAN_COMPACT_VARYINGS:
case PIPE_CAP_TGSI_CAN_COMPACT_CONSTANTS:
return 0; /* state trackers will know better */
+ case PIPE_CAP_USER_CONSTANT_BUFFERS:
+ case PIPE_CAP_USER_INDEX_BUFFERS:
+ case PIPE_CAP_USER_VERTEX_BUFFERS:
+ return 1;
+ case PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT:
+ return 256;
+ case PIPE_CAP_MIN_MAP_BUFFER_ALIGNMENT:
+ return NOUVEAU_MIN_BUFFER_MAP_ALIGN;
+ case PIPE_CAP_VERTEX_BUFFER_OFFSET_4BYTE_ALIGNED_ONLY:
+ case PIPE_CAP_VERTEX_BUFFER_STRIDE_4BYTE_ALIGNED_ONLY:
+ case PIPE_CAP_VERTEX_ELEMENT_SRC_OFFSET_4BYTE_ALIGNED_ONLY:
+ case PIPE_CAP_TEXTURE_MULTISAMPLE:
+ case PIPE_CAP_TEXTURE_BUFFER_OBJECTS:
+ return 0;
default:
NOUVEAU_ERR("unknown PIPE_CAP %d\n", param);
return 0;
case PIPE_SHADER_CAP_MAX_CONSTS:
return 65536 / 16;
case PIPE_SHADER_CAP_MAX_CONST_BUFFERS:
- return 14;
+ return NVC0_MAX_PIPE_CONSTBUFS;
case PIPE_SHADER_CAP_MAX_ADDRS:
return 1;
case PIPE_SHADER_CAP_INDIRECT_INPUT_ADDR:
if (screen->base.pushbuf)
screen->base.pushbuf->user_priv = NULL;
- if (screen->blitctx)
- FREE(screen->blitctx);
+ if (screen->blitter)
+ nvc0_blitter_destroy(screen);
nouveau_bo_ref(NULL, &screen->text);
+ nouveau_bo_ref(NULL, &screen->uniform_bo);
nouveau_bo_ref(NULL, &screen->tls);
nouveau_bo_ref(NULL, &screen->txc);
nouveau_bo_ref(NULL, &screen->fence.bo);
- nouveau_bo_ref(NULL, &screen->vfetch_cache);
+ nouveau_bo_ref(NULL, &screen->poly_cache);
nouveau_heap_destroy(&screen->lib_code);
nouveau_heap_destroy(&screen->text_heap);
- if (screen->tic.entries)
- FREE(screen->tic.entries);
+ FREE(screen->tic.entries);
nouveau_mm_destroy(screen->mm_VRAM_fe0);
- nouveau_object_del(&screen->fermi);
+ nouveau_object_del(&screen->eng3d);
nouveau_object_del(&screen->eng2d);
nouveau_object_del(&screen->m2mf);
}
static void
-nvc0_magic_3d_init(struct nouveau_pushbuf *push)
+nvc0_magic_3d_init(struct nouveau_pushbuf *push, uint16_t obj_class)
{
BEGIN_NVC0(push, SUBC_3D(0x10cc), 1);
PUSH_DATA (push, 0xff);
BEGIN_NVC0(push, SUBC_3D(0x10e0), 2);
- PUSH_DATA(push, 0xff);
- PUSH_DATA(push, 0xff);
+ PUSH_DATA (push, 0xff);
+ PUSH_DATA (push, 0xff);
BEGIN_NVC0(push, SUBC_3D(0x10ec), 2);
- PUSH_DATA(push, 0xff);
- PUSH_DATA(push, 0xff);
+ PUSH_DATA (push, 0xff);
+ PUSH_DATA (push, 0xff);
BEGIN_NVC0(push, SUBC_3D(0x074c), 1);
PUSH_DATA (push, 0x3f);
BEGIN_NVC0(push, SUBC_3D(0x0de8), 1);
PUSH_DATA (push, 1);
-#if 0 /* software method */
- BEGIN_NVC0(push, SUBC_3D(0x1528), 1); /* MP poke */
- PUSH_DATA (push, 0);
-#endif
-
BEGIN_NVC0(push, SUBC_3D(0x12ac), 1);
PUSH_DATA (push, 0);
BEGIN_NVC0(push, SUBC_3D(0x0218), 1);
BEGIN_NVC0(push, SUBC_3D(0x12d8), 2);
PUSH_DATA (push, 0x10);
PUSH_DATA (push, 0x10);
- BEGIN_NVC0(push, SUBC_3D(0x06d4), 1);
- PUSH_DATA (push, 8);
BEGIN_NVC0(push, SUBC_3D(0x1140), 1);
PUSH_DATA (push, 0x10);
BEGIN_NVC0(push, SUBC_3D(0x1610), 1);
BEGIN_NVC0(push, SUBC_3D(0x164c), 1);
PUSH_DATA (push, 1 << 12);
- BEGIN_NVC0(push, SUBC_3D(0x151c), 1);
- PUSH_DATA (push, 1);
BEGIN_NVC0(push, SUBC_3D(0x030c), 1);
PUSH_DATA (push, 0);
BEGIN_NVC0(push, SUBC_3D(0x0300), 1);
PUSH_DATA (push, 3);
-#if 0 /* software method */
- BEGIN_NVC0(push, SUBC_3D(0x1280), 1); /* PGRAPH poke */
- PUSH_DATA (push, 0);
-#endif
+
BEGIN_NVC0(push, SUBC_3D(0x02d0), 1);
- PUSH_DATA (push, 0x1f40);
+ PUSH_DATA (push, 0x3fffff);
BEGIN_NVC0(push, SUBC_3D(0x0fdc), 1);
PUSH_DATA (push, 1);
BEGIN_NVC0(push, SUBC_3D(0x19c0), 1);
PUSH_DATA (push, 1);
BEGIN_NVC0(push, SUBC_3D(0x075c), 1);
PUSH_DATA (push, 3);
+
+ if (obj_class >= NVE4_3D_CLASS) {
+ BEGIN_NVC0(push, SUBC_3D(0x07fc), 1);
+ PUSH_DATA (push, 1);
+ }
+
+ /* TODO: find out what software methods 0x1528, 0x1280 and (on nve4) 0x02dc
+ * are supposed to do */
}
static void
struct pipe_screen *pscreen;
struct nouveau_object *chan;
struct nouveau_pushbuf *push;
+ uint32_t obj_class;
int ret;
unsigned i;
union nouveau_bo_config mm_config;
+ switch (dev->chipset & ~0xf) {
+ case 0xc0:
+ case 0xd0:
+ case 0xe0:
+ break;
+ default:
+ return NULL;
+ }
+
screen = CALLOC_STRUCT(nvc0_screen);
if (!screen)
return NULL;
pscreen = &screen->base.base;
- screen->base.sysmem_bindings = PIPE_BIND_CONSTANT_BUFFER;
-
ret = nouveau_screen_init(&screen->base, dev);
if (ret) {
nvc0_screen_destroy(pscreen);
push = screen->base.pushbuf;
push->user_priv = screen;
+ screen->base.vidmem_bindings |= PIPE_BIND_CONSTANT_BUFFER |
+ PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_INDEX_BUFFER;
+ screen->base.sysmem_bindings |=
+ PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_INDEX_BUFFER;
+
pscreen->destroy = nvc0_screen_destroy;
pscreen->context_create = nvc0_create;
pscreen->is_format_supported = nvc0_screen_is_format_supported;
screen->base.fence.emit = nvc0_screen_fence_emit;
screen->base.fence.update = nvc0_screen_fence_update;
- ret = nouveau_object_new(chan, 0xbeef9039, NVC0_M2MF_CLASS, NULL, 0,
+ switch (dev->chipset & 0xf0) {
+ case 0xe0:
+ obj_class = NVE4_P2MF_CLASS;
+ break;
+ default:
+ obj_class = NVC0_M2MF_CLASS;
+ break;
+ }
+ ret = nouveau_object_new(chan, 0xbeef323f, obj_class, NULL, 0,
&screen->m2mf);
if (ret)
FAIL_SCREEN_INIT("Error allocating PGRAPH context for M2MF: %d\n", ret);
BEGIN_NVC0(push, SUBC_M2MF(NV01_SUBCHAN_OBJECT), 1);
PUSH_DATA (push, screen->m2mf->oclass);
- BEGIN_NVC0(push, NVC0_M2MF(NOTIFY_ADDRESS_HIGH), 3);
- PUSH_DATAh(push, screen->fence.bo->offset + 16);
- PUSH_DATA (push, screen->fence.bo->offset + 16);
- PUSH_DATA (push, 0);
+ if (screen->m2mf->oclass == NVE4_P2MF_CLASS) {
+ BEGIN_NVC0(push, SUBC_COPY(NV01_SUBCHAN_OBJECT), 1);
+ PUSH_DATA (push, 0xa0b5);
+ }
ret = nouveau_object_new(chan, 0xbeef902d, NVC0_2D_CLASS, NULL, 0,
&screen->eng2d);
BEGIN_NVC0(push, SUBC_2D(0x0888), 1);
PUSH_DATA (push, 1);
- ret = nouveau_object_new(chan, 0xbeef9097, NVC0_3D_CLASS, NULL, 0,
- &screen->fermi);
+ BEGIN_NVC0(push, SUBC_2D(NVC0_GRAPH_NOTIFY_ADDRESS_HIGH), 2);
+ PUSH_DATAh(push, screen->fence.bo->offset + 16);
+ PUSH_DATA (push, screen->fence.bo->offset + 16);
+
+ switch (dev->chipset & 0xf0) {
+ case 0xe0:
+ obj_class = NVE4_3D_CLASS;
+ break;
+ case 0xd0:
+ case 0xc0:
+ default:
+ switch (dev->chipset) {
+ case 0xd9:
+ case 0xc8:
+ obj_class = NVC8_3D_CLASS;
+ break;
+ case 0xc1:
+ obj_class = NVC1_3D_CLASS;
+ break;
+ default:
+ obj_class = NVC0_3D_CLASS;
+ break;
+ }
+ break;
+ }
+ ret = nouveau_object_new(chan, 0xbeef003d, obj_class, NULL, 0,
+ &screen->eng3d);
if (ret)
FAIL_SCREEN_INIT("Error allocating PGRAPH context for 3D: %d\n", ret);
+ screen->base.class_3d = obj_class;
BEGIN_NVC0(push, SUBC_3D(NV01_SUBCHAN_OBJECT), 1);
- PUSH_DATA (push, screen->fermi->oclass);
- BEGIN_NVC0(push, NVC0_3D(NOTIFY_ADDRESS_HIGH), 3);
- PUSH_DATAh(push, screen->fence.bo->offset + 32);
- PUSH_DATA (push, screen->fence.bo->offset + 32);
- PUSH_DATA (push, 0);
+ PUSH_DATA (push, screen->eng3d->oclass);
BEGIN_NVC0(push, NVC0_3D(COND_MODE), 1);
PUSH_DATA (push, NVC0_3D_COND_MODE_ALWAYS);
PUSH_DATA (push, 1);
BEGIN_NVC0(push, NVC0_3D(BLEND_ENABLE_COMMON), 1);
PUSH_DATA (push, 0);
- BEGIN_NVC0(push, NVC0_3D(TEX_MISC), 1);
- PUSH_DATA (push, NVC0_3D_TEX_MISC_SEAMLESS_CUBE_MAP);
+ if (screen->eng3d->oclass < NVE4_3D_CLASS) {
+ BEGIN_NVC0(push, NVC0_3D(TEX_MISC), 1);
+ PUSH_DATA (push, NVC0_3D_TEX_MISC_SEAMLESS_CUBE_MAP);
+ } else {
+ BEGIN_NVC0(push, NVE4_3D(TEX_CB_INDEX), 1);
+ PUSH_DATA (push, 15);
+ }
+ BEGIN_NVC0(push, NVC0_3D(CALL_LIMIT_LOG), 1);
+ PUSH_DATA (push, 8); /* 128 */
+ BEGIN_NVC0(push, NVC0_3D(ZCULL_STATCTRS_ENABLE), 1);
+ PUSH_DATA (push, 1);
+ if (screen->eng3d->oclass >= NVC1_3D_CLASS) {
+ BEGIN_NVC0(push, NVC0_3D(CACHE_SPLIT), 1);
+ PUSH_DATA (push, NVC0_3D_CACHE_SPLIT_48K_SHARED_16K_L1);
+ }
- nvc0_magic_3d_init(push);
+ nvc0_magic_3d_init(push, screen->eng3d->oclass);
ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 1 << 17, 1 << 20, NULL,
&screen->text);
nouveau_heap_init(&screen->text_heap, 0, (1 << 20) - 0x100);
ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 1 << 12, 6 << 16, NULL,
- &screen->uniforms);
+ &screen->uniform_bo);
if (ret)
goto fail;
- /* auxiliary constants (6 user clip planes, base instance id) */
- BEGIN_NVC0(push, NVC0_3D(CB_SIZE), 3);
- PUSH_DATA (push, 256);
- PUSH_DATAh(push, screen->uniforms->offset + (5 << 16));
- PUSH_DATA (push, screen->uniforms->offset + (5 << 16));
for (i = 0; i < 5; ++i) {
+ /* TIC and TSC entries for each unit (nve4+ only) */
+ /* auxiliary constants (6 user clip planes, base instance id) */
+ BEGIN_NVC0(push, NVC0_3D(CB_SIZE), 3);
+ PUSH_DATA (push, 512);
+ PUSH_DATAh(push, screen->uniform_bo->offset + (5 << 16) + (i << 9));
+ PUSH_DATA (push, screen->uniform_bo->offset + (5 << 16) + (i << 9));
BEGIN_NVC0(push, NVC0_3D(CB_BIND(i)), 1);
PUSH_DATA (push, (15 << 4) | 1);
+ if (screen->eng3d->oclass >= NVE4_3D_CLASS) {
+ unsigned j;
+ BEGIN_1IC0(push, NVC0_3D(CB_POS), 9);
+ PUSH_DATA (push, 0);
+ for (j = 0; j < 8; ++j)
+ PUSH_DATA(push, j);
+ } else {
+ BEGIN_NVC0(push, NVC0_3D(TEX_LIMITS(i)), 1);
+ PUSH_DATA (push, 0x54);
+ }
}
+ BEGIN_NVC0(push, NVC0_3D(LINKED_TSC), 1);
+ PUSH_DATA (push, 0);
+
+ /* return { 0.0, 0.0, 0.0, 0.0 } for out-of-bounds vtxbuf access */
+ BEGIN_NVC0(push, NVC0_3D(CB_SIZE), 3);
+ PUSH_DATA (push, 256);
+ PUSH_DATAh(push, screen->uniform_bo->offset + (5 << 16) + (6 << 9));
+ PUSH_DATA (push, screen->uniform_bo->offset + (5 << 16) + (6 << 9));
+ BEGIN_1IC0(push, NVC0_3D(CB_POS), 5);
+ PUSH_DATA (push, 0);
+ PUSH_DATAf(push, 0.0f);
+ PUSH_DATAf(push, 0.0f);
+ PUSH_DATAf(push, 0.0f);
+ PUSH_DATAf(push, 0.0f);
+ BEGIN_NVC0(push, NVC0_3D(VERTEX_RUNOUT_ADDRESS_HIGH), 2);
+ PUSH_DATAh(push, screen->uniform_bo->offset + (5 << 16) + (6 << 9));
+ PUSH_DATA (push, screen->uniform_bo->offset + (5 << 16) + (6 << 9));
+
+ /* max MPs * max warps per MP (TODO: ask kernel) */
+ if (screen->eng3d->oclass >= NVE4_3D_CLASS)
+ screen->tls_size = 8 * 64;
+ else
+ screen->tls_size = 16 * 48;
+ screen->tls_size *= NVC0_CAP_MAX_PROGRAM_TEMPS * 16;
+ screen->tls_size = align(screen->tls_size, 1 << 17);
- screen->tls_size = (16 * 32) * (NVC0_CAP_MAX_PROGRAM_TEMPS * 16);
ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 1 << 17,
screen->tls_size, NULL, &screen->tls);
if (ret)
BEGIN_NVC0(push, NVC0_3D(LOCAL_BASE), 1);
PUSH_DATA (push, 0);
- for (i = 0; i < 5; ++i) {
- BEGIN_NVC0(push, NVC0_3D(TEX_LIMITS(i)), 1);
- PUSH_DATA (push, 0x54);
- }
- BEGIN_NVC0(push, NVC0_3D(LINKED_TSC), 1);
- PUSH_DATA (push, 0);
-
ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 1 << 17, 1 << 20, NULL,
- &screen->vfetch_cache);
+ &screen->poly_cache);
if (ret)
goto fail;
BEGIN_NVC0(push, NVC0_3D(VERTEX_QUARANTINE_ADDRESS_HIGH), 3);
- PUSH_DATAh(push, screen->vfetch_cache->offset);
- PUSH_DATA (push, screen->vfetch_cache->offset);
+ PUSH_DATAh(push, screen->poly_cache->offset);
+ PUSH_DATA (push, screen->poly_cache->offset);
PUSH_DATA (push, 3);
ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 1 << 17, 1 << 17, NULL,
IMMED_NVC0(push, NVC0_3D(EDGEFLAG), 1);
- BEGIN_NVC0(push, NVC0_3D(VERTEX_RUNOUT_ADDRESS_HIGH), 2);
- PUSH_DATA (push, 0xab);
- PUSH_DATA (push, 0x00000000);
-
PUSH_KICK (push);
screen->tic.entries = CALLOC(4096, sizeof(void *));
mm_config.nvc0.memtype = 0xfe0;
screen->mm_VRAM_fe0 = nouveau_mm_create(dev, NOUVEAU_BO_VRAM, &mm_config);
- if (!nvc0_blitctx_create(screen))
+ if (!nvc0_blitter_create(screen))
goto fail;
nouveau_fence_new(&screen->base, &screen->base.fence.current, FALSE);