nv50_screen.c 14.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
/*
 * Copyright 2008 Ben Skeggs
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

Ben Skeggs's avatar
Ben Skeggs committed
23 24 25 26 27
#include "pipe/p_screen.h"

#include "nv50_context.h"
#include "nv50_screen.h"

28 29
#include "nouveau/nouveau_stateobj.h"

Ben Skeggs's avatar
Ben Skeggs committed
30 31
static boolean
nv50_screen_is_format_supported(struct pipe_screen *pscreen,
32 33 34
				enum pipe_format format,
				enum pipe_texture_target target,
				unsigned tex_usage, unsigned geom_flags)
Ben Skeggs's avatar
Ben Skeggs committed
35
{
36
	if (tex_usage & PIPE_TEXTURE_USAGE_RENDER_TARGET) {
37
		switch (format) {
Jose Fonseca's avatar
Jose Fonseca committed
38 39 40
		case PIPE_FORMAT_B8G8R8X8_UNORM:
		case PIPE_FORMAT_B8G8R8A8_UNORM:
		case PIPE_FORMAT_B5G6R5_UNORM:
41 42 43 44 45
		case PIPE_FORMAT_R16G16B16A16_SNORM:
		case PIPE_FORMAT_R16G16B16A16_UNORM:
		case PIPE_FORMAT_R32G32B32A32_FLOAT:
		case PIPE_FORMAT_R16G16_SNORM:
		case PIPE_FORMAT_R16G16_UNORM:
46 47 48 49 50 51 52
			return TRUE;
		default:
			break;
		}
	} else
	if (tex_usage & PIPE_TEXTURE_USAGE_DEPTH_STENCIL) {
		switch (format) {
53 54
		case PIPE_FORMAT_Z32_FLOAT:
		case PIPE_FORMAT_S8Z24_UNORM:
Jose Fonseca's avatar
Jose Fonseca committed
55 56
		case PIPE_FORMAT_Z24X8_UNORM:
		case PIPE_FORMAT_Z24S8_UNORM:
57 58 59 60
			return TRUE;
		default:
			break;
		}
61
	} else {
62
		switch (format) {
Jose Fonseca's avatar
Jose Fonseca committed
63 64 65 66 67 68 69
		case PIPE_FORMAT_B8G8R8A8_UNORM:
		case PIPE_FORMAT_B8G8R8X8_UNORM:
		case PIPE_FORMAT_B8G8R8A8_SRGB:
		case PIPE_FORMAT_B8G8R8X8_SRGB:
		case PIPE_FORMAT_B5G5R5A1_UNORM:
		case PIPE_FORMAT_B4G4R4A4_UNORM:
		case PIPE_FORMAT_B5G6R5_UNORM:
Ben Skeggs's avatar
Ben Skeggs committed
70 71
		case PIPE_FORMAT_L8_UNORM:
		case PIPE_FORMAT_A8_UNORM:
72
		case PIPE_FORMAT_I8_UNORM:
Jose Fonseca's avatar
Jose Fonseca committed
73
		case PIPE_FORMAT_L8A8_UNORM:
Ben Skeggs's avatar
Ben Skeggs committed
74 75 76 77
		case PIPE_FORMAT_DXT1_RGB:
		case PIPE_FORMAT_DXT1_RGBA:
		case PIPE_FORMAT_DXT3_RGBA:
		case PIPE_FORMAT_DXT5_RGBA:
78
		case PIPE_FORMAT_S8Z24_UNORM:
Jose Fonseca's avatar
Jose Fonseca committed
79
		case PIPE_FORMAT_Z24S8_UNORM:
80 81 82 83 84 85
		case PIPE_FORMAT_Z32_FLOAT:
		case PIPE_FORMAT_R16G16B16A16_SNORM:
		case PIPE_FORMAT_R16G16B16A16_UNORM:
		case PIPE_FORMAT_R32G32B32A32_FLOAT:
		case PIPE_FORMAT_R16G16_SNORM:
		case PIPE_FORMAT_R16G16_UNORM:
86 87 88 89 90 91
			return TRUE;
		default:
			break;
		}
	}

Ben Skeggs's avatar
Ben Skeggs committed
92 93 94 95 96 97
	return FALSE;
}

static int
nv50_screen_get_param(struct pipe_screen *pscreen, int param)
{
98 99
	struct nv50_screen *screen = nv50_screen(pscreen);

Ben Skeggs's avatar
Ben Skeggs committed
100 101 102
	switch (param) {
	case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS:
		return 32;
103 104 105 106
	case PIPE_CAP_MAX_VERTEX_TEXTURE_UNITS:
		return 32;
	case PIPE_CAP_MAX_COMBINED_SAMPLERS:
		return 64;
Ben Skeggs's avatar
Ben Skeggs committed
107
	case PIPE_CAP_NPOT_TEXTURES:
Ben Skeggs's avatar
Ben Skeggs committed
108
		return 1;
Ben Skeggs's avatar
Ben Skeggs committed
109 110 111
	case PIPE_CAP_TWO_SIDED_STENCIL:
		return 1;
	case PIPE_CAP_GLSL:
112
		return 1;
Ben Skeggs's avatar
Ben Skeggs committed
113
	case PIPE_CAP_ANISOTROPIC_FILTER:
Ben Skeggs's avatar
Ben Skeggs committed
114
		return 1;
Ben Skeggs's avatar
Ben Skeggs committed
115
	case PIPE_CAP_POINT_SPRITE:
116
		return 1;
Ben Skeggs's avatar
Ben Skeggs committed
117 118 119
	case PIPE_CAP_MAX_RENDER_TARGETS:
		return 8;
	case PIPE_CAP_OCCLUSION_QUERY:
Ben Skeggs's avatar
Ben Skeggs committed
120
		return 1;
Ben Skeggs's avatar
Ben Skeggs committed
121
	case PIPE_CAP_TEXTURE_SHADOW_MAP:
Ben Skeggs's avatar
Ben Skeggs committed
122
		return 1;
Ben Skeggs's avatar
Ben Skeggs committed
123 124 125 126 127 128
	case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
		return 13;
	case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
		return 10;
	case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:
		return 13;
129 130 131
	case PIPE_CAP_TEXTURE_MIRROR_CLAMP:
	case PIPE_CAP_TEXTURE_MIRROR_REPEAT:
		return 1;
132
	case PIPE_CAP_TGSI_CONT_SUPPORTED:
133
		return 1;
134 135
	case PIPE_CAP_BLEND_EQUATION_SEPARATE:
		return 1;
Victor Stinner's avatar
Victor Stinner committed
136
	case NOUVEAU_CAP_HW_VTXBUF:
137
		return screen->force_push ? 0 : 1;
Victor Stinner's avatar
Victor Stinner committed
138
	case NOUVEAU_CAP_HW_IDXBUF:
139
		return screen->force_push ? 0 : 1;
140
	case PIPE_CAP_INDEP_BLEND_ENABLE:
141
		return 1;
142 143
	case PIPE_CAP_INDEP_BLEND_FUNC:
		return 0;
144 145 146 147 148 149
	case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT:
	case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER:
		return 1;
	case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT:
	case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER:
		return 0;
Ben Skeggs's avatar
Ben Skeggs committed
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
	default:
		NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param);
		return 0;
	}
}

static float
nv50_screen_get_paramf(struct pipe_screen *pscreen, int param)
{
	switch (param) {
	case PIPE_CAP_MAX_LINE_WIDTH:
	case PIPE_CAP_MAX_LINE_WIDTH_AA:
		return 10.0;
	case PIPE_CAP_MAX_POINT_WIDTH:
	case PIPE_CAP_MAX_POINT_WIDTH_AA:
		return 64.0;
	case PIPE_CAP_MAX_TEXTURE_ANISOTROPY:
		return 16.0;
	case PIPE_CAP_MAX_TEXTURE_LOD_BIAS:
		return 4.0;
	default:
		NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param);
		return 0.0;
	}
}

static void
nv50_screen_destroy(struct pipe_screen *pscreen)
{
179
	struct nv50_screen *screen = nv50_screen(pscreen);
180 181
	unsigned i;

182
	for (i = 0; i < 3; i++) {
183 184 185 186 187 188 189 190 191 192
		if (screen->constbuf_parm[i])
			nouveau_bo_ref(NULL, &screen->constbuf_parm[i]);
	}

	if (screen->constbuf_misc[0])
		nouveau_bo_ref(NULL, &screen->constbuf_misc[0]);
	if (screen->tic)
		nouveau_bo_ref(NULL, &screen->tic);
	if (screen->tsc)
		nouveau_bo_ref(NULL, &screen->tsc);
193

194 195 196 197
	nouveau_notifier_free(&screen->sync);
	nouveau_grobj_free(&screen->tesla);
	nouveau_grobj_free(&screen->eng2d);
	nouveau_grobj_free(&screen->m2mf);
198 199 200
	nouveau_resource_destroy(&screen->immd_heap[0]);
	nouveau_resource_destroy(&screen->parm_heap[0]);
	nouveau_resource_destroy(&screen->parm_heap[1]);
201 202
	nouveau_screen_fini(&screen->base);
	FREE(screen);
Ben Skeggs's avatar
Ben Skeggs committed
203 204
}

205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253
#define BGN_RELOC(ch, bo, gr, m, n, fl) \
   OUT_RELOC(ch, bo, (n << 18) | (gr->subc << 13) | m, fl, 0, 0)

void
nv50_screen_relocs(struct nv50_screen *screen)
{
	struct nouveau_channel *chan = screen->base.channel;
	struct nouveau_grobj *tesla = screen->tesla;
	unsigned i;
	const unsigned rl = NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_DUMMY;

	MARK_RING (chan, 28, 26);

	/* cause grobj autobind */
	BEGIN_RING(chan, tesla, 0x0100, 1);
	OUT_RING  (chan, 0);

	BGN_RELOC (chan, screen->tic, tesla, NV50TCL_TIC_ADDRESS_HIGH, 2, rl);
	OUT_RELOCh(chan, screen->tic, 0, rl);
	OUT_RELOCl(chan, screen->tic, 0, rl);

	BGN_RELOC (chan, screen->tsc, tesla, NV50TCL_TSC_ADDRESS_HIGH, 2, rl);
	OUT_RELOCh(chan, screen->tsc, 0, rl);
	OUT_RELOCl(chan, screen->tsc, 0, rl);

	BGN_RELOC (chan, screen->constbuf_misc[0],
		   tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3, rl);
	OUT_RELOCh(chan, screen->constbuf_misc[0], 0, rl);
	OUT_RELOCl(chan, screen->constbuf_misc[0], 0, rl);
	OUT_RELOC (chan, screen->constbuf_misc[0],
		   (NV50_CB_PMISC << 16) | 0x0200, rl, 0, 0);

	BGN_RELOC (chan, screen->constbuf_misc[0],
		   tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3, rl);
	OUT_RELOCh(chan, screen->constbuf_misc[0], 0x200, rl);
	OUT_RELOCl(chan, screen->constbuf_misc[0], 0x200, rl);
	OUT_RELOC (chan, screen->constbuf_misc[0],
		   (NV50_CB_AUX << 16) | 0x0200, rl, 0, 0);

	for (i = 0; i < 3; ++i) {
		BGN_RELOC (chan, screen->constbuf_parm[i],
			   tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3, rl);
		OUT_RELOCh(chan, screen->constbuf_parm[i], 0, rl);
		OUT_RELOCl(chan, screen->constbuf_parm[i], 0, rl);
		OUT_RELOC (chan, screen->constbuf_parm[i],
			   ((NV50_CB_PVP + i) << 16) | 0x0800, rl, 0, 0);
	}
}

Ben Skeggs's avatar
Ben Skeggs committed
254
struct pipe_screen *
255
nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev)
Ben Skeggs's avatar
Ben Skeggs committed
256 257
{
	struct nv50_screen *screen = CALLOC_STRUCT(nv50_screen);
258
	struct nouveau_channel *chan;
259
	struct pipe_screen *pscreen;
260 261 262
	unsigned chipset = dev->chipset;
	unsigned tesla_class = 0;
	int ret, i;
263
	const unsigned rl = NOUVEAU_BO_VRAM | NOUVEAU_BO_RD;
Ben Skeggs's avatar
Ben Skeggs committed
264 265 266

	if (!screen)
		return NULL;
267 268
	pscreen = &screen->base.base;

269
	ret = nouveau_screen_init(&screen->base, dev);
270 271 272 273
	if (ret) {
		nv50_screen_destroy(pscreen);
		return NULL;
	}
274
	chan = screen->base.channel;
Ben Skeggs's avatar
Ben Skeggs committed
275

276 277 278 279 280
	pscreen->winsys = ws;
	pscreen->destroy = nv50_screen_destroy;
	pscreen->get_param = nv50_screen_get_param;
	pscreen->get_paramf = nv50_screen_get_paramf;
	pscreen->is_format_supported = nv50_screen_is_format_supported;
281
	pscreen->context_create = nv50_create;
282 283 284

	nv50_screen_init_miptree_functions(pscreen);

285
	/* DMA engine object */
286 287
	ret = nouveau_grobj_alloc(chan, 0xbeef5039,
		NV50_MEMORY_TO_MEMORY_FORMAT, &screen->m2mf);
288 289
	if (ret) {
		NOUVEAU_ERR("Error creating M2MF object: %d\n", ret);
290
		nv50_screen_destroy(pscreen);
291 292 293
		return NULL;
	}

294
	/* 2D object */
295
	ret = nouveau_grobj_alloc(chan, 0xbeef502d, NV50_2D, &screen->eng2d);
296 297
	if (ret) {
		NOUVEAU_ERR("Error creating 2D object: %d\n", ret);
298
		nv50_screen_destroy(pscreen);
299 300 301
		return NULL;
	}

302
	/* 3D object */
303 304
	switch (chipset & 0xf0) {
	case 0x50:
305
		tesla_class = NV50TCL;
306 307 308
		break;
	case 0x80:
	case 0x90:
309
		tesla_class = NV84TCL;
310
		break;
311
	case 0xa0:
312 313 314 315 316 317 318
		switch (chipset) {
		case 0xa0:
		case 0xaa:
		case 0xac:
			tesla_class = NVA0TCL;
			break;
		default:
319
			tesla_class = NVA8TCL;
320 321
			break;
		}
322
		break;
323 324
	default:
		NOUVEAU_ERR("Not a known NV50 chipset: NV%02x\n", chipset);
325
		nv50_screen_destroy(pscreen);
326
		return NULL;
327 328
	}

329 330
	ret = nouveau_grobj_alloc(chan, 0xbeef5097, tesla_class,
		&screen->tesla);
331 332
	if (ret) {
		NOUVEAU_ERR("Error creating 3D object: %d\n", ret);
333
		nv50_screen_destroy(pscreen);
334 335 336 337
		return NULL;
	}

	/* Sync notifier */
338
	ret = nouveau_notifier_alloc(chan, 0xbeef0301, 1, &screen->sync);
339 340
	if (ret) {
		NOUVEAU_ERR("Error creating notifier object: %d\n", ret);
341
		nv50_screen_destroy(pscreen);
342 343 344
		return NULL;
	}

345
	/* Static M2MF init */
346 347 348 349 350
	BEGIN_RING(chan, screen->m2mf,
		   NV04_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 3);
	OUT_RING  (chan, screen->sync->handle);
	OUT_RING  (chan, chan->vram->handle);
	OUT_RING  (chan, chan->vram->handle);
351

352
	/* Static 2D init */
353 354 355 356 357 358 359 360 361 362 363
	BEGIN_RING(chan, screen->eng2d, NV50_2D_DMA_NOTIFY, 4);
	OUT_RING  (chan, screen->sync->handle);
	OUT_RING  (chan, chan->vram->handle);
	OUT_RING  (chan, chan->vram->handle);
	OUT_RING  (chan, chan->vram->handle);
	BEGIN_RING(chan, screen->eng2d, NV50_2D_OPERATION, 1);
	OUT_RING  (chan, NV50_2D_OPERATION_SRCCOPY);
	BEGIN_RING(chan, screen->eng2d, NV50_2D_CLIP_ENABLE, 1);
	OUT_RING  (chan, 0);
	BEGIN_RING(chan, screen->eng2d, 0x0888, 1);
	OUT_RING  (chan, 1);
364

365
	/* Static tesla init */
366 367 368 369 370
	BEGIN_RING(chan, screen->tesla, NV50TCL_COND_MODE, 1);
	OUT_RING  (chan, NV50TCL_COND_MODE_ALWAYS);
	BEGIN_RING(chan, screen->tesla, NV50TCL_DMA_NOTIFY, 1);
	OUT_RING  (chan, screen->sync->handle);
	BEGIN_RING(chan, screen->tesla, NV50TCL_DMA_ZETA, 11);
371
	for (i = 0; i < 11; i++)
372 373 374
		OUT_RING  (chan, chan->vram->handle);
	BEGIN_RING(chan, screen->tesla,
		   NV50TCL_DMA_COLOR(0), NV50TCL_DMA_COLOR__SIZE);
375
	for (i = 0; i < NV50TCL_DMA_COLOR__SIZE; i++)
376 377 378 379
		OUT_RING  (chan, chan->vram->handle);

	BEGIN_RING(chan, screen->tesla, NV50TCL_RT_CONTROL, 1);
	OUT_RING  (chan, 1);
380

381
	/* activate all 32 lanes (threads) in a warp */
382 383 384 385
	BEGIN_RING(chan, screen->tesla, NV50TCL_WARP_HALVES, 1);
	OUT_RING  (chan, 2);
	BEGIN_RING(chan, screen->tesla, 0x1400, 1);
	OUT_RING  (chan, 0xf);
386

387
	/* max TIC (bits 4:8) & TSC (ignored) bindings, per program type */
388
	for (i = 0; i < 3; ++i) {
389 390
		BEGIN_RING(chan, screen->tesla, NV50TCL_TEX_LIMITS(i), 1);
		OUT_RING  (chan, 0x54);
391 392
	}

393
	/* origin is top left (set to 1 for bottom left) */
394 395 396 397
	BEGIN_RING(chan, screen->tesla, NV50TCL_Y_ORIGIN_BOTTOM, 1);
	OUT_RING  (chan, 0);
	BEGIN_RING(chan, screen->tesla, NV50TCL_VP_REG_ALLOC_RESULT, 1);
	OUT_RING  (chan, 8);
398

399
	/* constant buffers for immediates and VP/FP parameters */
400
	ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, (32 * 4) * 4,
401 402
			     &screen->constbuf_misc[0]);
	if (ret) {
403
		nv50_screen_destroy(pscreen);
404 405
		return NULL;
	}
406 407 408 409 410 411 412 413
	BEGIN_RING(chan, screen->tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3);
	OUT_RELOCh(chan, screen->constbuf_misc[0], 0, rl);
	OUT_RELOCl(chan, screen->constbuf_misc[0], 0, rl);
	OUT_RING  (chan, (NV50_CB_PMISC << 16) | 0x0200);
	BEGIN_RING(chan, screen->tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3);
	OUT_RELOCh(chan, screen->constbuf_misc[0], 0x200, rl);
	OUT_RELOCl(chan, screen->constbuf_misc[0], 0x200, rl);
	OUT_RING  (chan, (NV50_CB_AUX << 16) | 0x0200);
414

415
	for (i = 0; i < 3; i++) {
416
		ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, (256 * 4) * 4,
417 418
				     &screen->constbuf_parm[i]);
		if (ret) {
419
			nv50_screen_destroy(pscreen);
420 421
			return NULL;
		}
422 423 424 425
		BEGIN_RING(chan, screen->tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3);
		OUT_RELOCh(chan, screen->constbuf_parm[i], 0, rl);
		OUT_RELOCl(chan, screen->constbuf_parm[i], 0, rl);
		OUT_RING  (chan, ((NV50_CB_PVP + i) << 16) | 0x0800);
426
	}
427

428
	if (nouveau_resource_init(&screen->immd_heap[0], 0, 128) ||
429 430
	    nouveau_resource_init(&screen->parm_heap[0], 0, 512) ||
	    nouveau_resource_init(&screen->parm_heap[1], 0, 512))
431 432
	{
		NOUVEAU_ERR("Error initialising constant buffers.\n");
433
		nv50_screen_destroy(pscreen);
434 435 436
		return NULL;
	}

437
	ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, 3 * 32 * (8 * 4),
438
			     &screen->tic);
439
	if (ret) {
440
		nv50_screen_destroy(pscreen);
441 442
		return NULL;
	}
443 444 445 446
	BEGIN_RING(chan, screen->tesla, NV50TCL_TIC_ADDRESS_HIGH, 3);
	OUT_RELOCh(chan, screen->tic, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
	OUT_RELOCl(chan, screen->tic, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
	OUT_RING  (chan, 3 * 32 - 1);
447

448
	ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, 3 * 32 * (8 * 4),
449
			     &screen->tsc);
450
	if (ret) {
451
		nv50_screen_destroy(pscreen);
452 453
		return NULL;
	}
454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476
	BEGIN_RING(chan, screen->tesla, NV50TCL_TSC_ADDRESS_HIGH, 3);
	OUT_RELOCh(chan, screen->tsc, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
	OUT_RELOCl(chan, screen->tsc, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
	OUT_RING  (chan, 0); /* ignored if TSC_LINKED (0x1234) == 1 */

	/* map constant buffers:
	 *  B = buffer ID (maybe more than 1 byte)
	 *  N = CB index used in shader instruction
	 *  P = program type (0 = VP, 2 = GP, 3 = FP)
	 * SET_PROGRAM_CB = 0x000BBNP1
	 */
	BEGIN_RING_NI(chan, screen->tesla, NV50TCL_SET_PROGRAM_CB, 8);
	/* bind immediate buffer */
	OUT_RING  (chan, 0x001 | (NV50_CB_PMISC << 12));
	OUT_RING  (chan, 0x021 | (NV50_CB_PMISC << 12));
	OUT_RING  (chan, 0x031 | (NV50_CB_PMISC << 12));
	/* bind auxiliary constbuf to immediate data bo */
	OUT_RING  (chan, 0x201 | (NV50_CB_AUX << 12));
	OUT_RING  (chan, 0x221 | (NV50_CB_AUX << 12));
	/* bind parameter buffers */
	OUT_RING  (chan, 0x101 | (NV50_CB_PVP << 12));
	OUT_RING  (chan, 0x121 | (NV50_CB_PGP << 12));
	OUT_RING  (chan, 0x131 | (NV50_CB_PFP << 12));
477

478
	/* Vertex array limits - max them out */
479
	for (i = 0; i < 16; i++) {
480 481 482 483
		BEGIN_RING(chan, screen->tesla,
			   NV50TCL_VERTEX_ARRAY_LIMIT_HIGH(i), 2);
		OUT_RING  (chan, 0x000000ff);
		OUT_RING  (chan, 0xffffffff);
484
	}
Ben Skeggs's avatar
Ben Skeggs committed
485

486 487 488
	BEGIN_RING(chan, screen->tesla, NV50TCL_DEPTH_RANGE_NEAR(0), 2);
	OUT_RINGf (chan, 0.0f);
	OUT_RINGf (chan, 1.0f);
489

490
	/* no dynamic combination of TIC & TSC entries => only BIND_TIC used */
491 492
	BEGIN_RING(chan, screen->tesla, NV50TCL_LINKED_TSC, 1);
	OUT_RING  (chan, 1);
Ben Skeggs's avatar
Ben Skeggs committed
493

494 495
	BEGIN_RING(chan, screen->tesla, NV50TCL_EDGEFLAG_ENABLE, 1);
	OUT_RING  (chan, 1); /* default edgeflag to TRUE */
496

497
	FIRE_RING (chan);
498

499
	screen->force_push = debug_get_bool_option("NV50_ALWAYS_PUSH", FALSE);
500
	return pscreen;
Ben Skeggs's avatar
Ben Skeggs committed
501 502
}