Merge branch 'upstream-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 #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_bo_priv *fb_bo;
77
78 fb_bo = calloc(1, sizeof(struct nouveau_bo_priv));
79 fb_bo->drm.offset = nv_screen->front_offset;
80 fb_bo->drm.flags = NOUVEAU_MEM_FB;
81 fb_bo->drm.size = nv_screen->front_pitch *
82 nv_screen->front_height;
83 fb_bo->refcount = 1;
84 fb_bo->base.flags = NOUVEAU_BO_PIN | NOUVEAU_BO_VRAM;
85 fb_bo->base.offset = fb_bo->drm.offset;
86 fb_bo->base.handle = (unsigned long)fb_bo;
87 fb_bo->base.size = fb_bo->drm.size;
88 fb_bo->base.device = nv_screen->device;
89
90 fb_surf = calloc(1, sizeof(struct pipe_surface));
91 fb_surf->cpp = nv_screen->front_cpp;
92 fb_surf->pitch = nv_screen->front_pitch / fb_surf->cpp;
93 fb_surf->height = nv_screen->front_height;
94 fb_surf->refcount = 1;
95 fb_surf->buffer = (void *)fb_bo;
96
97 nv->frontbuffer = fb_surf;
98 }
99
100 if ((ret = nouveau_grobj_alloc(nv->channel, 0x00000000, 0x30,
101 &nv->NvNull))) {
102 NOUVEAU_ERR("Error creating NULL object: %d\n", ret);
103 return GL_FALSE;
104 }
105 nv->next_handle = 0x80000000;
106
107 if ((ret = nouveau_notifier_alloc(nv->channel, nv->next_handle++, 1,
108 &nv->sync_notifier))) {
109 NOUVEAU_ERR("Error creating channel sync notifier: %d\n", ret);
110 return GL_FALSE;
111 }
112
113 if (nv->chipset < 0x50)
114 ret = nouveau_surface_init_nv04(nv);
115 else
116 ret = nouveau_surface_init_nv50(nv);
117 if (ret) {
118 return GL_FALSE;
119 }
120
121 if (!getenv("NOUVEAU_FORCE_SOFTPIPE")) {
122 pipe = nouveau_pipe_create(nv);
123 if (!pipe)
124 NOUVEAU_ERR("Couldn't create hw pipe\n");
125 }
126
127 if (!pipe) {
128 NOUVEAU_MSG("Using softpipe\n");
129 pipe = nouveau_create_softpipe(nv);
130 if (!pipe) {
131 NOUVEAU_ERR("Error creating pipe, bailing\n");
132 return GL_FALSE;
133 }
134 }
135
136 pipe->priv = nv;
137 nv->st = st_create_context(pipe, glVis, st_share);
138 return GL_TRUE;
139 }
140
141 void
142 nouveau_context_destroy(__DRIcontextPrivate *driContextPriv)
143 {
144 struct nouveau_context *nv = driContextPriv->driverPrivate;
145
146 assert(nv);
147
148 st_flush(nv->st, PIPE_FLUSH_WAIT);
149 st_destroy_context(nv->st);
150
151 nouveau_grobj_free(&nv->NvCtxSurf2D);
152 nouveau_grobj_free(&nv->NvImageBlit);
153 nouveau_channel_free(&nv->channel);
154
155 free(nv);
156 }
157
158 GLboolean
159 nouveau_context_bind(__DRIcontextPrivate *driContextPriv,
160 __DRIdrawablePrivate *driDrawPriv,
161 __DRIdrawablePrivate *driReadPriv)
162 {
163 struct nouveau_context *nv;
164 struct nouveau_framebuffer *draw, *read;
165
166 if (!driContextPriv) {
167 st_make_current(NULL, NULL, NULL);
168 return GL_TRUE;
169 }
170
171 nv = driContextPriv->driverPrivate;
172 draw = driDrawPriv->driverPrivate;
173 read = driReadPriv->driverPrivate;
174
175 st_make_current(nv->st, draw->stfb, read->stfb);
176
177 if ((nv->dri_drawable != driDrawPriv) ||
178 (nv->last_stamp != driDrawPriv->lastStamp)) {
179 nv->dri_drawable = driDrawPriv;
180 st_resize_framebuffer(draw->stfb, driDrawPriv->w,
181 driDrawPriv->h);
182 nv->last_stamp = driDrawPriv->lastStamp;
183 }
184
185 if (driDrawPriv != driReadPriv) {
186 st_resize_framebuffer(read->stfb, driReadPriv->w,
187 driReadPriv->h);
188 }
189
190 return GL_TRUE;
191 }
192
193 GLboolean
194 nouveau_context_unbind(__DRIcontextPrivate *driContextPriv)
195 {
196 struct nouveau_context *nv = driContextPriv->driverPrivate;
197 (void)nv;
198
199 st_flush(nv->st, 0);
200 return GL_TRUE;
201 }
202