[g3dvl] make pipe_context mandatory for creation pipe_video_context
[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_context *vctx, 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(vctx);
63
64 struct vl_dri_screen *vl_dri_scrn = (struct vl_dri_screen*)vctx->vscreen;
65 assert(vl_dri_scrn);
66
67 dri2_front = DRI2GetBuffers(vl_dri_scrn->dri_screen->display,
68 drawable, &w, &h, attachments, 1, &count);
69
70 assert(count == 1);
71
72 if (dri2_front) {
73 struct winsys_handle dri2_front_handle =
74 {
75 .type = DRM_API_HANDLE_TYPE_SHARED,
76 .handle = dri2_front->name,
77 .stride = dri2_front->pitch
78 };
79 struct pipe_resource template;
80 struct pipe_surface surf_template;
81
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;
86 template.width0 = w;
87 template.height0 = h;
88 template.depth0 = 1;
89 template.usage = PIPE_USAGE_STATIC;
90 template.bind = PIPE_BIND_RENDER_TARGET;
91 template.flags = 0;
92
93 front_tex = vl_dri_scrn->base.pscreen->resource_from_handle(vl_dri_scrn->base.pscreen, &template, &dri2_front_handle);
94 if (front_tex) {
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);
99 }
100 pipe_resource_reference(&front_tex, NULL);
101 Xfree(dri2_front);
102 }
103
104 return front_surf;
105 }
106
107 static void
108 vl_dri2_flush_frontbuffer(struct pipe_screen *screen,
109 struct pipe_resource *resource,
110 unsigned level, unsigned layer,
111 void *context_private)
112 {
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;
115
116 assert(screen);
117 assert(resource);
118 assert(context_private);
119
120 dri2CopyDrawable(vl_dri_scrn->dri_screen, vl_dri_scrn->last_seen_drawable,
121 DRI_BUFFER_FRONT_LEFT, DRI_BUFFER_FAKE_FRONT_LEFT);
122 }
123
124 struct pipe_surface*
125 vl_drawable_surface_get(struct vl_context *vctx, Drawable drawable)
126 {
127 assert(vctx);
128
129 struct vl_dri_screen *vl_dri_scrn = (struct vl_dri_screen*)vctx->vscreen;
130 assert(vl_dri_scrn);
131
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);
139 }
140 vl_dri_scrn->last_seen_drawable = drawable;
141 }
142
143 return vl_dri2_get_front(vctx, drawable);
144 }
145
146 void*
147 vl_contextprivate_get(struct vl_context *vctx, struct pipe_surface *displaytarget)
148 {
149 return vctx;
150 }
151
152 static unsigned drawable_hash(void *key)
153 {
154 Drawable drawable = (Drawable)key;
155 assert(drawable != None);
156 return util_hash_crc32(&drawable, sizeof(Drawable));
157 }
158
159 static int drawable_cmp(void *key1, void *key2)
160 {
161 Drawable d1 = (Drawable)key1;
162 Drawable d2 = (Drawable)key2;
163 assert(d1 != None);
164 assert(d2 != None);
165 return d1 != d2;
166 }
167
168 static enum pipe_error
169 drawable_destroy(void *key, void *value, void *data)
170 {
171 Drawable drawable = (Drawable)key;
172 struct vl_dri_screen *vl_dri_scrn = (struct vl_dri_screen*)data;
173
174 assert(drawable != None);
175 assert(value);
176 assert(data);
177
178 dri2DestroyDrawable(vl_dri_scrn->dri_screen, drawable);
179
180 return PIPE_OK;
181 }
182
183 struct vl_screen*
184 vl_screen_create(Display *display, int screen)
185 {
186 struct vl_dri_screen *vl_dri_scrn;
187
188 assert(display);
189
190 vl_dri_scrn = CALLOC_STRUCT(vl_dri_screen);
191 if (!vl_dri_scrn)
192 goto no_struct;
193
194 if (dri2CreateScreen(display, screen, &vl_dri_scrn->dri_screen))
195 goto no_dri2screen;
196
197 vl_dri_scrn->base.pscreen = driver_descriptor.create_screen(vl_dri_scrn->dri_screen->fd);
198
199 if (!vl_dri_scrn->base.pscreen)
200 goto no_pscreen;
201
202 vl_dri_scrn->drawable_table = util_hash_table_create(&drawable_hash, &drawable_cmp);
203 if (!vl_dri_scrn->drawable_table)
204 goto no_hash;
205
206 vl_dri_scrn->last_seen_drawable = None;
207 vl_dri_scrn->base.pscreen->flush_frontbuffer = vl_dri2_flush_frontbuffer;
208
209 return &vl_dri_scrn->base;
210
211 no_hash:
212 vl_dri_scrn->base.pscreen->destroy(vl_dri_scrn->base.pscreen);
213 no_pscreen:
214 dri2DestroyScreen(vl_dri_scrn->dri_screen);
215 no_dri2screen:
216 FREE(vl_dri_scrn);
217 no_struct:
218 return NULL;
219 }
220
221 void vl_screen_destroy(struct vl_screen *vscreen)
222 {
223 struct vl_dri_screen *vl_dri_scrn = (struct vl_dri_screen*)vscreen;
224
225 assert(vscreen);
226
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);
231 FREE(vl_dri_scrn);
232 }
233
234 struct vl_context*
235 vl_video_create(struct vl_screen *vscreen)
236 {
237 struct vl_dri_screen *vl_dri_scrn = (struct vl_dri_screen*)vscreen;
238 struct vl_dri_context *vl_dri_ctx;
239
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));
244 goto no_vpipe;
245 }
246
247 vl_dri_ctx = CALLOC_STRUCT(vl_dri_context);
248 if (!vl_dri_ctx)
249 goto no_struct;
250
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));
256 goto no_pipe;
257 }
258
259 vl_dri_ctx->base.vpipe = vscreen->pscreen->video_context_create(vscreen->pscreen,
260 vl_dri_ctx->base.pipe,
261 vl_dri_ctx);
262
263 if (!vl_dri_ctx->base.vpipe)
264 goto no_pipe;
265
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;
269
270 return &vl_dri_ctx->base;
271
272 no_pipe:
273 FREE(vl_dri_ctx);
274
275 no_struct:
276 no_vpipe:
277 return NULL;
278 }
279
280 void vl_video_destroy(struct vl_context *vctx)
281 {
282 struct vl_dri_context *vl_dri_ctx = (struct vl_dri_context*)vctx;
283
284 assert(vctx);
285
286 vl_dri_ctx->base.pipe->destroy(vl_dri_ctx->base.pipe);
287 vl_dri_ctx->base.vpipe->destroy(vl_dri_ctx->base.vpipe);
288 FREE(vl_dri_ctx);
289 }