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