1 #include <pipe/p_defines.h>
2 #include <pipe/p_context.h>
3 #include <pipe/p_screen.h>
4 #include <util/u_memory.h>
5 #include "nouveau_context.h"
6 #include "nouveau_dri.h"
7 #include "nouveau_local.h"
8 #include "nouveau_screen.h"
9 #include "nouveau_winsys_pipe.h"
12 nouveau_channel_context_destroy(struct nouveau_channel_context
*nvc
)
14 nouveau_grobj_free(&nvc
->NvCtxSurf2D
);
15 nouveau_grobj_free(&nvc
->NvImageBlit
);
16 nouveau_grobj_free(&nvc
->NvGdiRect
);
17 nouveau_grobj_free(&nvc
->NvM2MF
);
18 nouveau_grobj_free(&nvc
->Nv2D
);
19 nouveau_grobj_free(&nvc
->NvSwzSurf
);
20 nouveau_grobj_free(&nvc
->NvSIFM
);
22 nouveau_notifier_free(&nvc
->sync_notifier
);
24 nouveau_channel_free(&nvc
->channel
);
29 static struct nouveau_channel_context
*
30 nouveau_channel_context_create(struct nouveau_device
*dev
)
32 struct nouveau_channel_context
*nvc
;
35 nvc
= CALLOC_STRUCT(nouveau_channel_context
);
39 if ((ret
= nouveau_channel_alloc(dev
, 0x8003d001, 0x8003d002,
41 NOUVEAU_ERR("Error creating GPU channel: %d\n", ret
);
42 nouveau_channel_context_destroy(nvc
);
46 nvc
->next_handle
= 0x88000000;
48 if ((ret
= nouveau_notifier_alloc(nvc
->channel
, nvc
->next_handle
++, 1,
49 &nvc
->sync_notifier
))) {
50 NOUVEAU_ERR("Error creating channel sync notifier: %d\n", ret
);
51 nouveau_channel_context_destroy(nvc
);
55 switch (dev
->chipset
& 0xf0) {
59 ret
= nouveau_surface_channel_create_nv50(nvc
);
62 ret
= nouveau_surface_channel_create_nv04(nvc
);
67 NOUVEAU_ERR("Error initialising surface objects: %d\n", ret
);
68 nouveau_channel_context_destroy(nvc
);
76 nouveau_context_init(struct nouveau_screen
*nv_screen
,
77 drm_context_t hHWContext
, drmLock
*sarea_lock
,
78 struct nouveau_context
*nv_share
,
79 struct nouveau_context
*nv
)
81 struct pipe_context
*pipe
= NULL
;
82 struct nouveau_channel_context
*nvc
= NULL
;
83 struct nouveau_device
*dev
= nv_screen
->device
;
86 switch (dev
->chipset
& 0xf0) {
103 NOUVEAU_ERR("Unsupported chipset: NV%02x\n", dev
->chipset
);
107 nv
->nv_screen
= nv_screen
;
110 struct nouveau_device_priv
*nvdev
= nouveau_device(dev
);
112 nvdev
->ctx
= hHWContext
;
113 nvdev
->lock
= sarea_lock
;
116 /* Attempt to share a single channel between multiple contexts from
119 nvc
= nv_screen
->nvc
;
120 if (!nvc
&& nv_share
)
123 /*XXX: temporary - disable multi-context/single-channel on pre-NV4x */
124 switch (dev
->chipset
& 0xf0) {
139 nvc
= nouveau_channel_context_create(dev
);
141 NOUVEAU_ERR("Failed initialising GPU context\n");
144 nv_screen
->nvc
= nvc
;
150 /* Find a free slot for a pipe context, allocate a new one if needed */
152 for (i
= 0; i
< nvc
->nr_pctx
; i
++) {
153 if (nvc
->pctx
[i
] == NULL
) {
159 if (nv
->pctx_id
< 0) {
160 nv
->pctx_id
= nvc
->nr_pctx
++;
163 sizeof(struct pipe_context
*) * nvc
->nr_pctx
);
167 switch (dev
->chipset
& 0xf0) {
171 if (nouveau_surface_init_nv50(nv
))
175 if (nouveau_surface_init_nv04(nv
))
180 if (!getenv("NOUVEAU_FORCE_SOFTPIPE")) {
181 struct pipe_screen
*pscreen
;
183 pipe
= nouveau_pipe_create(nv
);
185 NOUVEAU_ERR("Couldn't create hw pipe\n");
186 pscreen
= nvc
->pscreen
;
188 nv
->cap
.hw_vertex_buffer
=
189 pscreen
->get_param(pscreen
, NOUVEAU_CAP_HW_VTXBUF
);
190 nv
->cap
.hw_index_buffer
=
191 pscreen
->get_param(pscreen
, NOUVEAU_CAP_HW_IDXBUF
);
195 NOUVEAU_MSG("Using softpipe\n");
196 pipe
= nouveau_create_softpipe(nv
);
198 NOUVEAU_ERR("Error creating pipe, bailing\n");
204 struct pipe_texture
*fb_tex
;
205 struct pipe_surface
*fb_surf
;
206 struct nouveau_pipe_buffer
*fb_buf
;
207 enum pipe_format format
;
209 fb_buf
= calloc(1, sizeof(struct nouveau_pipe_buffer
));
210 fb_buf
->base
.refcount
= 1;
211 fb_buf
->base
.usage
= PIPE_BUFFER_USAGE_PIXEL
;
213 nouveau_bo_fake(dev
, nv_screen
->front_offset
, NOUVEAU_BO_VRAM
,
214 nv_screen
->front_pitch
*nv_screen
->front_height
,
217 if (nv_screen
->front_cpp
== 4)
218 format
= PIPE_FORMAT_A8R8G8B8_UNORM
;
220 format
= PIPE_FORMAT_R5G6B5_UNORM
;
222 fb_surf
= nouveau_surface_buffer_ref(nv
, &fb_buf
->base
, format
,
223 nv_screen
->front_pitch
/
224 nv_screen
->front_cpp
,
225 nv_screen
->front_height
,
226 nv_screen
->front_pitch
,
229 nv
->frontbuffer
= fb_surf
;
230 nv
->frontbuffer_texture
= fb_tex
;
238 nouveau_context_cleanup(struct nouveau_context
*nv
)
240 struct nouveau_channel_context
*nvc
= nv
->nvc
;
244 if (nv
->pctx_id
>= 0) {
245 nvc
->pctx
[nv
->pctx_id
] = NULL
;
246 if (--nvc
->refcount
<= 0) {
247 nouveau_channel_context_destroy(nvc
);
248 nv
->nv_screen
->nvc
= NULL
;
252 /* XXX: Who cleans up the pipe? */