// // Copyright 2015 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // // validationEGL.h: Validation functions for generic EGL entry point parameters #ifndef LIBANGLE_VALIDATIONEGL_H_ #define LIBANGLE_VALIDATIONEGL_H_ #include "common/PackedEnums.h" #include "libANGLE/Error.h" #include "libANGLE/Thread.h" #include #include namespace gl { class Context; } namespace egl { constexpr EGLint kEglMajorVersion = 1; constexpr EGLint kEglMinorVersion = 5; class AttributeMap; struct ClientExtensions; struct Config; class Device; class Display; class Image; class Stream; class Surface; class Sync; class Thread; class LabeledObject; struct ValidationContext { ValidationContext(Thread *threadIn, const char *entryPointIn, const LabeledObject *objectIn) : eglThread(threadIn), entryPoint(entryPointIn), labeledObject(objectIn) {} // We should remove the message-less overload once we have messages for all EGL errors. void setError(EGLint error) const; ANGLE_FORMAT_PRINTF(3, 4) void setError(EGLint error, const char *message...) const; Thread *eglThread; const char *entryPoint; const LabeledObject *labeledObject; }; // Object validation bool ValidateDisplay(const ValidationContext *val, const Display *display); bool ValidateSurface(const ValidationContext *val, const Display *display, const Surface *surface); bool ValidateConfig(const ValidationContext *val, const Display *display, const Config *config); bool ValidateContext(const ValidationContext *val, const Display *display, const gl::Context *context); bool ValidateImage(const ValidationContext *val, const Display *display, const Image *image); bool ValidateDevice(const ValidationContext *val, const Device *device); bool ValidateSync(const ValidationContext *val, const Display *display, const Sync *sync); // Return the requested object only if it is valid (otherwise nullptr) const Thread *GetThreadIfValid(const Thread *thread); const Display *GetDisplayIfValid(const Display *display); const Surface *GetSurfaceIfValid(const Display *display, const Surface *surface); const Image *GetImageIfValid(const Display *display, const Image *image); const Stream *GetStreamIfValid(const Display *display, const Stream *stream); const gl::Context *GetContextIfValid(const Display *display, const gl::Context *context); const Device *GetDeviceIfValid(const Device *device); const Sync *GetSyncIfValid(const Display *display, const Sync *sync); LabeledObject *GetLabeledObjectIfValid(Thread *thread, const Display *display, ObjectType objectType, EGLObjectKHR object); // A template struct for determining the default value to return for each entry point. template struct DefaultReturnValue { static constexpr ReturnType kValue = static_cast(0); }; template ReturnType GetDefaultReturnValue(Thread *thread); template <> ANGLE_INLINE EGLint GetDefaultReturnValue(Thread *thread) { return thread->getError(); } template ANGLE_INLINE ReturnType GetDefaultReturnValue(Thread *thread) { return DefaultReturnValue::kValue; } // First case: handling packed enums. template typename std::enable_if::value, PackedT>::type PackParam(FromT from) { return FromEGLenum(from); } // This and the next 2 template specializations handle distinguishing between EGLint, EGLAttrib // and other. This is needed because on some architectures EGLint and EGLAttrib are not the same // base type. Previously the code conditionally compiled 2 specializations on 64 bit but it turns // out on WatchOS the assumption about 32/64 bit and if EGLint and ELGAttrib are the same or // different did not hold. template ::value>::type * = nullptr, typename std::enable_if::value>::type * = nullptr> typename std::remove_reference::type PackParam(FromT attribs) { return AttributeMap::CreateFromIntArray(attribs); } template ::value>::type * = nullptr, typename std::enable_if::value>::type * = nullptr, typename std::enable_if::value>::type * = nullptr> typename std::remove_reference::type PackParam(FromT attribs) { return AttributeMap::CreateFromAttribArray(attribs); } template ::value>::type * = nullptr, typename std::enable_if::value>::type * = nullptr, typename std::enable_if::value>::type * = nullptr> typename std::remove_reference::type PackParam(FromT attribs) { return static_cast(attribs); } } // namespace egl #define ANGLE_EGL_VALIDATE(THREAD, EP, OBJ, RETURN_TYPE, ...) \ do \ { \ const char *epname = "egl" #EP; \ ValidationContext vctx(THREAD, epname, OBJ); \ auto ANGLE_LOCAL_VAR = (Validate##EP(&vctx, ##__VA_ARGS__)); \ if (!ANGLE_LOCAL_VAR) \ { \ return GetDefaultReturnValue(THREAD); \ } \ } while (0) #define ANGLE_EGL_VALIDATE_VOID(THREAD, EP, OBJ, ...) \ do \ { \ const char *epname = "egl" #EP; \ ValidationContext vctx(THREAD, epname, OBJ); \ auto ANGLE_LOCAL_VAR = (Validate##EP(&vctx, ##__VA_ARGS__)); \ if (!ANGLE_LOCAL_VAR) \ { \ return; \ } \ } while (0) #define ANGLE_EGL_TRY(THREAD, EXPR, FUNCNAME, LABELOBJECT) \ do \ { \ auto ANGLE_LOCAL_VAR = (EXPR); \ if (ANGLE_LOCAL_VAR.isError()) \ return THREAD->setError(ANGLE_LOCAL_VAR, FUNCNAME, LABELOBJECT); \ } while (0) #define ANGLE_EGL_TRY_RETURN(THREAD, EXPR, FUNCNAME, LABELOBJECT, RETVAL) \ do \ { \ auto ANGLE_LOCAL_VAR = (EXPR); \ if (ANGLE_LOCAL_VAR.isError()) \ { \ THREAD->setError(ANGLE_LOCAL_VAR, FUNCNAME, LABELOBJECT); \ return RETVAL; \ } \ } while (0) #define ANGLE_EGLBOOLEAN_TRY(EXPR) \ do \ { \ EGLBoolean ANGLE_LOCAL_VAR = (EXPR); \ if (ANGLE_LOCAL_VAR != EGL_TRUE) \ { \ return ANGLE_LOCAL_VAR; \ } \ } while (0) #endif // LIBANGLE_VALIDATIONEGL_H_