Merge branch 'upstream-gallium-0.1' into darktama-gallium-0.1
[mesa.git] / src / mesa / pipe / nv40 / nv40_context.c
1 #include "pipe/draw/draw_context.h"
2 #include "pipe/p_defines.h"
3 #include "pipe/p_winsys.h"
4 #include "pipe/p_util.h"
5
6 #include "nv40_context.h"
7 #include "nv40_dma.h"
8
9 static boolean
10 nv40_is_format_supported(struct pipe_context *pipe, enum pipe_format format,
11 uint type)
12 {
13 switch (type) {
14 case PIPE_SURFACE:
15 switch (format) {
16 case PIPE_FORMAT_A8R8G8B8_UNORM:
17 case PIPE_FORMAT_R5G6B5_UNORM:
18 case PIPE_FORMAT_Z24S8_UNORM:
19 case PIPE_FORMAT_Z16_UNORM:
20 return TRUE;
21 default:
22 break;
23 }
24 break;
25 case PIPE_TEXTURE:
26 switch (format) {
27 case PIPE_FORMAT_A8R8G8B8_UNORM:
28 case PIPE_FORMAT_A1R5G5B5_UNORM:
29 case PIPE_FORMAT_A4R4G4B4_UNORM:
30 case PIPE_FORMAT_R5G6B5_UNORM:
31 case PIPE_FORMAT_U_L8:
32 case PIPE_FORMAT_U_A8:
33 case PIPE_FORMAT_U_I8:
34 case PIPE_FORMAT_U_A8_L8:
35 case PIPE_FORMAT_Z16_UNORM:
36 case PIPE_FORMAT_Z24S8_UNORM:
37 return TRUE;
38 default:
39 break;
40 }
41 break;
42 default:
43 assert(0);
44 };
45
46 return FALSE;
47 }
48
49 static const char *
50 nv40_get_name(struct pipe_context *pipe)
51 {
52 struct nv40_context *nv40 = (struct nv40_context *)pipe;
53 static char buffer[128];
54
55 snprintf(buffer, sizeof(buffer), "NV%02X", nv40->chipset);
56 return buffer;
57 }
58
59 static const char *
60 nv40_get_vendor(struct pipe_context *pipe)
61 {
62 return "nouveau";
63 }
64
65 static int
66 nv40_get_param(struct pipe_context *pipe, int param)
67 {
68 switch (param) {
69 case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS:
70 return 16;
71 case PIPE_CAP_NPOT_TEXTURES:
72 return 1;
73 case PIPE_CAP_TWO_SIDED_STENCIL:
74 return 1;
75 case PIPE_CAP_GLSL:
76 return 0;
77 case PIPE_CAP_S3TC:
78 return 0;
79 case PIPE_CAP_ANISOTROPIC_FILTER:
80 return 1;
81 case PIPE_CAP_POINT_SPRITE:
82 return 1;
83 case PIPE_CAP_MAX_RENDER_TARGETS:
84 return 4;
85 case PIPE_CAP_OCCLUSION_QUERY:
86 return 1;
87 case PIPE_CAP_TEXTURE_SHADOW_MAP:
88 return 1;
89 case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
90 return 13;
91 case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
92 return 10;
93 case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:
94 return 13;
95 default:
96 NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param);
97 return 0;
98 }
99 }
100
101 static float
102 nv40_get_paramf(struct pipe_context *pipe, int param)
103 {
104 switch (param) {
105 case PIPE_CAP_MAX_LINE_WIDTH:
106 case PIPE_CAP_MAX_LINE_WIDTH_AA:
107 return 10.0;
108 case PIPE_CAP_MAX_POINT_WIDTH:
109 case PIPE_CAP_MAX_POINT_WIDTH_AA:
110 return 64.0;
111 case PIPE_CAP_MAX_TEXTURE_ANISOTROPY:
112 return 16.0;
113 case PIPE_CAP_MAX_TEXTURE_LOD_BIAS:
114 return 4.0;
115 default:
116 NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param);
117 return 0.0;
118 }
119 }
120
121 static void
122 nv40_flush(struct pipe_context *pipe, unsigned flags)
123 {
124 struct nv40_context *nv40 = (struct nv40_context *)pipe;
125 struct nouveau_winsys *nvws = nv40->nvws;
126
127 if (flags & PIPE_FLUSH_TEXTURE_CACHE) {
128 BEGIN_RING(curie, 0x1fd8, 1);
129 OUT_RING (2);
130 BEGIN_RING(curie, 0x1fd8, 1);
131 OUT_RING (1);
132 }
133
134 if (flags & PIPE_FLUSH_WAIT) {
135 nvws->notifier_reset(nv40->sync, 0);
136 BEGIN_RING(curie, 0x104, 1);
137 OUT_RING (0);
138 BEGIN_RING(curie, 0x100, 1);
139 OUT_RING (0);
140 }
141
142 FIRE_RING();
143
144 if (flags & PIPE_FLUSH_WAIT)
145 nvws->notifier_wait(nv40->sync, 0, 0, 2000);
146 }
147
148 static void
149 nv40_destroy(struct pipe_context *pipe)
150 {
151 struct nv40_context *nv40 = (struct nv40_context *)pipe;
152
153 draw_destroy(nv40->draw);
154 free(nv40);
155 }
156
157 static boolean
158 nv40_init_hwctx(struct nv40_context *nv40, int curie_class)
159 {
160 struct nouveau_winsys *nvws = nv40->nvws;
161 int ret;
162
163 if ((ret = nvws->notifier_alloc(nvws, nv40->num_query_objects,
164 &nv40->query))) {
165 NOUVEAU_ERR("Error creating query notifier objects: %d\n", ret);
166 return FALSE;
167 }
168
169 if ((ret = nvws->grobj_alloc(nvws, curie_class,
170 &nv40->curie))) {
171 NOUVEAU_ERR("Error creating 3D object: %d\n", ret);
172 return FALSE;
173 }
174
175 BEGIN_RING(curie, NV40TCL_DMA_NOTIFY, 1);
176 OUT_RING (nv40->sync->handle);
177 BEGIN_RING(curie, NV40TCL_DMA_TEXTURE0, 2);
178 OUT_RING (nvws->channel->vram->handle);
179 OUT_RING (nvws->channel->gart->handle);
180 BEGIN_RING(curie, NV40TCL_DMA_COLOR1, 1);
181 OUT_RING (nvws->channel->vram->handle);
182 BEGIN_RING(curie, NV40TCL_DMA_COLOR0, 2);
183 OUT_RING (nvws->channel->vram->handle);
184 OUT_RING (nvws->channel->vram->handle);
185 BEGIN_RING(curie, NV40TCL_DMA_VTXBUF0, 2);
186 OUT_RING (nvws->channel->vram->handle);
187 OUT_RING (nvws->channel->gart->handle);
188 BEGIN_RING(curie, NV40TCL_DMA_FENCE, 2);
189 OUT_RING (0);
190 OUT_RING (nv40->query->handle);
191 BEGIN_RING(curie, NV40TCL_DMA_UNK01AC, 2);
192 OUT_RING (nvws->channel->vram->handle);
193 OUT_RING (nvws->channel->vram->handle);
194 BEGIN_RING(curie, NV40TCL_DMA_COLOR2, 2);
195 OUT_RING (nvws->channel->vram->handle);
196 OUT_RING (nvws->channel->vram->handle);
197
198 BEGIN_RING(curie, 0x1ea4, 3);
199 OUT_RING (0x00000010);
200 OUT_RING (0x01000100);
201 OUT_RING (0xff800006);
202
203 /* vtxprog output routing */
204 BEGIN_RING(curie, 0x1fc4, 1);
205 OUT_RING (0x06144321);
206 BEGIN_RING(curie, 0x1fc8, 2);
207 OUT_RING (0xedcba987);
208 OUT_RING (0x00000021);
209 BEGIN_RING(curie, 0x1fd0, 1);
210 OUT_RING (0x00171615);
211 BEGIN_RING(curie, 0x1fd4, 1);
212 OUT_RING (0x001b1a19);
213
214 BEGIN_RING(curie, 0x1ef8, 1);
215 OUT_RING (0x0020ffff);
216 BEGIN_RING(curie, 0x1d64, 1);
217 OUT_RING (0x00d30000);
218 BEGIN_RING(curie, 0x1e94, 1);
219 OUT_RING (0x00000001);
220
221 FIRE_RING ();
222 return TRUE;
223 }
224
225 #define GRCLASS4097_CHIPSETS 0x00000baf
226 #define GRCLASS4497_CHIPSETS 0x00005450
227 struct pipe_context *
228 nv40_create(struct pipe_winsys *pipe_winsys, struct nouveau_winsys *nvws,
229 unsigned chipset)
230 {
231 struct nv40_context *nv40;
232 int curie_class, ret;
233
234 if ((chipset & 0xf0) != 0x40) {
235 NOUVEAU_ERR("Not a NV4X chipset\n");
236 return NULL;
237 }
238
239 if (GRCLASS4097_CHIPSETS & (1 << (chipset & 0x0f))) {
240 curie_class = 0x4097;
241 } else
242 if (GRCLASS4497_CHIPSETS & (1 << (chipset & 0x0f))) {
243 curie_class = 0x4497;
244 } else {
245 NOUVEAU_ERR("Unknown NV4X chipset: NV%02x\n", chipset);
246 return NULL;
247 }
248
249 nv40 = CALLOC_STRUCT(nv40_context);
250 if (!nv40)
251 return NULL;
252 nv40->chipset = chipset;
253 nv40->nvws = nvws;
254
255 if ((ret = nvws->notifier_alloc(nvws, 1, &nv40->sync))) {
256 NOUVEAU_ERR("Error creating notifier object: %d\n", ret);
257 free(nv40);
258 return NULL;
259 }
260
261 nv40->num_query_objects = 32;
262 nv40->query_objects = calloc(nv40->num_query_objects,
263 sizeof(struct pipe_query_object *));
264 if (!nv40->query_objects) {
265 free(nv40);
266 return NULL;
267 }
268
269 if (nvws->res_init(&nv40->vertprog.exec_heap, 0, 512) ||
270 nvws->res_init(&nv40->vertprog.data_heap, 0, 256)) {
271 nvws->res_free(&nv40->vertprog.exec_heap);
272 nvws->res_free(&nv40->vertprog.data_heap);
273 free(nv40);
274 return NULL;
275 }
276
277 if (!nv40_init_hwctx(nv40, curie_class)) {
278 free(nv40);
279 return NULL;
280 }
281
282 nv40->pipe.winsys = pipe_winsys;
283
284 nv40->pipe.destroy = nv40_destroy;
285 nv40->pipe.is_format_supported = nv40_is_format_supported;
286 nv40->pipe.get_name = nv40_get_name;
287 nv40->pipe.get_vendor = nv40_get_vendor;
288 nv40->pipe.get_param = nv40_get_param;
289 nv40->pipe.get_paramf = nv40_get_paramf;
290
291 nv40->pipe.draw_arrays = nv40_draw_arrays;
292 nv40->pipe.draw_elements = nv40_draw_elements;
293 nv40->pipe.clear = nv40_clear;
294
295 nv40->pipe.flush = nv40_flush;
296
297 nv40_init_query_functions(nv40);
298 nv40_init_surface_functions(nv40);
299 nv40_init_state_functions(nv40);
300 nv40_init_miptree_functions(nv40);
301
302 nv40->draw = draw_create();
303 assert(nv40->draw);
304 draw_set_rasterize_stage(nv40->draw, nv40_draw_render_stage(nv40));
305
306 return &nv40->pipe;
307 }
308
309