1 /**************************************************************************
2  *
3  * Copyright 2009-2010 Chia-I Wu <olvaffe@gmail.com>
4  * Copyright 2010-2011 LunarG, Inc.
5  * All Rights Reserved.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a
8  * copy of this software and associated documentation files (the
9  * "Software"), to deal in the Software without restriction, including
10  * without limitation the rights to use, copy, modify, merge, publish,
11  * distribute, sub license, and/or sell copies of the Software, and to
12  * permit persons to whom the Software is furnished to do so, subject to
13  * the following conditions:
14  *
15  * The above copyright notice and this permission notice (including the
16  * next paragraph) shall be included in all copies or substantial portions
17  * of the Software.
18  *
19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
22  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25  * DEALINGS IN THE SOFTWARE.
26  *
27  **************************************************************************/
28 
29 
30 #include <assert.h>
31 #include <string.h>
32 
33 #include "eglcurrent.h"
34 #include "eglimage.h"
35 #include "egllog.h"
36 
37 static EGLint
_eglParseKHRImageAttribs(_EGLImageAttribs * attrs,_EGLDisplay * dpy,EGLint attr,EGLint val)38 _eglParseKHRImageAttribs(_EGLImageAttribs *attrs, _EGLDisplay *dpy,
39                          EGLint attr, EGLint val)
40 {
41    switch (attr) {
42    case EGL_IMAGE_PRESERVED_KHR:
43       if (!dpy->Extensions.KHR_image_base)
44          return EGL_BAD_PARAMETER;
45 
46       attrs->ImagePreserved = val;
47       break;
48 
49    case EGL_GL_TEXTURE_LEVEL_KHR:
50       if (!dpy->Extensions.KHR_gl_texture_2D_image)
51          return EGL_BAD_PARAMETER;
52 
53       attrs->GLTextureLevel = val;
54       break;
55    case EGL_GL_TEXTURE_ZOFFSET_KHR:
56       if (!dpy->Extensions.KHR_gl_texture_3D_image)
57          return EGL_BAD_PARAMETER;
58 
59       attrs->GLTextureZOffset = val;
60       break;
61    default:
62       return EGL_BAD_PARAMETER;
63    }
64 
65    return EGL_SUCCESS;
66 }
67 
68 static EGLint
_eglParseMESADrmImageAttribs(_EGLImageAttribs * attrs,_EGLDisplay * dpy,EGLint attr,EGLint val)69 _eglParseMESADrmImageAttribs(_EGLImageAttribs *attrs, _EGLDisplay *dpy,
70                              EGLint attr, EGLint val)
71 {
72    if (!dpy->Extensions.MESA_drm_image)
73       return EGL_BAD_PARAMETER;
74 
75    switch (attr) {
76    case EGL_WIDTH:
77       attrs->Width = val;
78       break;
79    case EGL_HEIGHT:
80       attrs->Height = val;
81       break;
82    case EGL_DRM_BUFFER_FORMAT_MESA:
83       attrs->DRMBufferFormatMESA = val;
84       break;
85    case EGL_DRM_BUFFER_USE_MESA:
86       attrs->DRMBufferUseMESA = val;
87       break;
88    case EGL_DRM_BUFFER_STRIDE_MESA:
89       attrs->DRMBufferStrideMESA = val;
90       break;
91    default:
92       return EGL_BAD_PARAMETER;
93    }
94 
95    return EGL_SUCCESS;
96 }
97 
98 static EGLint
_eglParseWLBindWaylandDisplayAttribs(_EGLImageAttribs * attrs,_EGLDisplay * dpy,EGLint attr,EGLint val)99 _eglParseWLBindWaylandDisplayAttribs(_EGLImageAttribs *attrs, _EGLDisplay *dpy,
100                                      EGLint attr, EGLint val)
101 {
102    if (!dpy->Extensions.WL_bind_wayland_display)
103       return EGL_BAD_PARAMETER;
104 
105    switch (attr) {
106    case EGL_WAYLAND_PLANE_WL:
107       attrs->PlaneWL = val;
108       break;
109    default:
110       return EGL_BAD_PARAMETER;
111    }
112 
113    return EGL_SUCCESS;
114 }
115 
116 static EGLint
_eglParseEXTImageDmaBufImportAttribs(_EGLImageAttribs * attrs,_EGLDisplay * dpy,EGLint attr,EGLint val)117 _eglParseEXTImageDmaBufImportAttribs(_EGLImageAttribs *attrs, _EGLDisplay *dpy,
118                                      EGLint attr, EGLint val)
119 {
120    if (!dpy->Extensions.EXT_image_dma_buf_import)
121       return EGL_BAD_PARAMETER;
122 
123    switch (attr) {
124    case EGL_WIDTH:
125       attrs->Width = val;
126       break;
127    case EGL_HEIGHT:
128       attrs->Height = val;
129       break;
130    case EGL_LINUX_DRM_FOURCC_EXT:
131       attrs->DMABufFourCC.Value = val;
132       attrs->DMABufFourCC.IsPresent = EGL_TRUE;
133       break;
134    case EGL_DMA_BUF_PLANE0_FD_EXT:
135       attrs->DMABufPlaneFds[0].Value = val;
136       attrs->DMABufPlaneFds[0].IsPresent = EGL_TRUE;
137       break;
138    case EGL_DMA_BUF_PLANE0_OFFSET_EXT:
139       attrs->DMABufPlaneOffsets[0].Value = val;
140       attrs->DMABufPlaneOffsets[0].IsPresent = EGL_TRUE;
141       break;
142    case EGL_DMA_BUF_PLANE0_PITCH_EXT:
143       attrs->DMABufPlanePitches[0].Value = val;
144       attrs->DMABufPlanePitches[0].IsPresent = EGL_TRUE;
145       break;
146    case EGL_DMA_BUF_PLANE1_FD_EXT:
147       attrs->DMABufPlaneFds[1].Value = val;
148       attrs->DMABufPlaneFds[1].IsPresent = EGL_TRUE;
149       break;
150    case EGL_DMA_BUF_PLANE1_OFFSET_EXT:
151       attrs->DMABufPlaneOffsets[1].Value = val;
152       attrs->DMABufPlaneOffsets[1].IsPresent = EGL_TRUE;
153       break;
154    case EGL_DMA_BUF_PLANE1_PITCH_EXT:
155       attrs->DMABufPlanePitches[1].Value = val;
156       attrs->DMABufPlanePitches[1].IsPresent = EGL_TRUE;
157       break;
158    case EGL_DMA_BUF_PLANE2_FD_EXT:
159       attrs->DMABufPlaneFds[2].Value = val;
160       attrs->DMABufPlaneFds[2].IsPresent = EGL_TRUE;
161       break;
162    case EGL_DMA_BUF_PLANE2_OFFSET_EXT:
163       attrs->DMABufPlaneOffsets[2].Value = val;
164       attrs->DMABufPlaneOffsets[2].IsPresent = EGL_TRUE;
165       break;
166    case EGL_DMA_BUF_PLANE2_PITCH_EXT:
167       attrs->DMABufPlanePitches[2].Value = val;
168       attrs->DMABufPlanePitches[2].IsPresent = EGL_TRUE;
169       break;
170    case EGL_YUV_COLOR_SPACE_HINT_EXT:
171       if (val != EGL_ITU_REC601_EXT && val != EGL_ITU_REC709_EXT &&
172           val != EGL_ITU_REC2020_EXT)
173          return EGL_BAD_ATTRIBUTE;
174 
175       attrs->DMABufYuvColorSpaceHint.Value = val;
176       attrs->DMABufYuvColorSpaceHint.IsPresent = EGL_TRUE;
177       break;
178    case EGL_SAMPLE_RANGE_HINT_EXT:
179       if (val != EGL_YUV_FULL_RANGE_EXT && val != EGL_YUV_NARROW_RANGE_EXT)
180          return EGL_BAD_ATTRIBUTE;
181 
182       attrs->DMABufSampleRangeHint.Value = val;
183       attrs->DMABufSampleRangeHint.IsPresent = EGL_TRUE;
184       break;
185    case EGL_YUV_CHROMA_HORIZONTAL_SITING_HINT_EXT:
186       if (val != EGL_YUV_CHROMA_SITING_0_EXT &&
187           val != EGL_YUV_CHROMA_SITING_0_5_EXT)
188          return EGL_BAD_ATTRIBUTE;
189 
190       attrs->DMABufChromaHorizontalSiting.Value = val;
191       attrs->DMABufChromaHorizontalSiting.IsPresent = EGL_TRUE;
192       break;
193    case EGL_YUV_CHROMA_VERTICAL_SITING_HINT_EXT:
194       if (val != EGL_YUV_CHROMA_SITING_0_EXT &&
195           val != EGL_YUV_CHROMA_SITING_0_5_EXT)
196          return EGL_BAD_ATTRIBUTE;
197 
198       attrs->DMABufChromaVerticalSiting.Value = val;
199       attrs->DMABufChromaVerticalSiting.IsPresent = EGL_TRUE;
200       break;
201    default:
202       return EGL_BAD_PARAMETER;
203    }
204 
205    return EGL_SUCCESS;
206 }
207 
208 static EGLint
_eglParseEXTImageDmaBufImportModifiersAttribs(_EGLImageAttribs * attrs,_EGLDisplay * dpy,EGLint attr,EGLint val)209 _eglParseEXTImageDmaBufImportModifiersAttribs(_EGLImageAttribs *attrs,
210                                               _EGLDisplay *dpy,
211                                               EGLint attr, EGLint val)
212 {
213    if (!dpy->Extensions.EXT_image_dma_buf_import_modifiers)
214       return EGL_BAD_PARAMETER;
215 
216    switch (attr) {
217    case EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT:
218       attrs->DMABufPlaneModifiersLo[0].Value = val;
219       attrs->DMABufPlaneModifiersLo[0].IsPresent = EGL_TRUE;
220       break;
221    case EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT:
222       attrs->DMABufPlaneModifiersHi[0].Value = val;
223       attrs->DMABufPlaneModifiersHi[0].IsPresent = EGL_TRUE;
224       break;
225    case EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT:
226       attrs->DMABufPlaneModifiersLo[1].Value = val;
227       attrs->DMABufPlaneModifiersLo[1].IsPresent = EGL_TRUE;
228       break;
229    case EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT:
230       attrs->DMABufPlaneModifiersHi[1].Value = val;
231       attrs->DMABufPlaneModifiersHi[1].IsPresent = EGL_TRUE;
232       break;
233    case EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT:
234       attrs->DMABufPlaneModifiersLo[2].Value = val;
235       attrs->DMABufPlaneModifiersLo[2].IsPresent = EGL_TRUE;
236       break;
237    case EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT:
238       attrs->DMABufPlaneModifiersHi[2].Value = val;
239       attrs->DMABufPlaneModifiersHi[2].IsPresent = EGL_TRUE;
240       break;
241    case EGL_DMA_BUF_PLANE3_FD_EXT:
242       attrs->DMABufPlaneFds[3].Value = val;
243       attrs->DMABufPlaneFds[3].IsPresent = EGL_TRUE;
244       break;
245    case EGL_DMA_BUF_PLANE3_OFFSET_EXT:
246       attrs->DMABufPlaneOffsets[3].Value = val;
247       attrs->DMABufPlaneOffsets[3].IsPresent = EGL_TRUE;
248       break;
249    case EGL_DMA_BUF_PLANE3_PITCH_EXT:
250       attrs->DMABufPlanePitches[3].Value = val;
251       attrs->DMABufPlanePitches[3].IsPresent = EGL_TRUE;
252       break;
253    case EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT:
254       attrs->DMABufPlaneModifiersLo[3].Value = val;
255       attrs->DMABufPlaneModifiersLo[3].IsPresent = EGL_TRUE;
256       break;
257    case EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT:
258       attrs->DMABufPlaneModifiersHi[3].Value = val;
259       attrs->DMABufPlaneModifiersHi[3].IsPresent = EGL_TRUE;
260       break;
261    default:
262       return EGL_BAD_PARAMETER;
263    }
264 
265    return EGL_SUCCESS;
266 }
267 
268 /**
269  * Parse the list of image attributes.
270  *
271  * Returns EGL_TRUE on success and EGL_FALSE otherwise.
272  * Function calls _eglError to set the correct error code.
273  */
274 EGLBoolean
_eglParseImageAttribList(_EGLImageAttribs * attrs,_EGLDisplay * dpy,const EGLint * attrib_list)275 _eglParseImageAttribList(_EGLImageAttribs *attrs, _EGLDisplay *dpy,
276                          const EGLint *attrib_list)
277 {
278    EGLint i, err;
279 
280    memset(attrs, 0, sizeof(*attrs));
281 
282    if (!attrib_list)
283       return EGL_TRUE;
284 
285    for (i = 0; attrib_list[i] != EGL_NONE; i++) {
286       EGLint attr = attrib_list[i++];
287       EGLint val = attrib_list[i];
288 
289       err = _eglParseKHRImageAttribs(attrs, dpy, attr, val);
290       if (err == EGL_SUCCESS)
291          continue;
292 
293       err = _eglParseMESADrmImageAttribs(attrs, dpy, attr, val);
294       if (err == EGL_SUCCESS)
295          continue;
296 
297       err = _eglParseWLBindWaylandDisplayAttribs(attrs, dpy, attr, val);
298       if (err == EGL_SUCCESS)
299          continue;
300 
301       err = _eglParseEXTImageDmaBufImportAttribs(attrs, dpy, attr, val);
302       if (err == EGL_SUCCESS)
303          continue;
304 
305       /* EXT_image_dma_buf_import states that if invalid value is provided for
306        * its attributes, we should return EGL_BAD_ATTRIBUTE.
307        * Bail out ASAP, since follow-up calls can return another EGL_BAD error.
308        */
309       if (err == EGL_BAD_ATTRIBUTE)
310          return _eglError(err, __func__);
311 
312       err = _eglParseEXTImageDmaBufImportModifiersAttribs(attrs, dpy, attr, val);
313       if (err == EGL_SUCCESS)
314          continue;
315 
316       return _eglError(err, __func__);
317    }
318 
319    return EGL_TRUE;
320 }
321