1 /**************************************************************************
3 * Copyright 2010 Thomas Balling Sørensen.
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 **************************************************************************/
30 #include <sys/timeb.h>
32 #include <vdpau/vdpau.h>
34 #include "util/u_debug.h"
35 #include "util/u_memory.h"
37 #include "vdpau_private.h"
40 * Create a VdpPresentationQueue.
43 vlVdpPresentationQueueCreate(VdpDevice device
,
44 VdpPresentationQueueTarget presentation_queue_target
,
45 VdpPresentationQueue
*presentation_queue
)
47 vlVdpPresentationQueue
*pq
= NULL
;
50 VDPAU_MSG(VDPAU_TRACE
, "[VDPAU] Creating PresentationQueue\n");
52 if (!presentation_queue
)
53 return VDP_STATUS_INVALID_POINTER
;
55 vlVdpDevice
*dev
= vlGetDataHTAB(device
);
57 return VDP_STATUS_INVALID_HANDLE
;
59 vlVdpPresentationQueueTarget
*pqt
= vlGetDataHTAB(presentation_queue_target
);
61 return VDP_STATUS_INVALID_HANDLE
;
63 if (dev
!= pqt
->device
)
64 return VDP_STATUS_HANDLE_DEVICE_MISMATCH
;
66 pq
= CALLOC(1, sizeof(vlVdpPresentationQueue
));
68 return VDP_STATUS_RESOURCES
;
71 pq
->drawable
= pqt
->drawable
;
73 if (!vl_compositor_init(&pq
->compositor
, dev
->context
->pipe
)) {
74 ret
= VDP_STATUS_ERROR
;
78 vl_compositor_reset_dirty_area(&pq
->dirty_area
);
80 *presentation_queue
= vlAddDataHTAB(pq
);
81 if (*presentation_queue
== 0) {
82 ret
= VDP_STATUS_ERROR
;
95 * Destroy a VdpPresentationQueue.
98 vlVdpPresentationQueueDestroy(VdpPresentationQueue presentation_queue
)
100 vlVdpPresentationQueue
*pq
;
102 VDPAU_MSG(VDPAU_TRACE
, "[VDPAU] Destroying PresentationQueue\n");
104 pq
= vlGetDataHTAB(presentation_queue
);
106 return VDP_STATUS_INVALID_HANDLE
;
108 vl_compositor_cleanup(&pq
->compositor
);
110 vlRemoveDataHTAB(presentation_queue
);
113 return VDP_STATUS_OK
;
117 * Configure the background color setting.
120 vlVdpPresentationQueueSetBackgroundColor(VdpPresentationQueue presentation_queue
,
121 VdpColor
*const background_color
)
123 vlVdpPresentationQueue
*pq
;
124 union pipe_color_union color
;
126 VDPAU_MSG(VDPAU_TRACE
, "[VDPAU] Setting background color\n");
128 if (!background_color
)
129 return VDP_STATUS_INVALID_POINTER
;
131 pq
= vlGetDataHTAB(presentation_queue
);
133 return VDP_STATUS_INVALID_HANDLE
;
135 color
.f
[0] = background_color
->red
;
136 color
.f
[1] = background_color
->green
;
137 color
.f
[2] = background_color
->blue
;
138 color
.f
[3] = background_color
->alpha
;
140 vl_compositor_set_clear_color(&pq
->compositor
, &color
);
142 return VDP_STATUS_OK
;
146 * Retrieve the current background color setting.
149 vlVdpPresentationQueueGetBackgroundColor(VdpPresentationQueue presentation_queue
,
150 VdpColor
*const background_color
)
152 vlVdpPresentationQueue
*pq
;
153 union pipe_color_union color
;
155 VDPAU_MSG(VDPAU_TRACE
, "[VDPAU] Getting background color\n");
157 if (!background_color
)
158 return VDP_STATUS_INVALID_POINTER
;
160 pq
= vlGetDataHTAB(presentation_queue
);
162 return VDP_STATUS_INVALID_HANDLE
;
164 vl_compositor_get_clear_color(&pq
->compositor
, &color
);
166 background_color
->red
= color
.f
[0];
167 background_color
->green
= color
.f
[1];
168 background_color
->blue
= color
.f
[2];
169 background_color
->alpha
= color
.f
[3];
171 return VDP_STATUS_OK
;
175 * Retrieve the presentation queue's "current" time.
178 vlVdpPresentationQueueGetTime(VdpPresentationQueue presentation_queue
,
179 VdpTime
*current_time
)
181 vlVdpPresentationQueue
*pq
;
184 VDPAU_MSG(VDPAU_TRACE
, "[VDPAU] Getting queue time\n");
187 return VDP_STATUS_INVALID_POINTER
;
189 pq
= vlGetDataHTAB(presentation_queue
);
191 return VDP_STATUS_INVALID_HANDLE
;
193 clock_gettime(CLOCK_REALTIME
, &ts
);
194 *current_time
= (uint64_t)ts
.tv_sec
* 1000000000LL + (uint64_t)ts
.tv_nsec
;
196 return VDP_STATUS_OK
;
200 * Enter a surface into the presentation queue.
203 vlVdpPresentationQueueDisplay(VdpPresentationQueue presentation_queue
,
204 VdpOutputSurface surface
,
206 uint32_t clip_height
,
207 VdpTime earliest_presentation_time
)
209 static int dump_window
= -1;
211 vlVdpPresentationQueue
*pq
;
212 vlVdpOutputSurface
*surf
;
214 struct pipe_context
*pipe
;
215 struct pipe_surface
*drawable_surface
;
216 struct pipe_video_rect src_rect
, dst_clip
;
218 pq
= vlGetDataHTAB(presentation_queue
);
220 return VDP_STATUS_INVALID_HANDLE
;
222 drawable_surface
= vl_drawable_surface_get(pq
->device
->context
, pq
->drawable
);
223 if (!drawable_surface
)
224 return VDP_STATUS_INVALID_HANDLE
;
226 surf
= vlGetDataHTAB(surface
);
228 return VDP_STATUS_INVALID_HANDLE
;
230 surf
->timestamp
= (vlVdpTime
)earliest_presentation_time
;
234 src_rect
.w
= drawable_surface
->width
;
235 src_rect
.h
= drawable_surface
->height
;
239 dst_clip
.w
= clip_width
;
240 dst_clip
.h
= clip_height
;
242 vl_compositor_clear_layers(&pq
->compositor
);
243 vl_compositor_set_rgba_layer(&pq
->compositor
, 0, surf
->sampler_view
, &src_rect
, NULL
);
244 vl_compositor_render(&pq
->compositor
, drawable_surface
, NULL
, &dst_clip
, &pq
->dirty_area
);
246 pipe
= pq
->device
->context
->pipe
;
248 pipe
->screen
->flush_frontbuffer
251 drawable_surface
->texture
,
253 vl_contextprivate_get(pq
->device
->context
, drawable_surface
)
256 pipe
->screen
->fence_reference(pipe
->screen
, &surf
->fence
, NULL
);
257 pipe
->flush(pipe
, &surf
->fence
);
259 if (dump_window
== -1) {
260 dump_window
= debug_get_num_option("VDPAU_DUMP", 0);
264 static unsigned int framenum
= 0;
267 sprintf(cmd
, "xwd -id %d -out vdpau_frame_%08d.xwd", (int)pq
->drawable
, ++framenum
);
268 if (system(cmd
) != 0)
269 VDPAU_MSG(VDPAU_TRACE
, "[VDPAU] Dumping surface %d failed.\n", surface
);
272 pipe_surface_reference(&drawable_surface
, NULL
);
274 return VDP_STATUS_OK
;
278 * Wait for a surface to finish being displayed.
281 vlVdpPresentationQueueBlockUntilSurfaceIdle(VdpPresentationQueue presentation_queue
,
282 VdpOutputSurface surface
,
283 VdpTime
*first_presentation_time
)
285 vlVdpPresentationQueue
*pq
;
286 vlVdpOutputSurface
*surf
;
287 struct pipe_screen
*screen
;
289 if (!first_presentation_time
)
290 return VDP_STATUS_INVALID_POINTER
;
292 pq
= vlGetDataHTAB(presentation_queue
);
294 return VDP_STATUS_INVALID_HANDLE
;
296 surf
= vlGetDataHTAB(surface
);
298 return VDP_STATUS_INVALID_HANDLE
;
301 screen
= pq
->device
->context
->pipe
->screen
;
302 screen
->fence_finish(screen
, surf
->fence
, 0);
305 // We actually need to query the timestamp of the last VSYNC event from the hardware
306 vlVdpPresentationQueueGetTime(presentation_queue
, first_presentation_time
);
308 return VDP_STATUS_OK
;
312 * Poll the current queue status of a surface.
315 vlVdpPresentationQueueQuerySurfaceStatus(VdpPresentationQueue presentation_queue
,
316 VdpOutputSurface surface
,
317 VdpPresentationQueueStatus
*status
,
318 VdpTime
*first_presentation_time
)
320 vlVdpPresentationQueue
*pq
;
321 vlVdpOutputSurface
*surf
;
322 struct pipe_screen
*screen
;
324 if (!(status
&& first_presentation_time
))
325 return VDP_STATUS_INVALID_POINTER
;
327 pq
= vlGetDataHTAB(presentation_queue
);
329 return VDP_STATUS_INVALID_HANDLE
;
331 surf
= vlGetDataHTAB(surface
);
333 return VDP_STATUS_INVALID_HANDLE
;
335 *first_presentation_time
= 0;
338 *status
= VDP_PRESENTATION_QUEUE_STATUS_IDLE
;
340 screen
= pq
->device
->context
->pipe
->screen
;
341 if (screen
->fence_signalled(screen
, surf
->fence
)) {
342 screen
->fence_reference(screen
, &surf
->fence
, NULL
);
343 *status
= VDP_PRESENTATION_QUEUE_STATUS_VISIBLE
;
345 // We actually need to query the timestamp of the last VSYNC event from the hardware
346 vlVdpPresentationQueueGetTime(presentation_queue
, first_presentation_time
);
347 *first_presentation_time
+= 1;
349 *status
= VDP_PRESENTATION_QUEUE_STATUS_QUEUED
;
353 return VDP_STATUS_OK
;