Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/frontends/xvmc/context.c
4566 views
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 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 <assert.h>
29
30
#include <X11/Xlibint.h>
31
#include <X11/extensions/XvMClib.h>
32
33
#include "pipe/p_screen.h"
34
#include "pipe/p_video_codec.h"
35
#include "pipe/p_video_state.h"
36
#include "pipe/p_state.h"
37
38
#include "util/u_memory.h"
39
40
#include "vl/vl_csc.h"
41
#include "vl/vl_winsys.h"
42
43
#include "xvmc_private.h"
44
45
static Status Validate(Display *dpy, XvPortID port, int surface_type_id,
46
unsigned int width, unsigned int height, int flags,
47
bool *found_port, int *screen, int *chroma_format,
48
int *mc_type, int *surface_flags,
49
unsigned short *subpic_max_w,
50
unsigned short *subpic_max_h)
51
{
52
bool found_surface = false;
53
XvAdaptorInfo *adaptor_info;
54
unsigned int num_adaptors;
55
int num_types;
56
unsigned int max_width = 0, max_height = 0;
57
Status ret;
58
59
assert(dpy);
60
assert(found_port);
61
assert(screen);
62
assert(chroma_format);
63
assert(mc_type);
64
assert(surface_flags);
65
assert(subpic_max_w);
66
assert(subpic_max_h);
67
68
*found_port = false;
69
70
for (int i = 0; i < XScreenCount(dpy); ++i) {
71
ret = XvQueryAdaptors(dpy, XRootWindow(dpy, i), &num_adaptors, &adaptor_info);
72
if (ret != Success)
73
return ret;
74
75
for (unsigned int j = 0; j < num_adaptors && !*found_port; ++j) {
76
for (unsigned int k = 0; k < adaptor_info[j].num_ports && !*found_port; ++k) {
77
XvMCSurfaceInfo *surface_info;
78
79
if (adaptor_info[j].base_id + k != port)
80
continue;
81
82
*found_port = true;
83
84
surface_info = XvMCListSurfaceTypes(dpy, adaptor_info[j].base_id, &num_types);
85
if (!surface_info) {
86
XvFreeAdaptorInfo(adaptor_info);
87
return BadAlloc;
88
}
89
90
for (int l = 0; l < num_types && !found_surface; ++l) {
91
if (surface_info[l].surface_type_id != surface_type_id)
92
continue;
93
94
found_surface = true;
95
max_width = surface_info[l].max_width;
96
max_height = surface_info[l].max_height;
97
*chroma_format = surface_info[l].chroma_format;
98
*mc_type = surface_info[l].mc_type;
99
*surface_flags = surface_info[l].flags;
100
*subpic_max_w = surface_info[l].subpicture_max_width;
101
*subpic_max_h = surface_info[l].subpicture_max_height;
102
*screen = i;
103
104
XVMC_MSG(XVMC_TRACE, "[XvMC] Found requested context surface format.\n" \
105
"[XvMC] screen=%u, port=%u\n" \
106
"[XvMC] id=0x%08X\n" \
107
"[XvMC] max width=%u, max height=%u\n" \
108
"[XvMC] chroma format=0x%08X\n" \
109
"[XvMC] acceleration level=0x%08X\n" \
110
"[XvMC] flags=0x%08X\n" \
111
"[XvMC] subpicture max width=%u, max height=%u\n",
112
i, port, surface_type_id, max_width, max_height, *chroma_format,
113
*mc_type, *surface_flags, *subpic_max_w, *subpic_max_h);
114
}
115
116
free(surface_info);
117
}
118
}
119
120
XvFreeAdaptorInfo(adaptor_info);
121
}
122
123
if (!*found_port) {
124
XVMC_MSG(XVMC_ERR, "[XvMC] Could not find a suitable port.\n");
125
return XvBadPort;
126
}
127
if (!found_surface) {
128
XVMC_MSG(XVMC_ERR, "[XvMC] Could not find a suitable surface.\n");
129
return BadMatch;
130
}
131
if (width > max_width || height > max_height) {
132
XVMC_MSG(XVMC_ERR, "[XvMC] Requested context dimensions (w=%u,h=%u) too large (max w=%u,h=%u).\n",
133
width, height, max_width, max_height);
134
return BadValue;
135
}
136
if (flags != XVMC_DIRECT && flags != 0) {
137
XVMC_MSG(XVMC_ERR, "[XvMC] Invalid context flags 0x%08X.\n", flags);
138
return BadValue;
139
}
140
141
return Success;
142
}
143
144
static enum pipe_video_profile ProfileToPipe(int xvmc_profile)
145
{
146
if (xvmc_profile & XVMC_MPEG_1)
147
assert(0);
148
if (xvmc_profile & XVMC_MPEG_2)
149
return PIPE_VIDEO_PROFILE_MPEG2_MAIN;
150
if (xvmc_profile & XVMC_H263)
151
assert(0);
152
if (xvmc_profile & XVMC_MPEG_4)
153
assert(0);
154
155
assert(0);
156
157
XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized profile 0x%08X.\n", xvmc_profile);
158
159
return -1;
160
}
161
162
static enum pipe_video_chroma_format FormatToPipe(int xvmc_format)
163
{
164
switch (xvmc_format) {
165
case XVMC_CHROMA_FORMAT_420:
166
return PIPE_VIDEO_CHROMA_FORMAT_420;
167
case XVMC_CHROMA_FORMAT_422:
168
return PIPE_VIDEO_CHROMA_FORMAT_422;
169
case XVMC_CHROMA_FORMAT_444:
170
return PIPE_VIDEO_CHROMA_FORMAT_444;
171
default:
172
assert(0);
173
}
174
175
XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized format 0x%08X.\n", xvmc_format);
176
177
return -1;
178
}
179
180
PUBLIC
181
Status XvMCCreateContext(Display *dpy, XvPortID port, int surface_type_id,
182
int width, int height, int flags, XvMCContext *context)
183
{
184
bool found_port;
185
int scrn = 0;
186
int chroma_format = 0;
187
int mc_type = 0;
188
int surface_flags = 0;
189
unsigned short subpic_max_w = 0;
190
unsigned short subpic_max_h = 0;
191
Status ret;
192
struct vl_screen *vscreen;
193
struct pipe_context *pipe;
194
struct pipe_video_codec templat = {0};
195
XvMCContextPrivate *context_priv;
196
vl_csc_matrix csc;
197
198
XVMC_MSG(XVMC_TRACE, "[XvMC] Creating context %p.\n", context);
199
200
assert(dpy);
201
202
if (!context)
203
return XvMCBadContext;
204
205
ret = Validate(dpy, port, surface_type_id, width, height, flags,
206
&found_port, &scrn, &chroma_format, &mc_type, &surface_flags,
207
&subpic_max_w, &subpic_max_h);
208
209
/* Success and XvBadPort have the same value */
210
if (ret != Success || !found_port)
211
return ret;
212
213
/* XXX: Current limits */
214
if (chroma_format != XVMC_CHROMA_FORMAT_420) {
215
XVMC_MSG(XVMC_ERR, "[XvMC] Cannot decode requested surface type. Unsupported chroma format.\n");
216
return BadImplementation;
217
}
218
if ((mc_type & ~XVMC_IDCT) != (XVMC_MOCOMP | XVMC_MPEG_2)) {
219
XVMC_MSG(XVMC_ERR, "[XvMC] Cannot decode requested surface type. Non-MPEG2/Mocomp/iDCT acceleration unsupported.\n");
220
return BadImplementation;
221
}
222
if (surface_flags & XVMC_INTRA_UNSIGNED) {
223
XVMC_MSG(XVMC_ERR, "[XvMC] Cannot decode requested surface type. Unsigned intra unsupported.\n");
224
return BadImplementation;
225
}
226
227
context_priv = CALLOC(1, sizeof(XvMCContextPrivate));
228
if (!context_priv)
229
return BadAlloc;
230
231
/* TODO: Reuse screen if process creates another context */
232
vscreen = vl_dri3_screen_create(dpy, scrn);
233
if (!vscreen)
234
vscreen = vl_dri2_screen_create(dpy, scrn);
235
236
if (!vscreen) {
237
XVMC_MSG(XVMC_ERR, "[XvMC] Could not create VL screen.\n");
238
FREE(context_priv);
239
return BadAlloc;
240
}
241
242
pipe = vscreen->pscreen->context_create(vscreen->pscreen, NULL, 0);
243
if (!pipe) {
244
XVMC_MSG(XVMC_ERR, "[XvMC] Could not create VL context.\n");
245
vscreen->destroy(vscreen);
246
FREE(context_priv);
247
return BadAlloc;
248
}
249
250
templat.profile = ProfileToPipe(mc_type);
251
templat.entrypoint = (mc_type & XVMC_IDCT) ? PIPE_VIDEO_ENTRYPOINT_IDCT : PIPE_VIDEO_ENTRYPOINT_MC;
252
templat.chroma_format = FormatToPipe(chroma_format);
253
templat.width = width;
254
templat.height = height;
255
templat.max_references = 2;
256
templat.expect_chunked_decode = true;
257
258
context_priv->decoder = pipe->create_video_codec(pipe, &templat);
259
260
if (!context_priv->decoder) {
261
XVMC_MSG(XVMC_ERR, "[XvMC] Could not create VL decoder.\n");
262
pipe->destroy(pipe);
263
vscreen->destroy(vscreen);
264
FREE(context_priv);
265
return BadAlloc;
266
}
267
268
if (!vl_compositor_init(&context_priv->compositor, pipe)) {
269
XVMC_MSG(XVMC_ERR, "[XvMC] Could not create VL compositor.\n");
270
context_priv->decoder->destroy(context_priv->decoder);
271
pipe->destroy(pipe);
272
vscreen->destroy(vscreen);
273
FREE(context_priv);
274
return BadAlloc;
275
}
276
277
if (!vl_compositor_init_state(&context_priv->cstate, pipe)) {
278
XVMC_MSG(XVMC_ERR, "[XvMC] Could not create VL compositor state.\n");
279
vl_compositor_cleanup(&context_priv->compositor);
280
context_priv->decoder->destroy(context_priv->decoder);
281
pipe->destroy(pipe);
282
vscreen->destroy(vscreen);
283
FREE(context_priv);
284
return BadAlloc;
285
}
286
287
288
context_priv->color_standard =
289
debug_get_bool_option("G3DVL_NO_CSC", FALSE) ?
290
VL_CSC_COLOR_STANDARD_IDENTITY : VL_CSC_COLOR_STANDARD_BT_601;
291
context_priv->procamp = vl_default_procamp;
292
293
vl_csc_get_matrix
294
(
295
context_priv->color_standard,
296
&context_priv->procamp, true, &csc
297
);
298
vl_compositor_set_csc_matrix(&context_priv->cstate, (const vl_csc_matrix *)&csc, 1.0f, 0.0f);
299
300
context_priv->vscreen = vscreen;
301
context_priv->pipe = pipe;
302
context_priv->subpicture_max_width = subpic_max_w;
303
context_priv->subpicture_max_height = subpic_max_h;
304
305
context->context_id = XAllocID(dpy);
306
context->surface_type_id = surface_type_id;
307
context->width = width;
308
context->height = height;
309
context->flags = flags;
310
context->port = port;
311
context->privData = context_priv;
312
313
SyncHandle();
314
315
XVMC_MSG(XVMC_TRACE, "[XvMC] Context %p created.\n", context);
316
317
return Success;
318
}
319
320
PUBLIC
321
Status XvMCDestroyContext(Display *dpy, XvMCContext *context)
322
{
323
XvMCContextPrivate *context_priv;
324
325
XVMC_MSG(XVMC_TRACE, "[XvMC] Destroying context %p.\n", context);
326
327
assert(dpy);
328
329
if (!context || !context->privData)
330
return XvMCBadContext;
331
332
context_priv = context->privData;
333
context_priv->decoder->destroy(context_priv->decoder);
334
vl_compositor_cleanup_state(&context_priv->cstate);
335
vl_compositor_cleanup(&context_priv->compositor);
336
context_priv->pipe->destroy(context_priv->pipe);
337
context_priv->vscreen->destroy(context_priv->vscreen);
338
FREE(context_priv);
339
context->privData = NULL;
340
341
XVMC_MSG(XVMC_TRACE, "[XvMC] Context %p destroyed.\n", context);
342
343
return Success;
344
}
345
346