2
* vdpau_driver.c - VDPAU driver
4
* vdpau-video (C) 2009-2010 Splitted-Desktop Systems
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22
#include "vdpau_driver.h"
23
#include "vdpau_buffer.h"
24
#include "vdpau_decode.h"
25
#include "vdpau_image.h"
26
#include "vdpau_subpic.h"
27
#include "vdpau_mixer.h"
28
#include "vdpau_video.h"
29
#include "vdpau_video_x11.h"
31
#include "vdpau_video_glx.h"
38
// Check for VA/GLX changes from libVA API >= 0.31.0-sds2
39
#if VA_CHECK_VERSION(0,31,1) || (VA_CHECK_VERSION(0,31,0) && VA_SDS_VERSION >= 2)
40
#define VA_DRIVER_VTABLE_GLX(ctx) (&(ctx)->vtable.glx)
41
typedef struct VADriverVTableGLX *VADriverVTableGLXP;
43
#define VA_DRIVER_VTABLE_GLX(ctx) (&(ctx)->vtable)
44
typedef struct VADriverVTable *VADriverVTableGLXP;
47
// Return TRUE if underlying VDPAU implementation is NVIDIA
49
vdpau_is_nvidia(vdpau_driver_data_t *driver_data, int *major, int *minor)
51
uint32_t nvidia_version = 0;
53
if (driver_data->vdp_impl_type == VDP_IMPLEMENTATION_NVIDIA)
54
nvidia_version = driver_data->vdp_impl_version;
56
*major = nvidia_version >> 16;
58
*minor = nvidia_version & 0xffff;
59
return nvidia_version != 0;
62
// Translate VdpStatus to an appropriate VAStatus
64
vdpau_get_VAStatus(vdpau_driver_data_t *driver_data, VdpStatus vdp_status)
67
const char *vdp_status_string;
71
va_status = VA_STATUS_SUCCESS;
73
case VDP_STATUS_NO_IMPLEMENTATION:
74
va_status = VA_STATUS_ERROR_UNIMPLEMENTED;
76
case VDP_STATUS_INVALID_CHROMA_TYPE:
77
va_status = VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT;
79
case VDP_STATUS_INVALID_DECODER_PROFILE:
80
va_status = VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
82
case VDP_STATUS_RESOURCES:
83
va_status = VA_STATUS_ERROR_ALLOCATION_FAILED;
86
vdp_status_string = vdpau_get_error_string(driver_data, vdp_status);
87
D(bug("WARNING: unknown VdpStatus %d: %s\n", vdp_status,
88
vdp_status_string ? vdp_status_string : "<unknown error>"));
89
va_status = VA_STATUS_ERROR_UNKNOWN;
95
// Destroy BUFFER objects
96
static void destroy_buffer_cb(object_base_p obj, void *user_data)
98
object_buffer_p const obj_buffer = (object_buffer_p)obj;
99
vdpau_driver_data_t * const driver_data = user_data;
101
destroy_va_buffer(driver_data, obj_buffer);
104
// Destroy MIXER objects
105
static void destroy_mixer_cb(object_base_p obj, void *user_data)
107
object_mixer_p const obj_mixer = (object_mixer_p)obj;
108
vdpau_driver_data_t * const driver_data = user_data;
110
video_mixer_destroy(driver_data, obj_mixer);
113
// Destroy object heap
114
typedef void (*destroy_heap_func_t)(object_base_p obj, void *user_data);
120
destroy_heap_func_t destroy_func,
125
object_heap_iterator iter;
130
obj = object_heap_first(heap, &iter);
132
vdpau_information_message("vaTerminate(): %s ID 0x%08x is still allocated, destroying\n", name, obj->id);
134
destroy_func(obj, user_data);
136
object_heap_free(heap, obj);
137
obj = object_heap_next(heap, &iter);
139
object_heap_destroy(heap);
142
#define DESTROY_HEAP(heap, func) \
143
destroy_heap(#heap, &driver_data->heap##_heap, func, driver_data)
145
#define CREATE_HEAP(type, id) do { \
146
int result = object_heap_init(&driver_data->type##_heap, \
147
sizeof(struct object_##type), \
148
VDPAU_##id##_ID_OFFSET); \
149
ASSERT(result == 0); \
151
return VA_STATUS_ERROR_UNKNOWN; \
155
static VAStatus vdpau_Terminate(VADriverContextP ctx)
157
VDPAU_DRIVER_DATA_INIT;
159
DESTROY_HEAP(buffer, destroy_buffer_cb);
160
DESTROY_HEAP(image, NULL);
161
DESTROY_HEAP(subpicture, NULL);
162
DESTROY_HEAP(output, NULL);
163
DESTROY_HEAP(surface, NULL);
164
DESTROY_HEAP(context, NULL);
165
DESTROY_HEAP(config, NULL);
166
DESTROY_HEAP(mixer, destroy_mixer_cb);
168
DESTROY_HEAP(glx_surface, NULL);
171
free(driver_data->gl_data);
172
vdpau_gate_exit(driver_data);
174
free(ctx->pDriverData);
175
ctx->pDriverData = NULL;
177
return VA_STATUS_SUCCESS;
181
static VAStatus vdpau_do_Initialize(VADriverContextP ctx)
183
VDPAU_DRIVER_DATA_INIT;
185
VdpStatus vdp_status;
186
vdp_status = vdp_device_create_x11(ctx->x11_dpy, ctx->x11_screen,
187
&driver_data->vdp_device,
188
&driver_data->vdp_get_proc_address);
189
ASSERT(vdp_status == VDP_STATUS_OK);
190
if (vdp_status != VDP_STATUS_OK)
191
return VA_STATUS_ERROR_UNKNOWN;
193
if (vdpau_gate_init(driver_data) < 0)
194
return VA_STATUS_ERROR_UNKNOWN;
196
uint32_t api_version;
197
vdp_status = vdpau_get_api_version(driver_data, &api_version);
198
ASSERT(vdp_status == VDP_STATUS_OK);
199
if (vdp_status != VDP_STATUS_OK)
200
return vdpau_get_VAStatus(driver_data, vdp_status);
201
if (api_version != VDPAU_VERSION)
202
return VA_STATUS_ERROR_UNKNOWN;
204
const char *impl_string = NULL;
205
vdp_status = vdpau_get_information_string(driver_data, &impl_string);
206
ASSERT(vdp_status == VDP_STATUS_OK);
207
if (vdp_status != VDP_STATUS_OK)
208
return vdpau_get_VAStatus(driver_data, vdp_status);
210
/* XXX: set impl_type and impl_version if there is any useful info */
213
CREATE_HEAP(config, CONFIG);
214
CREATE_HEAP(context, CONTEXT);
215
CREATE_HEAP(surface, SURFACE);
216
CREATE_HEAP(buffer, BUFFER);
217
CREATE_HEAP(output, OUTPUT);
218
CREATE_HEAP(image, IMAGE);
219
CREATE_HEAP(subpicture, SUBPICTURE);
220
CREATE_HEAP(mixer, MIXER);
222
CREATE_HEAP(glx_surface, GLX_SURFACE);
225
static char vendor[256] = {0, };
226
if (vendor[0] == '\0')
227
sprintf(vendor, "%s %s - %d.%d.%d",
228
VDPAU_STR_DRIVER_VENDOR,
229
VDPAU_STR_DRIVER_NAME,
230
VDPAU_VIDEO_MAJOR_VERSION,
231
VDPAU_VIDEO_MINOR_VERSION,
232
VDPAU_VIDEO_MICRO_VERSION);
234
ctx->version_major = VA_MAJOR_VERSION;
235
ctx->version_minor = VA_MINOR_VERSION;
236
ctx->max_profiles = VDPAU_MAX_PROFILES;
237
ctx->max_entrypoints = VDPAU_MAX_ENTRYPOINTS;
238
ctx->max_attributes = VDPAU_MAX_CONFIG_ATTRIBUTES;
239
ctx->max_image_formats = VDPAU_MAX_IMAGE_FORMATS;
240
ctx->max_subpic_formats = VDPAU_MAX_SUBPICTURE_FORMATS;
241
ctx->max_display_attributes = VDPAU_MAX_DISPLAY_ATTRIBUTES;
242
ctx->str_vendor = vendor;
244
ctx->vtable.vaTerminate = vdpau_Terminate;
245
ctx->vtable.vaQueryConfigEntrypoints = vdpau_QueryConfigEntrypoints;
246
ctx->vtable.vaQueryConfigProfiles = vdpau_QueryConfigProfiles;
247
ctx->vtable.vaQueryConfigEntrypoints = vdpau_QueryConfigEntrypoints;
248
ctx->vtable.vaQueryConfigAttributes = vdpau_QueryConfigAttributes;
249
ctx->vtable.vaCreateConfig = vdpau_CreateConfig;
250
ctx->vtable.vaDestroyConfig = vdpau_DestroyConfig;
251
ctx->vtable.vaGetConfigAttributes = vdpau_GetConfigAttributes;
252
ctx->vtable.vaCreateSurfaces = vdpau_CreateSurfaces;
253
ctx->vtable.vaDestroySurfaces = vdpau_DestroySurfaces;
254
ctx->vtable.vaCreateContext = vdpau_CreateContext;
255
ctx->vtable.vaDestroyContext = vdpau_DestroyContext;
256
ctx->vtable.vaCreateBuffer = vdpau_CreateBuffer;
257
ctx->vtable.vaBufferSetNumElements = vdpau_BufferSetNumElements;
258
ctx->vtable.vaMapBuffer = vdpau_MapBuffer;
259
ctx->vtable.vaUnmapBuffer = vdpau_UnmapBuffer;
260
ctx->vtable.vaDestroyBuffer = vdpau_DestroyBuffer;
261
ctx->vtable.vaBeginPicture = vdpau_BeginPicture;
262
ctx->vtable.vaRenderPicture = vdpau_RenderPicture;
263
ctx->vtable.vaEndPicture = vdpau_EndPicture;
264
#if VA_CHECK_VERSION(0,31,0)
265
ctx->vtable.vaSyncSurface = vdpau_SyncSurface2;
267
ctx->vtable.vaSyncSurface = vdpau_SyncSurface3;
269
ctx->vtable.vaQuerySurfaceStatus = vdpau_QuerySurfaceStatus;
270
ctx->vtable.vaPutSurface = vdpau_PutSurface;
271
ctx->vtable.vaQueryImageFormats = vdpau_QueryImageFormats;
272
ctx->vtable.vaCreateImage = vdpau_CreateImage;
273
ctx->vtable.vaDeriveImage = vdpau_DeriveImage;
274
ctx->vtable.vaDestroyImage = vdpau_DestroyImage;
275
ctx->vtable.vaSetImagePalette = vdpau_SetImagePalette;
276
ctx->vtable.vaGetImage = vdpau_GetImage;
277
#if VA_CHECK_VERSION(0,31,0)
278
ctx->vtable.vaPutImage = vdpau_PutImage_full;
280
ctx->vtable.vaPutImage = vdpau_PutImage;
281
ctx->vtable.vaPutImage2 = vdpau_PutImage_full;
283
ctx->vtable.vaQuerySubpictureFormats = vdpau_QuerySubpictureFormats;
284
ctx->vtable.vaCreateSubpicture = vdpau_CreateSubpicture;
285
ctx->vtable.vaDestroySubpicture = vdpau_DestroySubpicture;
286
ctx->vtable.vaSetSubpictureImage = vdpau_SetSubpictureImage;
287
ctx->vtable.vaSetSubpictureChromakey = vdpau_SetSubpictureChromakey;
288
ctx->vtable.vaSetSubpictureGlobalAlpha = vdpau_SetSubpictureGlobalAlpha;
289
#if VA_CHECK_VERSION(0,31,0)
290
ctx->vtable.vaAssociateSubpicture = vdpau_AssociateSubpicture_full;
292
ctx->vtable.vaAssociateSubpicture = vdpau_AssociateSubpicture;
293
ctx->vtable.vaAssociateSubpicture2 = vdpau_AssociateSubpicture_full;
295
ctx->vtable.vaDeassociateSubpicture = vdpau_DeassociateSubpicture;
296
ctx->vtable.vaQueryDisplayAttributes = vdpau_QueryDisplayAttributes;
297
ctx->vtable.vaGetDisplayAttributes = vdpau_GetDisplayAttributes;
298
ctx->vtable.vaSetDisplayAttributes = vdpau_SetDisplayAttributes;
299
#if VA_CHECK_VERSION(0,30,0)
300
ctx->vtable.vaCreateSurfaceFromCIFrame = vdpau_CreateSurfaceFromCIFrame;
301
ctx->vtable.vaCreateSurfaceFromV4L2Buf = vdpau_CreateSurfaceFromV4L2Buf;
302
ctx->vtable.vaCopySurfaceToBuffer = vdpau_CopySurfaceToBuffer;
304
ctx->vtable.vaSetSubpicturePalette = vdpau_SetSubpicturePalette;
305
ctx->vtable.vaDbgCopySurfaceToBuffer = vdpau_DbgCopySurfaceToBuffer;
309
VADriverVTableGLXP const glx_vtable = VA_DRIVER_VTABLE_GLX(ctx);
310
glx_vtable->vaCreateSurfaceGLX = vdpau_CreateSurfaceGLX;
311
glx_vtable->vaDestroySurfaceGLX = vdpau_DestroySurfaceGLX;
312
glx_vtable->vaAssociateSurfaceGLX = vdpau_AssociateSurfaceGLX;
313
glx_vtable->vaDeassociateSurfaceGLX = vdpau_DeassociateSurfaceGLX;
314
glx_vtable->vaSyncSurfaceGLX = vdpau_SyncSurfaceGLX;
315
glx_vtable->vaBeginRenderSurfaceGLX = vdpau_BeginRenderSurfaceGLX;
316
glx_vtable->vaEndRenderSurfaceGLX = vdpau_EndRenderSurfaceGLX;
317
glx_vtable->vaCopySurfaceGLX = vdpau_CopySurfaceGLX;
320
return VA_STATUS_SUCCESS;
323
static VAStatus vdpau_Initialize(VADriverContextP ctx)
325
struct vdpau_driver_data *driver_data;
327
driver_data = (struct vdpau_driver_data *)calloc(1, sizeof(*driver_data));
329
return VA_STATUS_ERROR_ALLOCATION_FAILED;
330
ctx->pDriverData = (void *)driver_data;
331
driver_data->va_context = ctx;
333
VAStatus va_status = vdpau_do_Initialize(ctx);
334
if (va_status != VA_STATUS_SUCCESS)
335
vdpau_Terminate(ctx);
339
VAStatus VA_DRIVER_INIT_FUNC(VADriverContextP ctx)
341
return vdpau_Initialize(ctx);