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 * disp,EGLint attr,EGLint val)38 _eglParseKHRImageAttribs(_EGLImageAttribs *attrs, _EGLDisplay *disp,
39                          EGLint attr, EGLint val)
40 {
41    switch (attr) {
42    case EGL_IMAGE_PRESERVED_KHR:
43       if (!disp->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 (!disp->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 (!disp->Extensions.KHR_gl_texture_3D_image)
57          return EGL_BAD_PARAMETER;
58 
59       attrs->GLTextureZOffset = val;
60       break;
61    case EGL_PROTECTED_CONTENT_EXT:
62       if (!disp->Extensions.EXT_protected_surface)
63          return EGL_BAD_PARAMETER;
64 
65       attrs->ProtectedContent = val;
66       break;
67    default:
68       return EGL_BAD_PARAMETER;
69    }
70 
71    return EGL_SUCCESS;
72 }
73 
74 static EGLint
_eglParseMESADrmImageAttribs(_EGLImageAttribs * attrs,_EGLDisplay * disp,EGLint attr,EGLint val)75 _eglParseMESADrmImageAttribs(_EGLImageAttribs *attrs, _EGLDisplay *disp,
76                              EGLint attr, EGLint val)
77 {
78    if (!disp->Extensions.MESA_drm_image)
79       return EGL_BAD_PARAMETER;
80 
81    switch (attr) {
82    case EGL_WIDTH:
83       attrs->Width = val;
84       break;
85    case EGL_HEIGHT:
86       attrs->Height = val;
87       break;
88    case EGL_DRM_BUFFER_FORMAT_MESA:
89       attrs->DRMBufferFormatMESA = val;
90       break;
91    case EGL_DRM_BUFFER_USE_MESA:
92       attrs->DRMBufferUseMESA = val;
93       break;
94    case EGL_DRM_BUFFER_STRIDE_MESA:
95       attrs->DRMBufferStrideMESA = val;
96       break;
97    default:
98       return EGL_BAD_PARAMETER;
99    }
100 
101    return EGL_SUCCESS;
102 }
103 
104 static EGLint
_eglParseWLBindWaylandDisplayAttribs(_EGLImageAttribs * attrs,_EGLDisplay * disp,EGLint attr,EGLint val)105 _eglParseWLBindWaylandDisplayAttribs(_EGLImageAttribs *attrs, _EGLDisplay *disp,
106                                      EGLint attr, EGLint val)
107 {
108    if (!disp->Extensions.WL_bind_wayland_display)
109       return EGL_BAD_PARAMETER;
110 
111    switch (attr) {
112    case EGL_WAYLAND_PLANE_WL:
113       attrs->PlaneWL = val;
114       break;
115    default:
116       return EGL_BAD_PARAMETER;
117    }
118 
119    return EGL_SUCCESS;
120 }
121 
122 static EGLint
_eglParseEXTImageDmaBufImportAttribs(_EGLImageAttribs * attrs,_EGLDisplay * disp,EGLint attr,EGLint val)123 _eglParseEXTImageDmaBufImportAttribs(_EGLImageAttribs *attrs, _EGLDisplay *disp,
124                                      EGLint attr, EGLint val)
125 {
126    if (!disp->Extensions.EXT_image_dma_buf_import)
127       return EGL_BAD_PARAMETER;
128 
129    switch (attr) {
130    case EGL_WIDTH:
131       attrs->Width = val;
132       break;
133    case EGL_HEIGHT:
134       attrs->Height = val;
135       break;
136    case EGL_LINUX_DRM_FOURCC_EXT:
137       attrs->DMABufFourCC.Value = val;
138       attrs->DMABufFourCC.IsPresent = EGL_TRUE;
139       break;
140    case EGL_DMA_BUF_PLANE0_FD_EXT:
141       attrs->DMABufPlaneFds[0].Value = val;
142       attrs->DMABufPlaneFds[0].IsPresent = EGL_TRUE;
143       break;
144    case EGL_DMA_BUF_PLANE0_OFFSET_EXT:
145       attrs->DMABufPlaneOffsets[0].Value = val;
146       attrs->DMABufPlaneOffsets[0].IsPresent = EGL_TRUE;
147       break;
148    case EGL_DMA_BUF_PLANE0_PITCH_EXT:
149       attrs->DMABufPlanePitches[0].Value = val;
150       attrs->DMABufPlanePitches[0].IsPresent = EGL_TRUE;
151       break;
152    case EGL_DMA_BUF_PLANE1_FD_EXT:
153       attrs->DMABufPlaneFds[1].Value = val;
154       attrs->DMABufPlaneFds[1].IsPresent = EGL_TRUE;
155       break;
156    case EGL_DMA_BUF_PLANE1_OFFSET_EXT:
157       attrs->DMABufPlaneOffsets[1].Value = val;
158       attrs->DMABufPlaneOffsets[1].IsPresent = EGL_TRUE;
159       break;
160    case EGL_DMA_BUF_PLANE1_PITCH_EXT:
161       attrs->DMABufPlanePitches[1].Value = val;
162       attrs->DMABufPlanePitches[1].IsPresent = EGL_TRUE;
163       break;
164    case EGL_DMA_BUF_PLANE2_FD_EXT:
165       attrs->DMABufPlaneFds[2].Value = val;
166       attrs->DMABufPlaneFds[2].IsPresent = EGL_TRUE;
167       break;
168    case EGL_DMA_BUF_PLANE2_OFFSET_EXT:
169       attrs->DMABufPlaneOffsets[2].Value = val;
170       attrs->DMABufPlaneOffsets[2].IsPresent = EGL_TRUE;
171       break;
172    case EGL_DMA_BUF_PLANE2_PITCH_EXT:
173       attrs->DMABufPlanePitches[2].Value = val;
174       attrs->DMABufPlanePitches[2].IsPresent = EGL_TRUE;
175       break;
176    case EGL_YUV_COLOR_SPACE_HINT_EXT:
177       if (val != EGL_ITU_REC601_EXT && val != EGL_ITU_REC709_EXT &&
178           val != EGL_ITU_REC2020_EXT)
179          return EGL_BAD_ATTRIBUTE;
180 
181       attrs->DMABufYuvColorSpaceHint.Value = val;
182       attrs->DMABufYuvColorSpaceHint.IsPresent = EGL_TRUE;
183       break;
184    case EGL_SAMPLE_RANGE_HINT_EXT:
185       if (val != EGL_YUV_FULL_RANGE_EXT && val != EGL_YUV_NARROW_RANGE_EXT)
186          return EGL_BAD_ATTRIBUTE;
187 
188       attrs->DMABufSampleRangeHint.Value = val;
189       attrs->DMABufSampleRangeHint.IsPresent = EGL_TRUE;
190       break;
191    case EGL_YUV_CHROMA_HORIZONTAL_SITING_HINT_EXT:
192       if (val != EGL_YUV_CHROMA_SITING_0_EXT &&
193           val != EGL_YUV_CHROMA_SITING_0_5_EXT)
194          return EGL_BAD_ATTRIBUTE;
195 
196       attrs->DMABufChromaHorizontalSiting.Value = val;
197       attrs->DMABufChromaHorizontalSiting.IsPresent = EGL_TRUE;
198       break;
199    case EGL_YUV_CHROMA_VERTICAL_SITING_HINT_EXT:
200       if (val != EGL_YUV_CHROMA_SITING_0_EXT &&
201           val != EGL_YUV_CHROMA_SITING_0_5_EXT)
202          return EGL_BAD_ATTRIBUTE;
203 
204       attrs->DMABufChromaVerticalSiting.Value = val;
205       attrs->DMABufChromaVerticalSiting.IsPresent = EGL_TRUE;
206       break;
207    default:
208       return EGL_BAD_PARAMETER;
209    }
210 
211    return EGL_SUCCESS;
212 }
213 
214 static EGLint
_eglParseEXTImageDmaBufImportModifiersAttribs(_EGLImageAttribs * attrs,_EGLDisplay * disp,EGLint attr,EGLint val)215 _eglParseEXTImageDmaBufImportModifiersAttribs(_EGLImageAttribs *attrs,
216                                               _EGLDisplay *disp,
217                                               EGLint attr, EGLint val)
218 {
219    if (!disp->Extensions.EXT_image_dma_buf_import_modifiers)
220       return EGL_BAD_PARAMETER;
221 
222    switch (attr) {
223    case EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT:
224       attrs->DMABufPlaneModifiersLo[0].Value = val;
225       attrs->DMABufPlaneModifiersLo[0].IsPresent = EGL_TRUE;
226       break;
227    case EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT:
228       attrs->DMABufPlaneModifiersHi[0].Value = val;
229       attrs->DMABufPlaneModifiersHi[0].IsPresent = EGL_TRUE;
230       break;
231    case EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT:
232       attrs->DMABufPlaneModifiersLo[1].Value = val;
233       attrs->DMABufPlaneModifiersLo[1].IsPresent = EGL_TRUE;
234       break;
235    case EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT:
236       attrs->DMABufPlaneModifiersHi[1].Value = val;
237       attrs->DMABufPlaneModifiersHi[1].IsPresent = EGL_TRUE;
238       break;
239    case EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT:
240       attrs->DMABufPlaneModifiersLo[2].Value = val;
241       attrs->DMABufPlaneModifiersLo[2].IsPresent = EGL_TRUE;
242       break;
243    case EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT:
244       attrs->DMABufPlaneModifiersHi[2].Value = val;
245       attrs->DMABufPlaneModifiersHi[2].IsPresent = EGL_TRUE;
246       break;
247    case EGL_DMA_BUF_PLANE3_FD_EXT:
248       attrs->DMABufPlaneFds[3].Value = val;
249       attrs->DMABufPlaneFds[3].IsPresent = EGL_TRUE;
250       break;
251    case EGL_DMA_BUF_PLANE3_OFFSET_EXT:
252       attrs->DMABufPlaneOffsets[3].Value = val;
253       attrs->DMABufPlaneOffsets[3].IsPresent = EGL_TRUE;
254       break;
255    case EGL_DMA_BUF_PLANE3_PITCH_EXT:
256       attrs->DMABufPlanePitches[3].Value = val;
257       attrs->DMABufPlanePitches[3].IsPresent = EGL_TRUE;
258       break;
259    case EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT:
260       attrs->DMABufPlaneModifiersLo[3].Value = val;
261       attrs->DMABufPlaneModifiersLo[3].IsPresent = EGL_TRUE;
262       break;
263    case EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT:
264       attrs->DMABufPlaneModifiersHi[3].Value = val;
265       attrs->DMABufPlaneModifiersHi[3].IsPresent = EGL_TRUE;
266       break;
267    default:
268       return EGL_BAD_PARAMETER;
269    }
270 
271    return EGL_SUCCESS;
272 }
273 
274 /**
275  * Parse the list of image attributes.
276  *
277  * Returns EGL_TRUE on success and EGL_FALSE otherwise.
278  * Function calls _eglError to set the correct error code.
279  */
280 EGLBoolean
_eglParseImageAttribList(_EGLImageAttribs * attrs,_EGLDisplay * disp,const EGLint * attrib_list)281 _eglParseImageAttribList(_EGLImageAttribs *attrs, _EGLDisplay *disp,
282                          const EGLint *attrib_list)
283 {
284    EGLint i, err;
285 
286    memset(attrs, 0, sizeof(*attrs));
287 
288    if (!attrib_list)
289       return EGL_TRUE;
290 
291    for (i = 0; attrib_list[i] != EGL_NONE; i++) {
292       EGLint attr = attrib_list[i++];
293       EGLint val = attrib_list[i];
294 
295       err = _eglParseKHRImageAttribs(attrs, disp, attr, val);
296       if (err == EGL_SUCCESS)
297          continue;
298 
299       err = _eglParseMESADrmImageAttribs(attrs, disp, attr, val);
300       if (err == EGL_SUCCESS)
301          continue;
302 
303       err = _eglParseWLBindWaylandDisplayAttribs(attrs, disp, attr, val);
304       if (err == EGL_SUCCESS)
305          continue;
306 
307       err = _eglParseEXTImageDmaBufImportAttribs(attrs, disp, attr, val);
308       if (err == EGL_SUCCESS)
309          continue;
310 
311       /* EXT_image_dma_buf_import states that if invalid value is provided for
312        * its attributes, we should return EGL_BAD_ATTRIBUTE.
313        * Bail out ASAP, since follow-up calls can return another EGL_BAD error.
314        */
315       if (err == EGL_BAD_ATTRIBUTE)
316          return _eglError(err, __func__);
317 
318       err = _eglParseEXTImageDmaBufImportModifiersAttribs(attrs, disp, attr, val);
319       if (err == EGL_SUCCESS)
320          continue;
321 
322       return _eglError(err, __func__);
323    }
324 
325    return EGL_TRUE;
326 }
327