nv50_screen.c revision fa4b2439d4f240a5e573d4ea198b829791d614f4
1#include "pipe/p_screen.h"
2#include "pipe/p_util.h"
3
4#include "nv50_context.h"
5#include "nv50_screen.h"
6
7#include "nouveau/nouveau_stateobj.h"
8
9#define NV5X_GRCLASS5097_CHIPSETS 0x00000001
10#define NV8X_GRCLASS8297_CHIPSETS 0x00000010
11#define NV9X_GRCLASS8297_CHIPSETS 0x00000004
12
13static boolean
14nv50_screen_is_format_supported(struct pipe_screen *pscreen,
15				enum pipe_format format, uint type)
16{
17	switch (type) {
18	case PIPE_SURFACE:
19		switch (format) {
20		case PIPE_FORMAT_A8R8G8B8_UNORM:
21		case PIPE_FORMAT_R5G6B5_UNORM:
22		case PIPE_FORMAT_Z24S8_UNORM:
23		case PIPE_FORMAT_Z16_UNORM:
24			return TRUE;
25		default:
26			break;
27		}
28		break;
29	case PIPE_TEXTURE:
30		switch (format) {
31		case PIPE_FORMAT_I8_UNORM:
32			return TRUE;
33		default:
34			break;
35		}
36		break;
37	default:
38		assert(0);
39	}
40
41	return FALSE;
42}
43
44static const char *
45nv50_screen_get_name(struct pipe_screen *pscreen)
46{
47	struct nv50_screen *screen = nv50_screen(pscreen);
48	struct nouveau_device *dev = screen->nvws->channel->device;
49	static char buffer[128];
50
51	snprintf(buffer, sizeof(buffer), "NV%02X", dev->chipset);
52	return buffer;
53}
54
55static const char *
56nv50_screen_get_vendor(struct pipe_screen *pscreen)
57{
58	return "nouveau";
59}
60
61static int
62nv50_screen_get_param(struct pipe_screen *pscreen, int param)
63{
64	switch (param) {
65	case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS:
66		return 32;
67	case PIPE_CAP_NPOT_TEXTURES:
68		return 0;
69	case PIPE_CAP_TWO_SIDED_STENCIL:
70		return 1;
71	case PIPE_CAP_GLSL:
72		return 0;
73	case PIPE_CAP_S3TC:
74		return 0;
75	case PIPE_CAP_ANISOTROPIC_FILTER:
76		return 0;
77	case PIPE_CAP_POINT_SPRITE:
78		return 0;
79	case PIPE_CAP_MAX_RENDER_TARGETS:
80		return 8;
81	case PIPE_CAP_OCCLUSION_QUERY:
82		return 0;
83	case PIPE_CAP_TEXTURE_SHADOW_MAP:
84		return 0;
85	case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
86		return 13;
87	case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
88		return 10;
89	case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:
90		return 13;
91	case NOUVEAU_CAP_HW_VTXBUF:
92	case NOUVEAU_CAP_HW_IDXBUF:
93		return 0;
94	default:
95		NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param);
96		return 0;
97	}
98}
99
100static float
101nv50_screen_get_paramf(struct pipe_screen *pscreen, int param)
102{
103	switch (param) {
104	case PIPE_CAP_MAX_LINE_WIDTH:
105	case PIPE_CAP_MAX_LINE_WIDTH_AA:
106		return 10.0;
107	case PIPE_CAP_MAX_POINT_WIDTH:
108	case PIPE_CAP_MAX_POINT_WIDTH_AA:
109		return 64.0;
110	case PIPE_CAP_MAX_TEXTURE_ANISOTROPY:
111		return 16.0;
112	case PIPE_CAP_MAX_TEXTURE_LOD_BIAS:
113		return 4.0;
114	default:
115		NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param);
116		return 0.0;
117	}
118}
119
120static void *
121nv50_surface_map(struct pipe_screen *screen, struct pipe_surface *surface,
122		 unsigned flags )
123{
124	struct pipe_winsys *ws = screen->winsys;
125	void *map;
126
127	map = ws->buffer_map(ws, surface->buffer, flags);
128	if (!map)
129		return NULL;
130
131	return map + surface->offset;
132}
133
134static void
135nv50_surface_unmap(struct pipe_screen *screen, struct pipe_surface *surface)
136{
137	struct pipe_winsys *ws = screen->winsys;
138
139	ws->buffer_unmap(ws, surface->buffer);
140}
141
142static void
143nv50_screen_destroy(struct pipe_screen *pscreen)
144{
145	FREE(pscreen);
146}
147
148struct pipe_screen *
149nv50_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws)
150{
151	struct nv50_screen *screen = CALLOC_STRUCT(nv50_screen);
152	struct nouveau_stateobj *so;
153	unsigned tesla_class = 0, ret;
154	unsigned chipset = nvws->channel->device->chipset;
155	int i;
156
157	if (!screen)
158		return NULL;
159	screen->nvws = nvws;
160
161	/* 3D object */
162	if ((chipset & 0xf0) != 0x50 && (chipset & 0xf0) != 0x80) {
163		NOUVEAU_ERR("Not a G8x chipset\n");
164		nv50_screen_destroy(&screen->pipe);
165		return NULL;
166	}
167
168	switch (chipset & 0xf0) {
169	case 0x50:
170		if (NV5X_GRCLASS5097_CHIPSETS & (1 << (chipset & 0x0f)))
171			tesla_class = 0x5097;
172		break;
173	case 0x80:
174		if (NV8X_GRCLASS8297_CHIPSETS & (1 << (chipset & 0x0f)))
175			tesla_class = 0x8297;
176		break;
177	case 0x90:
178		if (NV9X_GRCLASS8297_CHIPSETS & (1 << (chipset & 0x0f)))
179			tesla_class = 0x8297;
180		break;
181	default:
182		break;
183	}
184
185	if (tesla_class == 0) {
186		NOUVEAU_ERR("Unknown G8x chipset: NV%02x\n", chipset);
187		nv50_screen_destroy(&screen->pipe);
188		return NULL;
189	}
190
191	ret = nvws->grobj_alloc(nvws, tesla_class, &screen->tesla);
192	if (ret) {
193		NOUVEAU_ERR("Error creating 3D object: %d\n", ret);
194		nv50_screen_destroy(&screen->pipe);
195		return NULL;
196	}
197
198	/* Sync notifier */
199	ret = nvws->notifier_alloc(nvws, 1, &screen->sync);
200	if (ret) {
201		NOUVEAU_ERR("Error creating notifier object: %d\n", ret);
202		nv50_screen_destroy(&screen->pipe);
203		return NULL;
204	}
205
206	/* Static tesla init */
207	so = so_new(128, 0);
208	so_method(so, screen->tesla, NV50TCL_DMA_NOTIFY, 1);
209	so_data  (so, screen->sync->handle);
210	so_method(so, screen->tesla, NV50TCL_DMA_IN_MEMORY0(0),
211		  NV50TCL_DMA_IN_MEMORY0__SIZE);
212	for (i = 0; i < NV50TCL_DMA_IN_MEMORY0__SIZE; i++)
213		so_data(so, nvws->channel->vram->handle);
214	so_method(so, screen->tesla, NV50TCL_DMA_IN_MEMORY1(0),
215		  NV50TCL_DMA_IN_MEMORY1__SIZE);
216	for (i = 0; i < NV50TCL_DMA_IN_MEMORY1__SIZE; i++)
217		so_data(so, nvws->channel->vram->handle);
218
219	so_emit(nvws, so);
220	so_ref(NULL, &so);
221	nvws->push_flush(nvws, 0, NULL);
222
223	screen->pipe.winsys = ws;
224
225	screen->pipe.destroy = nv50_screen_destroy;
226
227	screen->pipe.get_name = nv50_screen_get_name;
228	screen->pipe.get_vendor = nv50_screen_get_vendor;
229	screen->pipe.get_param = nv50_screen_get_param;
230	screen->pipe.get_paramf = nv50_screen_get_paramf;
231
232	screen->pipe.is_format_supported = nv50_screen_is_format_supported;
233
234	screen->pipe.surface_map = nv50_surface_map;
235	screen->pipe.surface_unmap = nv50_surface_unmap;
236
237	nv50_screen_init_miptree_functions(&screen->pipe);
238
239	return &screen->pipe;
240}
241
242