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_driver.h>
36 #include <X11/Xlibint.h>
40 struct vl_screen base
;
41 dri_screen_t
*dri_screen
;
42 struct util_hash_table
*drawable_table
;
43 Drawable last_seen_drawable
;
48 struct vl_context base
;
52 static struct pipe_surface
*
53 vl_dri2_get_front(struct vl_context
*vctx
, Drawable drawable
)
56 unsigned int attachments
[1] = {DRI_BUFFER_FRONT_LEFT
};
58 DRI2Buffer
*dri2_front
;
59 struct pipe_resource
*front_tex
;
60 struct pipe_surface
*front_surf
= NULL
;
64 struct vl_dri_screen
*vl_dri_scrn
= (struct vl_dri_screen
*)vctx
->vscreen
;
67 dri2_front
= DRI2GetBuffers(vl_dri_scrn
->dri_screen
->display
,
68 drawable
, &w
, &h
, attachments
, 1, &count
);
73 struct winsys_handle dri2_front_handle
=
75 .type
= DRM_API_HANDLE_TYPE_SHARED
,
76 .handle
= dri2_front
->name
,
77 .stride
= dri2_front
->pitch
79 struct pipe_resource
template;
80 struct pipe_surface surf_template
;
82 memset(&template, 0, sizeof(struct pipe_resource
));
83 template.target
= PIPE_TEXTURE_2D
;
84 template.format
= PIPE_FORMAT_B8G8R8X8_UNORM
;
85 template.last_level
= 0;
89 template.usage
= PIPE_USAGE_STATIC
;
90 template.bind
= PIPE_BIND_RENDER_TARGET
;
93 front_tex
= vl_dri_scrn
->base
.pscreen
->resource_from_handle(vl_dri_scrn
->base
.pscreen
, &template, &dri2_front_handle
);
95 memset(&surf_template
, 0, sizeof(surf_template
));
96 surf_template
.format
= front_tex
->format
;
97 surf_template
.usage
= PIPE_BIND_RENDER_TARGET
;
98 front_surf
= vctx
->vpipe
->create_surface(vctx
->vpipe
, front_tex
, &surf_template
);
100 pipe_resource_reference(&front_tex
, NULL
);
108 vl_dri2_flush_frontbuffer(struct pipe_screen
*screen
,
109 struct pipe_resource
*resource
,
110 unsigned level
, unsigned layer
,
111 void *context_private
)
113 struct vl_dri_context
*vl_dri_ctx
= (struct vl_dri_context
*)context_private
;
114 struct vl_dri_screen
*vl_dri_scrn
= (struct vl_dri_screen
*)vl_dri_ctx
->base
.vscreen
;
118 assert(context_private
);
120 dri2CopyDrawable(vl_dri_scrn
->dri_screen
, vl_dri_scrn
->last_seen_drawable
,
121 DRI_BUFFER_FRONT_LEFT
, DRI_BUFFER_FAKE_FRONT_LEFT
);
125 vl_drawable_surface_get(struct vl_context
*vctx
, Drawable drawable
)
129 struct vl_dri_screen
*vl_dri_scrn
= (struct vl_dri_screen
*)vctx
->vscreen
;
132 if (vl_dri_scrn
->last_seen_drawable
!= drawable
) {
133 /* Hash table business depends on this equality */
134 assert(None
== NULL
);
135 Drawable lookup_drawable
= (Drawable
)util_hash_table_get(vl_dri_scrn
->drawable_table
, (void*)drawable
);
136 if (lookup_drawable
== None
) {
137 dri2CreateDrawable(vl_dri_scrn
->dri_screen
, drawable
);
138 util_hash_table_set(vl_dri_scrn
->drawable_table
, (void*)drawable
, (void*)drawable
);
140 vl_dri_scrn
->last_seen_drawable
= drawable
;
143 return vl_dri2_get_front(vctx
, drawable
);
147 vl_contextprivate_get(struct vl_context
*vctx
, struct pipe_surface
*displaytarget
)
152 static unsigned drawable_hash(void *key
)
154 Drawable drawable
= (Drawable
)key
;
155 assert(drawable
!= None
);
156 return util_hash_crc32(&drawable
, sizeof(Drawable
));
159 static int drawable_cmp(void *key1
, void *key2
)
161 Drawable d1
= (Drawable
)key1
;
162 Drawable d2
= (Drawable
)key2
;
168 static enum pipe_error
169 drawable_destroy(void *key
, void *value
, void *data
)
171 Drawable drawable
= (Drawable
)key
;
172 struct vl_dri_screen
*vl_dri_scrn
= (struct vl_dri_screen
*)data
;
174 assert(drawable
!= None
);
178 dri2DestroyDrawable(vl_dri_scrn
->dri_screen
, drawable
);
184 vl_screen_create(Display
*display
, int screen
)
186 struct vl_dri_screen
*vl_dri_scrn
;
190 vl_dri_scrn
= CALLOC_STRUCT(vl_dri_screen
);
194 if (dri2CreateScreen(display
, screen
, &vl_dri_scrn
->dri_screen
))
197 vl_dri_scrn
->base
.pscreen
= driver_descriptor
.create_screen(vl_dri_scrn
->dri_screen
->fd
);
199 if (!vl_dri_scrn
->base
.pscreen
)
202 vl_dri_scrn
->drawable_table
= util_hash_table_create(&drawable_hash
, &drawable_cmp
);
203 if (!vl_dri_scrn
->drawable_table
)
206 vl_dri_scrn
->last_seen_drawable
= None
;
207 vl_dri_scrn
->base
.pscreen
->flush_frontbuffer
= vl_dri2_flush_frontbuffer
;
209 return &vl_dri_scrn
->base
;
212 vl_dri_scrn
->base
.pscreen
->destroy(vl_dri_scrn
->base
.pscreen
);
214 dri2DestroyScreen(vl_dri_scrn
->dri_screen
);
221 void vl_screen_destroy(struct vl_screen
*vscreen
)
223 struct vl_dri_screen
*vl_dri_scrn
= (struct vl_dri_screen
*)vscreen
;
227 util_hash_table_foreach(vl_dri_scrn
->drawable_table
, drawable_destroy
, vl_dri_scrn
);
228 util_hash_table_destroy(vl_dri_scrn
->drawable_table
);
229 vl_dri_scrn
->base
.pscreen
->destroy(vl_dri_scrn
->base
.pscreen
);
230 dri2DestroyScreen(vl_dri_scrn
->dri_screen
);
235 vl_video_create(struct vl_screen
*vscreen
)
237 struct vl_dri_screen
*vl_dri_scrn
= (struct vl_dri_screen
*)vscreen
;
238 struct vl_dri_context
*vl_dri_ctx
;
240 if (!vscreen
->pscreen
->video_context_create
) {
241 debug_printf("[G3DVL] No video support found on %s/%s.\n",
242 vscreen
->pscreen
->get_vendor(vscreen
->pscreen
),
243 vscreen
->pscreen
->get_name(vscreen
->pscreen
));
247 vl_dri_ctx
= CALLOC_STRUCT(vl_dri_context
);
251 vl_dri_ctx
->base
.pipe
= vscreen
->pscreen
->context_create(vscreen
->pscreen
, vl_dri_ctx
);
252 if (!vl_dri_ctx
->base
.pipe
) {
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 vl_dri_ctx
->base
.pipe
,
263 if (!vl_dri_ctx
->base
.vpipe
)
266 vl_dri_ctx
->base
.vpipe
->priv
= vl_dri_ctx
;
267 vl_dri_ctx
->base
.vscreen
= vscreen
;
268 vl_dri_ctx
->fd
= vl_dri_scrn
->dri_screen
->fd
;
270 return &vl_dri_ctx
->base
;
280 void vl_video_destroy(struct vl_context
*vctx
)
282 struct vl_dri_context
*vl_dri_ctx
= (struct vl_dri_context
*)vctx
;
286 vl_dri_ctx
->base
.pipe
->destroy(vl_dri_ctx
->base
.pipe
);
287 vl_dri_ctx
->base
.vpipe
->destroy(vl_dri_ctx
->base
.vpipe
);