Merge branch 'master' of ssh://git.freedesktop.org/git/mesa/mesa into pipe-video
[mesa.git] / src / gallium / winsys / g3dvl / dri / dri_winsys.c
1 /**************************************************************************
2 *
3 * Copyright 2009 Younes Manton.
4 * All Rights Reserved.
5 *
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:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
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.
25 *
26 **************************************************************************/
27
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>
37
38 struct vl_dri_screen
39 {
40 struct vl_screen base;
41 dri_screen_t *dri_screen;
42 struct util_hash_table *drawable_table;
43 Drawable last_seen_drawable;
44 };
45
46 struct vl_dri_context
47 {
48 struct vl_context base;
49 int fd;
50 };
51
52 static struct pipe_surface*
53 vl_dri2_get_front(struct vl_dri_screen *vl_dri_scrn, Drawable drawable)
54 {
55 int w, h;
56 unsigned int attachments[1] = {DRI_BUFFER_FRONT_LEFT};
57 int count;
58 DRI2Buffer *dri2_front;
59 struct pipe_resource *front_tex;
60 struct pipe_surface *front_surf = NULL;
61
62 assert(vl_dri_scrn);
63
64 dri2_front = DRI2GetBuffers(vl_dri_scrn->dri_screen->display,
65 drawable, &w, &h, attachments, 1, &count);
66
67 assert(count == 1);
68
69 if (dri2_front) {
70 struct winsys_handle dri2_front_handle =
71 {
72 .type = DRM_API_HANDLE_TYPE_SHARED,
73 .handle = dri2_front->name,
74 .stride = dri2_front->pitch
75 };
76 struct pipe_resource template;
77
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;
82 template.width0 = w;
83 template.height0 = h;
84 template.depth0 = 1;
85 template.usage = PIPE_USAGE_STATIC;
86 template.bind = PIPE_BIND_RENDER_TARGET;
87 template.flags = 0;
88
89 front_tex = vl_dri_scrn->base.pscreen->resource_from_handle(vl_dri_scrn->base.pscreen, &template, &dri2_front_handle);
90 if (front_tex)
91 front_surf = vl_dri_scrn->base.pscreen->get_tex_surface(vl_dri_scrn->base.pscreen,
92 front_tex, 0, 0, 0,
93 PIPE_BIND_RENDER_TARGET);
94 pipe_resource_reference(&front_tex, NULL);
95 Xfree(dri2_front);
96 }
97
98 return front_surf;
99 }
100
101 static void
102 vl_dri2_flush_frontbuffer(struct pipe_screen *screen,
103 struct pipe_surface *surf, void *context_private)
104 {
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;
107
108 assert(screen);
109 assert(surf);
110 assert(context_private);
111
112 dri2CopyDrawable(vl_dri_scrn->dri_screen, vl_dri_scrn->last_seen_drawable,
113 DRI_BUFFER_FRONT_LEFT, DRI_BUFFER_FAKE_FRONT_LEFT);
114 }
115
116 struct pipe_surface*
117 vl_drawable_surface_get(struct vl_screen *vscreen, Drawable drawable)
118 {
119 struct vl_dri_screen *vl_dri_scrn = (struct vl_dri_screen*)vscreen;
120
121 assert(vscreen);
122
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);
130 }
131 vl_dri_scrn->last_seen_drawable = drawable;
132 }
133
134 return vl_dri2_get_front(vl_dri_scrn, drawable);
135 }
136
137 void*
138 vl_contextprivate_get(struct vl_context *vctx, struct pipe_surface *displaytarget)
139 {
140 return vctx;
141 }
142
143 static unsigned drawable_hash(void *key)
144 {
145 Drawable drawable = (Drawable)key;
146 assert(drawable != None);
147 return util_hash_crc32(&drawable, sizeof(Drawable));
148 }
149
150 static int drawable_cmp(void *key1, void *key2)
151 {
152 Drawable d1 = (Drawable)key1;
153 Drawable d2 = (Drawable)key2;
154 assert(d1 != None);
155 assert(d2 != None);
156 return d1 != d2;
157 }
158
159 static enum pipe_error
160 drawable_destroy(void *key, void *value, void *data)
161 {
162 Drawable drawable = (Drawable)key;
163 struct vl_dri_screen *vl_dri_scrn = (struct vl_dri_screen*)data;
164
165 assert(drawable != None);
166 assert(value);
167 assert(data);
168
169 dri2DestroyDrawable(vl_dri_scrn->dri_screen, drawable);
170
171 return PIPE_OK;
172 }
173
174 struct vl_screen*
175 vl_screen_create(Display *display, int screen)
176 {
177 struct vl_dri_screen *vl_dri_scrn;
178
179 assert(display);
180
181 vl_dri_scrn = CALLOC_STRUCT(vl_dri_screen);
182 if (!vl_dri_scrn)
183 goto no_struct;
184
185 if (dri2CreateScreen(display, screen, &vl_dri_scrn->dri_screen))
186 goto no_dri2screen;
187
188 vl_dri_scrn->base.pscreen = driver_descriptor.create_screen(vl_dri_scrn->dri_screen->fd);
189
190 if (!vl_dri_scrn->base.pscreen)
191 goto no_pscreen;
192
193 vl_dri_scrn->drawable_table = util_hash_table_create(&drawable_hash, &drawable_cmp);
194 if (!vl_dri_scrn->drawable_table)
195 goto no_hash;
196
197 vl_dri_scrn->last_seen_drawable = None;
198 vl_dri_scrn->base.pscreen->flush_frontbuffer = vl_dri2_flush_frontbuffer;
199
200 return &vl_dri_scrn->base;
201
202 no_hash:
203 vl_dri_scrn->base.pscreen->destroy(vl_dri_scrn->base.pscreen);
204 no_pscreen:
205 dri2DestroyScreen(vl_dri_scrn->dri_screen);
206 no_dri2screen:
207 FREE(vl_dri_scrn);
208 no_struct:
209 return NULL;
210 }
211
212 void vl_screen_destroy(struct vl_screen *vscreen)
213 {
214 struct vl_dri_screen *vl_dri_scrn = (struct vl_dri_screen*)vscreen;
215
216 assert(vscreen);
217
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);
222 FREE(vl_dri_scrn);
223 }
224
225 struct vl_context*
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)
230 {
231 struct vl_dri_screen *vl_dri_scrn = (struct vl_dri_screen*)vscreen;
232 struct vl_dri_context *vl_dri_ctx;
233
234 vl_dri_ctx = CALLOC_STRUCT(vl_dri_context);
235 if (!vl_dri_ctx)
236 goto no_struct;
237
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));
242 goto no_vpipe;
243 }
244
245 vl_dri_ctx->base.vpipe = vscreen->pscreen->video_context_create(vscreen->pscreen,
246 profile, chroma_format,
247 width, height,
248 vl_dri_ctx);
249
250 if (!vl_dri_ctx->base.vpipe)
251 goto no_vpipe;
252
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;
256
257 return &vl_dri_ctx->base;
258
259 no_vpipe:
260 FREE(vl_dri_ctx);
261 no_struct:
262 return NULL;
263 }
264
265 void vl_video_destroy(struct vl_context *vctx)
266 {
267 struct vl_dri_context *vl_dri_ctx = (struct vl_dri_context*)vctx;
268
269 assert(vctx);
270
271 vl_dri_ctx->base.vpipe->destroy(vl_dri_ctx->base.vpipe);
272 FREE(vl_dri_ctx);
273 }