1 #include "pipe/p_context.h"
2 #include "pipe/p_state.h"
3 #include "util/u_memory.h"
5 #include "nouveau_drm_api.h"
7 #include "nouveau_drmif.h"
8 #include "nouveau_channel.h"
9 #include "nouveau_bo.h"
11 #include "nouveau/nouveau_winsys.h"
12 #include "nouveau/nouveau_screen.h"
14 static struct pipe_surface
*
15 dri_surface_from_handle(struct drm_api
*api
, struct pipe_screen
*pscreen
,
16 unsigned handle
, enum pipe_format format
,
17 unsigned width
, unsigned height
, unsigned pitch
)
19 struct pipe_surface
*ps
= NULL
;
20 struct pipe_texture
*pt
= NULL
;
21 struct pipe_texture tmpl
;
23 memset(&tmpl
, 0, sizeof(tmpl
));
24 tmpl
.tex_usage
= PIPE_TEXTURE_USAGE_PRIMARY
;
25 tmpl
.target
= PIPE_TEXTURE_2D
;
30 tmpl
.height0
= height
;
32 pt
= api
->texture_from_shared_handle(api
, pscreen
, &tmpl
,
33 "front buffer", pitch
, handle
);
37 ps
= pscreen
->get_tex_surface(pscreen
, pt
, 0, 0, 0,
38 PIPE_BUFFER_USAGE_GPU_READ
|
39 PIPE_BUFFER_USAGE_GPU_WRITE
);
41 /* we don't need the texture from this point on */
42 pipe_texture_reference(&pt
, NULL
);
46 static struct pipe_surface
*
47 nouveau_dri1_front_surface(struct pipe_screen
*screen
)
49 return nouveau_winsys_screen(screen
)->front
;
52 static struct dri1_api nouveau_dri1_api
= {
53 nouveau_dri1_front_surface
,
56 static struct pipe_screen
*
57 nouveau_drm_create_screen(struct drm_api
*api
, int fd
,
58 struct drm_create_screen_arg
*arg
)
60 struct dri1_create_screen_arg
*dri1
= (void *)arg
;
61 struct nouveau_winsys
*nvws
;
62 struct pipe_winsys
*ws
;
63 struct nouveau_device
*dev
= NULL
;
64 struct pipe_screen
*(*init
)(struct pipe_winsys
*,
65 struct nouveau_device
*);
68 ret
= nouveau_device_open_existing(&dev
, 0, fd
, 0);
72 switch (dev
->chipset
& 0xf0) {
74 init
= nv04_screen_create
;
77 init
= nv10_screen_create
;
80 init
= nv20_screen_create
;
83 init
= nv30_screen_create
;
87 init
= nv40_screen_create
;
92 init
= nv50_screen_create
;
95 debug_printf("%s: unknown chipset nv%02x\n", __func__
,
100 nvws
= CALLOC_STRUCT(nouveau_winsys
);
102 nouveau_device_close(&dev
);
107 nvws
->pscreen
= init(ws
, dev
);
108 if (!nvws
->pscreen
) {
113 if (arg
&& arg
->mode
== DRM_CREATE_DRI1
) {
114 struct nouveau_dri
*nvdri
= dri1
->ddx_info
;
115 enum pipe_format format
;
117 if (nvdri
->bpp
== 16)
118 format
= PIPE_FORMAT_R5G6B5_UNORM
;
120 format
= PIPE_FORMAT_A8R8G8B8_UNORM
;
122 nvws
->front
= dri_surface_from_handle(api
, nvws
->pscreen
,
124 format
, nvdri
->width
,
129 debug_printf("%s: error referencing front buffer\n",
135 dri1
->api
= &nouveau_dri1_api
;
138 return nvws
->pscreen
;
141 static struct pipe_context
*
142 nouveau_drm_create_context(struct drm_api
*api
, struct pipe_screen
*pscreen
)
144 struct nouveau_winsys
*nvws
= nouveau_winsys_screen(pscreen
);
145 struct pipe_context
*(*init
)(struct pipe_screen
*, unsigned);
146 unsigned chipset
= nouveau_screen(pscreen
)->device
->chipset
;
149 switch (chipset
& 0xf0) {
172 debug_printf("%s: unknown chipset nv%02x\n", __func__
, chipset
);
176 /* Find a free slot for a pipe context, allocate a new one if needed */
177 for (i
= 0; i
< nvws
->nr_pctx
; i
++) {
178 if (nvws
->pctx
[i
] == NULL
)
182 if (i
== nvws
->nr_pctx
) {
184 nvws
->pctx
= realloc(nvws
->pctx
,
185 sizeof(*nvws
->pctx
) * nvws
->nr_pctx
);
188 nvws
->pctx
[i
] = init(pscreen
, i
);
189 return nvws
->pctx
[i
];
192 typedef struct pipe_video_context
* (*nouveau_video_create
)(struct pipe_context
*pipe
,
193 enum pipe_video_profile profile
,
194 enum pipe_video_chroma_format chroma_format
,
195 unsigned width
, unsigned height
,
198 static struct pipe_video_context
*
199 nouveau_drm_create_video_context(struct drm_api
*api
, struct pipe_screen
*pscreen
,
200 enum pipe_video_profile profile
,
201 enum pipe_video_chroma_format chroma_format
,
202 unsigned width
, unsigned height
)
204 struct nouveau_winsys
*nvws
= nouveau_winsys_screen(pscreen
);
205 nouveau_video_create init
;
206 unsigned chipset
= nouveau_screen(pscreen
)->device
->chipset
;
207 struct pipe_context
*pipe
;
210 switch (chipset
& 0xf0) {
213 init
= nv40_video_create
;
216 debug_printf("%s: unknown chipset nv%02x\n", __func__
, chipset
);
220 /* Find a free slot for a pipe video context, allocate a new one if needed */
221 for (i
= 0; i
< nvws
->nr_pvctx
; i
++) {
222 if (nvws
->pvctx
[i
] == NULL
)
226 if (i
== nvws
->nr_pvctx
) {
228 nvws
->pvctx
= realloc(nvws
->pvctx
,
229 sizeof(*nvws
->pvctx
) * nvws
->nr_pvctx
);
232 pipe
= nouveau_drm_create_context(api
, pscreen
);
236 nvws
->pvctx
[i
] = init(pipe
, profile
, chroma_format
, width
, height
, i
);
237 return nvws
->pvctx
[i
];
240 static struct pipe_texture
*
241 nouveau_drm_pt_from_name(struct drm_api
*api
, struct pipe_screen
*pscreen
,
242 struct pipe_texture
*templ
, const char *name
,
243 unsigned stride
, unsigned handle
)
245 struct nouveau_device
*dev
= nouveau_screen(pscreen
)->device
;
246 struct pipe_texture
*pt
;
247 struct pipe_buffer
*pb
;
250 pb
= CALLOC(1, sizeof(struct pipe_buffer
) + sizeof(struct nouveau_bo
*));
254 ret
= nouveau_bo_handle_ref(dev
, handle
, (struct nouveau_bo
**)(pb
+1));
256 debug_printf("%s: ref name 0x%08x failed with %d\n",
257 __func__
, handle
, ret
);
262 pipe_reference_init(&pb
->reference
, 1);
263 pb
->screen
= pscreen
;
265 pb
->usage
= PIPE_BUFFER_USAGE_GPU_READ_WRITE
|
266 PIPE_BUFFER_USAGE_CPU_READ_WRITE
;
267 pb
->size
= nouveau_bo(pb
)->size
;
268 pt
= pscreen
->texture_blanket(pscreen
, templ
, &stride
, pb
);
269 pipe_buffer_reference(&pb
, NULL
);
274 nouveau_drm_name_from_pt(struct drm_api
*api
, struct pipe_screen
*pscreen
,
275 struct pipe_texture
*pt
, unsigned *stride
,
278 struct nouveau_miptree
*mt
= nouveau_miptree(pt
);
283 return nouveau_bo_handle_get(mt
->bo
, handle
) == 0;
287 nouveau_drm_handle_from_pt(struct drm_api
*api
, struct pipe_screen
*pscreen
,
288 struct pipe_texture
*pt
, unsigned *stride
,
291 struct nouveau_miptree
*mt
= nouveau_miptree(pt
);
296 *handle
= mt
->bo
->handle
;
297 *stride
= pf_get_stride(mt
->base
.format
, mt
->base
.width0
);
301 struct drm_api drm_api_hooks
= {
302 .create_screen
= nouveau_drm_create_screen
,
303 .create_context
= nouveau_drm_create_context
,
304 .create_video_context
= nouveau_drm_create_video_context
,
305 .texture_from_shared_handle
= nouveau_drm_pt_from_name
,
306 .shared_handle_from_texture
= nouveau_drm_name_from_pt
,
307 .local_handle_from_texture
= nouveau_drm_handle_from_pt
,
312 return &drm_api_hooks
;