1 #include "pipe/p_defines.h"
2 #include "pipe/p_context.h"
3 #include "pipe/p_screen.h"
4 #include "pipe/p_util.h"
6 #include "nouveau_context.h"
7 #include "nouveau_dri.h"
8 #include "nouveau_local.h"
9 #include "nouveau_screen.h"
10 #include "nouveau_winsys_pipe.h"
14 static const struct dri_debug_control debug_control[] = {
18 int __nouveau_debug = 0;
23 * TODO: Re-examine dri_screen, dri_context, nouveau_screen, nouveau_context
24 * relationships, seems like there is a lot of room for simplification there.
28 nouveau_channel_context_destroy(struct nouveau_channel_context
*nvc
)
30 nouveau_grobj_free(&nvc
->NvCtxSurf2D
);
31 nouveau_grobj_free(&nvc
->NvImageBlit
);
32 nouveau_grobj_free(&nvc
->NvGdiRect
);
33 nouveau_grobj_free(&nvc
->NvM2MF
);
34 nouveau_grobj_free(&nvc
->Nv2D
);
35 nouveau_grobj_free(&nvc
->NvSwzSurf
);
36 nouveau_grobj_free(&nvc
->NvSIFM
);
38 nouveau_notifier_free(&nvc
->sync_notifier
);
40 nouveau_channel_free(&nvc
->channel
);
45 static struct nouveau_channel_context
*
46 nouveau_channel_context_create(struct nouveau_device
*dev
)
48 struct nouveau_channel_context
*nvc
;
51 nvc
= CALLOC_STRUCT(nouveau_channel_context
);
55 if ((ret
= nouveau_channel_alloc(dev
, 0x8003d001, 0x8003d002,
57 NOUVEAU_ERR("Error creating GPU channel: %d\n", ret
);
58 nouveau_channel_context_destroy(nvc
);
62 nvc
->next_handle
= 0x80000000;
64 if ((ret
= nouveau_notifier_alloc(nvc
->channel
, nvc
->next_handle
++, 1,
65 &nvc
->sync_notifier
))) {
66 NOUVEAU_ERR("Error creating channel sync notifier: %d\n", ret
);
67 nouveau_channel_context_destroy(nvc
);
71 switch (dev
->chipset
& 0xf0) {
75 ret
= nouveau_surface_channel_create_nv50(nvc
);
78 ret
= nouveau_surface_channel_create_nv04(nvc
);
83 NOUVEAU_ERR("Error initialising surface objects: %d\n", ret
);
84 nouveau_channel_context_destroy(nvc
);
92 nouveau_context_create(dri_context_t
*dri_context
)
94 dri_screen_t
*dri_screen
= dri_context
->dri_screen
;
95 struct nouveau_screen
*nv_screen
= dri_screen
->private;
96 struct nouveau_context
*nv
= CALLOC_STRUCT(nouveau_context
);
97 struct pipe_context
*pipe
= NULL
;
98 struct nouveau_channel_context
*nvc
= NULL
;
99 struct nouveau_device
*dev
= nv_screen
->device
;
102 switch (dev
->chipset
& 0xf0) {
117 NOUVEAU_ERR("Unsupported chipset: NV%02x\n", dev
->chipset
);
121 dri_context
->private = (void*)nv
;
122 nv
->dri_context
= dri_context
;
123 nv
->nv_screen
= nv_screen
;
126 struct nouveau_device_priv
*nvdev
= nouveau_device(dev
);
128 nvdev
->ctx
= dri_context
->drm_context
;
129 nvdev
->lock
= (drmLock
*)&dri_screen
->sarea
->lock
;
133 driParseConfigFiles(&nv->dri_option_cache, &nv_screen->option_cache,
134 nv->dri_screen->myNum, "nouveau");
136 __nouveau_debug = driParseDebugString(getenv("NOUVEAU_DEBUG"),
141 /*XXX: Hack up a fake region and buffer object for front buffer.
142 * This will go away with TTM, replaced with a simple reference
143 * of the front buffer handle passed to us by the DDX.
146 struct pipe_surface
*fb_surf
;
147 struct nouveau_pipe_buffer
*fb_buf
;
148 struct nouveau_bo_priv
*fb_bo
;
150 fb_bo
= calloc(1, sizeof(struct nouveau_bo_priv
));
151 fb_bo
->drm
.offset
= nv_screen
->front_offset
;
152 fb_bo
->drm
.flags
= NOUVEAU_MEM_FB
;
153 fb_bo
->drm
.size
= nv_screen
->front_pitch
*
154 nv_screen
->front_height
;
156 fb_bo
->base
.flags
= NOUVEAU_BO_PIN
| NOUVEAU_BO_VRAM
;
157 fb_bo
->base
.offset
= fb_bo
->drm
.offset
;
158 fb_bo
->base
.handle
= (unsigned long)fb_bo
;
159 fb_bo
->base
.size
= fb_bo
->drm
.size
;
160 fb_bo
->base
.device
= nv_screen
->device
;
162 fb_buf
= calloc(1, sizeof(struct nouveau_pipe_buffer
));
163 fb_buf
->bo
= &fb_bo
->base
;
165 fb_surf
= calloc(1, sizeof(struct pipe_surface
));
166 if (nv_screen
->front_cpp
== 2)
167 fb_surf
->format
= PIPE_FORMAT_R5G6B5_UNORM
;
169 fb_surf
->format
= PIPE_FORMAT_A8R8G8B8_UNORM
;
170 pf_get_block(fb_surf
->format
, &fb_surf
->block
);
171 fb_surf
->width
= nv_screen
->front_pitch
/ nv_screen
->front_cpp
;
172 fb_surf
->height
= nv_screen
->front_height
;
173 fb_surf
->stride
= fb_surf
->width
* fb_surf
->block
.size
;
174 fb_surf
->refcount
= 1;
175 fb_surf
->buffer
= &fb_buf
->base
;
177 nv
->frontbuffer
= fb_surf
;
180 nvc
= nv_screen
->nvc
;
183 nvc
= nouveau_channel_context_create(dev
);
185 NOUVEAU_ERR("Failed initialising GPU context\n");
188 nv_screen
->nvc
= nvc
;
194 /* Find a free slot for a pipe context, allocate a new one if needed */
196 for (i
= 0; i
< nvc
->nr_pctx
; i
++) {
197 if (nvc
->pctx
[i
] == NULL
) {
203 if (nv
->pctx_id
< 0) {
204 nv
->pctx_id
= nvc
->nr_pctx
++;
207 sizeof(struct pipe_context
*) * nvc
->nr_pctx
);
211 switch (dev
->chipset
& 0xf0) {
215 if (nouveau_surface_init_nv50(nv
))
219 if (nouveau_surface_init_nv04(nv
))
224 if (!getenv("NOUVEAU_FORCE_SOFTPIPE")) {
225 struct pipe_screen
*pscreen
;
227 pipe
= nouveau_pipe_create(nv
);
229 NOUVEAU_ERR("Couldn't create hw pipe\n");
230 pscreen
= nvc
->pscreen
;
232 nv
->cap
.hw_vertex_buffer
=
233 pscreen
->get_param(pscreen
, NOUVEAU_CAP_HW_VTXBUF
);
234 nv
->cap
.hw_index_buffer
=
235 pscreen
->get_param(pscreen
, NOUVEAU_CAP_HW_IDXBUF
);
238 /* XXX: nouveau_winsys_softpipe needs a mesa header removed before we can compile it. */
241 NOUVEAU_MSG("Using softpipe\n");
242 pipe = nouveau_create_softpipe(nv);
244 NOUVEAU_ERR("Error creating pipe, bailing\n");
250 NOUVEAU_ERR("Error creating pipe, bailing\n");
260 nouveau_context_destroy(dri_context_t
*dri_context
)
262 struct nouveau_context
*nv
= dri_context
->private;
263 struct nouveau_channel_context
*nvc
= nv
->nvc
;
267 if (nv
->pctx_id
>= 0) {
268 nvc
->pctx
[nv
->pctx_id
] = NULL
;
269 if (--nvc
->refcount
<= 0) {
270 nouveau_channel_context_destroy(nvc
);
271 nv
->nv_screen
->nvc
= NULL
;
279 nouveau_context_bind(struct nouveau_context
*nv
, dri_drawable_t
*dri_drawable
)
282 assert(dri_drawable
);
284 if (nv
->dri_drawable
!= dri_drawable
)
286 nv
->dri_drawable
= dri_drawable
;
287 dri_drawable
->private = nv
;
294 nouveau_context_unbind(struct nouveau_context
*nv
)
298 nv
->dri_drawable
= NULL
;
303 /* Show starts here */
305 int bind_pipe_drawable(struct pipe_context
*pipe
, Drawable drawable
)
307 struct nouveau_context
*nv
;
308 dri_drawable_t
*dri_drawable
;
312 driCreateDrawable(nv
->nv_screen
->dri_screen
, drawable
, &dri_drawable
);
314 nouveau_context_bind(nv
, dri_drawable
);
319 int unbind_pipe_drawable(struct pipe_context
*pipe
)
321 nouveau_context_unbind(pipe
->priv
);
326 struct pipe_context
* create_pipe_context(Display
*display
, int screen
)
328 dri_screen_t
*dri_screen
;
329 dri_framebuffer_t dri_framebuf
;
330 dri_context_t
*dri_context
;
331 struct nouveau_context
*nv
;
333 driCreateScreen(display
, screen
, &dri_screen
, &dri_framebuf
);
334 driCreateContext(dri_screen
, XDefaultVisual(display
, screen
), &dri_context
);
336 nouveau_screen_create(dri_screen
, &dri_framebuf
);
337 nouveau_context_create(dri_context
);
339 nv
= dri_context
->private;
341 return nv
->nvc
->pctx
[nv
->pctx_id
];
344 int destroy_pipe_context(struct pipe_context
*pipe
)
346 struct pipe_screen
*screen
;
347 struct pipe_winsys
*winsys
;
348 struct nouveau_context
*nv
;
349 dri_screen_t
*dri_screen
;
350 dri_context_t
*dri_context
;
354 screen
= pipe
->screen
;
355 winsys
= pipe
->winsys
;
357 dri_context
= nv
->dri_context
;
358 dri_screen
= dri_context
->dri_screen
;
361 screen
->destroy(screen
);
364 nouveau_context_destroy(dri_context
);
365 nouveau_screen_destroy(dri_screen
);
366 driDestroyContext(dri_context
);
367 driDestroyScreen(dri_screen
);