Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/frontends/vdpau/presentation.c
4565 views
1
/**************************************************************************
2
*
3
* Copyright 2010 Thomas Balling Sørensen.
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 VMWARE 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 <stdio.h>
29
#include <vdpau/vdpau.h>
30
31
#include "util/u_debug.h"
32
#include "util/u_memory.h"
33
34
#include "vdpau_private.h"
35
36
/**
37
* Create a VdpPresentationQueue.
38
*/
39
VdpStatus
40
vlVdpPresentationQueueCreate(VdpDevice device,
41
VdpPresentationQueueTarget presentation_queue_target,
42
VdpPresentationQueue *presentation_queue)
43
{
44
vlVdpPresentationQueue *pq = NULL;
45
VdpStatus ret;
46
47
if (!presentation_queue)
48
return VDP_STATUS_INVALID_POINTER;
49
50
vlVdpDevice *dev = vlGetDataHTAB(device);
51
if (!dev)
52
return VDP_STATUS_INVALID_HANDLE;
53
54
vlVdpPresentationQueueTarget *pqt = vlGetDataHTAB(presentation_queue_target);
55
if (!pqt)
56
return VDP_STATUS_INVALID_HANDLE;
57
58
if (dev != pqt->device)
59
return VDP_STATUS_HANDLE_DEVICE_MISMATCH;
60
61
pq = CALLOC(1, sizeof(vlVdpPresentationQueue));
62
if (!pq)
63
return VDP_STATUS_RESOURCES;
64
65
DeviceReference(&pq->device, dev);
66
pq->drawable = pqt->drawable;
67
68
mtx_lock(&dev->mutex);
69
if (!vl_compositor_init_state(&pq->cstate, dev->context)) {
70
mtx_unlock(&dev->mutex);
71
ret = VDP_STATUS_ERROR;
72
goto no_compositor;
73
}
74
mtx_unlock(&dev->mutex);
75
76
*presentation_queue = vlAddDataHTAB(pq);
77
if (*presentation_queue == 0) {
78
ret = VDP_STATUS_ERROR;
79
goto no_handle;
80
}
81
82
return VDP_STATUS_OK;
83
84
no_handle:
85
no_compositor:
86
DeviceReference(&pq->device, NULL);
87
FREE(pq);
88
return ret;
89
}
90
91
/**
92
* Destroy a VdpPresentationQueue.
93
*/
94
VdpStatus
95
vlVdpPresentationQueueDestroy(VdpPresentationQueue presentation_queue)
96
{
97
vlVdpPresentationQueue *pq;
98
99
pq = vlGetDataHTAB(presentation_queue);
100
if (!pq)
101
return VDP_STATUS_INVALID_HANDLE;
102
103
mtx_lock(&pq->device->mutex);
104
vl_compositor_cleanup_state(&pq->cstate);
105
mtx_unlock(&pq->device->mutex);
106
107
vlRemoveDataHTAB(presentation_queue);
108
DeviceReference(&pq->device, NULL);
109
FREE(pq);
110
111
return VDP_STATUS_OK;
112
}
113
114
/**
115
* Configure the background color setting.
116
*/
117
VdpStatus
118
vlVdpPresentationQueueSetBackgroundColor(VdpPresentationQueue presentation_queue,
119
VdpColor *const background_color)
120
{
121
vlVdpPresentationQueue *pq;
122
union pipe_color_union color;
123
124
if (!background_color)
125
return VDP_STATUS_INVALID_POINTER;
126
127
pq = vlGetDataHTAB(presentation_queue);
128
if (!pq)
129
return VDP_STATUS_INVALID_HANDLE;
130
131
color.f[0] = background_color->red;
132
color.f[1] = background_color->green;
133
color.f[2] = background_color->blue;
134
color.f[3] = background_color->alpha;
135
136
mtx_lock(&pq->device->mutex);
137
vl_compositor_set_clear_color(&pq->cstate, &color);
138
mtx_unlock(&pq->device->mutex);
139
140
return VDP_STATUS_OK;
141
}
142
143
/**
144
* Retrieve the current background color setting.
145
*/
146
VdpStatus
147
vlVdpPresentationQueueGetBackgroundColor(VdpPresentationQueue presentation_queue,
148
VdpColor *const background_color)
149
{
150
vlVdpPresentationQueue *pq;
151
union pipe_color_union color;
152
153
if (!background_color)
154
return VDP_STATUS_INVALID_POINTER;
155
156
pq = vlGetDataHTAB(presentation_queue);
157
if (!pq)
158
return VDP_STATUS_INVALID_HANDLE;
159
160
mtx_lock(&pq->device->mutex);
161
vl_compositor_get_clear_color(&pq->cstate, &color);
162
mtx_unlock(&pq->device->mutex);
163
164
background_color->red = color.f[0];
165
background_color->green = color.f[1];
166
background_color->blue = color.f[2];
167
background_color->alpha = color.f[3];
168
169
return VDP_STATUS_OK;
170
}
171
172
/**
173
* Retrieve the presentation queue's "current" time.
174
*/
175
VdpStatus
176
vlVdpPresentationQueueGetTime(VdpPresentationQueue presentation_queue,
177
VdpTime *current_time)
178
{
179
vlVdpPresentationQueue *pq;
180
181
if (!current_time)
182
return VDP_STATUS_INVALID_POINTER;
183
184
pq = vlGetDataHTAB(presentation_queue);
185
if (!pq)
186
return VDP_STATUS_INVALID_HANDLE;
187
188
mtx_lock(&pq->device->mutex);
189
*current_time = pq->device->vscreen->get_timestamp(pq->device->vscreen,
190
(void *)pq->drawable);
191
mtx_unlock(&pq->device->mutex);
192
193
return VDP_STATUS_OK;
194
}
195
196
/**
197
* Enter a surface into the presentation queue.
198
*/
199
VdpStatus
200
vlVdpPresentationQueueDisplay(VdpPresentationQueue presentation_queue,
201
VdpOutputSurface surface,
202
uint32_t clip_width,
203
uint32_t clip_height,
204
VdpTime earliest_presentation_time)
205
{
206
static int dump_window = -1;
207
208
vlVdpPresentationQueue *pq;
209
vlVdpOutputSurface *surf;
210
211
struct pipe_context *pipe;
212
struct pipe_resource *tex;
213
struct pipe_surface surf_templ, *surf_draw = NULL;
214
struct u_rect src_rect, dst_clip, *dirty_area;
215
216
struct vl_compositor *compositor;
217
struct vl_compositor_state *cstate;
218
struct vl_screen *vscreen;
219
220
pq = vlGetDataHTAB(presentation_queue);
221
if (!pq)
222
return VDP_STATUS_INVALID_HANDLE;
223
224
surf = vlGetDataHTAB(surface);
225
if (!surf)
226
return VDP_STATUS_INVALID_HANDLE;
227
228
pipe = pq->device->context;
229
compositor = &pq->device->compositor;
230
cstate = &pq->cstate;
231
vscreen = pq->device->vscreen;
232
233
mtx_lock(&pq->device->mutex);
234
if (vscreen->set_back_texture_from_output && surf->send_to_X)
235
vscreen->set_back_texture_from_output(vscreen, surf->surface->texture, clip_width, clip_height);
236
tex = vscreen->texture_from_drawable(vscreen, (void *)pq->drawable);
237
if (!tex) {
238
mtx_unlock(&pq->device->mutex);
239
return VDP_STATUS_INVALID_HANDLE;
240
}
241
242
if (!vscreen->set_back_texture_from_output || !surf->send_to_X) {
243
dirty_area = vscreen->get_dirty_area(vscreen);
244
245
memset(&surf_templ, 0, sizeof(surf_templ));
246
surf_templ.format = tex->format;
247
surf_draw = pipe->create_surface(pipe, tex, &surf_templ);
248
249
dst_clip.x0 = 0;
250
dst_clip.y0 = 0;
251
dst_clip.x1 = clip_width ? clip_width : surf_draw->width;
252
dst_clip.y1 = clip_height ? clip_height : surf_draw->height;
253
254
src_rect.x0 = 0;
255
src_rect.y0 = 0;
256
src_rect.x1 = surf_draw->width;
257
src_rect.y1 = surf_draw->height;
258
259
vl_compositor_clear_layers(cstate);
260
vl_compositor_set_rgba_layer(cstate, compositor, 0, surf->sampler_view, &src_rect, NULL, NULL);
261
vl_compositor_set_dst_clip(cstate, &dst_clip);
262
vl_compositor_render(cstate, compositor, surf_draw, dirty_area, true);
263
}
264
265
vscreen->set_next_timestamp(vscreen, earliest_presentation_time);
266
267
// flush before calling flush_frontbuffer so that rendering is flushed
268
// to back buffer so the texture can be copied in flush_frontbuffer
269
pipe->screen->fence_reference(pipe->screen, &surf->fence, NULL);
270
pipe->flush(pipe, &surf->fence, 0);
271
pipe->screen->flush_frontbuffer(pipe->screen, pipe, tex, 0, 0,
272
vscreen->get_private(vscreen), NULL);
273
274
pq->last_surf = surf;
275
276
if (dump_window == -1) {
277
dump_window = debug_get_num_option("VDPAU_DUMP", 0);
278
}
279
280
if (dump_window) {
281
static unsigned int framenum = 0;
282
char cmd[256];
283
284
if (framenum) {
285
sprintf(cmd, "xwd -id %d -silent -out vdpau_frame_%08d.xwd", (int)pq->drawable, framenum);
286
if (system(cmd) != 0)
287
VDPAU_MSG(VDPAU_ERR, "[VDPAU] Dumping surface %d failed.\n", surface);
288
}
289
framenum++;
290
}
291
292
if (!vscreen->set_back_texture_from_output || !surf->send_to_X) {
293
pipe_resource_reference(&tex, NULL);
294
pipe_surface_reference(&surf_draw, NULL);
295
}
296
mtx_unlock(&pq->device->mutex);
297
298
return VDP_STATUS_OK;
299
}
300
301
/**
302
* Wait for a surface to finish being displayed.
303
*/
304
VdpStatus
305
vlVdpPresentationQueueBlockUntilSurfaceIdle(VdpPresentationQueue presentation_queue,
306
VdpOutputSurface surface,
307
VdpTime *first_presentation_time)
308
{
309
vlVdpPresentationQueue *pq;
310
vlVdpOutputSurface *surf;
311
struct pipe_screen *screen;
312
313
if (!first_presentation_time)
314
return VDP_STATUS_INVALID_POINTER;
315
316
pq = vlGetDataHTAB(presentation_queue);
317
if (!pq)
318
return VDP_STATUS_INVALID_HANDLE;
319
320
surf = vlGetDataHTAB(surface);
321
if (!surf)
322
return VDP_STATUS_INVALID_HANDLE;
323
324
mtx_lock(&pq->device->mutex);
325
if (surf->fence) {
326
screen = pq->device->vscreen->pscreen;
327
screen->fence_finish(screen, NULL, surf->fence, PIPE_TIMEOUT_INFINITE);
328
screen->fence_reference(screen, &surf->fence, NULL);
329
}
330
mtx_unlock(&pq->device->mutex);
331
332
return vlVdpPresentationQueueGetTime(presentation_queue, first_presentation_time);
333
}
334
335
/**
336
* Poll the current queue status of a surface.
337
*/
338
VdpStatus
339
vlVdpPresentationQueueQuerySurfaceStatus(VdpPresentationQueue presentation_queue,
340
VdpOutputSurface surface,
341
VdpPresentationQueueStatus *status,
342
VdpTime *first_presentation_time)
343
{
344
vlVdpPresentationQueue *pq;
345
vlVdpOutputSurface *surf;
346
struct pipe_screen *screen;
347
348
if (!(status && first_presentation_time))
349
return VDP_STATUS_INVALID_POINTER;
350
351
pq = vlGetDataHTAB(presentation_queue);
352
if (!pq)
353
return VDP_STATUS_INVALID_HANDLE;
354
355
surf = vlGetDataHTAB(surface);
356
if (!surf)
357
return VDP_STATUS_INVALID_HANDLE;
358
359
*first_presentation_time = 0;
360
361
if (!surf->fence) {
362
if (pq->last_surf == surf)
363
*status = VDP_PRESENTATION_QUEUE_STATUS_VISIBLE;
364
else
365
*status = VDP_PRESENTATION_QUEUE_STATUS_IDLE;
366
} else {
367
mtx_lock(&pq->device->mutex);
368
screen = pq->device->vscreen->pscreen;
369
if (screen->fence_finish(screen, NULL, surf->fence, 0)) {
370
screen->fence_reference(screen, &surf->fence, NULL);
371
*status = VDP_PRESENTATION_QUEUE_STATUS_VISIBLE;
372
mtx_unlock(&pq->device->mutex);
373
374
// We actually need to query the timestamp of the last VSYNC event from the hardware
375
vlVdpPresentationQueueGetTime(presentation_queue, first_presentation_time);
376
*first_presentation_time += 1;
377
} else {
378
*status = VDP_PRESENTATION_QUEUE_STATUS_QUEUED;
379
mtx_unlock(&pq->device->mutex);
380
}
381
}
382
383
return VDP_STATUS_OK;
384
}
385
386