nouveau: implement pipe_screen
[mesa.git] / src / gallium / drivers / nv40 / nv40_context.c
1 #include "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_screen.h"
8
9 #define NV4X_GRCLASS4097_CHIPSETS 0x00000baf
10 #define NV4X_GRCLASS4497_CHIPSETS 0x00005450
11 #define NV6X_GRCLASS4497_CHIPSETS 0x00000088
12
13 static void
14 nv40_flush(struct pipe_context *pipe, unsigned flags)
15 {
16 struct nv40_context *nv40 = nv40_context(pipe);
17 struct nouveau_winsys *nvws = nv40->nvws;
18
19 if (flags & PIPE_FLUSH_TEXTURE_CACHE) {
20 BEGIN_RING(curie, 0x1fd8, 1);
21 OUT_RING (2);
22 BEGIN_RING(curie, 0x1fd8, 1);
23 OUT_RING (1);
24 }
25
26 if (flags & PIPE_FLUSH_WAIT) {
27 nvws->notifier_reset(nv40->hw->sync, 0);
28 BEGIN_RING(curie, 0x104, 1);
29 OUT_RING (0);
30 BEGIN_RING(curie, 0x100, 1);
31 OUT_RING (0);
32 }
33
34 FIRE_RING();
35
36 if (flags & PIPE_FLUSH_WAIT)
37 nvws->notifier_wait(nv40->hw->sync, 0, 0, 2000);
38 }
39
40 static void
41 nv40_channel_takedown(struct nv40_channel_context *cnv40)
42 {
43 struct nouveau_winsys *nvws = cnv40->nvws;
44
45 nvws->res_free(&cnv40->vp_exec_heap);
46 nvws->res_free(&cnv40->vp_data_heap);
47 nvws->res_free(&cnv40->query_heap);
48 nvws->notifier_free(&cnv40->query);
49 nvws->notifier_free(&cnv40->sync);
50 nvws->grobj_free(&cnv40->curie);
51 free(cnv40);
52 }
53
54 static struct nv40_channel_context *
55 nv40_channel_init(struct pipe_winsys *ws, struct nouveau_winsys *nvws,
56 unsigned chipset)
57 {
58 struct nv40_channel_context *cnv40 = NULL;
59 struct nouveau_stateobj *so;
60 unsigned curie_class = 0;
61 int ret;
62
63 switch (chipset & 0xf0) {
64 case 0x40:
65 if (NV4X_GRCLASS4097_CHIPSETS & (1 << (chipset & 0x0f)))
66 curie_class = NV40TCL;
67 else
68 if (NV4X_GRCLASS4497_CHIPSETS & (1 << (chipset & 0x0f)))
69 curie_class = NV44TCL;
70 break;
71 case 0x60:
72 if (NV6X_GRCLASS4497_CHIPSETS & (1 << (chipset & 0x0f)))
73 curie_class = NV44TCL;
74 break;
75 default:
76 break;
77 }
78
79 if (!curie_class) {
80 NOUVEAU_ERR("Unknown nv4x chipset: nv%02x\n", chipset);
81 return NULL;
82 }
83
84 cnv40 = CALLOC(1, sizeof(struct nv40_channel_context));
85 if (!cnv40)
86 return NULL;
87 cnv40->chipset = chipset;
88 cnv40->nvws = nvws;
89
90 /* Notifier for sync purposes */
91 ret = nvws->notifier_alloc(nvws, 1, &cnv40->sync);
92 if (ret) {
93 NOUVEAU_ERR("Error creating notifier object: %d\n", ret);
94 nv40_channel_takedown(cnv40);
95 return NULL;
96 }
97
98 /* Query objects */
99 ret = nvws->notifier_alloc(nvws, 32, &cnv40->query);
100 if (ret) {
101 NOUVEAU_ERR("Error initialising query objects: %d\n", ret);
102 nv40_channel_takedown(cnv40);
103 return NULL;
104 }
105
106 ret = nvws->res_init(&cnv40->query_heap, 0, 32);
107 if (ret) {
108 NOUVEAU_ERR("Error initialising query object heap: %d\n", ret);
109 nv40_channel_takedown(cnv40);
110 return NULL;
111 }
112
113 /* Vtxprog resources */
114 if (nvws->res_init(&cnv40->vp_exec_heap, 0, 512) ||
115 nvws->res_init(&cnv40->vp_data_heap, 0, 256)) {
116 nv40_channel_takedown(cnv40);
117 return NULL;
118 }
119
120 /* 3D object */
121 ret = nvws->grobj_alloc(nvws, curie_class, &cnv40->curie);
122 if (ret) {
123 NOUVEAU_ERR("Error creating 3D object: %d\n", ret);
124 return FALSE;
125 }
126
127 /* Static curie initialisation */
128 so = so_new(128, 0);
129 so_method(so, cnv40->curie, NV40TCL_DMA_NOTIFY, 1);
130 so_data (so, cnv40->sync->handle);
131 so_method(so, cnv40->curie, NV40TCL_DMA_TEXTURE0, 2);
132 so_data (so, nvws->channel->vram->handle);
133 so_data (so, nvws->channel->gart->handle);
134 so_method(so, cnv40->curie, NV40TCL_DMA_COLOR1, 1);
135 so_data (so, nvws->channel->vram->handle);
136 so_method(so, cnv40->curie, NV40TCL_DMA_COLOR0, 2);
137 so_data (so, nvws->channel->vram->handle);
138 so_data (so, nvws->channel->vram->handle);
139 so_method(so, cnv40->curie, NV40TCL_DMA_VTXBUF0, 2);
140 so_data (so, nvws->channel->vram->handle);
141 so_data (so, nvws->channel->gart->handle);
142 so_method(so, cnv40->curie, NV40TCL_DMA_FENCE, 2);
143 so_data (so, 0);
144 so_data (so, cnv40->query->handle);
145 so_method(so, cnv40->curie, NV40TCL_DMA_UNK01AC, 2);
146 so_data (so, nvws->channel->vram->handle);
147 so_data (so, nvws->channel->vram->handle);
148 so_method(so, cnv40->curie, NV40TCL_DMA_COLOR2, 2);
149 so_data (so, nvws->channel->vram->handle);
150 so_data (so, nvws->channel->vram->handle);
151
152 so_method(so, cnv40->curie, 0x1ea4, 3);
153 so_data (so, 0x00000010);
154 so_data (so, 0x01000100);
155 so_data (so, 0xff800006);
156
157 /* vtxprog output routing */
158 so_method(so, cnv40->curie, 0x1fc4, 1);
159 so_data (so, 0x06144321);
160 so_method(so, cnv40->curie, 0x1fc8, 2);
161 so_data (so, 0xedcba987);
162 so_data (so, 0x00000021);
163 so_method(so, cnv40->curie, 0x1fd0, 1);
164 so_data (so, 0x00171615);
165 so_method(so, cnv40->curie, 0x1fd4, 1);
166 so_data (so, 0x001b1a19);
167
168 so_method(so, cnv40->curie, 0x1ef8, 1);
169 so_data (so, 0x0020ffff);
170 so_method(so, cnv40->curie, 0x1d64, 1);
171 so_data (so, 0x00d30000);
172 so_method(so, cnv40->curie, 0x1e94, 1);
173 so_data (so, 0x00000001);
174
175 so_emit(nvws, so);
176 so_ref(NULL, &so);
177 nvws->push_flush(nvws->channel, 0);
178
179 return cnv40;
180 }
181
182 static void
183 nv40_destroy(struct pipe_context *pipe)
184 {
185 struct nv40_context *nv40 = nv40_context(pipe);
186
187 if (nv40->draw)
188 draw_destroy(nv40->draw);
189
190 if (nv40->hw) {
191 if (--nv40->hw->refcount == 0)
192 nv40_channel_takedown(nv40->hw);
193 }
194
195 free(nv40);
196 }
197
198 struct pipe_context *
199 nv40_create(struct pipe_screen *pscreen, struct nouveau_winsys *nvws)
200 {
201 struct pipe_winsys *ws = pscreen->winsys;
202 struct nv40_context *nv40;
203 unsigned chipset = nv40_screen(pscreen)->chipset;
204
205 nv40 = CALLOC(1, sizeof(struct nv40_context));
206 if (!nv40)
207 return NULL;
208
209 nv40->hw = nv40_channel_init(ws, nvws, chipset);
210 if (!nv40->hw) {
211 nv40_destroy(&nv40->pipe);
212 return NULL;
213 }
214
215 nv40->chipset = chipset;
216 nv40->nvws = nvws;
217
218 nv40->pipe.winsys = ws;
219 nv40->pipe.screen = pscreen;
220 nv40->pipe.destroy = nv40_destroy;
221 nv40->pipe.draw_arrays = nv40_draw_arrays;
222 nv40->pipe.draw_elements = nv40_draw_elements;
223 nv40->pipe.clear = nv40_clear;
224 nv40->pipe.flush = nv40_flush;
225
226 nv40_init_query_functions(nv40);
227 nv40_init_surface_functions(nv40);
228 nv40_init_state_functions(nv40);
229 nv40_init_miptree_functions(nv40);
230
231 nv40->draw = draw_create();
232 assert(nv40->draw);
233 draw_set_rasterize_stage(nv40->draw, nv40_draw_render_stage(nv40));
234
235 return &nv40->pipe;
236 }
237