Merge branch 'upstream-gallium-0.1' into nouveau-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 #include "utils.h"
5
6 #include "state_tracker/st_public.h"
7 #include "pipe/p_defines.h"
8 #include "pipe/p_context.h"
9
10 #include "nouveau_context.h"
11 #include "nouveau_dri.h"
12 #include "nouveau_local.h"
13 #include "nouveau_screen.h"
14 #include "nouveau_winsys_pipe.h"
15
16 #ifdef DEBUG
17 static const struct dri_debug_control debug_control[] = {
18 { "bo", DEBUG_BO },
19 { NULL, 0 }
20 };
21 int __nouveau_debug = 0;
22 #endif
23
24 GLboolean
25 nouveau_context_create(const __GLcontextModes *glVis,
26 __DRIcontextPrivate *driContextPriv,
27 void *sharedContextPrivate)
28 {
29 __DRIscreenPrivate *driScrnPriv = driContextPriv->driScreenPriv;
30 struct nouveau_screen *nv_screen = driScrnPriv->private;
31 struct nouveau_context *nv = CALLOC_STRUCT(nouveau_context);
32 struct nouveau_device_priv *nvdev;
33 struct pipe_context *pipe = NULL;
34 struct st_context *st_share = NULL;
35 int ret;
36
37 if (sharedContextPrivate) {
38 st_share = ((struct nouveau_context *)sharedContextPrivate)->st;
39 }
40
41 if ((ret = nouveau_device_get_param(nv_screen->device,
42 NOUVEAU_GETPARAM_CHIPSET_ID,
43 &nv->chipset))) {
44 NOUVEAU_ERR("Error determining chipset id: %d\n", ret);
45 return GL_FALSE;
46 }
47
48 if ((ret = nouveau_channel_alloc(nv_screen->device,
49 0x8003d001, 0x8003d002,
50 &nv->channel))) {
51 NOUVEAU_ERR("Error creating GPU channel: %d\n", ret);
52 return GL_FALSE;
53 }
54
55 driContextPriv->driverPrivate = (void *)nv;
56 nv->nv_screen = nv_screen;
57 nv->dri_screen = driScrnPriv;
58
59 nvdev = nouveau_device(nv_screen->device);
60 nvdev->ctx = driContextPriv->hHWContext;
61 nvdev->lock = (drmLock *)&driScrnPriv->pSAREA->lock;
62
63 driParseConfigFiles(&nv->dri_option_cache, &nv_screen->option_cache,
64 nv->dri_screen->myNum, "nouveau");
65 #ifdef DEBUG
66 __nouveau_debug = driParseDebugString(getenv("NOUVEAU_DEBUG"),
67 debug_control);
68 #endif
69
70 /*XXX: Hack up a fake region and buffer object for front buffer.
71 * This will go away with TTM, replaced with a simple reference
72 * of the front buffer handle passed to us by the DDX.
73 */
74 {
75 struct pipe_surface *fb_surf;
76 struct nouveau_pipe_buffer *fb_buf;
77 struct nouveau_bo_priv *fb_bo;
78
79 fb_bo = calloc(1, sizeof(struct nouveau_bo_priv));
80 fb_bo->drm.offset = nv_screen->front_offset;
81 fb_bo->drm.flags = NOUVEAU_MEM_FB;
82 fb_bo->drm.size = nv_screen->front_pitch *
83 nv_screen->front_height;
84 fb_bo->refcount = 1;
85 fb_bo->base.flags = NOUVEAU_BO_PIN | NOUVEAU_BO_VRAM;
86 fb_bo->base.offset = fb_bo->drm.offset;
87 fb_bo->base.handle = (unsigned long)fb_bo;
88 fb_bo->base.size = fb_bo->drm.size;
89 fb_bo->base.device = nv_screen->device;
90
91 fb_buf = calloc(1, sizeof(struct nouveau_pipe_buffer));
92 fb_buf->bo = &fb_bo->base;
93
94 fb_surf = calloc(1, sizeof(struct pipe_surface));
95 fb_surf->cpp = nv_screen->front_cpp;
96 fb_surf->pitch = nv_screen->front_pitch / fb_surf->cpp;
97 fb_surf->height = nv_screen->front_height;
98 fb_surf->refcount = 1;
99 fb_surf->buffer = &fb_buf->base;
100
101 nv->frontbuffer = fb_surf;
102 }
103
104 if ((ret = nouveau_grobj_alloc(nv->channel, 0x00000000, 0x30,
105 &nv->NvNull))) {
106 NOUVEAU_ERR("Error creating NULL object: %d\n", ret);
107 return GL_FALSE;
108 }
109 nv->next_handle = 0x80000000;
110
111 if ((ret = nouveau_notifier_alloc(nv->channel, nv->next_handle++, 1,
112 &nv->sync_notifier))) {
113 NOUVEAU_ERR("Error creating channel sync notifier: %d\n", ret);
114 return GL_FALSE;
115 }
116
117 if (nv->chipset < 0x50)
118 ret = nouveau_surface_init_nv04(nv);
119 else
120 ret = nouveau_surface_init_nv50(nv);
121 if (ret) {
122 return GL_FALSE;
123 }
124
125 if (!getenv("NOUVEAU_FORCE_SOFTPIPE")) {
126 pipe = nouveau_pipe_create(nv);
127 if (!pipe)
128 NOUVEAU_ERR("Couldn't create hw pipe\n");
129 }
130
131 if (!pipe) {
132 NOUVEAU_MSG("Using softpipe\n");
133 pipe = nouveau_create_softpipe(nv);
134 if (!pipe) {
135 NOUVEAU_ERR("Error creating pipe, bailing\n");
136 return GL_FALSE;
137 }
138 }
139
140 pipe->priv = nv;
141 nv->st = st_create_context(pipe, glVis, st_share);
142 return GL_TRUE;
143 }
144
145 void
146 nouveau_context_destroy(__DRIcontextPrivate *driContextPriv)
147 {
148 struct nouveau_context *nv = driContextPriv->driverPrivate;
149
150 assert(nv);
151
152 st_flush(nv->st, PIPE_FLUSH_WAIT);
153 st_destroy_context(nv->st);
154
155 nouveau_grobj_free(&nv->NvCtxSurf2D);
156 nouveau_grobj_free(&nv->NvImageBlit);
157 nouveau_channel_free(&nv->channel);
158
159 free(nv);
160 }
161
162 GLboolean
163 nouveau_context_bind(__DRIcontextPrivate *driContextPriv,
164 __DRIdrawablePrivate *driDrawPriv,
165 __DRIdrawablePrivate *driReadPriv)
166 {
167 struct nouveau_context *nv;
168 struct nouveau_framebuffer *draw, *read;
169
170 if (!driContextPriv) {
171 st_make_current(NULL, NULL, NULL);
172 return GL_TRUE;
173 }
174
175 nv = driContextPriv->driverPrivate;
176 draw = driDrawPriv->driverPrivate;
177 read = driReadPriv->driverPrivate;
178
179 st_make_current(nv->st, draw->stfb, read->stfb);
180
181 if ((nv->dri_drawable != driDrawPriv) ||
182 (nv->last_stamp != driDrawPriv->lastStamp)) {
183 nv->dri_drawable = driDrawPriv;
184 st_resize_framebuffer(draw->stfb, driDrawPriv->w,
185 driDrawPriv->h);
186 nv->last_stamp = driDrawPriv->lastStamp;
187 }
188
189 if (driDrawPriv != driReadPriv) {
190 st_resize_framebuffer(read->stfb, driReadPriv->w,
191 driReadPriv->h);
192 }
193
194 return GL_TRUE;
195 }
196
197 GLboolean
198 nouveau_context_unbind(__DRIcontextPrivate *driContextPriv)
199 {
200 struct nouveau_context *nv = driContextPriv->driverPrivate;
201 (void)nv;
202
203 st_flush(nv->st, 0);
204 return GL_TRUE;
205 }
206