validationEGL.h (8832B)
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 { 43 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, const Surface *surface); 60 bool ValidateConfig(const ValidationContext *val, const Display *display, const Config *config); 61 bool ValidateContext(const ValidationContext *val, 62 const Display *display, 63 const gl::Context *context); 64 bool ValidateImage(const ValidationContext *val, const Display *display, const Image *image); 65 bool ValidateDevice(const ValidationContext *val, const Device *device); 66 bool ValidateSync(const ValidationContext *val, const Display *display, const Sync *sync); 67 68 // Return the requested object only if it is valid (otherwise nullptr) 69 const Thread *GetThreadIfValid(const Thread *thread); 70 const Display *GetDisplayIfValid(const Display *display); 71 const Surface *GetSurfaceIfValid(const Display *display, const Surface *surface); 72 const Image *GetImageIfValid(const Display *display, const Image *image); 73 const Stream *GetStreamIfValid(const Display *display, const Stream *stream); 74 const gl::Context *GetContextIfValid(const Display *display, const gl::Context *context); 75 const Device *GetDeviceIfValid(const Device *device); 76 const Sync *GetSyncIfValid(const Display *display, const Sync *sync); 77 LabeledObject *GetLabeledObjectIfValid(Thread *thread, 78 const Display *display, 79 ObjectType objectType, 80 EGLObjectKHR object); 81 82 // A template struct for determining the default value to return for each entry point. 83 template <angle::EntryPoint EP, typename ReturnType> 84 struct DefaultReturnValue 85 { 86 static constexpr ReturnType kValue = static_cast<ReturnType>(0); 87 }; 88 89 template <angle::EntryPoint EP, typename ReturnType> 90 ReturnType GetDefaultReturnValue(Thread *thread); 91 92 template <> 93 ANGLE_INLINE EGLint 94 GetDefaultReturnValue<angle::EntryPoint::EGLLabelObjectKHR, EGLint>(Thread *thread) 95 { 96 return thread->getError(); 97 } 98 99 template <angle::EntryPoint EP, typename ReturnType> 100 ANGLE_INLINE ReturnType GetDefaultReturnValue(Thread *thread) 101 { 102 return DefaultReturnValue<EP, ReturnType>::kValue; 103 } 104 105 // First case: handling packed enums. 106 template <typename PackedT, typename FromT> 107 typename std::enable_if<std::is_enum<PackedT>::value, PackedT>::type PackParam(FromT from) 108 { 109 return FromEGLenum<PackedT>(from); 110 } 111 112 // This and the next 2 template specializations handle distinguishing between EGLint, EGLAttrib 113 // and other. This is needed because on some architectures EGLint and EGLAttrib are not the same 114 // base type. Previously the code conditionally compiled 2 specializations on 64 bit but it turns 115 // out on WatchOS the assumption about 32/64 bit and if EGLint and ELGAttrib are the same or 116 // different did not hold. 117 template <typename PackedT, 118 typename FromT, 119 typename std::enable_if<!std::is_enum<PackedT>::value>::type * = nullptr, 120 typename std::enable_if<std::is_same<FromT, const EGLint *>::value>::type * = nullptr> 121 typename std::remove_reference<PackedT>::type PackParam(FromT attribs) 122 { 123 return AttributeMap::CreateFromIntArray(attribs); 124 } 125 126 template <typename PackedT, 127 typename FromT, 128 typename std::enable_if<!std::is_enum<PackedT>::value>::type * = nullptr, 129 typename std::enable_if<!std::is_same<FromT, const EGLint *>::value>::type * = nullptr, 130 typename std::enable_if<std::is_same<FromT, const EGLAttrib *>::value>::type * = nullptr> 131 typename std::remove_reference<PackedT>::type PackParam(FromT attribs) 132 { 133 return AttributeMap::CreateFromAttribArray(attribs); 134 } 135 136 template <typename PackedT, 137 typename FromT, 138 typename std::enable_if<!std::is_enum<PackedT>::value>::type * = nullptr, 139 typename std::enable_if<!std::is_same<FromT, const EGLint *>::value>::type * = nullptr, 140 typename std::enable_if<!std::is_same<FromT, const EGLAttrib *>::value>::type * = nullptr> 141 typename std::remove_reference<PackedT>::type PackParam(FromT attribs) 142 { 143 return static_cast<PackedT>(attribs); 144 } 145 146 } // namespace egl 147 148 #define ANGLE_EGL_VALIDATE(THREAD, EP, OBJ, RETURN_TYPE, ...) \ 149 do \ 150 { \ 151 const char *epname = "egl" #EP; \ 152 ValidationContext vctx(THREAD, epname, OBJ); \ 153 auto ANGLE_LOCAL_VAR = (Validate##EP(&vctx, ##__VA_ARGS__)); \ 154 if (!ANGLE_LOCAL_VAR) \ 155 { \ 156 return GetDefaultReturnValue<angle::EntryPoint::EGL##EP, RETURN_TYPE>(THREAD); \ 157 } \ 158 } while (0) 159 160 #define ANGLE_EGL_VALIDATE_VOID(THREAD, EP, OBJ, ...) \ 161 do \ 162 { \ 163 const char *epname = "egl" #EP; \ 164 ValidationContext vctx(THREAD, epname, OBJ); \ 165 auto ANGLE_LOCAL_VAR = (Validate##EP(&vctx, ##__VA_ARGS__)); \ 166 if (!ANGLE_LOCAL_VAR) \ 167 { \ 168 return; \ 169 } \ 170 } while (0) 171 172 #define ANGLE_EGL_TRY(THREAD, EXPR, FUNCNAME, LABELOBJECT) \ 173 do \ 174 { \ 175 auto ANGLE_LOCAL_VAR = (EXPR); \ 176 if (ANGLE_LOCAL_VAR.isError()) \ 177 return THREAD->setError(ANGLE_LOCAL_VAR, FUNCNAME, LABELOBJECT); \ 178 } while (0) 179 180 #define ANGLE_EGL_TRY_RETURN(THREAD, EXPR, FUNCNAME, LABELOBJECT, RETVAL) \ 181 do \ 182 { \ 183 auto ANGLE_LOCAL_VAR = (EXPR); \ 184 if (ANGLE_LOCAL_VAR.isError()) \ 185 { \ 186 THREAD->setError(ANGLE_LOCAL_VAR, FUNCNAME, LABELOBJECT); \ 187 return RETVAL; \ 188 } \ 189 } while (0) 190 191 #define ANGLE_EGLBOOLEAN_TRY(EXPR) \ 192 do \ 193 { \ 194 EGLBoolean ANGLE_LOCAL_VAR = (EXPR); \ 195 if (ANGLE_LOCAL_VAR != EGL_TRUE) \ 196 { \ 197 return ANGLE_LOCAL_VAR; \ 198 } \ 199 } while (0) 200 201 #endif // LIBANGLE_VALIDATIONEGL_H_