1 #include "main/glheader.h"
2 #include "glapi/glthread.h"
3 #include <GL/internal/glcore.h>
6 #include "state_tracker/st_public.h"
7 #include "state_tracker/st_context.h"
8 #include "pipe/p_defines.h"
9 #include "pipe/p_context.h"
10 #include "pipe/p_screen.h"
12 #include "nouveau_context.h"
13 #include "nouveau_dri.h"
14 #include "nouveau_local.h"
15 #include "nouveau_screen.h"
16 #include "nouveau_winsys_pipe.h"
19 static const struct dri_debug_control debug_control
[] = {
23 int __nouveau_debug
= 0;
27 nouveau_channel_context_destroy(struct nouveau_channel_context
*nvc
)
29 nouveau_grobj_free(&nvc
->NvCtxSurf2D
);
30 nouveau_grobj_free(&nvc
->NvImageBlit
);
31 nouveau_grobj_free(&nvc
->NvGdiRect
);
32 nouveau_grobj_free(&nvc
->NvM2MF
);
33 nouveau_grobj_free(&nvc
->Nv2D
);
34 nouveau_grobj_free(&nvc
->NvSwzSurf
);
35 nouveau_grobj_free(&nvc
->NvSIFM
);
37 nouveau_notifier_free(&nvc
->sync_notifier
);
39 nouveau_channel_free(&nvc
->channel
);
44 static struct nouveau_channel_context
*
45 nouveau_channel_context_create(struct nouveau_device
*dev
)
47 struct nouveau_channel_context
*nvc
;
50 nvc
= CALLOC_STRUCT(nouveau_channel_context
);
54 if ((ret
= nouveau_channel_alloc(dev
, 0x8003d001, 0x8003d002,
56 NOUVEAU_ERR("Error creating GPU channel: %d\n", ret
);
57 nouveau_channel_context_destroy(nvc
);
61 nvc
->next_handle
= 0x80000000;
63 if ((ret
= nouveau_notifier_alloc(nvc
->channel
, nvc
->next_handle
++, 1,
64 &nvc
->sync_notifier
))) {
65 NOUVEAU_ERR("Error creating channel sync notifier: %d\n", ret
);
66 nouveau_channel_context_destroy(nvc
);
70 switch (dev
->chipset
& 0xf0) {
74 ret
= nouveau_surface_channel_create_nv50(nvc
);
77 ret
= nouveau_surface_channel_create_nv04(nvc
);
82 NOUVEAU_ERR("Error initialising surface objects: %d\n", ret
);
83 nouveau_channel_context_destroy(nvc
);
91 nouveau_context_create(const __GLcontextModes
*glVis
,
92 __DRIcontextPrivate
*driContextPriv
,
93 void *sharedContextPrivate
)
95 __DRIscreenPrivate
*driScrnPriv
= driContextPriv
->driScreenPriv
;
96 struct nouveau_screen
*nv_screen
= driScrnPriv
->private;
97 struct nouveau_context
*nv
= CALLOC_STRUCT(nouveau_context
);
98 struct pipe_context
*pipe
= NULL
;
99 struct st_context
*st_share
= NULL
;
100 struct nouveau_channel_context
*nvc
= NULL
;
101 struct nouveau_device
*dev
= nv_screen
->device
;
104 if (sharedContextPrivate
) {
105 st_share
= ((struct nouveau_context
*)sharedContextPrivate
)->st
;
108 switch (dev
->chipset
& 0xf0) {
123 NOUVEAU_ERR("Unsupported chipset: NV%02x\n", dev
->chipset
);
127 driContextPriv
->driverPrivate
= (void *)nv
;
128 nv
->nv_screen
= nv_screen
;
129 nv
->dri_screen
= driScrnPriv
;
132 struct nouveau_device_priv
*nvdev
= nouveau_device(dev
);
134 nvdev
->ctx
= driContextPriv
->hHWContext
;
135 nvdev
->lock
= (drmLock
*)&driScrnPriv
->pSAREA
->lock
;
138 driParseConfigFiles(&nv
->dri_option_cache
, &nv_screen
->option_cache
,
139 nv
->dri_screen
->myNum
, "nouveau");
141 __nouveau_debug
= driParseDebugString(getenv("NOUVEAU_DEBUG"),
145 /*XXX: Hack up a fake region and buffer object for front buffer.
146 * This will go away with TTM, replaced with a simple reference
147 * of the front buffer handle passed to us by the DDX.
150 struct pipe_surface
*fb_surf
;
151 struct nouveau_pipe_buffer
*fb_buf
;
152 struct nouveau_bo_priv
*fb_bo
;
154 fb_bo
= calloc(1, sizeof(struct nouveau_bo_priv
));
155 fb_bo
->drm
.offset
= nv_screen
->front_offset
;
156 fb_bo
->drm
.flags
= NOUVEAU_MEM_FB
;
157 fb_bo
->drm
.size
= nv_screen
->front_pitch
*
158 nv_screen
->front_height
;
160 fb_bo
->base
.flags
= NOUVEAU_BO_PIN
| NOUVEAU_BO_VRAM
;
161 fb_bo
->base
.offset
= fb_bo
->drm
.offset
;
162 fb_bo
->base
.handle
= (unsigned long)fb_bo
;
163 fb_bo
->base
.size
= fb_bo
->drm
.size
;
164 fb_bo
->base
.device
= nv_screen
->device
;
166 fb_buf
= calloc(1, sizeof(struct nouveau_pipe_buffer
));
167 fb_buf
->bo
= &fb_bo
->base
;
169 fb_surf
= calloc(1, sizeof(struct pipe_surface
));
170 if (nv_screen
->front_cpp
== 2)
171 fb_surf
->format
= PIPE_FORMAT_R5G6B5_UNORM
;
173 fb_surf
->format
= PIPE_FORMAT_A8R8G8B8_UNORM
;
174 pf_get_block(fb_surf
->format
, &fb_surf
->block
);
175 fb_surf
->width
= nv_screen
->front_pitch
/ nv_screen
->front_cpp
;
176 fb_surf
->height
= nv_screen
->front_height
;
177 fb_surf
->stride
= fb_surf
->width
* fb_surf
->block
.size
;
178 fb_surf
->refcount
= 1;
179 fb_surf
->buffer
= &fb_buf
->base
;
181 nv
->frontbuffer
= fb_surf
;
184 /* Attempt to share a single channel between multiple contexts from
187 nvc
= nv_screen
->nvc
;
188 if (!nvc
&& st_share
) {
189 struct nouveau_context
*snv
= st_share
->pipe
->priv
;
195 /*XXX: temporary - disable multi-context/single-channel on pre-NV4x */
196 switch (dev
->chipset
& 0xf0) {
211 nvc
= nouveau_channel_context_create(dev
);
213 NOUVEAU_ERR("Failed initialising GPU context\n");
216 nv_screen
->nvc
= nvc
;
222 /* Find a free slot for a pipe context, allocate a new one if needed */
224 for (i
= 0; i
< nvc
->nr_pctx
; i
++) {
225 if (nvc
->pctx
[i
] == NULL
) {
231 if (nv
->pctx_id
< 0) {
232 nv
->pctx_id
= nvc
->nr_pctx
++;
235 sizeof(struct pipe_context
*) * nvc
->nr_pctx
);
239 switch (dev
->chipset
& 0xf0) {
243 if (nouveau_surface_init_nv50(nv
))
247 if (nouveau_surface_init_nv04(nv
))
252 if (!getenv("NOUVEAU_FORCE_SOFTPIPE")) {
253 struct pipe_screen
*pscreen
;
255 pipe
= nouveau_pipe_create(nv
);
257 NOUVEAU_ERR("Couldn't create hw pipe\n");
258 pscreen
= nvc
->pscreen
;
260 nv
->cap
.hw_vertex_buffer
=
261 pscreen
->get_param(pscreen
, NOUVEAU_CAP_HW_VTXBUF
);
262 nv
->cap
.hw_index_buffer
=
263 pscreen
->get_param(pscreen
, NOUVEAU_CAP_HW_IDXBUF
);
267 NOUVEAU_MSG("Using softpipe\n");
268 pipe
= nouveau_create_softpipe(nv
);
270 NOUVEAU_ERR("Error creating pipe, bailing\n");
276 nv
->st
= st_create_context(pipe
, glVis
, st_share
);
281 nouveau_context_destroy(__DRIcontextPrivate
*driContextPriv
)
283 struct nouveau_context
*nv
= driContextPriv
->driverPrivate
;
284 struct nouveau_channel_context
*nvc
= nv
->nvc
;
289 st_destroy_context(nv
->st
);
291 if (nv
->pctx_id
>= 0) {
292 nvc
->pctx
[nv
->pctx_id
] = NULL
;
293 if (--nvc
->refcount
<= 0) {
294 nouveau_channel_context_destroy(nvc
);
295 nv
->nv_screen
->nvc
= NULL
;
303 nouveau_context_bind(__DRIcontextPrivate
*driContextPriv
,
304 __DRIdrawablePrivate
*driDrawPriv
,
305 __DRIdrawablePrivate
*driReadPriv
)
307 struct nouveau_context
*nv
;
308 struct nouveau_framebuffer
*draw
, *read
;
310 if (!driContextPriv
) {
311 st_make_current(NULL
, NULL
, NULL
);
315 nv
= driContextPriv
->driverPrivate
;
316 draw
= driDrawPriv
->driverPrivate
;
317 read
= driReadPriv
->driverPrivate
;
319 st_make_current(nv
->st
, draw
->stfb
, read
->stfb
);
321 if ((nv
->dri_drawable
!= driDrawPriv
) ||
322 (nv
->last_stamp
!= driDrawPriv
->lastStamp
)) {
323 nv
->dri_drawable
= driDrawPriv
;
324 st_resize_framebuffer(draw
->stfb
, driDrawPriv
->w
,
326 nv
->last_stamp
= driDrawPriv
->lastStamp
;
329 if (driDrawPriv
!= driReadPriv
) {
330 st_resize_framebuffer(read
->stfb
, driReadPriv
->w
,
338 nouveau_context_unbind(__DRIcontextPrivate
*driContextPriv
)
340 struct nouveau_context
*nv
= driContextPriv
->driverPrivate
;
343 st_flush(nv
->st
, 0, NULL
);