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