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