1 /**************************************************************************
3 * Copyright 2009 Younes Manton.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 **************************************************************************/
28 #include <vl_winsys.h>
29 #include <driclient.h>
30 #include <pipe/p_video_context.h>
31 #include <pipe/p_state.h>
32 #include <util/u_memory.h>
33 #include <util/u_hash.h>
34 #include <util/u_hash_table.h>
35 #include <state_tracker/drm_api.h>
36 #include <X11/Xlibint.h>
40 struct vl_screen base
;
42 dri_screen_t
*dri_screen
;
43 struct util_hash_table
*drawable_table
;
44 Drawable last_seen_drawable
;
49 struct vl_context base
;
53 static struct pipe_surface
*
54 vl_dri2_get_front(struct vl_dri_screen
*vl_dri_scrn
, Drawable drawable
)
57 unsigned int attachments
[1] = {DRI_BUFFER_FRONT_LEFT
};
59 DRI2Buffer
*dri2_front
;
60 struct pipe_resource
*front_tex
;
61 struct pipe_surface
*front_surf
= NULL
;
65 dri2_front
= DRI2GetBuffers(vl_dri_scrn
->dri_screen
->display
,
66 drawable
, &w
, &h
, attachments
, 1, &count
);
71 struct winsys_handle dri2_front_handle
=
73 .type
= DRM_API_HANDLE_TYPE_SHARED
,
74 .handle
= dri2_front
->name
,
75 .stride
= dri2_front
->pitch
77 struct pipe_resource
template;
79 memset(&template, 0, sizeof(struct pipe_resource
));
80 template.target
= PIPE_TEXTURE_2D
;
81 template.format
= PIPE_FORMAT_B8G8R8X8_UNORM
;
82 template.last_level
= 0;
86 template.usage
= PIPE_USAGE_STATIC
;
87 template.bind
= PIPE_BIND_RENDER_TARGET
;
90 front_tex
= vl_dri_scrn
->base
.pscreen
->resource_from_handle(vl_dri_scrn
->base
.pscreen
, &template, &dri2_front_handle
);
92 front_surf
= vl_dri_scrn
->base
.pscreen
->get_tex_surface(vl_dri_scrn
->base
.pscreen
,
94 PIPE_BIND_RENDER_TARGET
);
95 pipe_resource_reference(&front_tex
, NULL
);
103 vl_dri2_flush_frontbuffer(struct pipe_screen
*screen
,
104 struct pipe_surface
*surf
, void *context_private
)
106 struct vl_dri_context
*vl_dri_ctx
= (struct vl_dri_context
*)context_private
;
107 struct vl_dri_screen
*vl_dri_scrn
= (struct vl_dri_screen
*)vl_dri_ctx
->base
.vscreen
;
111 assert(context_private
);
113 dri2CopyDrawable(vl_dri_scrn
->dri_screen
, vl_dri_scrn
->last_seen_drawable
,
114 DRI_BUFFER_FRONT_LEFT
, DRI_BUFFER_FAKE_FRONT_LEFT
);
118 vl_drawable_surface_get(struct vl_screen
*vscreen
, Drawable drawable
)
120 struct vl_dri_screen
*vl_dri_scrn
= (struct vl_dri_screen
*)vscreen
;
124 if (vl_dri_scrn
->last_seen_drawable
!= drawable
) {
125 /* Hash table business depends on this equality */
126 assert(None
== NULL
);
127 Drawable lookup_drawable
= (Drawable
)util_hash_table_get(vl_dri_scrn
->drawable_table
, (void*)drawable
);
128 if (lookup_drawable
== None
) {
129 dri2CreateDrawable(vl_dri_scrn
->dri_screen
, drawable
);
130 util_hash_table_set(vl_dri_scrn
->drawable_table
, (void*)drawable
, (void*)drawable
);
132 vl_dri_scrn
->last_seen_drawable
= drawable
;
135 return vl_dri2_get_front(vl_dri_scrn
, drawable
);
139 vl_contextprivate_get(struct vl_context
*vctx
, struct pipe_surface
*displaytarget
)
144 static unsigned drawable_hash(void *key
)
146 Drawable drawable
= (Drawable
)key
;
147 assert(drawable
!= None
);
148 return util_hash_crc32(&drawable
, sizeof(Drawable
));
151 static int drawable_cmp(void *key1
, void *key2
)
153 Drawable d1
= (Drawable
)key1
;
154 Drawable d2
= (Drawable
)key2
;
160 static enum pipe_error
161 drawable_destroy(void *key
, void *value
, void *data
)
163 Drawable drawable
= (Drawable
)key
;
164 struct vl_dri_screen
*vl_dri_scrn
= (struct vl_dri_screen
*)data
;
166 assert(drawable
!= None
);
170 dri2DestroyDrawable(vl_dri_scrn
->dri_screen
, drawable
);
176 vl_screen_create(Display
*display
, int screen
)
178 struct vl_dri_screen
*vl_dri_scrn
;
179 struct drm_create_screen_arg arg
;
183 vl_dri_scrn
= CALLOC_STRUCT(vl_dri_screen
);
187 if (dri2CreateScreen(display
, screen
, &vl_dri_scrn
->dri_screen
))
190 vl_dri_scrn
->api
= drm_api_create();
191 if (!vl_dri_scrn
->api
)
194 arg
.mode
= DRM_CREATE_NORMAL
;
196 vl_dri_scrn
->base
.pscreen
= vl_dri_scrn
->api
->create_screen(vl_dri_scrn
->api
,
197 vl_dri_scrn
->dri_screen
->fd
,
200 if (!vl_dri_scrn
->base
.pscreen
)
203 vl_dri_scrn
->drawable_table
= util_hash_table_create(&drawable_hash
, &drawable_cmp
);
204 if (!vl_dri_scrn
->drawable_table
)
207 vl_dri_scrn
->last_seen_drawable
= None
;
208 vl_dri_scrn
->base
.pscreen
->flush_frontbuffer
= vl_dri2_flush_frontbuffer
;
210 return &vl_dri_scrn
->base
;
213 vl_dri_scrn
->base
.pscreen
->destroy(vl_dri_scrn
->base
.pscreen
);
215 vl_dri_scrn
->api
->destroy(vl_dri_scrn
->api
);
217 dri2DestroyScreen(vl_dri_scrn
->dri_screen
);
224 void vl_screen_destroy(struct vl_screen
*vscreen
)
226 struct vl_dri_screen
*vl_dri_scrn
= (struct vl_dri_screen
*)vscreen
;
230 util_hash_table_foreach(vl_dri_scrn
->drawable_table
, drawable_destroy
, vl_dri_scrn
);
231 util_hash_table_destroy(vl_dri_scrn
->drawable_table
);
232 vl_dri_scrn
->base
.pscreen
->destroy(vl_dri_scrn
->base
.pscreen
);
233 if (vl_dri_scrn
->api
->destroy
)
234 vl_dri_scrn
->api
->destroy(vl_dri_scrn
->api
);
235 dri2DestroyScreen(vl_dri_scrn
->dri_screen
);
240 vl_video_create(struct vl_screen
*vscreen
,
241 enum pipe_video_profile profile
,
242 enum pipe_video_chroma_format chroma_format
,
243 unsigned width
, unsigned height
)
245 struct vl_dri_screen
*vl_dri_scrn
= (struct vl_dri_screen
*)vscreen
;
246 struct vl_dri_context
*vl_dri_ctx
;
248 vl_dri_ctx
= CALLOC_STRUCT(vl_dri_context
);
252 if (!vscreen
->pscreen
->video_context_create
) {
253 debug_printf("[G3DVL] No video support found on %s/%s.\n",
254 vscreen
->pscreen
->get_vendor(vscreen
->pscreen
),
255 vscreen
->pscreen
->get_name(vscreen
->pscreen
));
259 vl_dri_ctx
->base
.vpipe
= vscreen
->pscreen
->video_context_create(vscreen
->pscreen
,
260 profile
, chroma_format
,
264 if (!vl_dri_ctx
->base
.vpipe
)
267 vl_dri_ctx
->base
.vpipe
->priv
= vl_dri_ctx
;
268 vl_dri_ctx
->base
.vscreen
= vscreen
;
269 vl_dri_ctx
->fd
= vl_dri_scrn
->dri_screen
->fd
;
271 return &vl_dri_ctx
->base
;
279 void vl_video_destroy(struct vl_context
*vctx
)
281 struct vl_dri_context
*vl_dri_ctx
= (struct vl_dri_context
*)vctx
;
285 vl_dri_ctx
->base
.vpipe
->destroy(vl_dri_ctx
->base
.vpipe
);