1 #include "pipe/p_context.h"
2 #include "pipe/p_state.h"
3 #include "util/u_format.h"
4 #include "util/u_memory.h"
5 #include "util/u_inlines.h"
7 #include "nouveau_drm_api.h"
9 #include "nouveau_drmif.h"
10 #include "nouveau_channel.h"
11 #include "nouveau_bo.h"
13 #include "nouveau/nouveau_winsys.h"
14 #include "nouveau/nouveau_screen.h"
16 static struct pipe_surface
*
17 dri_surface_from_handle(struct drm_api
*api
, struct pipe_screen
*pscreen
,
18 unsigned handle
, enum pipe_format format
,
19 unsigned width
, unsigned height
, unsigned pitch
)
21 struct pipe_surface
*ps
= NULL
;
22 struct pipe_texture
*pt
= NULL
;
23 struct pipe_texture tmpl
;
25 memset(&tmpl
, 0, sizeof(tmpl
));
26 tmpl
.tex_usage
= PIPE_TEXTURE_USAGE_PRIMARY
;
27 tmpl
.target
= PIPE_TEXTURE_2D
;
32 tmpl
.height0
= height
;
34 pt
= api
->texture_from_shared_handle(api
, pscreen
, &tmpl
,
35 "front buffer", pitch
, handle
);
39 ps
= pscreen
->get_tex_surface(pscreen
, pt
, 0, 0, 0,
40 PIPE_BUFFER_USAGE_GPU_READ
|
41 PIPE_BUFFER_USAGE_GPU_WRITE
);
43 /* we don't need the texture from this point on */
44 pipe_texture_reference(&pt
, NULL
);
48 static struct pipe_surface
*
49 nouveau_dri1_front_surface(struct pipe_screen
*screen
)
51 return nouveau_winsys_screen(screen
)->front
;
54 static struct dri1_api nouveau_dri1_api
= {
55 nouveau_dri1_front_surface
,
59 nouveau_drm_destroy_winsys(struct pipe_winsys
*s
)
61 struct nouveau_winsys
*nv_winsys
= nouveau_winsys(s
);
62 struct nouveau_screen
*nv_screen
= nouveau_screen(nv_winsys
->pscreen
);
63 nouveau_device_close(&nv_screen
->device
);
67 static struct pipe_screen
*
68 nouveau_drm_create_screen(struct drm_api
*api
, int fd
,
69 struct drm_create_screen_arg
*arg
)
71 struct dri1_create_screen_arg
*dri1
= (void *)arg
;
72 struct nouveau_winsys
*nvws
;
73 struct pipe_winsys
*ws
;
74 struct nouveau_device
*dev
= NULL
;
75 struct pipe_screen
*(*init
)(struct pipe_winsys
*,
76 struct nouveau_device
*);
79 ret
= nouveau_device_open_existing(&dev
, 0, fd
, 0);
83 switch (dev
->chipset
& 0xf0) {
85 init
= nv30_screen_create
;
89 init
= nv40_screen_create
;
95 init
= nv50_screen_create
;
98 debug_printf("%s: unknown chipset nv%02x\n", __func__
,
103 nvws
= CALLOC_STRUCT(nouveau_winsys
);
105 nouveau_device_close(&dev
);
109 ws
->destroy
= nouveau_drm_destroy_winsys
;
111 nvws
->pscreen
= init(ws
, dev
);
112 if (!nvws
->pscreen
) {
117 if (arg
&& arg
->mode
== DRM_CREATE_DRI1
) {
118 struct nouveau_dri
*nvdri
= dri1
->ddx_info
;
119 enum pipe_format format
;
121 if (nvdri
->bpp
== 16)
122 format
= PIPE_FORMAT_B5G6R5_UNORM
;
124 format
= PIPE_FORMAT_B8G8R8A8_UNORM
;
126 nvws
->front
= dri_surface_from_handle(api
, nvws
->pscreen
,
128 format
, nvdri
->width
,
133 debug_printf("%s: error referencing front buffer\n",
139 dri1
->api
= &nouveau_dri1_api
;
142 return nvws
->pscreen
;
145 static struct pipe_texture
*
146 nouveau_drm_pt_from_name(struct drm_api
*api
, struct pipe_screen
*pscreen
,
147 struct pipe_texture
*templ
, const char *name
,
148 unsigned stride
, unsigned handle
)
150 struct nouveau_device
*dev
= nouveau_screen(pscreen
)->device
;
151 struct pipe_texture
*pt
;
152 struct pipe_buffer
*pb
;
155 pb
= CALLOC(1, sizeof(struct pipe_buffer
) + sizeof(struct nouveau_bo
*));
159 ret
= nouveau_bo_handle_ref(dev
, handle
, (struct nouveau_bo
**)(pb
+1));
161 debug_printf("%s: ref name 0x%08x failed with %d\n",
162 __func__
, handle
, ret
);
167 pipe_reference_init(&pb
->reference
, 1);
168 pb
->screen
= pscreen
;
170 pb
->usage
= PIPE_BUFFER_USAGE_GPU_READ_WRITE
|
171 PIPE_BUFFER_USAGE_CPU_READ_WRITE
;
172 pb
->size
= nouveau_bo(pb
)->size
;
173 pt
= pscreen
->texture_blanket(pscreen
, templ
, &stride
, pb
);
174 pipe_buffer_reference(&pb
, NULL
);
179 nouveau_drm_name_from_pt(struct drm_api
*api
, struct pipe_screen
*pscreen
,
180 struct pipe_texture
*pt
, unsigned *stride
,
183 struct nouveau_miptree
*mt
= nouveau_miptree(pt
);
188 return nouveau_bo_handle_get(mt
->bo
, handle
) == 0;
192 nouveau_drm_handle_from_pt(struct drm_api
*api
, struct pipe_screen
*pscreen
,
193 struct pipe_texture
*pt
, unsigned *stride
,
196 struct nouveau_miptree
*mt
= nouveau_miptree(pt
);
201 *handle
= mt
->bo
->handle
;
202 *stride
= util_format_get_stride(mt
->base
.format
, mt
->base
.width0
);
206 struct drm_api drm_api_hooks
= {
208 .driver_name
= "nouveau",
209 .create_screen
= nouveau_drm_create_screen
,
210 .texture_from_shared_handle
= nouveau_drm_pt_from_name
,
211 .shared_handle_from_texture
= nouveau_drm_name_from_pt
,
212 .local_handle_from_texture
= nouveau_drm_handle_from_pt
,
217 return &drm_api_hooks
;