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
;
48 struct vl_context base
;
52 dri_context_t
*dri_context
;
54 struct pipe_video_context
*vpipe
;
55 dri_drawable_t
*drawable
;
56 struct pipe_surface
*dri2_front
;
60 vl_dri_lock(void *priv
)
62 struct vl_dri_context
*vl_dri_ctx
= priv
;
63 drm_context_t hw_context
;
68 hw_context
= vl_dri_ctx
->dri_context
->drm_context
;
70 DRM_CAS(vl_dri_ctx
->lock
, hw_context
, DRM_LOCK_HELD
| hw_context
, ret
);
72 drmGetLock(vl_dri_ctx
->fd
, hw_context
, 0);
73 vl_dri_ctx
->lost_lock
= TRUE
;
75 vl_dri_ctx
->is_locked
= TRUE
;
79 vl_dri_unlock(void *priv
)
81 struct vl_dri_context
*vl_dri_ctx
= priv
;
82 drm_context_t hw_context
;
86 hw_context
= vl_dri_ctx
->dri_context
->drm_context
;
88 vl_dri_ctx
->is_locked
= FALSE
;
89 DRM_UNLOCK(vl_dri_ctx
->fd
, vl_dri_ctx
->lock
, hw_context
);
93 vl_dri_is_locked(void *priv
)
95 struct vl_dri_context
*vl_dri_ctx
= priv
;
99 return vl_dri_ctx
->is_locked
;
103 vl_dri_lost_lock(void *priv
)
105 struct vl_dri_context
*vl_dri_ctx
= priv
;
109 return vl_dri_ctx
->lost_lock
;
113 vl_dri_clear_lost_lock(void *priv
)
115 struct vl_dri_context
*vl_dri_ctx
= priv
;
119 vl_dri_ctx
->lost_lock
= FALSE
;
122 struct dri1_api_lock_funcs dri1_lf
=
125 .unlock
= vl_dri_unlock
,
126 .is_locked
= vl_dri_is_locked
,
127 .is_lock_lost
= vl_dri_lost_lock
,
128 .clear_lost_lock
= vl_dri_clear_lost_lock
132 vl_dri_copy_version(struct dri1_api_version
*dst
, dri_version_t
*src
)
136 dst
->major
= src
->major
;
137 dst
->minor
= src
->minor
;
138 dst
->patch_level
= src
->patch
;
142 vl_dri_intersect_src_bbox(struct drm_clip_rect
*dst
, int dst_x
, int dst_y
,
143 const struct drm_clip_rect
*src
, const struct drm_clip_rect
*bbox
)
152 xy1
= ((int)src
->x1
> (int)bbox
->x1
+ dst_x
) ? src
->x1
:
153 (int)bbox
->x1
+ dst_x
;
154 xy2
= ((int)src
->x2
< (int)bbox
->x2
+ dst_x
) ? src
->x2
:
155 (int)bbox
->x2
+ dst_x
;
156 if (xy1
>= xy2
|| xy1
< 0)
162 xy1
= ((int)src
->y1
> (int)bbox
->y1
+ dst_y
) ? src
->y1
:
163 (int)bbox
->y1
+ dst_y
;
164 xy2
= ((int)src
->y2
< (int)bbox
->y2
+ dst_y
) ? src
->y2
:
165 (int)bbox
->y2
+ dst_y
;
166 if (xy1
>= xy2
|| xy1
< 0)
175 vl_clip_copy(struct vl_dri_context
*vl_dri_ctx
,
176 struct pipe_surface
*dst
,
177 struct pipe_surface
*src
,
178 const struct drm_clip_rect
*src_bbox
)
180 struct pipe_video_context
*vpipe
;
181 struct drm_clip_rect clip
;
182 struct drm_clip_rect
*cur
;
190 vpipe
= vl_dri_ctx
->base
.vpipe
;
192 assert(vl_dri_ctx
->drawable
->cliprects
);
193 assert(vl_dri_ctx
->drawable
->num_cliprects
> 0);
195 cur
= vl_dri_ctx
->drawable
->cliprects
;
197 for (i
= 0; i
< vl_dri_ctx
->drawable
->num_cliprects
; ++i
) {
198 if (vl_dri_intersect_src_bbox(&clip
, vl_dri_ctx
->drawable
->x
, vl_dri_ctx
->drawable
->y
, cur
++, src_bbox
))
201 vpipe
, dst
, clip
.x1
, clip
.y1
, src
,
202 (int)clip
.x1
- vl_dri_ctx
->drawable
->x
,
203 (int)clip
.y1
- vl_dri_ctx
->drawable
->y
,
204 clip
.x2
- clip
.x1
, clip
.y2
- clip
.y1
210 vl_dri_update_drawables_locked(struct vl_dri_context
*vl_dri_ctx
)
212 struct vl_dri_screen
*vl_dri_scrn
;
216 vl_dri_scrn
= (struct vl_dri_screen
*)vl_dri_ctx
->base
.vscreen
;
218 if (vl_dri_ctx
->lost_lock
) {
219 vl_dri_ctx
->lost_lock
= FALSE
;
220 DRI_VALIDATE_DRAWABLE_INFO(vl_dri_scrn
->dri_screen
, vl_dri_ctx
->drawable
);
225 vl_dri_flush_frontbuffer(struct pipe_screen
*screen
,
226 struct pipe_surface
*surf
, void *context_private
)
228 struct vl_dri_context
*vl_dri_ctx
= (struct vl_dri_context
*)context_private
;
229 struct vl_dri_screen
*vl_dri_scrn
;
230 struct drm_clip_rect src_bbox
;
231 boolean save_lost_lock
= FALSE
;
235 assert(context_private
);
237 vl_dri_scrn
= (struct vl_dri_screen
*)vl_dri_ctx
->base
.vscreen
;
239 vl_dri_lock(vl_dri_ctx
);
241 save_lost_lock
= vl_dri_ctx
->lost_lock
;
243 vl_dri_update_drawables_locked(vl_dri_ctx
);
245 if (vl_dri_ctx
->drawable
->cliprects
) {
247 src_bbox
.x2
= vl_dri_ctx
->drawable
->w
;
249 src_bbox
.y2
= vl_dri_ctx
->drawable
->h
;
252 if (vl_dri_scrn
->_api_hooks
->present_locked
)
253 vl_dri_scrn
->api_hooks
->present_locked(pipe
, surf
,
254 vl_dri_ctx
->drawable
->cliprects
,
255 vl_dri_ctx
->drawable
->num_cliprects
,
256 vl_dri_ctx
->drawable
->x
, vl_dri_drawable
->y
,
257 &bbox
, NULL
/*fence*/);
260 if (vl_dri_scrn
->api_hooks
->front_srf_locked
) {
261 struct pipe_surface
*front
= vl_dri_scrn
->api_hooks
->front_srf_locked(screen
);
264 vl_clip_copy(vl_dri_ctx
, front
, surf
, &src_bbox
);
266 //st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, fence);
270 vl_dri_ctx
->lost_lock
= save_lost_lock
;
272 vl_dri_unlock(vl_dri_ctx
);
275 static struct pipe_surface
*
276 vl_dri2_get_front(struct vl_dri_screen
*vl_dri_scrn
, Drawable drawable
)
279 unsigned int attachments
[1] = {DRI_BUFFER_FRONT_LEFT
};
281 DRI2Buffer
*dri2_front
;
282 struct pipe_resource
template, *front_tex
;
283 struct pipe_surface
*front_surf
= NULL
;
287 dri2_front
= DRI2GetBuffers(vl_dri_scrn
->dri_screen
->display
,
288 drawable
, &w
, &h
, attachments
, 1, &count
);
290 struct winsys_handle dri2_front_handle
=
292 .type
= DRM_API_HANDLE_TYPE_SHARED
,
293 .handle
= dri2_front
->name
,
294 .stride
= dri2_front
->pitch
296 front_tex
= vl_dri_scrn
->base
.pscreen
->resource_from_handle(vl_dri_scrn
->base
.pscreen
, &template, &dri2_front_handle
);
298 front_surf
= vl_dri_scrn
->base
.pscreen
->get_tex_surface(vl_dri_scrn
->base
.pscreen
,
300 /*PIPE_BIND_RENDER_TARGET*/ PIPE_BIND_BLIT_DESTINATION
);
301 pipe_resource_reference(&front_tex
, NULL
);
308 vl_dri2_flush_frontbuffer(struct pipe_screen
*screen
,
309 struct pipe_surface
*surf
, void *context_private
)
311 struct vl_dri_context
*vl_dri_ctx
= (struct vl_dri_context
*)context_private
;
312 struct vl_dri_screen
*vl_dri_scrn
;
313 struct pipe_video_context
*vpipe
;
317 assert(context_private
);
318 assert(vl_dri_ctx
->dri2_front
);
320 vl_dri_scrn
= (struct vl_dri_screen
*)vl_dri_ctx
->base
.vscreen
;
321 vpipe
= vl_dri_ctx
->base
.vpipe
;
323 /* XXX: Why not just render to fake front? */
324 vpipe
->surface_copy(vpipe
, vl_dri_ctx
->dri2_front
, 0, 0, surf
, 0, 0, surf
->width
, surf
->height
);
326 //st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, fence);
331 vl_video_bind_drawable(struct vl_context
*vctx
, Drawable drawable
)
333 struct vl_dri_context
*vl_dri_ctx
= (struct vl_dri_context
*)vctx
;
334 struct vl_dri_screen
*vl_dri_scrn
;
335 dri_drawable_t
*dri_drawable
;
336 Drawable old_drawable
= None
;
340 if (vl_dri_ctx
->drawable
)
341 old_drawable
= vl_dri_ctx
->drawable
->x_drawable
;
343 if (drawable
!= old_drawable
) {
344 vl_dri_scrn
= (struct vl_dri_screen
*)vl_dri_ctx
->base
.vscreen
;
345 if (vl_dri_scrn
->dri2
) {
346 /* XXX: Need dri2CreateDrawable()? */
347 vl_dri_ctx
->dri2_front
= vl_dri2_get_front(vl_dri_scrn
, drawable
);
350 driCreateDrawable(vl_dri_scrn
->dri_screen
, drawable
, &dri_drawable
);
351 vl_dri_ctx
->drawable
= dri_drawable
;
359 vl_screen_create(Display
*display
, int screen
)
361 struct vl_dri_screen
*vl_dri_scrn
;
362 struct dri1_create_screen_arg arg
;
366 vl_dri_scrn
= CALLOC_STRUCT(vl_dri_screen
);
371 if (dri2CreateScreen(display
, screen
, &vl_dri_scrn
->dri_screen
)) {
372 /* If not, try DRI */
373 if (driCreateScreen(display
, screen
, &vl_dri_scrn
->dri_screen
, &vl_dri_scrn
->dri_framebuf
)) {
380 arg
.base
.mode
= DRM_CREATE_DRI1
;
382 arg
.ddx_info
= vl_dri_scrn
->dri_framebuf
.private;
383 arg
.ddx_info_size
= vl_dri_scrn
->dri_framebuf
.private_size
;
384 arg
.sarea
= vl_dri_scrn
->dri_screen
->sarea
;
385 vl_dri_copy_version(&arg
.ddx_version
, &vl_dri_scrn
->dri_screen
->ddx
);
386 vl_dri_copy_version(&arg
.dri_version
, &vl_dri_scrn
->dri_screen
->dri
);
387 vl_dri_copy_version(&arg
.drm_version
, &vl_dri_scrn
->dri_screen
->drm
);
389 vl_dri_scrn
->dri2
= FALSE
;
394 arg
.base
.mode
= DRM_CREATE_NORMAL
;
395 vl_dri_scrn
->dri2
= TRUE
;
398 vl_dri_scrn
->api
= drm_api_create();
399 if (!vl_dri_scrn
->api
) {
404 vl_dri_scrn
->base
.pscreen
= vl_dri_scrn
->api
->create_screen(vl_dri_scrn
->api
,
405 vl_dri_scrn
->dri_screen
->fd
,
408 if (!vl_dri_scrn
->base
.pscreen
) {
413 if (!vl_dri_scrn
->dri2
) {
414 vl_dri_scrn
->visual
= XDefaultVisual(display
, screen
);
415 vl_dri_scrn
->api_hooks
= arg
.api
;
416 vl_dri_scrn
->base
.format
= vl_dri_scrn
->api_hooks
->front_srf_locked(vl_dri_scrn
->base
.pscreen
)->format
;
417 vl_dri_scrn
->base
.pscreen
->flush_frontbuffer
= vl_dri_flush_frontbuffer
;
420 vl_dri_scrn
->base
.pscreen
->flush_frontbuffer
= vl_dri2_flush_frontbuffer
;
422 return &vl_dri_scrn
->base
;
425 void vl_screen_destroy(struct vl_screen
*vscreen
)
427 struct vl_dri_screen
*vl_dri_scrn
= (struct vl_dri_screen
*)vscreen
;
431 vl_dri_scrn
->base
.pscreen
->destroy(vl_dri_scrn
->base
.pscreen
);
432 if (vl_dri_scrn
->dri2
)
433 dri2DestroyScreen(vl_dri_scrn
->dri_screen
);
435 driDestroyScreen(vl_dri_scrn
->dri_screen
);
440 vl_video_create(struct vl_screen
*vscreen
,
441 enum pipe_video_profile profile
,
442 enum pipe_video_chroma_format chroma_format
,
443 unsigned width
, unsigned height
)
445 struct vl_dri_screen
*vl_dri_scrn
= (struct vl_dri_screen
*)vscreen
;
446 struct vl_dri_context
*vl_dri_ctx
;
448 vl_dri_ctx
= CALLOC_STRUCT(vl_dri_context
);
452 /* XXX: Is default visual correct/sufficient here? */
453 if (!vl_dri_scrn
->dri2
)
454 driCreateContext(vl_dri_scrn
->dri_screen
, vl_dri_scrn
->visual
, &vl_dri_ctx
->dri_context
);
456 if (!vscreen
->pscreen
->video_context_create
) {
457 debug_printf("[G3DVL] No video support found on %s/%s.\n",
458 vscreen
->pscreen
->get_vendor(vscreen
->pscreen
),
459 vscreen
->pscreen
->get_name(vscreen
->pscreen
));
464 vl_dri_ctx
->base
.vpipe
= vscreen
->pscreen
->video_context_create(vscreen
->pscreen
,
465 profile
, chroma_format
,
467 vl_dri_ctx
->dri_context
);
469 if (!vl_dri_ctx
->base
.vpipe
) {
474 vl_dri_ctx
->base
.vpipe
->priv
= vl_dri_ctx
;
475 vl_dri_ctx
->base
.vscreen
= vscreen
;
476 vl_dri_ctx
->fd
= vl_dri_scrn
->dri_screen
->fd
;
477 if (!vl_dri_scrn
->dri2
)
478 vl_dri_ctx
->lock
= (drmLock
*)&vl_dri_scrn
->dri_screen
->sarea
->lock
;
480 return &vl_dri_ctx
->base
;
483 void vl_video_destroy(struct vl_context
*vctx
)
485 struct vl_dri_context
*vl_dri_ctx
= (struct vl_dri_context
*)vctx
;
489 vl_dri_ctx
->base
.vpipe
->destroy(vl_dri_ctx
->base
.vpipe
);
490 if (!((struct vl_dri_screen
*)vctx
->vscreen
)->dri2
)
491 driDestroyContext(vl_dri_ctx
->dri_context
);