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_dri_screen
*vl_dri_scrn
, 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 dri2_front
= DRI2GetBuffers(vl_dri_scrn
->dri_screen
->display
,
65 drawable
, &w
, &h
, attachments
, 1, &count
);
70 struct winsys_handle dri2_front_handle
=
72 .type
= DRM_API_HANDLE_TYPE_SHARED
,
73 .handle
= dri2_front
->name
,
74 .stride
= dri2_front
->pitch
76 struct pipe_resource
template;
78 memset(&template, 0, sizeof(struct pipe_resource
));
79 template.target
= PIPE_TEXTURE_2D
;
80 template.format
= PIPE_FORMAT_B8G8R8X8_UNORM
;
81 template.last_level
= 0;
85 template.usage
= PIPE_USAGE_STATIC
;
86 template.bind
= PIPE_BIND_RENDER_TARGET
;
89 front_tex
= vl_dri_scrn
->base
.pscreen
->resource_from_handle(vl_dri_scrn
->base
.pscreen
, &template, &dri2_front_handle
);
91 front_surf
= vl_dri_scrn
->base
.pscreen
->get_tex_surface(vl_dri_scrn
->base
.pscreen
,
93 PIPE_BIND_RENDER_TARGET
);
94 pipe_resource_reference(&front_tex
, NULL
);
102 vl_dri2_flush_frontbuffer(struct pipe_screen
*screen
,
103 struct pipe_surface
*surf
, void *context_private
)
105 struct vl_dri_context
*vl_dri_ctx
= (struct vl_dri_context
*)context_private
;
106 struct vl_dri_screen
*vl_dri_scrn
= (struct vl_dri_screen
*)vl_dri_ctx
->base
.vscreen
;
110 assert(context_private
);
112 dri2CopyDrawable(vl_dri_scrn
->dri_screen
, vl_dri_scrn
->last_seen_drawable
,
113 DRI_BUFFER_FRONT_LEFT
, DRI_BUFFER_FAKE_FRONT_LEFT
);
117 vl_drawable_surface_get(struct vl_screen
*vscreen
, Drawable drawable
)
119 struct vl_dri_screen
*vl_dri_scrn
= (struct vl_dri_screen
*)vscreen
;
123 if (vl_dri_scrn
->last_seen_drawable
!= drawable
) {
124 /* Hash table business depends on this equality */
125 assert(None
== NULL
);
126 Drawable lookup_drawable
= (Drawable
)util_hash_table_get(vl_dri_scrn
->drawable_table
, (void*)drawable
);
127 if (lookup_drawable
== None
) {
128 dri2CreateDrawable(vl_dri_scrn
->dri_screen
, drawable
);
129 util_hash_table_set(vl_dri_scrn
->drawable_table
, (void*)drawable
, (void*)drawable
);
131 vl_dri_scrn
->last_seen_drawable
= drawable
;
134 return vl_dri2_get_front(vl_dri_scrn
, drawable
);
138 vl_contextprivate_get(struct vl_context
*vctx
, struct pipe_surface
*displaytarget
)
143 static unsigned drawable_hash(void *key
)
145 Drawable drawable
= (Drawable
)key
;
146 assert(drawable
!= None
);
147 return util_hash_crc32(&drawable
, sizeof(Drawable
));
150 static int drawable_cmp(void *key1
, void *key2
)
152 Drawable d1
= (Drawable
)key1
;
153 Drawable d2
= (Drawable
)key2
;
159 static enum pipe_error
160 drawable_destroy(void *key
, void *value
, void *data
)
162 Drawable drawable
= (Drawable
)key
;
163 struct vl_dri_screen
*vl_dri_scrn
= (struct vl_dri_screen
*)data
;
165 assert(drawable
!= None
);
169 dri2DestroyDrawable(vl_dri_scrn
->dri_screen
, drawable
);
175 vl_screen_create(Display
*display
, int screen
)
177 struct vl_dri_screen
*vl_dri_scrn
;
181 vl_dri_scrn
= CALLOC_STRUCT(vl_dri_screen
);
185 if (dri2CreateScreen(display
, screen
, &vl_dri_scrn
->dri_screen
))
188 vl_dri_scrn
->base
.pscreen
= driver_descriptor
.create_screen(vl_dri_scrn
->dri_screen
->fd
);
190 if (!vl_dri_scrn
->base
.pscreen
)
193 vl_dri_scrn
->drawable_table
= util_hash_table_create(&drawable_hash
, &drawable_cmp
);
194 if (!vl_dri_scrn
->drawable_table
)
197 vl_dri_scrn
->last_seen_drawable
= None
;
198 vl_dri_scrn
->base
.pscreen
->flush_frontbuffer
= vl_dri2_flush_frontbuffer
;
200 return &vl_dri_scrn
->base
;
203 vl_dri_scrn
->base
.pscreen
->destroy(vl_dri_scrn
->base
.pscreen
);
205 dri2DestroyScreen(vl_dri_scrn
->dri_screen
);
212 void vl_screen_destroy(struct vl_screen
*vscreen
)
214 struct vl_dri_screen
*vl_dri_scrn
= (struct vl_dri_screen
*)vscreen
;
218 util_hash_table_foreach(vl_dri_scrn
->drawable_table
, drawable_destroy
, vl_dri_scrn
);
219 util_hash_table_destroy(vl_dri_scrn
->drawable_table
);
220 vl_dri_scrn
->base
.pscreen
->destroy(vl_dri_scrn
->base
.pscreen
);
221 dri2DestroyScreen(vl_dri_scrn
->dri_screen
);
226 vl_video_create(struct vl_screen
*vscreen
,
227 enum pipe_video_profile profile
,
228 enum pipe_video_chroma_format chroma_format
,
229 unsigned width
, unsigned height
)
231 struct vl_dri_screen
*vl_dri_scrn
= (struct vl_dri_screen
*)vscreen
;
232 struct vl_dri_context
*vl_dri_ctx
;
234 vl_dri_ctx
= CALLOC_STRUCT(vl_dri_context
);
238 if (!vscreen
->pscreen
->video_context_create
) {
239 debug_printf("[G3DVL] No video support found on %s/%s.\n",
240 vscreen
->pscreen
->get_vendor(vscreen
->pscreen
),
241 vscreen
->pscreen
->get_name(vscreen
->pscreen
));
245 vl_dri_ctx
->base
.vpipe
= vscreen
->pscreen
->video_context_create(vscreen
->pscreen
,
246 profile
, chroma_format
,
250 if (!vl_dri_ctx
->base
.vpipe
)
253 vl_dri_ctx
->base
.vpipe
->priv
= vl_dri_ctx
;
254 vl_dri_ctx
->base
.vscreen
= vscreen
;
255 vl_dri_ctx
->fd
= vl_dri_scrn
->dri_screen
->fd
;
257 return &vl_dri_ctx
->base
;
265 void vl_video_destroy(struct vl_context
*vctx
)
267 struct vl_dri_context
*vl_dri_ctx
= (struct vl_dri_context
*)vctx
;
271 vl_dri_ctx
->base
.vpipe
->destroy(vl_dri_ctx
->base
.vpipe
);