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 
27 class AttributeMap;
28 struct ClientExtensions;
29 struct Config;
30 class Device;
31 class Display;
32 class Image;
33 class Stream;
34 class Surface;
35 class Sync;
36 class Thread;
37 class LabeledObject;
38 
39 struct ValidationContext
40 {
ValidationContextValidationContext41     ValidationContext(Thread *threadIn, const char *entryPointIn, const LabeledObject *objectIn)
42         : eglThread(threadIn), entryPoint(entryPointIn), labeledObject(objectIn)
43     {}
44 
45     // We should remove the message-less overload once we have messages for all EGL errors.
46     void setError(EGLint error) const;
47     void setError(EGLint error, const char *message...) const;
48 
49     Thread *eglThread;
50     const char *entryPoint;
51     const LabeledObject *labeledObject;
52 };
53 
54 // Object validation
55 bool ValidateDisplay(const ValidationContext *val, const Display *display);
56 bool ValidateSurface(const ValidationContext *val, const Display *display, const Surface *surface);
57 bool ValidateConfig(const ValidationContext *val, const Display *display, const Config *config);
58 bool ValidateContext(const ValidationContext *val,
59                      const Display *display,
60                      const gl::Context *context);
61 bool ValidateImage(const ValidationContext *val, const Display *display, const Image *image);
62 bool ValidateDevice(const ValidationContext *val, const Device *device);
63 bool ValidateSync(const ValidationContext *val, const Display *display, const Sync *sync);
64 
65 // Return the requested object only if it is valid (otherwise nullptr)
66 const Thread *GetThreadIfValid(const Thread *thread);
67 const Display *GetDisplayIfValid(const Display *display);
68 const Surface *GetSurfaceIfValid(const Display *display, const Surface *surface);
69 const Image *GetImageIfValid(const Display *display, const Image *image);
70 const Stream *GetStreamIfValid(const Display *display, const Stream *stream);
71 const gl::Context *GetContextIfValid(const Display *display, const gl::Context *context);
72 const Device *GetDeviceIfValid(const Device *device);
73 const Sync *GetSyncIfValid(const Display *display, const Sync *sync);
74 LabeledObject *GetLabeledObjectIfValid(Thread *thread,
75                                        const Display *display,
76                                        ObjectType objectType,
77                                        EGLObjectKHR object);
78 
79 // A template struct for determining the default value to return for each entry point.
80 template <angle::EntryPoint EP, typename ReturnType>
81 struct DefaultReturnValue
82 {
83     static constexpr ReturnType kValue = static_cast<ReturnType>(0);
84 };
85 
86 template <angle::EntryPoint EP, typename ReturnType>
87 ReturnType GetDefaultReturnValue(Thread *thread);
88 
89 template <>
90 ANGLE_INLINE EGLint
91 GetDefaultReturnValue<angle::EntryPoint::EGLLabelObjectKHR, EGLint>(Thread *thread)
92 {
93     return thread->getError();
94 }
95 
96 template <angle::EntryPoint EP, typename ReturnType>
GetDefaultReturnValue(Thread * thread)97 ANGLE_INLINE ReturnType GetDefaultReturnValue(Thread *thread)
98 {
99     return DefaultReturnValue<EP, ReturnType>::kValue;
100 }
101 
102 // First case: handling packed enums.
103 template <typename PackedT, typename FromT>
PackParam(FromT from)104 typename std::enable_if<std::is_enum<PackedT>::value, PackedT>::type PackParam(FromT from)
105 {
106     return FromEGLenum<PackedT>(from);
107 }
108 
109 // Second case: handling other types.
110 template <typename PackedT, typename FromT>
111 typename std::enable_if<!std::is_enum<PackedT>::value,
112                         typename std::remove_reference<PackedT>::type>::type
113 PackParam(FromT from);
114 
115 template <>
116 inline const AttributeMap PackParam<const AttributeMap &, const EGLint *>(const EGLint *attribs)
117 {
118     return AttributeMap::CreateFromIntArray(attribs);
119 }
120 
121 // In a 32-bit environment the EGLAttrib and EGLint types are the same. We need to mask out one of
122 // the two specializations to avoid having an override ambiguity.
123 #if defined(ANGLE_IS_64_BIT_CPU)
124 template <>
125 inline const AttributeMap PackParam<const AttributeMap &, const EGLAttrib *>(
126     const EGLAttrib *attribs)
127 {
128     return AttributeMap::CreateFromAttribArray(attribs);
129 }
130 #endif  // defined(ANGLE_IS_64_BIT_CPU)
131 
132 template <typename PackedT, typename FromT>
133 inline typename std::enable_if<!std::is_enum<PackedT>::value,
134                                typename std::remove_reference<PackedT>::type>::type
PackParam(FromT from)135 PackParam(FromT from)
136 {
137     return static_cast<PackedT>(from);
138 }
139 }  // namespace egl
140 
141 #define ANGLE_EGL_VALIDATE(THREAD, EP, OBJ, RETURN_TYPE, ...)                              \
142     do                                                                                     \
143     {                                                                                      \
144         const char *epname = "egl" #EP;                                                    \
145         ValidationContext vctx(THREAD, epname, OBJ);                                       \
146         auto ANGLE_LOCAL_VAR = (Validate##EP(&vctx, ##__VA_ARGS__));                       \
147         if (!ANGLE_LOCAL_VAR)                                                              \
148         {                                                                                  \
149             return GetDefaultReturnValue<angle::EntryPoint::EGL##EP, RETURN_TYPE>(THREAD); \
150         }                                                                                  \
151     } while (0)
152 
153 #define ANGLE_EGL_VALIDATE_VOID(THREAD, EP, OBJ, ...)                \
154     do                                                               \
155     {                                                                \
156         const char *epname = "egl" #EP;                              \
157         ValidationContext vctx(THREAD, epname, OBJ);                 \
158         auto ANGLE_LOCAL_VAR = (Validate##EP(&vctx, ##__VA_ARGS__)); \
159         if (!ANGLE_LOCAL_VAR)                                        \
160         {                                                            \
161             return;                                                  \
162         }                                                            \
163     } while (0)
164 
165 #define ANGLE_EGL_TRY(THREAD, EXPR, FUNCNAME, LABELOBJECT)                   \
166     do                                                                       \
167     {                                                                        \
168         auto ANGLE_LOCAL_VAR = (EXPR);                                       \
169         if (ANGLE_LOCAL_VAR.isError())                                       \
170             return THREAD->setError(ANGLE_LOCAL_VAR, FUNCNAME, LABELOBJECT); \
171     } while (0)
172 
173 #define ANGLE_EGL_TRY_RETURN(THREAD, EXPR, FUNCNAME, LABELOBJECT, RETVAL) \
174     do                                                                    \
175     {                                                                     \
176         auto ANGLE_LOCAL_VAR = (EXPR);                                    \
177         if (ANGLE_LOCAL_VAR.isError())                                    \
178         {                                                                 \
179             THREAD->setError(ANGLE_LOCAL_VAR, FUNCNAME, LABELOBJECT);     \
180             return RETVAL;                                                \
181         }                                                                 \
182     } while (0)
183 
184 #endif  // LIBANGLE_VALIDATIONEGL_H_
185