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 "sysdeps.h"
26 #include <stdlib.h>
27 #include "va_glx_private.h"
28 #include "va_glx_impl.h"
29 
30 #define INIT_CONTEXT(ctx, dpy) do {                             \
31         if (!vaDisplayIsValid(dpy))                             \
32             return VA_STATUS_ERROR_INVALID_DISPLAY;             \
33                                                                 \
34         ctx = ((VADisplayContextP)(dpy))->pDriverContext;       \
35         if (!(ctx))                                             \
36             return VA_STATUS_ERROR_INVALID_DISPLAY;             \
37                                                                 \
38         VAStatus status = va_glx_init_context(ctx);             \
39         if (status != VA_STATUS_SUCCESS)                        \
40             return status;                                      \
41     } while (0)
42 
43 #define INVOKE(ctx, func, args) do {                            \
44         VADriverVTableGLXP vtable;                              \
45         vtable = &VA_DRIVER_CONTEXT_GLX(ctx)->vtable;           \
46         if (!vtable->va##func##GLX)                             \
47             return VA_STATUS_ERROR_UNIMPLEMENTED;               \
48         status = vtable->va##func##GLX args;                    \
49     } while (0)
50 
51 
52 // Destroy VA/GLX display context
va_DisplayContextDestroy(VADisplayContextP pDisplayContext)53 static void va_DisplayContextDestroy(VADisplayContextP pDisplayContext)
54 {
55     VADisplayContextGLXP pDisplayContextGLX;
56     VADriverContextP     pDriverContext;
57     VADriverContextGLXP  pDriverContextGLX;
58 
59     if (!pDisplayContext)
60         return;
61 
62     pDriverContext     = pDisplayContext->pDriverContext;
63     pDriverContextGLX  = pDriverContext->glx;
64     if (pDriverContextGLX) {
65         free(pDriverContextGLX);
66         pDriverContext->glx = NULL;
67     }
68 
69     pDisplayContextGLX = pDisplayContext->opaque;
70     if (pDisplayContextGLX) {
71         vaDestroyFunc vaDestroy = pDisplayContextGLX->vaDestroy;
72         free(pDisplayContextGLX);
73         pDisplayContext->opaque = NULL;
74         if (vaDestroy)
75             vaDestroy(pDisplayContext);
76     }
77 }
78 
79 // Return a suitable VADisplay for VA API
vaGetDisplayGLX(Display * native_dpy)80 VADisplay vaGetDisplayGLX(Display *native_dpy)
81 {
82     VADisplay            dpy                = NULL;
83     VADisplayContextP    pDisplayContext    = NULL;
84     VADisplayContextGLXP pDisplayContextGLX = NULL;
85     VADriverContextP     pDriverContext;
86     VADriverContextGLXP  pDriverContextGLX  = NULL;
87 
88     dpy = vaGetDisplay(native_dpy);
89     if (!dpy)
90         return NULL;
91     pDisplayContext = (VADisplayContextP)dpy;
92     pDriverContext  = pDisplayContext->pDriverContext;
93 
94     pDisplayContextGLX = calloc(1, sizeof(*pDisplayContextGLX));
95     if (!pDisplayContextGLX)
96         goto error;
97 
98     pDriverContextGLX = calloc(1, sizeof(*pDriverContextGLX));
99     if (!pDriverContextGLX)
100         goto error;
101 
102     pDriverContext->display_type  = VA_DISPLAY_GLX;
103     pDisplayContextGLX->vaDestroy = pDisplayContext->vaDestroy;
104     pDisplayContext->vaDestroy    = va_DisplayContextDestroy;
105     pDisplayContext->opaque       = pDisplayContextGLX;
106     pDriverContext->glx           = pDriverContextGLX;
107     return dpy;
108 
109 error:
110     free(pDriverContextGLX);
111     free(pDisplayContextGLX);
112     pDisplayContext->vaDestroy(pDisplayContext);
113     return NULL;
114 }
115 
116 // Create a surface used for display to OpenGL
vaCreateSurfaceGLX(VADisplay dpy,GLenum target,GLuint texture,void ** gl_surface)117 VAStatus vaCreateSurfaceGLX(
118     VADisplay dpy,
119     GLenum    target,
120     GLuint    texture,
121     void    **gl_surface
122 )
123 {
124     VADriverContextP ctx;
125     VAStatus status;
126 
127     /* Make sure it is a valid GL texture object */
128     if (!glIsTexture(texture))
129         return VA_STATUS_ERROR_INVALID_PARAMETER;
130 
131     INIT_CONTEXT(ctx, dpy);
132 
133     INVOKE(ctx, CreateSurface, (ctx, target, texture, gl_surface));
134     return status;
135 }
136 
137 // Destroy a VA/GLX surface
vaDestroySurfaceGLX(VADisplay dpy,void * gl_surface)138 VAStatus vaDestroySurfaceGLX(
139     VADisplay dpy,
140     void     *gl_surface
141 )
142 {
143     VADriverContextP ctx;
144     VAStatus status;
145 
146     INIT_CONTEXT(ctx, dpy);
147 
148     INVOKE(ctx, DestroySurface, (ctx, gl_surface));
149     return status;
150 }
151 
152 // Copy a VA surface to a VA/GLX surface
vaCopySurfaceGLX(VADisplay dpy,void * gl_surface,VASurfaceID surface,unsigned int flags)153 VAStatus vaCopySurfaceGLX(
154     VADisplay    dpy,
155     void        *gl_surface,
156     VASurfaceID  surface,
157     unsigned int flags
158 )
159 {
160     VADriverContextP ctx;
161     VAStatus status;
162 
163     INIT_CONTEXT(ctx, dpy);
164 
165     INVOKE(ctx, CopySurface, (ctx, gl_surface, surface, flags));
166     return status;
167 }
168