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
*screen
,
17 enum pipe_format format
,
22 struct pipe_surface
*surface
= NULL
;
23 struct pipe_texture
*texture
= NULL
;
24 struct pipe_texture templat
;
25 struct pipe_buffer
*buf
= NULL
;
27 buf
= api
->buffer_from_handle(api
, screen
, "front buffer", handle
);
31 memset(&templat
, 0, sizeof(templat
));
32 templat
.tex_usage
= PIPE_TEXTURE_USAGE_PRIMARY
|
33 NOUVEAU_TEXTURE_USAGE_LINEAR
;
34 templat
.target
= PIPE_TEXTURE_2D
;
35 templat
.last_level
= 0;
37 templat
.format
= format
;
38 templat
.width
[0] = width
;
39 templat
.height
[0] = height
;
40 pf_get_block(templat
.format
, &templat
.block
);
42 texture
= screen
->texture_blanket(screen
,
47 /* we don't need the buffer from this point on */
48 pipe_buffer_reference(&buf
, NULL
);
53 surface
= screen
->get_tex_surface(screen
, texture
, 0, 0, 0,
54 PIPE_BUFFER_USAGE_GPU_READ
|
55 PIPE_BUFFER_USAGE_GPU_WRITE
);
57 /* we don't need the texture from this point on */
58 pipe_texture_reference(&texture
, NULL
);
62 static struct pipe_surface
*
63 nouveau_dri1_front_surface(struct pipe_context
*pipe
)
65 return nouveau_winsys_screen(pipe
->screen
)->front
;
68 static struct dri1_api nouveau_dri1_api
= {
69 nouveau_dri1_front_surface
,
72 static struct pipe_screen
*
73 nouveau_drm_create_screen(struct drm_api
*api
, int fd
,
74 struct drm_create_screen_arg
*arg
)
76 struct dri1_create_screen_arg
*dri1
= (void *)arg
;
77 struct nouveau_winsys
*nvws
;
78 struct pipe_winsys
*ws
;
79 struct nouveau_device
*dev
= NULL
;
80 struct pipe_screen
*(*init
)(struct pipe_winsys
*,
81 struct nouveau_device
*);
84 ret
= nouveau_device_open_existing(&dev
, 0, fd
, 0);
88 switch (dev
->chipset
& 0xf0) {
90 init
= nv04_screen_create
;
93 init
= nv10_screen_create
;
96 init
= nv20_screen_create
;
99 init
= nv30_screen_create
;
103 init
= nv40_screen_create
;
108 init
= nv50_screen_create
;
111 debug_printf("%s: unknown chipset nv%02x\n", __func__
,
116 nvws
= CALLOC_STRUCT(nouveau_winsys
);
118 nouveau_device_close(&dev
);
123 nvws
->pscreen
= init(ws
, dev
);
124 if (!nvws
->pscreen
) {
129 if (arg
->mode
== DRM_CREATE_DRI1
) {
130 struct nouveau_dri
*nvdri
= dri1
->ddx_info
;
131 enum pipe_format format
;
133 if (nvdri
->bpp
== 16)
134 format
= PIPE_FORMAT_R5G6B5_UNORM
;
136 format
= PIPE_FORMAT_A8R8G8B8_UNORM
;
138 nvws
->front
= dri_surface_from_handle(api
, nvws
->pscreen
,
140 format
, nvdri
->width
,
145 debug_printf("%s: error referencing front buffer\n",
151 dri1
->api
= &nouveau_dri1_api
;
154 return nvws
->pscreen
;
157 static struct pipe_context
*
158 nouveau_drm_create_context(struct drm_api
*api
, struct pipe_screen
*pscreen
)
160 struct nouveau_winsys
*nvws
= nouveau_winsys_screen(pscreen
);
161 struct pipe_context
*(*init
)(struct pipe_screen
*, unsigned);
162 unsigned chipset
= nouveau_screen(pscreen
)->device
->chipset
;
165 switch (chipset
& 0xf0) {
188 debug_printf("%s: unknown chipset nv%02x\n", __func__
, chipset
);
192 /* Find a free slot for a pipe context, allocate a new one if needed */
193 for (i
= 0; i
< nvws
->nr_pctx
; i
++) {
194 if (nvws
->pctx
[i
] == NULL
)
198 if (i
== nvws
->nr_pctx
) {
200 nvws
->pctx
= realloc(nvws
->pctx
,
201 sizeof(*nvws
->pctx
) * nvws
->nr_pctx
);
204 nvws
->pctx
[i
] = init(pscreen
, i
);
205 return nvws
->pctx
[i
];
209 nouveau_drm_pb_from_pt(struct drm_api
*api
, struct pipe_texture
*pt
,
210 struct pipe_buffer
**ppb
, unsigned *stride
)
215 static struct pipe_buffer
*
216 nouveau_drm_pb_from_handle(struct drm_api
*api
, struct pipe_screen
*pscreen
,
217 const char *name
, unsigned handle
)
219 struct nouveau_device
*dev
= nouveau_screen(pscreen
)->device
;
220 struct pipe_buffer
*pb
;
223 pb
= CALLOC(1, sizeof(struct pipe_buffer
) + sizeof(struct nouveau_bo
*));
227 ret
= nouveau_bo_handle_ref(dev
, handle
, (struct nouveau_bo
**)(pb
+1));
229 debug_printf("%s: ref name 0x%08x failed with %d\n",
230 __func__
, handle
, ret
);
235 pipe_reference_init(&pb
->reference
, 1);
236 pb
->screen
= pscreen
;
238 pb
->usage
= PIPE_BUFFER_USAGE_GPU_READ_WRITE
|
239 PIPE_BUFFER_USAGE_CPU_READ_WRITE
;
240 pb
->size
= nouveau_bo(pb
)->size
;
245 nouveau_drm_handle_from_pb(struct drm_api
*api
, struct pipe_screen
*pscreen
,
246 struct pipe_buffer
*pb
, unsigned *handle
)
248 struct nouveau_bo
*bo
= nouveau_bo(pb
);
253 *handle
= bo
->handle
;
258 nouveau_drm_name_from_pb(struct drm_api
*api
, struct pipe_screen
*pscreen
,
259 struct pipe_buffer
*pb
, unsigned *handle
)
261 struct nouveau_bo
*bo
= nouveau_bo(pb
);
266 return nouveau_bo_handle_get(bo
, handle
) == 0;
269 struct drm_api drm_api_hooks
= {
270 .create_screen
= nouveau_drm_create_screen
,
271 .create_context
= nouveau_drm_create_context
,
272 .buffer_from_texture
= nouveau_drm_pb_from_pt
,
273 .buffer_from_handle
= nouveau_drm_pb_from_handle
,
274 .handle_from_buffer
= nouveau_drm_handle_from_pb
,
275 .global_handle_from_buffer
= nouveau_drm_name_from_pb
,
280 return &drm_api_hooks
;