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 <state_tracker/dri1_api.h>
31 #include <pipe/p_video_context.h>
32 #include <pipe/p_state.h>
33 #include <util/u_memory.h>
37 struct vl_screen base
;
40 dri_screen_t
*dri_screen
;
41 dri_framebuffer_t dri_framebuf
;
42 struct dri1_api
*api_hooks
;
47 struct vl_context base
;
51 dri_context_t
*dri_context
;
53 struct pipe_video_context
*vpipe
;
54 dri_drawable_t
*drawable
;
58 vl_dri_lock(void *priv
)
60 struct vl_dri_context
*vl_dri_ctx
= priv
;
61 drm_context_t hw_context
;
66 hw_context
= vl_dri_ctx
->dri_context
->drm_context
;
68 DRM_CAS(vl_dri_ctx
->lock
, hw_context
, DRM_LOCK_HELD
| hw_context
, ret
);
70 drmGetLock(vl_dri_ctx
->fd
, hw_context
, 0);
71 vl_dri_ctx
->lost_lock
= TRUE
;
73 vl_dri_ctx
->is_locked
= TRUE
;
77 vl_dri_unlock(void *priv
)
79 struct vl_dri_context
*vl_dri_ctx
= priv
;
80 drm_context_t hw_context
;
84 hw_context
= vl_dri_ctx
->dri_context
->drm_context
;
86 vl_dri_ctx
->is_locked
= FALSE
;
87 DRM_UNLOCK(vl_dri_ctx
->fd
, vl_dri_ctx
->lock
, hw_context
);
91 vl_dri_is_locked(void *priv
)
93 struct vl_dri_context
*vl_dri_ctx
= priv
;
97 return vl_dri_ctx
->is_locked
;
101 vl_dri_lost_lock(void *priv
)
103 struct vl_dri_context
*vl_dri_ctx
= priv
;
107 return vl_dri_ctx
->lost_lock
;
111 vl_dri_clear_lost_lock(void *priv
)
113 struct vl_dri_context
*vl_dri_ctx
= priv
;
117 vl_dri_ctx
->lost_lock
= FALSE
;
120 struct dri1_api_lock_funcs dri1_lf
=
123 .unlock
= vl_dri_unlock
,
124 .is_locked
= vl_dri_is_locked
,
125 .is_lock_lost
= vl_dri_lost_lock
,
126 .clear_lost_lock
= vl_dri_clear_lost_lock
130 vl_dri_copy_version(struct dri1_api_version
*dst
, dri_version_t
*src
)
134 dst
->major
= src
->major
;
135 dst
->minor
= src
->minor
;
136 dst
->patch_level
= src
->patch
;
140 vl_dri_intersect_src_bbox(struct drm_clip_rect
*dst
, int dst_x
, int dst_y
,
141 const struct drm_clip_rect
*src
, const struct drm_clip_rect
*bbox
)
150 xy1
= ((int)src
->x1
> (int)bbox
->x1
+ dst_x
) ? src
->x1
:
151 (int)bbox
->x1
+ dst_x
;
152 xy2
= ((int)src
->x2
< (int)bbox
->x2
+ dst_x
) ? src
->x2
:
153 (int)bbox
->x2
+ dst_x
;
154 if (xy1
>= xy2
|| xy1
< 0)
160 xy1
= ((int)src
->y1
> (int)bbox
->y1
+ dst_y
) ? src
->y1
:
161 (int)bbox
->y1
+ dst_y
;
162 xy2
= ((int)src
->y2
< (int)bbox
->y2
+ dst_y
) ? src
->y2
:
163 (int)bbox
->y2
+ dst_y
;
164 if (xy1
>= xy2
|| xy1
< 0)
173 vl_clip_copy(struct vl_dri_context
*vl_dri_ctx
,
174 struct pipe_surface
*dst
,
175 struct pipe_surface
*src
,
176 const struct drm_clip_rect
*src_bbox
)
178 struct pipe_video_context
*vpipe
= vl_dri_ctx
->base
.vpipe
;
179 struct drm_clip_rect clip
;
180 struct drm_clip_rect
*cur
;
188 assert(vl_dri_ctx
->drawable
->cliprects
);
189 assert(vl_dri_ctx
->drawable
->num_cliprects
> 0);
191 cur
= vl_dri_ctx
->drawable
->cliprects
;
193 for (i
= 0; i
< vl_dri_ctx
->drawable
->num_cliprects
; ++i
) {
194 if (vl_dri_intersect_src_bbox(&clip
, vl_dri_ctx
->drawable
->x
, vl_dri_ctx
->drawable
->y
, cur
++, src_bbox
))
197 vpipe
, dst
, clip
.x1
, clip
.y1
, src
,
198 (int)clip
.x1
- vl_dri_ctx
->drawable
->x
,
199 (int)clip
.y1
- vl_dri_ctx
->drawable
->y
,
200 clip
.x2
- clip
.x1
, clip
.y2
- clip
.y1
206 vl_dri_update_drawables_locked(struct vl_dri_context
*vl_dri_ctx
)
208 struct vl_dri_screen
*vl_dri_scrn
;
212 vl_dri_scrn
= (struct vl_dri_screen
*)vl_dri_ctx
->base
.vscreen
;
214 if (vl_dri_ctx
->lost_lock
) {
215 vl_dri_ctx
->lost_lock
= FALSE
;
216 DRI_VALIDATE_DRAWABLE_INFO(vl_dri_scrn
->dri_screen
, vl_dri_ctx
->drawable
);
221 vl_dri_flush_frontbuffer(struct pipe_screen
*screen
,
222 struct pipe_surface
*surf
, void *context_private
)
224 struct vl_dri_context
*vl_dri_ctx
= (struct vl_dri_context
*)context_private
;
225 struct vl_dri_screen
*vl_dri_scrn
;
226 struct drm_clip_rect src_bbox
;
227 boolean save_lost_lock
= FALSE
;
231 assert(context_private
);
233 vl_dri_scrn
= (struct vl_dri_screen
*)vl_dri_ctx
->base
.vscreen
;
235 vl_dri_lock(vl_dri_ctx
);
237 save_lost_lock
= vl_dri_ctx
->lost_lock
;
239 vl_dri_update_drawables_locked(vl_dri_ctx
);
241 if (vl_dri_ctx
->drawable
->cliprects
) {
243 src_bbox
.x2
= vl_dri_ctx
->drawable
->w
;
245 src_bbox
.y2
= vl_dri_ctx
->drawable
->h
;
248 if (vl_dri_scrn
->_api_hooks
->present_locked
)
249 vl_dri_scrn
->api_hooks
->present_locked(pipe
, surf
,
250 vl_dri_ctx
->drawable
->cliprects
,
251 vl_dri_ctx
->drawable
->num_cliprects
,
252 vl_dri_ctx
->drawable
->x
, vl_dri_drawable
->y
,
253 &bbox
, NULL
/*fence*/);
256 if (vl_dri_scrn
->api_hooks
->front_srf_locked
) {
257 struct pipe_surface
*front
= vl_dri_scrn
->api_hooks
->front_srf_locked(screen
);
260 vl_clip_copy(vl_dri_ctx
, front
, surf
, &src_bbox
);
262 //st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, fence);
266 vl_dri_ctx
->lost_lock
= save_lost_lock
;
268 vl_dri_unlock(vl_dri_ctx
);
272 vl_video_bind_drawable(struct vl_context
*vctx
, Drawable drawable
)
274 struct vl_dri_context
*vl_dri_ctx
= (struct vl_dri_context
*)vctx
;
275 struct vl_dri_screen
*vl_dri_scrn
;
276 dri_drawable_t
*dri_drawable
;
277 Drawable old_drawable
= None
;
281 if (vl_dri_ctx
->drawable
)
282 old_drawable
= vl_dri_ctx
->drawable
->x_drawable
;
284 vl_dri_scrn
= (struct vl_dri_screen
*)vl_dri_ctx
->base
.vscreen
;
285 driCreateDrawable(vl_dri_scrn
->dri_screen
, drawable
, &dri_drawable
);
286 vl_dri_ctx
->drawable
= dri_drawable
;
292 vl_screen_create(Display
*display
, int screen
)
294 struct vl_dri_screen
*vl_dri_scrn
;
295 struct dri1_create_screen_arg arg
;
299 vl_dri_scrn
= CALLOC_STRUCT(vl_dri_screen
);
303 driCreateScreen(display
, screen
, &vl_dri_scrn
->dri_screen
, &vl_dri_scrn
->dri_framebuf
);
304 vl_dri_scrn
->api
= drm_api_create();
306 arg
.base
.mode
= DRM_CREATE_DRI1
;
308 arg
.ddx_info
= vl_dri_scrn
->dri_framebuf
.private;
309 arg
.ddx_info_size
= vl_dri_scrn
->dri_framebuf
.private_size
;
310 arg
.sarea
= vl_dri_scrn
->dri_screen
->sarea
;
311 vl_dri_copy_version(&arg
.ddx_version
, &vl_dri_scrn
->dri_screen
->ddx
);
312 vl_dri_copy_version(&arg
.dri_version
, &vl_dri_scrn
->dri_screen
->dri
);
313 vl_dri_copy_version(&arg
.drm_version
, &vl_dri_scrn
->dri_screen
->drm
);
316 vl_dri_scrn
->base
.pscreen
= vl_dri_scrn
->api
->create_screen(vl_dri_scrn
->api
,
317 vl_dri_scrn
->dri_screen
->fd
,
320 if (!vl_dri_scrn
->base
.pscreen
) {
325 vl_dri_scrn
->visual
= XDefaultVisual(display
, screen
);
326 vl_dri_scrn
->api_hooks
= arg
.api
;
327 vl_dri_scrn
->base
.pscreen
->flush_frontbuffer
= vl_dri_flush_frontbuffer
;
328 /* XXX: Safe to call this while unlocked? */
329 vl_dri_scrn
->base
.format
= vl_dri_scrn
->api_hooks
->front_srf_locked(vl_dri_scrn
->base
.pscreen
)->format
;
331 return &vl_dri_scrn
->base
;
334 void vl_screen_destroy(struct vl_screen
*vscreen
)
336 struct vl_dri_screen
*vl_dri_scrn
= (struct vl_dri_screen
*)vscreen
;
340 vl_dri_scrn
->base
.pscreen
->destroy(vl_dri_scrn
->base
.pscreen
);
341 driDestroyScreen(vl_dri_scrn
->dri_screen
);
346 vl_video_create(struct vl_screen
*vscreen
,
347 enum pipe_video_profile profile
,
348 enum pipe_video_chroma_format chroma_format
,
349 unsigned width
, unsigned height
)
351 struct vl_dri_screen
*vl_dri_scrn
= (struct vl_dri_screen
*)vscreen
;
352 struct vl_dri_context
*vl_dri_ctx
;
354 vl_dri_ctx
= CALLOC_STRUCT(vl_dri_context
);
358 /* XXX: Is default visual correct/sufficient here? */
359 driCreateContext(vl_dri_scrn
->dri_screen
, vl_dri_scrn
->visual
, &vl_dri_ctx
->dri_context
);
361 if (!vl_dri_scrn
->api
->create_video_context
) {
362 debug_printf("[G3DVL] No video support found on %s/%s.\n",
363 vl_dri_scrn
->base
.pscreen
->get_vendor(vl_dri_scrn
->base
.pscreen
),
364 vl_dri_scrn
->base
.pscreen
->get_name(vl_dri_scrn
->base
.pscreen
));
369 vl_dri_ctx
->base
.vpipe
= vl_dri_scrn
->api
->create_video_context(vl_dri_scrn
->api
,
371 profile
, chroma_format
,
374 if (!vl_dri_ctx
->base
.vpipe
) {
379 vl_dri_ctx
->base
.vpipe
->priv
= vl_dri_ctx
;
380 vl_dri_ctx
->base
.vscreen
= vscreen
;
381 vl_dri_ctx
->fd
= vl_dri_scrn
->dri_screen
->fd
;
382 vl_dri_ctx
->lock
= (drmLock
*)&vl_dri_scrn
->dri_screen
->sarea
->lock
;
384 return &vl_dri_ctx
->base
;
387 void vl_video_destroy(struct vl_context
*vctx
)
389 struct vl_dri_context
*vl_dri_ctx
= (struct vl_dri_context
*)vctx
;
393 vl_dri_ctx
->base
.vpipe
->destroy(vl_dri_ctx
->base
.vpipe
);