Use write posting in the kickoff function too.
[mesa.git] / src / mesa / drivers / dri / nouveau_winsys / nouveau_context.c
1 #include "glheader.h"
2 #include "context.h"
3 #include "extensions.h"
4
5 #include "tnl/tnl.h"
6 #include "tnl/t_pipeline.h"
7 #include "tnl/t_vertex.h"
8
9 #include "drivers/common/driverfuncs.h"
10
11 #include "drirenderbuffer.h"
12
13 #include "state_tracker/st_public.h"
14 #include "state_tracker/st_context.h"
15
16 #include "pipe/p_defines.h"
17 #include "pipe/p_context.h"
18
19 #include "nouveau_context.h"
20 #include "nouveau_dri.h"
21 #include "nouveau_local.h"
22 #include "nouveau_screen.h"
23 #include "nouveau_winsys_pipe.h"
24
25 #define need_GL_ARB_fragment_program
26 #define need_GL_ARB_multisample
27 #define need_GL_ARB_occlusion_query
28 #define need_GL_ARB_point_parameters
29 #define need_GL_ARB_texture_compression
30 #define need_GL_ARB_vertex_program
31 #define need_GL_ARB_vertex_buffer_object
32 #define need_GL_EXT_compiled_vertex_array
33 #define need_GL_EXT_fog_coord
34 #define need_GL_EXT_secondary_color
35 #define need_GL_EXT_framebuffer_object
36 #include "extension_helper.h"
37
38 const struct dri_extension common_extensions[] =
39 {
40 { NULL, 0 }
41 };
42
43 const struct dri_extension nv40_extensions[] =
44 {
45 { "GL_ARB_fragment_program", NULL },
46 { "GL_ARB_multisample", GL_ARB_multisample_functions },
47 { "GL_ARB_occlusion_query", GL_ARB_occlusion_query_functions },
48 { "GL_ARB_point_parameters", GL_ARB_point_parameters_functions },
49 { "GL_ARB_texture_border_clamp", NULL },
50 { "GL_ARB_texture_compression", GL_ARB_texture_compression_functions },
51 { "GL_ARB_texture_cube_map", NULL },
52 { "GL_ARB_texture_env_add", NULL },
53 { "GL_ARB_texture_env_combine", NULL },
54 { "GL_ARB_texture_env_crossbar", NULL },
55 { "GL_ARB_texture_env_dot3", NULL },
56 { "GL_ARB_texture_mirrored_repeat", NULL },
57 { "GL_ARB_texture_non_power_of_two", NULL },
58 { "GL_ARB_vertex_program", GL_ARB_vertex_program_functions },
59 { "GL_ARB_vertex_buffer_object", GL_ARB_vertex_buffer_object_functions },
60 { "GL_ATI_texture_env_combine3", NULL },
61 { "GL_EXT_compiled_vertex_array", GL_EXT_compiled_vertex_array_functions },
62 { "GL_EXT_fog_coord", GL_EXT_fog_coord_functions },
63 { "GL_EXT_framebuffer_object", GL_EXT_framebuffer_object_functions },
64 { "GL_EXT_secondary_color", GL_EXT_secondary_color_functions },
65 { "GL_EXT_texture_edge_clamp", NULL },
66 { "GL_EXT_texture_env_add", NULL },
67 { "GL_EXT_texture_env_combine", NULL },
68 { "GL_EXT_texture_env_dot3", NULL },
69 { "GL_EXT_texture_mirror_clamp", NULL },
70 { "GL_NV_texture_rectangle", NULL },
71 { NULL, 0 }
72 };
73
74 #ifdef DEBUG
75 static const struct dri_debug_control debug_control[] = {
76 { "bo", DEBUG_BO },
77 { NULL, 0 }
78 };
79 int __nouveau_debug = 0;
80 #endif
81
82 GLboolean
83 nouveau_context_create(const __GLcontextModes *glVis,
84 __DRIcontextPrivate *driContextPriv,
85 void *sharedContextPrivate)
86 {
87 __DRIscreenPrivate *driScrnPriv = driContextPriv->driScreenPriv;
88 struct nouveau_screen *nv_screen = driScrnPriv->private;
89 struct nouveau_context *nv = CALLOC_STRUCT(nouveau_context);
90 struct nouveau_device_priv *nvdev;
91 struct pipe_context *pipe = NULL;
92 struct st_context *st_share = NULL;
93 int ret;
94
95 if (sharedContextPrivate) {
96 st_share = ((struct nouveau_context *)sharedContextPrivate)->st;
97 }
98
99 if ((ret = nouveau_device_get_param(nv_screen->device,
100 NOUVEAU_GETPARAM_CHIPSET_ID,
101 &nv->chipset))) {
102 NOUVEAU_ERR("Error determining chipset id: %d\n", ret);
103 return GL_FALSE;
104 }
105
106 if ((ret = nouveau_channel_alloc(nv_screen->device,
107 0x8003d001, 0x8003d002,
108 &nv->channel))) {
109 NOUVEAU_ERR("Error creating GPU channel: %d\n", ret);
110 return GL_FALSE;
111 }
112
113 driContextPriv->driverPrivate = (void *)nv;
114 nv->nv_screen = nv_screen;
115 nv->dri_screen = driScrnPriv;
116
117 nvdev = nouveau_device(nv_screen->device);
118 nvdev->ctx = driContextPriv->hHWContext;
119 nvdev->lock = (drmLock *)&driScrnPriv->pSAREA->lock;
120
121 driParseConfigFiles(&nv->dri_option_cache, &nv_screen->option_cache,
122 nv->dri_screen->myNum, "nouveau");
123 #ifdef DEBUG
124 __nouveau_debug = driParseDebugString(getenv("NOUVEAU_DEBUG"),
125 debug_control);
126 #endif
127
128 if ((ret = nouveau_grobj_alloc(nv->channel, 0x00000000, 0x30,
129 &nv->NvNull))) {
130 NOUVEAU_ERR("Error creating NULL object: %d\n", ret);
131 return GL_FALSE;
132 }
133 nv->next_handle = 0x80000000;
134
135 if ((ret = nouveau_notifier_alloc(nv->channel, nv->next_handle++, 1,
136 &nv->sync_notifier))) {
137 NOUVEAU_ERR("Error creating channel sync notifier: %d\n", ret);
138 return GL_FALSE;
139 }
140
141 if (nv->chipset < 0x50)
142 ret = nouveau_region_init_nv04(nv);
143 else
144 ret = nouveau_region_init_nv50(nv);
145 if (ret) {
146 return GL_FALSE;
147 }
148
149 if (!getenv("NOUVEAU_FORCE_SOFTPIPE")) {
150 pipe = nouveau_pipe_create(nv);
151 if (!pipe)
152 NOUVEAU_ERR("Couldn't create hw pipe\n");
153 }
154
155 if (!pipe) {
156 NOUVEAU_MSG("Using softpipe\n");
157 pipe = nouveau_create_softpipe(nv);
158 if (!pipe) {
159 NOUVEAU_ERR("Error creating pipe, bailing\n");
160 return GL_FALSE;
161 }
162 }
163
164 pipe->priv = nv;
165 nv->st = st_create_context(pipe, glVis, st_share);
166 return GL_TRUE;
167 }
168
169 void
170 nouveau_context_destroy(__DRIcontextPrivate *driContextPriv)
171 {
172 struct nouveau_context *nv = driContextPriv->driverPrivate;
173
174 assert(nv);
175
176 st_flush(nv->st, PIPE_FLUSH_WAIT);
177 st_destroy_context(nv->st);
178
179 nouveau_grobj_free(&nv->NvCtxSurf2D);
180 nouveau_grobj_free(&nv->NvImageBlit);
181 nouveau_channel_free(&nv->channel);
182
183 free(nv);
184 }
185
186 GLboolean
187 nouveau_context_bind(__DRIcontextPrivate *driContextPriv,
188 __DRIdrawablePrivate *driDrawPriv,
189 __DRIdrawablePrivate *driReadPriv)
190 {
191 struct nouveau_context *nv;
192 struct nouveau_framebuffer *draw, *read;
193
194 if (!driContextPriv) {
195 st_make_current(NULL, NULL, NULL);
196 return GL_TRUE;
197 }
198
199 nv = driContextPriv->driverPrivate;
200 draw = driDrawPriv->driverPrivate;
201 read = driReadPriv->driverPrivate;
202
203 st_make_current(nv->st, draw->stfb, read->stfb);
204
205 if ((nv->dri_drawable != driDrawPriv) ||
206 (nv->last_stamp != driDrawPriv->lastStamp)) {
207 nv->dri_drawable = driDrawPriv;
208 st_resize_framebuffer(draw->stfb, driDrawPriv->w,
209 driDrawPriv->h);
210 nv->last_stamp = driDrawPriv->lastStamp;
211 }
212
213 if (driDrawPriv != driReadPriv) {
214 st_resize_framebuffer(read->stfb, driReadPriv->w,
215 driReadPriv->h);
216 }
217
218 return GL_TRUE;
219 }
220
221 GLboolean
222 nouveau_context_unbind(__DRIcontextPrivate *driContextPriv)
223 {
224 struct nouveau_context *nv = driContextPriv->driverPrivate;
225 (void)nv;
226
227 st_flush(nv->st, 0);
228 return GL_TRUE;
229 }
230