1 /*
2  * Copyright (C) 2009 Splitted-Desktop Systems. All Rights Reserved.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the
6  * "Software"), to deal in the Software without restriction, including
7  * without limitation the rights to use, copy, modify, merge, publish,
8  * distribute, sub license, and/or sell copies of the Software, and to
9  * permit persons to whom the Software is furnished to do so, subject to
10  * the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the
13  * next paragraph) shall be included in all copies or substantial portions
14  * of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
19  * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
20  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */
24 
25 #include <stdlib.h>
26 #include "va_glx_private.h"
27 #include "va_glx_impl.h"
28 
29 #define INIT_CONTEXT(ctx, dpy) do {                             \
30         if (!vaDisplayIsValid(dpy))                             \
31             return VA_STATUS_ERROR_INVALID_DISPLAY;             \
32                                                                 \
33         ctx = ((VADisplayContextP)(dpy))->pDriverContext;       \
34         if (!(ctx))                                             \
35             return VA_STATUS_ERROR_INVALID_DISPLAY;             \
36                                                                 \
37         VAStatus status = va_glx_init_context(ctx);             \
38         if (status != VA_STATUS_SUCCESS)                        \
39             return status;                                      \
40     } while (0)
41 
42 #define INVOKE(ctx, func, args) do {                            \
43         VADriverVTableGLXP vtable;                              \
44         vtable = &VA_DRIVER_CONTEXT_GLX(ctx)->vtable;           \
45         if (!vtable->va##func##GLX)                             \
46             return VA_STATUS_ERROR_UNIMPLEMENTED;               \
47         status = vtable->va##func##GLX args;                    \
48     } while (0)
49 
50 
51 // Destroy VA/GLX display context
va_DisplayContextDestroy(VADisplayContextP pDisplayContext)52 static void va_DisplayContextDestroy(VADisplayContextP pDisplayContext)
53 {
54     VADisplayContextGLXP pDisplayContextGLX;
55     VADriverContextP     pDriverContext;
56     VADriverContextGLXP  pDriverContextGLX;
57 
58     if (!pDisplayContext)
59         return;
60 
61     pDriverContext     = pDisplayContext->pDriverContext;
62     pDriverContextGLX  = pDriverContext->glx;
63     if (pDriverContextGLX) {
64         free(pDriverContextGLX);
65         pDriverContext->glx = NULL;
66     }
67 
68     pDisplayContextGLX = pDisplayContext->opaque;
69     if (pDisplayContextGLX) {
70         vaDestroyFunc vaDestroy = pDisplayContextGLX->vaDestroy;
71         free(pDisplayContextGLX);
72         pDisplayContext->opaque = NULL;
73         if (vaDestroy)
74             vaDestroy(pDisplayContext);
75     }
76 }
77 
78 // Return a suitable VADisplay for VA API
vaGetDisplayGLX(Display * native_dpy)79 VADisplay vaGetDisplayGLX(Display *native_dpy)
80 {
81     VADisplay            dpy                = NULL;
82     VADisplayContextP    pDisplayContext    = NULL;
83     VADisplayContextGLXP pDisplayContextGLX = NULL;
84     VADriverContextP     pDriverContext;
85     VADriverContextGLXP  pDriverContextGLX  = NULL;
86 
87     dpy = vaGetDisplay(native_dpy);
88     if (!dpy)
89         return NULL;
90     pDisplayContext = (VADisplayContextP)dpy;
91     pDriverContext  = pDisplayContext->pDriverContext;
92 
93     pDisplayContextGLX = calloc(1, sizeof(*pDisplayContextGLX));
94     if (!pDisplayContextGLX)
95         goto error;
96 
97     pDriverContextGLX = calloc(1, sizeof(*pDriverContextGLX));
98     if (!pDriverContextGLX)
99         goto error;
100 
101     pDriverContext->display_type  = VA_DISPLAY_GLX;
102     pDisplayContextGLX->vaDestroy = pDisplayContext->vaDestroy;
103     pDisplayContext->vaDestroy    = va_DisplayContextDestroy;
104     pDisplayContext->opaque       = pDisplayContextGLX;
105     pDriverContext->glx           = pDriverContextGLX;
106     return dpy;
107 
108 error:
109     free(pDriverContextGLX);
110     free(pDisplayContextGLX);
111     pDisplayContext->vaDestroy(pDisplayContext);
112     return NULL;
113 }
114 
115 // Create a surface used for display to OpenGL
vaCreateSurfaceGLX(VADisplay dpy,GLenum target,GLuint texture,void ** gl_surface)116 VAStatus vaCreateSurfaceGLX(
117     VADisplay dpy,
118     GLenum    target,
119     GLuint    texture,
120     void    **gl_surface
121 )
122 {
123     VADriverContextP ctx;
124     VAStatus status;
125 
126     /* Make sure it is a valid GL texture object */
127     if (!glIsTexture(texture))
128         return VA_STATUS_ERROR_INVALID_PARAMETER;
129 
130     INIT_CONTEXT(ctx, dpy);
131 
132     INVOKE(ctx, CreateSurface, (ctx, target, texture, gl_surface));
133     return status;
134 }
135 
136 // Destroy a VA/GLX surface
vaDestroySurfaceGLX(VADisplay dpy,void * gl_surface)137 VAStatus vaDestroySurfaceGLX(
138     VADisplay dpy,
139     void     *gl_surface
140 )
141 {
142     VADriverContextP ctx;
143     VAStatus status;
144 
145     INIT_CONTEXT(ctx, dpy);
146 
147     INVOKE(ctx, DestroySurface, (ctx, gl_surface));
148     return status;
149 }
150 
151 // Copy a VA surface to a VA/GLX surface
vaCopySurfaceGLX(VADisplay dpy,void * gl_surface,VASurfaceID surface,unsigned int flags)152 VAStatus vaCopySurfaceGLX(
153     VADisplay    dpy,
154     void        *gl_surface,
155     VASurfaceID  surface,
156     unsigned int flags
157 )
158 {
159     VADriverContextP ctx;
160     VAStatus status;
161 
162     INIT_CONTEXT(ctx, dpy);
163 
164     INVOKE(ctx, CopySurface, (ctx, gl_surface, surface, flags));
165     return status;
166 }
167