nouveau: Rename pipe formats.
[mesa.git] / src / gallium / drivers / nv30 / nv30_screen.c
1 #include "pipe/p_screen.h"
2 #include "pipe/p_state.h"
3
4 #include "nouveau/nouveau_screen.h"
5
6 #include "nv30_context.h"
7 #include "nv30_screen.h"
8
9 #define NV30TCL_CHIPSET_3X_MASK 0x00000003
10 #define NV34TCL_CHIPSET_3X_MASK 0x00000010
11 #define NV35TCL_CHIPSET_3X_MASK 0x000001e0
12
13 /* FIXME: It seems I should not include directly ../../winsys/drm/nouveau/drm/nouveau_drm_api.h
14 * to get the pointer to the context front buffer, so I copied nouveau_winsys here.
15 * nv30_screen_surface_format_supported() can then use it to enforce creating fbo
16 * with same number of bits everywhere.
17 */
18 struct nouveau_winsys {
19 struct pipe_winsys base;
20
21 struct pipe_screen *pscreen;
22
23 struct pipe_surface *front;
24 };
25
26 static int
27 nv30_screen_get_param(struct pipe_screen *pscreen, int param)
28 {
29 switch (param) {
30 case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS:
31 return 8;
32 case PIPE_CAP_NPOT_TEXTURES:
33 return 0;
34 case PIPE_CAP_TWO_SIDED_STENCIL:
35 return 1;
36 case PIPE_CAP_GLSL:
37 return 0;
38 case PIPE_CAP_ANISOTROPIC_FILTER:
39 return 1;
40 case PIPE_CAP_POINT_SPRITE:
41 return 1;
42 case PIPE_CAP_MAX_RENDER_TARGETS:
43 return 2;
44 case PIPE_CAP_OCCLUSION_QUERY:
45 return 1;
46 case PIPE_CAP_TEXTURE_SHADOW_MAP:
47 return 1;
48 case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
49 return 13;
50 case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
51 return 10;
52 case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:
53 return 13;
54 case PIPE_CAP_TEXTURE_MIRROR_CLAMP:
55 return 0;
56 case PIPE_CAP_TEXTURE_MIRROR_REPEAT:
57 return 1;
58 case PIPE_CAP_MAX_VERTEX_TEXTURE_UNITS:
59 return 0;
60 case PIPE_CAP_TGSI_CONT_SUPPORTED:
61 return 0;
62 case PIPE_CAP_BLEND_EQUATION_SEPARATE:
63 return 0;
64 case NOUVEAU_CAP_HW_VTXBUF:
65 case NOUVEAU_CAP_HW_IDXBUF:
66 return 1;
67 case PIPE_CAP_MAX_COMBINED_SAMPLERS:
68 return 16;
69 case PIPE_CAP_INDEP_BLEND_ENABLE:
70 return 0;
71 case PIPE_CAP_INDEP_BLEND_FUNC:
72 return 0;
73 case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT:
74 case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER:
75 return 1;
76 case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT:
77 case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER:
78 return 0;
79 default:
80 NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param);
81 return 0;
82 }
83 }
84
85 static float
86 nv30_screen_get_paramf(struct pipe_screen *pscreen, int param)
87 {
88 switch (param) {
89 case PIPE_CAP_MAX_LINE_WIDTH:
90 case PIPE_CAP_MAX_LINE_WIDTH_AA:
91 return 10.0;
92 case PIPE_CAP_MAX_POINT_WIDTH:
93 case PIPE_CAP_MAX_POINT_WIDTH_AA:
94 return 64.0;
95 case PIPE_CAP_MAX_TEXTURE_ANISOTROPY:
96 return 8.0;
97 case PIPE_CAP_MAX_TEXTURE_LOD_BIAS:
98 return 4.0;
99 default:
100 NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param);
101 return 0.0;
102 }
103 }
104
105 static boolean
106 nv30_screen_surface_format_supported(struct pipe_screen *pscreen,
107 enum pipe_format format,
108 enum pipe_texture_target target,
109 unsigned tex_usage, unsigned geom_flags)
110 {
111 struct pipe_surface *front = ((struct nouveau_winsys *) pscreen->winsys)->front;
112
113 if (tex_usage & PIPE_TEXTURE_USAGE_RENDER_TARGET) {
114 switch (format) {
115 case PIPE_FORMAT_B8G8R8A8_UNORM:
116 case PIPE_FORMAT_B5G6R5_UNORM:
117 return TRUE;
118 default:
119 break;
120 }
121 } else
122 if (tex_usage & PIPE_TEXTURE_USAGE_DEPTH_STENCIL) {
123 switch (format) {
124 case PIPE_FORMAT_S8Z24_UNORM:
125 case PIPE_FORMAT_X8Z24_UNORM:
126 return TRUE;
127 case PIPE_FORMAT_Z16_UNORM:
128 if (front) {
129 return (front->format == PIPE_FORMAT_B5G6R5_UNORM);
130 }
131 return TRUE;
132 default:
133 break;
134 }
135 } else {
136 switch (format) {
137 case PIPE_FORMAT_B8G8R8A8_UNORM:
138 case PIPE_FORMAT_B5G5R5A1_UNORM:
139 case PIPE_FORMAT_B4G4R4A4_UNORM:
140 case PIPE_FORMAT_B5G6R5_UNORM:
141 case PIPE_FORMAT_L8_UNORM:
142 case PIPE_FORMAT_A8_UNORM:
143 case PIPE_FORMAT_I8_UNORM:
144 case PIPE_FORMAT_L8A8_UNORM:
145 case PIPE_FORMAT_Z16_UNORM:
146 case PIPE_FORMAT_S8Z24_UNORM:
147 return TRUE;
148 default:
149 break;
150 }
151 }
152
153 return FALSE;
154 }
155
156 static struct pipe_buffer *
157 nv30_surface_buffer(struct pipe_surface *surf)
158 {
159 struct nv30_miptree *mt = (struct nv30_miptree *)surf->texture;
160
161 return mt->buffer;
162 }
163
164 static void
165 nv30_screen_destroy(struct pipe_screen *pscreen)
166 {
167 struct nv30_screen *screen = nv30_screen(pscreen);
168 unsigned i;
169
170 for (i = 0; i < NV30_STATE_MAX; i++) {
171 if (screen->state[i])
172 so_ref(NULL, &screen->state[i]);
173 }
174
175 nouveau_resource_destroy(&screen->vp_exec_heap);
176 nouveau_resource_destroy(&screen->vp_data_heap);
177 nouveau_resource_destroy(&screen->query_heap);
178 nouveau_notifier_free(&screen->query);
179 nouveau_notifier_free(&screen->sync);
180 nouveau_grobj_free(&screen->rankine);
181 nv04_surface_2d_takedown(&screen->eng2d);
182
183 nouveau_screen_fini(&screen->base);
184
185 FREE(pscreen);
186 }
187
188 struct pipe_screen *
189 nv30_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev)
190 {
191 struct nv30_screen *screen = CALLOC_STRUCT(nv30_screen);
192 struct nouveau_channel *chan;
193 struct pipe_screen *pscreen;
194 struct nouveau_stateobj *so;
195 unsigned rankine_class = 0;
196 int ret, i;
197
198 if (!screen)
199 return NULL;
200 pscreen = &screen->base.base;
201
202 ret = nouveau_screen_init(&screen->base, dev);
203 if (ret) {
204 nv30_screen_destroy(pscreen);
205 return NULL;
206 }
207 chan = screen->base.channel;
208
209 pscreen->winsys = ws;
210 pscreen->destroy = nv30_screen_destroy;
211 pscreen->get_param = nv30_screen_get_param;
212 pscreen->get_paramf = nv30_screen_get_paramf;
213 pscreen->is_format_supported = nv30_screen_surface_format_supported;
214 pscreen->context_create = nv30_create;
215
216 nv30_screen_init_miptree_functions(pscreen);
217 nv30_screen_init_transfer_functions(pscreen);
218
219 /* 3D object */
220 switch (dev->chipset & 0xf0) {
221 case 0x30:
222 if (NV30TCL_CHIPSET_3X_MASK & (1 << (dev->chipset & 0x0f)))
223 rankine_class = 0x0397;
224 else
225 if (NV34TCL_CHIPSET_3X_MASK & (1 << (dev->chipset & 0x0f)))
226 rankine_class = 0x0697;
227 else
228 if (NV35TCL_CHIPSET_3X_MASK & (1 << (dev->chipset & 0x0f)))
229 rankine_class = 0x0497;
230 break;
231 default:
232 break;
233 }
234
235 if (!rankine_class) {
236 NOUVEAU_ERR("Unknown nv3x chipset: nv%02x\n", dev->chipset);
237 return NULL;
238 }
239
240 ret = nouveau_grobj_alloc(chan, 0xbeef3097, rankine_class,
241 &screen->rankine);
242 if (ret) {
243 NOUVEAU_ERR("Error creating 3D object: %d\n", ret);
244 return FALSE;
245 }
246
247 /* 2D engine setup */
248 screen->eng2d = nv04_surface_2d_init(&screen->base);
249 screen->eng2d->buf = nv30_surface_buffer;
250
251 /* Notifier for sync purposes */
252 ret = nouveau_notifier_alloc(chan, 0xbeef0301, 1, &screen->sync);
253 if (ret) {
254 NOUVEAU_ERR("Error creating notifier object: %d\n", ret);
255 nv30_screen_destroy(pscreen);
256 return NULL;
257 }
258
259 /* Query objects */
260 ret = nouveau_notifier_alloc(chan, 0xbeef0302, 32, &screen->query);
261 if (ret) {
262 NOUVEAU_ERR("Error initialising query objects: %d\n", ret);
263 nv30_screen_destroy(pscreen);
264 return NULL;
265 }
266
267 ret = nouveau_resource_init(&screen->query_heap, 0, 32);
268 if (ret) {
269 NOUVEAU_ERR("Error initialising query object heap: %d\n", ret);
270 nv30_screen_destroy(pscreen);
271 return NULL;
272 }
273
274 /* Vtxprog resources */
275 if (nouveau_resource_init(&screen->vp_exec_heap, 0, 256) ||
276 nouveau_resource_init(&screen->vp_data_heap, 0, 256)) {
277 nv30_screen_destroy(pscreen);
278 return NULL;
279 }
280
281 /* Static rankine initialisation */
282 so = so_new(36, 60, 0);
283 so_method(so, screen->rankine, NV34TCL_DMA_NOTIFY, 1);
284 so_data (so, screen->sync->handle);
285 so_method(so, screen->rankine, NV34TCL_DMA_TEXTURE0, 2);
286 so_data (so, chan->vram->handle);
287 so_data (so, chan->gart->handle);
288 so_method(so, screen->rankine, NV34TCL_DMA_COLOR1, 1);
289 so_data (so, chan->vram->handle);
290 so_method(so, screen->rankine, NV34TCL_DMA_COLOR0, 2);
291 so_data (so, chan->vram->handle);
292 so_data (so, chan->vram->handle);
293 so_method(so, screen->rankine, NV34TCL_DMA_VTXBUF0, 2);
294 so_data (so, chan->vram->handle);
295 so_data (so, chan->gart->handle);
296 /* so_method(so, screen->rankine, NV34TCL_DMA_FENCE, 2);
297 so_data (so, 0);
298 so_data (so, screen->query->handle);*/
299 so_method(so, screen->rankine, NV34TCL_DMA_IN_MEMORY7, 1);
300 so_data (so, chan->vram->handle);
301 so_method(so, screen->rankine, NV34TCL_DMA_IN_MEMORY8, 1);
302 so_data (so, chan->vram->handle);
303
304 for (i=1; i<8; i++) {
305 so_method(so, screen->rankine, NV34TCL_VIEWPORT_CLIP_HORIZ(i), 1);
306 so_data (so, 0);
307 so_method(so, screen->rankine, NV34TCL_VIEWPORT_CLIP_VERT(i), 1);
308 so_data (so, 0);
309 }
310
311 so_method(so, screen->rankine, 0x220, 1);
312 so_data (so, 1);
313
314 so_method(so, screen->rankine, 0x03b0, 1);
315 so_data (so, 0x00100000);
316 so_method(so, screen->rankine, 0x1454, 1);
317 so_data (so, 0);
318 so_method(so, screen->rankine, 0x1d80, 1);
319 so_data (so, 3);
320 so_method(so, screen->rankine, 0x1450, 1);
321 so_data (so, 0x00030004);
322
323 /* NEW */
324 so_method(so, screen->rankine, 0x1e98, 1);
325 so_data (so, 0);
326 so_method(so, screen->rankine, 0x17e0, 3);
327 so_data (so, fui(0.0));
328 so_data (so, fui(0.0));
329 so_data (so, fui(1.0));
330 so_method(so, screen->rankine, 0x1f80, 16);
331 for (i=0; i<16; i++) {
332 so_data (so, (i==8) ? 0x0000ffff : 0);
333 }
334
335 so_method(so, screen->rankine, 0x120, 3);
336 so_data (so, 0);
337 so_data (so, 1);
338 so_data (so, 2);
339
340 so_method(so, screen->rankine, 0x1d88, 1);
341 so_data (so, 0x00001200);
342
343 so_method(so, screen->rankine, NV34TCL_RC_ENABLE, 1);
344 so_data (so, 0);
345
346 so_method(so, screen->rankine, NV34TCL_DEPTH_RANGE_NEAR, 2);
347 so_data (so, fui(0.0));
348 so_data (so, fui(1.0));
349
350 so_method(so, screen->rankine, NV34TCL_MULTISAMPLE_CONTROL, 1);
351 so_data (so, 0xffff0000);
352
353 /* enables use of vp rather than fixed-function somehow */
354 so_method(so, screen->rankine, 0x1e94, 1);
355 so_data (so, 0x13);
356
357 so_emit(chan, so);
358 so_ref(NULL, &so);
359 nouveau_pushbuf_flush(chan, 0);
360
361 return pscreen;
362 }