• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2015 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 // validationEGL.h: Validation functions for generic EGL entry point parameters
8 
9 #ifndef LIBANGLE_VALIDATIONEGL_H_
10 #define LIBANGLE_VALIDATIONEGL_H_
11 
12 #include "common/PackedEnums.h"
13 #include "libANGLE/Display.h"
14 #include "libANGLE/Error.h"
15 #include "libANGLE/Thread.h"
16 
17 #include <EGL/egl.h>
18 #include <EGL/eglext.h>
19 
20 namespace gl
21 {
22 class Context;
23 }
24 
25 namespace egl
26 {
27 constexpr EGLint kEglMajorVersion = 1;
28 constexpr EGLint kEglMinorVersion = 5;
29 
30 class AttributeMap;
31 struct ClientExtensions;
32 struct Config;
33 class Device;
34 class Display;
35 class Image;
36 class Stream;
37 class Surface;
38 class Sync;
39 class Thread;
40 class LabeledObject;
41 
42 struct ValidationContext
43 {
ValidationContextValidationContext44     ValidationContext(Thread *threadIn, const char *entryPointIn, const LabeledObject *objectIn)
45         : eglThread(threadIn), entryPoint(entryPointIn), labeledObject(objectIn)
46     {}
47 
48     // We should remove the message-less overload once we have messages for all EGL errors.
49     void setError(EGLint error) const;
50     ANGLE_FORMAT_PRINTF(3, 4)
51     void setError(EGLint error, const char *message...) const;
52 
53     Thread *eglThread;
54     const char *entryPoint;
55     const LabeledObject *labeledObject;
56 };
57 
58 // Object validation
59 bool ValidateDisplay(const ValidationContext *val, const Display *display);
60 bool ValidateSurface(const ValidationContext *val, const Display *display, SurfaceID surfaceID);
61 bool ValidateConfig(const ValidationContext *val, const Display *display, const Config *config);
62 bool ValidateContext(const ValidationContext *val, const Display *display, gl::ContextID contextID);
63 bool ValidateImage(const ValidationContext *val, const Display *display, ImageID imageID);
64 bool ValidateDevice(const ValidationContext *val, const Device *device);
65 bool ValidateSync(const ValidationContext *val, const Display *display, SyncID sync);
66 
67 // Return the requested object only if it is valid (otherwise nullptr)
68 const Thread *GetThreadIfValid(const Thread *thread);
69 const Display *GetDisplayIfValid(const Display *display);
70 const Surface *GetSurfaceIfValid(const Display *display, SurfaceID surfaceID);
71 const Image *GetImageIfValid(const Display *display, ImageID imageID);
72 const Stream *GetStreamIfValid(const Display *display, const Stream *stream);
73 const gl::Context *GetContextIfValid(const Display *display, gl::ContextID contextID);
74 gl::Context *GetContextIfValid(Display *display, gl::ContextID contextID);
75 const Device *GetDeviceIfValid(const Device *device);
76 const Sync *GetSyncIfValid(const Display *display, SyncID sync);
77 const LabeledObject *GetLabeledObjectIfValid(Thread *thread,
78                                              const Display *display,
79                                              ObjectType objectType,
80                                              EGLObjectKHR object);
81 LabeledObject *GetLabeledObjectIfValid(Thread *thread,
82                                        Display *display,
83                                        ObjectType objectType,
84                                        EGLObjectKHR object);
85 
86 // A template struct for determining the default value to return for each entry point.
87 template <angle::EntryPoint EP, typename ReturnType>
88 struct DefaultReturnValue
89 {
90     static constexpr ReturnType kValue = static_cast<ReturnType>(0);
91 };
92 
93 template <angle::EntryPoint EP, typename ReturnType>
94 ReturnType GetDefaultReturnValue(Thread *thread);
95 
96 template <>
97 ANGLE_INLINE EGLint
98 GetDefaultReturnValue<angle::EntryPoint::EGLLabelObjectKHR, EGLint>(Thread *thread)
99 {
100     return thread->getError();
101 }
102 
103 template <>
104 ANGLE_INLINE EGLint
105 GetDefaultReturnValue<angle::EntryPoint::EGLDupNativeFenceFDANDROID, EGLint>(Thread *thread)
106 {
107     return EGL_NO_NATIVE_FENCE_FD_ANDROID;
108 }
109 
110 template <angle::EntryPoint EP, typename ReturnType>
GetDefaultReturnValue(Thread * thread)111 ANGLE_INLINE ReturnType GetDefaultReturnValue(Thread *thread)
112 {
113     return DefaultReturnValue<EP, ReturnType>::kValue;
114 }
115 
116 // First case: handling packed enums.
117 template <typename PackedT, typename FromT>
PackParam(FromT from)118 typename std::enable_if<std::is_enum<PackedT>::value, PackedT>::type PackParam(FromT from)
119 {
120     return FromEGLenum<PackedT>(from);
121 }
122 
123 // Second case: handling resource ids.
124 template <typename PackedT,
125           typename FromT,
126           typename std::enable_if<IsResourceIDType<PackedT>::value>::type * = nullptr>
PackParam(FromT from)127 PackedT PackParam(FromT from)
128 {
129     return {static_cast<GLuint>(reinterpret_cast<uintptr_t>(from))};
130 }
131 
132 // This and the next 2 template specializations handle distinguishing between EGLint, EGLAttrib
133 // and other. This is needed because on some architectures EGLint and EGLAttrib are not the same
134 // base type. Previously the code conditionally compiled 2 specializations on 64 bit but it turns
135 // out on WatchOS the assumption about 32/64 bit and if EGLint and ELGAttrib are the same or
136 // different did not hold.
137 template <typename PackedT,
138           typename FromT,
139           typename std::enable_if<!std::is_enum<PackedT>::value>::type              * = nullptr,
140           typename std::enable_if<std::is_same<FromT, const EGLint *>::value>::type * = nullptr>
PackParam(FromT attribs)141 typename std::remove_reference<PackedT>::type PackParam(FromT attribs)
142 {
143     return AttributeMap::CreateFromIntArray(attribs);
144 }
145 
146 template <typename PackedT,
147           typename FromT,
148           typename std::enable_if<!std::is_enum<PackedT>::value>::type                 * = nullptr,
149           typename std::enable_if<!std::is_same<FromT, const EGLint *>::value>::type   * = nullptr,
150           typename std::enable_if<std::is_same<FromT, const EGLAttrib *>::value>::type * = nullptr>
PackParam(FromT attribs)151 typename std::remove_reference<PackedT>::type PackParam(FromT attribs)
152 {
153     return AttributeMap::CreateFromAttribArray(attribs);
154 }
155 
156 template <typename PackedT,
157           typename FromT,
158           typename std::enable_if<!std::is_enum<PackedT>::value>::type                  * = nullptr,
159           typename std::enable_if<!std::is_same<FromT, const EGLint *>::value>::type    * = nullptr,
160           typename std::enable_if<!std::is_same<FromT, const EGLAttrib *>::value>::type * = nullptr,
161           typename std::enable_if<!IsResourceIDType<PackedT>::value>::type              * = nullptr>
PackParam(FromT from)162 typename std::remove_reference<PackedT>::type PackParam(FromT from)
163 {
164     return static_cast<PackedT>(from);
165 }
166 
167 }  // namespace egl
168 
169 #define ANGLE_EGL_VALIDATE(THREAD, EP, OBJ, RETURN_TYPE, ...)                              \
170     do                                                                                     \
171     {                                                                                      \
172         const char *epname = "egl" #EP;                                                    \
173         ValidationContext vctx(THREAD, epname, OBJ);                                       \
174         auto ANGLE_LOCAL_VAR = (Validate##EP(&vctx, ##__VA_ARGS__));                       \
175         if (!ANGLE_LOCAL_VAR)                                                              \
176         {                                                                                  \
177             return GetDefaultReturnValue<angle::EntryPoint::EGL##EP, RETURN_TYPE>(THREAD); \
178         }                                                                                  \
179     } while (0)
180 
181 #define ANGLE_EGL_VALIDATE_VOID(THREAD, EP, OBJ, ...)                \
182     do                                                               \
183     {                                                                \
184         const char *epname = "egl" #EP;                              \
185         ValidationContext vctx(THREAD, epname, OBJ);                 \
186         auto ANGLE_LOCAL_VAR = (Validate##EP(&vctx, ##__VA_ARGS__)); \
187         if (!ANGLE_LOCAL_VAR)                                        \
188         {                                                            \
189             return;                                                  \
190         }                                                            \
191     } while (0)
192 
193 #define ANGLE_EGL_TRY(THREAD, EXPR, FUNCNAME, LABELOBJECT)                   \
194     do                                                                       \
195     {                                                                        \
196         auto ANGLE_LOCAL_VAR = (EXPR);                                       \
197         if (ANGLE_LOCAL_VAR.isError())                                       \
198             return THREAD->setError(ANGLE_LOCAL_VAR, FUNCNAME, LABELOBJECT); \
199     } while (0)
200 
201 #define ANGLE_EGL_TRY_RETURN(THREAD, EXPR, FUNCNAME, LABELOBJECT, RETVAL) \
202     do                                                                    \
203     {                                                                     \
204         auto ANGLE_LOCAL_VAR = (EXPR);                                    \
205         if (ANGLE_LOCAL_VAR.isError())                                    \
206         {                                                                 \
207             THREAD->setError(ANGLE_LOCAL_VAR, FUNCNAME, LABELOBJECT);     \
208             return RETVAL;                                                \
209         }                                                                 \
210     } while (0)
211 
212 #if ANGLE_USE_DISPLAY_PREPARE_FOR_CALL
213 #    define ANGLE_EGL_TRY_PREPARE_FOR_CALL_RETURN ANGLE_EGL_TRY_RETURN
214 #    define ANGLE_EGL_TRY_PREPARE_FOR_CALL ANGLE_EGL_TRY
215 #else
216 #    define ANGLE_EGL_TRY_PREPARE_FOR_CALL_RETURN(...)
217 #    define ANGLE_EGL_TRY_PREPARE_FOR_CALL(...)
218 #endif
219 
220 #define ANGLE_EGLBOOLEAN_TRY(EXPR)           \
221     do                                       \
222     {                                        \
223         EGLBoolean ANGLE_LOCAL_VAR = (EXPR); \
224         if (ANGLE_LOCAL_VAR != EGL_TRUE)     \
225         {                                    \
226             return ANGLE_LOCAL_VAR;          \
227         }                                    \
228     } while (0)
229 
230 #endif  // LIBANGLE_VALIDATIONEGL_H_
231