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