Array bound check
[platform/upstream/libva.git] / va / egl / va_egl.c
1 /*
2  * Copyright (c) 2007 Intel Corporation. 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 /*
26  * Initial EGL backend, and subject to change
27  *
28  * Gstreamer gst-gltexture has a framework to support associating a buffer
29  * to a texture via EGL_KHR_image_base and GL_OES_EGL_image_external.
30  *
31  * EGL_KHR_image_base:
32  *   EGLImageKHR eglCreateImageKHR(
33  *                           EGLDisplay dpy,
34  *                           EGLContext ctx,
35  *                           EGLenum target,
36  *                           EGLClientBuffer buffer,
37  *                           const EGLint *attrib_list)
38  *
39  * GL_OES_EGL_image_external:
40  * This extension provides a mechanism for creating EGLImage texture targets
41  * from EGLImages.  This extension defines a new texture target TEXTURE_EXTERNAL_OES.
42  * This texture target can only be specified using an EGLImage.
43  * The first eglCreateImageKHR will create an EGLImage from an EGLClientBufferm, and with
44  * an EGLImage, gst-gltexture can use GL_OES_EGL_image_external extension to create textures.
45  *
46  * eglCreateImageKHR and GL_OES_EGL_image_external are all called directly from gst-gltexture,
47  * thus the simplest way to support gst-gltexture is defining a new API to pass EGLClientBuffer
48  * to gst-gltexture.
49  *
50  * EGLClientBuffer is gfx/video driver implementation specific (?). It means we need to pass up
51  * the low-level buffer ID (or handle) of the decoded surface to gst-gltexture, and gst-gltexture
52  * then pass down it to gfx driver.  
53  *
54  * Bellow API vaGetEGLClientBufferFromSurface is for this purpose
55  */
56 #include "va_egl_private.h"
57 #include "va_egl_impl.h"
58
59 #define CTX(dpy) (((VADisplayContextP)dpy)->pDriverContext)
60 #define CHECK_DISPLAY(dpy) if( !vaDisplayIsValid(dpy) ) { return VA_STATUS_ERROR_INVALID_DISPLAY; }
61
62 #define INIT_CONTEXT(ctx, dpy) do {                             \
63         if (!vaDisplayIsValid(dpy))                             \
64             return VA_STATUS_ERROR_INVALID_DISPLAY;             \
65                                                                 \
66         ctx = ((VADisplayContextP)(dpy))->pDriverContext;       \
67         if (!(ctx))                                             \
68             return VA_STATUS_ERROR_INVALID_DISPLAY;             \
69                                                                 \
70         status = va_egl_init_context(dpy);                      \
71         if (status != VA_STATUS_SUCCESS)                        \
72             return status;                                      \
73     } while (0)
74
75 #define INVOKE(ctx, func, args) do {                            \
76         VADriverVTablePrivEGLP vtable;                          \
77         vtable = &VA_DRIVER_CONTEXT_EGL(ctx)->vtable;           \
78         if (!vtable->va##func##EGL)                             \
79             return VA_STATUS_ERROR_UNIMPLEMENTED;               \
80         status = vtable->va##func##EGL args;                    \
81     } while (0)
82
83
84 VAStatus vaGetEGLClientBufferFromSurface (
85     VADisplay dpy,
86     VASurfaceID surface,
87     EGLClientBuffer *buffer /* out*/
88 )
89 {
90   VADriverContextP ctx;
91   struct VADriverVTableEGL *va_egl;
92   CHECK_DISPLAY(dpy);
93   ctx = CTX(dpy);
94
95   va_egl = (struct VADriverVTableEGL *)ctx->vtable_egl;
96   if (va_egl && va_egl->vaGetEGLClientBufferFromSurface) {
97       return va_egl->vaGetEGLClientBufferFromSurface(ctx, surface, buffer);
98   } else
99       return VA_STATUS_ERROR_UNIMPLEMENTED;
100 }
101   
102 // Destroy VA/EGL display context
103 static void va_DisplayContextDestroy(VADisplayContextP pDisplayContext)
104 {
105     VADisplayContextEGLP pDisplayContextEGL;
106     VADriverContextP     pDriverContext;
107     VADriverContextEGLP  pDriverContextEGL;
108
109     if (!pDisplayContext)
110         return;
111
112     pDriverContext     = pDisplayContext->pDriverContext;
113     pDriverContextEGL  = pDriverContext->egl;
114     if (pDriverContextEGL) {
115         free(pDriverContextEGL);
116         pDriverContext->egl = NULL;
117     }
118
119     pDisplayContextEGL = pDisplayContext->opaque;
120     if (pDisplayContextEGL) {
121         vaDestroyFunc vaDestroy = pDisplayContextEGL->vaDestroy;
122         free(pDisplayContextEGL);
123         pDisplayContext->opaque = NULL;
124         if (vaDestroy)
125             vaDestroy(pDisplayContext);
126     }
127 }
128
129 // Return a suitable VADisplay for VA API
130 VADisplay vaGetDisplayEGL(VANativeDisplay native_dpy,
131                           EGLDisplay egl_dpy)
132 {
133     VADisplay            dpy                = NULL;
134     VADisplayContextP    pDisplayContext    = NULL;
135     VADisplayContextEGLP pDisplayContextEGL = NULL;
136     VADriverContextP     pDriverContext;
137     VADriverContextEGLP  pDriverContextEGL  = NULL;
138
139     dpy = vaGetDisplay(native_dpy);
140
141     if (!dpy)
142         return NULL;
143
144     if (egl_dpy == EGL_NO_DISPLAY)
145         goto error;
146
147     pDisplayContext = (VADisplayContextP)dpy;
148     pDriverContext  = pDisplayContext->pDriverContext;
149
150     pDisplayContextEGL = calloc(1, sizeof(*pDisplayContextEGL));
151     if (!pDisplayContextEGL)
152         goto error;
153
154     pDriverContextEGL = calloc(1, sizeof(*pDriverContextEGL));
155     if (!pDriverContextEGL)
156         goto error;
157
158     pDisplayContextEGL->vaDestroy = pDisplayContext->vaDestroy;
159     pDisplayContext->vaDestroy = va_DisplayContextDestroy;
160     pDisplayContext->opaque = pDisplayContextEGL;
161     pDriverContextEGL->egl_display = egl_dpy;
162     pDriverContext->egl = pDriverContextEGL;
163     return dpy;
164
165 error:
166     free(pDriverContextEGL);
167     free(pDisplayContextEGL);
168     pDisplayContext->vaDestroy(pDisplayContext);
169     return NULL;
170 }
171
172 int vaMaxNumSurfaceTargetsEGL(
173     VADisplay dpy
174 )
175 {
176     VADriverContextP ctx;
177     struct VADriverVTableEGL *va_egl;
178     CHECK_DISPLAY(dpy);
179     ctx = CTX(dpy);
180
181     va_egl = (struct VADriverVTableEGL *)ctx->vtable_egl;
182
183     if (va_egl)
184         return va_egl->max_egl_surface_targets;
185     else
186         return IMPL_MAX_EGL_SURFACE_TARGETS;
187 }
188
189 int vaMaxNumSurfaceAttributesEGL(
190     VADisplay dpy
191 )
192 {
193     VADriverContextP ctx;
194     struct VADriverVTableEGL *va_egl;
195     CHECK_DISPLAY(dpy);
196     ctx = CTX(dpy);
197
198     va_egl = (struct VADriverVTableEGL *)ctx->vtable_egl;
199
200     if (va_egl)
201         return va_egl->max_egl_surface_attributes;
202     else
203         return IMPL_MAX_EGL_SURFACE_ATTRIBUTES;
204 }
205
206 VAStatus vaQuerySurfaceTargetsEGL(
207     VADisplay dpy,
208     EGLenum *target_list,       /* out */
209     int *num_targets            /* out */
210 )
211 {
212     VADriverContextP ctx;
213     VAStatus status;
214
215     INIT_CONTEXT(ctx, dpy);
216
217     INVOKE(ctx, QuerySurfaceTargets, (dpy, target_list, num_targets));
218     return status;
219 }
220
221 VAStatus vaCreateSurfaceEGL(
222     VADisplay dpy,
223     EGLenum target,
224     unsigned int width,
225     unsigned int height,
226     VASurfaceEGL *gl_surface
227 )
228 {
229     VADriverContextP ctx;
230     VAStatus status;
231
232     INIT_CONTEXT(ctx, dpy);
233
234     INVOKE(ctx, CreateSurface, (dpy, target, width, height, gl_surface));
235     return status;
236 }
237
238 // Destroy a VA/EGL surface
239 VAStatus vaDestroySurfaceEGL(
240     VADisplay dpy,
241     VASurfaceEGL egl_surface
242 )
243 {
244     VADriverContextP ctx;
245     VAStatus status;
246
247     INIT_CONTEXT(ctx, dpy);
248
249     INVOKE(ctx, DestroySurface, (dpy, egl_surface));
250     return status;
251 }
252
253 VAStatus vaAssociateSurfaceEGL(
254     VADisplay dpy,
255     VASurfaceEGL egl_surface,
256     VASurfaceID surface,
257     unsigned int flags
258 )
259 {
260     VADriverContextP ctx;
261     VAStatus status;
262
263     INIT_CONTEXT(ctx, dpy);
264
265     INVOKE(ctx, AssociateSurface, (dpy, egl_surface, surface, flags));
266     return status;
267 }
268
269 VAStatus vaSyncSurfaceEGL(
270     VADisplay dpy,
271     VASurfaceEGL egl_surface
272 )
273 {
274     VADriverContextP ctx;
275     VAStatus status;
276
277     INIT_CONTEXT(ctx, dpy);
278
279     INVOKE(ctx, SyncSurface, (dpy, egl_surface));
280     return status;
281 }
282
283 VAStatus vaGetSurfaceInfoEGL(
284     VADisplay dpy,
285     VASurfaceEGL egl_surface,
286     EGLenum *target,            /* out, the type of <buffer> */
287     EGLClientBuffer *buffer,    /* out */
288     EGLint *attrib_list,        /* out, the last attribute must be EGL_NONE */
289     int *num_attribs            /* in/out */
290 )
291 {
292     VADriverContextP ctx;
293     VAStatus status;
294
295     INIT_CONTEXT(ctx, dpy);
296
297     INVOKE(ctx, GetSurfaceInfo, (dpy, egl_surface, target, buffer, attrib_list, num_attribs));
298     return status;
299 }
300
301 VAStatus vaDeassociateSurfaceEGL(
302     VADisplay dpy,
303     VASurfaceEGL egl_surface
304 )
305 {
306     VADriverContextP ctx;
307     VAStatus status;
308
309     INIT_CONTEXT(ctx, dpy);
310
311     INVOKE(ctx, DeassociateSurface, (dpy, egl_surface));
312     return status;
313 }
314