Commit 75359664 by Geoff Lang Committed by Commit Bot

Implement EGL_KHR_debug.

BUG=angleproject:1618 Change-Id: I790944b49badc910b6c72266469fcb8e86ac4252 Reviewed-on: https://chromium-review.googlesource.com/1019387 Commit-Queue: Geoff Lang <geofflang@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 448da49c
...@@ -16,6 +16,90 @@ namespace egl ...@@ -16,6 +16,90 @@ namespace egl
{ {
template <> template <>
MessageType FromEGLenum<MessageType>(EGLenum from)
{
switch (from)
{
case EGL_DEBUG_MSG_CRITICAL_KHR:
return MessageType::Critical;
case EGL_DEBUG_MSG_ERROR_KHR:
return MessageType::Error;
case EGL_DEBUG_MSG_WARN_KHR:
return MessageType::Warn;
case EGL_DEBUG_MSG_INFO_KHR:
return MessageType::Info;
default:
return MessageType::InvalidEnum;
}
}
EGLenum ToEGLenum(MessageType from)
{
switch (from)
{
case MessageType::Critical:
return EGL_DEBUG_MSG_CRITICAL_KHR;
case MessageType::Error:
return EGL_DEBUG_MSG_ERROR_KHR;
case MessageType::Warn:
return EGL_DEBUG_MSG_WARN_KHR;
case MessageType::Info:
return EGL_DEBUG_MSG_INFO_KHR;
default:
UNREACHABLE();
return 0;
}
}
template <>
ObjectType FromEGLenum<ObjectType>(EGLenum from)
{
switch (from)
{
case EGL_OBJECT_THREAD_KHR:
return ObjectType::Thread;
case EGL_OBJECT_DISPLAY_KHR:
return ObjectType::Display;
case EGL_OBJECT_CONTEXT_KHR:
return ObjectType::Context;
case EGL_OBJECT_SURFACE_KHR:
return ObjectType::Surface;
case EGL_OBJECT_IMAGE_KHR:
return ObjectType::Image;
case EGL_OBJECT_SYNC_KHR:
return ObjectType::Sync;
case EGL_OBJECT_STREAM_KHR:
return ObjectType::Stream;
default:
return ObjectType::InvalidEnum;
}
}
EGLenum ToEGLenum(ObjectType from)
{
switch (from)
{
case ObjectType::Thread:
return EGL_OBJECT_THREAD_KHR;
case ObjectType::Display:
return EGL_OBJECT_DISPLAY_KHR;
case ObjectType::Context:
return EGL_OBJECT_CONTEXT_KHR;
case ObjectType::Surface:
return EGL_OBJECT_SURFACE_KHR;
case ObjectType::Image:
return EGL_OBJECT_IMAGE_KHR;
case ObjectType::Sync:
return EGL_OBJECT_SYNC_KHR;
case ObjectType::Stream:
return EGL_OBJECT_STREAM_KHR;
default:
UNREACHABLE();
return 0;
}
}
template <>
TextureFormat FromEGLenum<TextureFormat>(EGLenum from) TextureFormat FromEGLenum<TextureFormat>(EGLenum from)
{ {
switch (from) switch (from)
......
...@@ -24,6 +24,39 @@ namespace egl ...@@ -24,6 +24,39 @@ namespace egl
template <typename Enum> template <typename Enum>
Enum FromEGLenum(EGLenum from); Enum FromEGLenum(EGLenum from);
enum class MessageType : uint8_t
{
Critical = 0,
Error = 1,
Warn = 2,
Info = 3,
InvalidEnum = 4,
EnumCount = 4,
};
template <>
MessageType FromEGLenum<MessageType>(EGLenum from);
EGLenum ToEGLenum(MessageType from);
enum class ObjectType : uint8_t
{
Thread = 0,
Display = 1,
Context = 2,
Surface = 3,
Image = 4,
Sync = 5,
Stream = 6,
InvalidEnum = 7,
EnumCount = 7,
};
template <>
ObjectType FromEGLenum<ObjectType>(EGLenum from);
EGLenum ToEGLenum(ObjectType from);
enum class TextureFormat : uint8_t enum class TextureFormat : uint8_t
{ {
NoTexture = 0, NoTexture = 0,
......
...@@ -149,6 +149,41 @@ TextureType SamplerTypeToTextureType(GLenum samplerType) ...@@ -149,6 +149,41 @@ TextureType SamplerTypeToTextureType(GLenum samplerType)
} // namespace gl } // namespace gl
namespace egl
{
MessageType ErrorCodeToMessageType(EGLint errorCode)
{
switch (errorCode)
{
case EGL_BAD_ALLOC:
case EGL_CONTEXT_LOST:
case EGL_NOT_INITIALIZED:
return MessageType::Critical;
case EGL_BAD_ACCESS:
case EGL_BAD_ATTRIBUTE:
case EGL_BAD_CONFIG:
case EGL_BAD_CONTEXT:
case EGL_BAD_CURRENT_SURFACE:
case EGL_BAD_DISPLAY:
case EGL_BAD_MATCH:
case EGL_BAD_NATIVE_PIXMAP:
case EGL_BAD_NATIVE_WINDOW:
case EGL_BAD_PARAMETER:
case EGL_BAD_SURFACE:
case EGL_BAD_STREAM_KHR:
case EGL_BAD_STATE_KHR:
case EGL_BAD_DEVICE_EXT:
return MessageType::Error;
case EGL_SUCCESS:
default:
UNREACHABLE();
return MessageType::InvalidEnum;
}
}
} // namespace egl
namespace egl_gl namespace egl_gl
{ {
......
...@@ -189,6 +189,11 @@ TextureType SamplerTypeToTextureType(GLenum samplerType); ...@@ -189,6 +189,11 @@ TextureType SamplerTypeToTextureType(GLenum samplerType);
} // namespace gl } // namespace gl
namespace egl
{
MessageType ErrorCodeToMessageType(EGLint errorCode);
} // namespace egl
namespace egl_gl namespace egl_gl
{ {
gl::TextureTarget EGLCubeMapTargetToCubeMapTarget(EGLenum eglTarget); gl::TextureTarget EGLCubeMapTargetToCubeMapTarget(EGLenum eglTarget);
......
...@@ -4,5 +4,22 @@ ...@@ -4,5 +4,22 @@
"NoTexture": "EGL_NO_TEXTURE", "NoTexture": "EGL_NO_TEXTURE",
"RGB": "EGL_TEXTURE_RGB", "RGB": "EGL_TEXTURE_RGB",
"RGBA": "EGL_TEXTURE_RGBA" "RGBA": "EGL_TEXTURE_RGBA"
},
"ObjectType":
{
"Thread": "EGL_OBJECT_THREAD_KHR",
"Display": "EGL_OBJECT_DISPLAY_KHR",
"Context": "EGL_OBJECT_CONTEXT_KHR",
"Surface": "EGL_OBJECT_SURFACE_KHR",
"Image": "EGL_OBJECT_IMAGE_KHR",
"Sync": "EGL_OBJECT_SYNC_KHR",
"Stream": "EGL_OBJECT_STREAM_KHR"
},
"MessageType":
{
"Critical": "EGL_DEBUG_MSG_CRITICAL_KHR",
"Error": "EGL_DEBUG_MSG_ERROR_KHR",
"Warn": "EGL_DEBUG_MSG_WARN_KHR",
"Info": "EGL_DEBUG_MSG_INFO_KHR"
} }
} }
...@@ -1387,7 +1387,8 @@ ClientExtensions::ClientExtensions() ...@@ -1387,7 +1387,8 @@ ClientExtensions::ClientExtensions()
x11Visual(false), x11Visual(false),
experimentalPresentPath(false), experimentalPresentPath(false),
clientGetAllProcAddresses(false), clientGetAllProcAddresses(false),
explicitContext(false) explicitContext(false),
debug(false)
{ {
} }
...@@ -1413,6 +1414,7 @@ std::vector<std::string> ClientExtensions::getStrings() const ...@@ -1413,6 +1414,7 @@ std::vector<std::string> ClientExtensions::getStrings() const
InsertExtensionString("EGL_ANGLE_experimental_present_path", experimentalPresentPath, &extensionStrings); InsertExtensionString("EGL_ANGLE_experimental_present_path", experimentalPresentPath, &extensionStrings);
InsertExtensionString("EGL_KHR_client_get_all_proc_addresses", clientGetAllProcAddresses, &extensionStrings); InsertExtensionString("EGL_KHR_client_get_all_proc_addresses", clientGetAllProcAddresses, &extensionStrings);
InsertExtensionString("EGL_ANGLE_explicit_context", explicitContext, &extensionStrings); InsertExtensionString("EGL_ANGLE_explicit_context", explicitContext, &extensionStrings);
InsertExtensionString("EGL_KHR_debug", debug, &extensionStrings);
// clang-format on // clang-format on
return extensionStrings; return extensionStrings;
......
...@@ -826,6 +826,9 @@ struct ClientExtensions ...@@ -826,6 +826,9 @@ struct ClientExtensions
// EGL_ANGLE_explicit_context // EGL_ANGLE_explicit_context
bool explicitContext; bool explicitContext;
// EGL_KHR_debug
bool debug;
}; };
} // namespace egl } // namespace egl
......
...@@ -280,6 +280,7 @@ Context::Context(rx::EGLImplFactory *implFactory, ...@@ -280,6 +280,7 @@ Context::Context(rx::EGLImplFactory *implFactory,
mDisplayTextureShareGroup(shareTextures != nullptr), mDisplayTextureShareGroup(shareTextures != nullptr),
mSavedArgsType(nullptr), mSavedArgsType(nullptr),
mImplementation(implFactory->createContext(mState)), mImplementation(implFactory->createContext(mState)),
mLabel(nullptr),
mCompiler(), mCompiler(),
mGLState(GetDebug(attribs), mGLState(GetDebug(attribs),
GetBindGeneratesResource(attribs), GetBindGeneratesResource(attribs),
...@@ -518,6 +519,16 @@ Context::~Context() ...@@ -518,6 +519,16 @@ Context::~Context()
{ {
} }
void Context::setLabel(EGLLabelKHR label)
{
mLabel = label;
}
EGLLabelKHR Context::getLabel() const
{
return mLabel;
}
egl::Error Context::makeCurrent(egl::Display *display, egl::Surface *surface) egl::Error Context::makeCurrent(egl::Display *display, egl::Surface *surface)
{ {
mCurrentDisplay = display; mCurrentDisplay = display;
...@@ -904,7 +915,7 @@ ProgramPipeline *Context::getProgramPipeline(GLuint handle) const ...@@ -904,7 +915,7 @@ ProgramPipeline *Context::getProgramPipeline(GLuint handle) const
return mState.mPipelines->getProgramPipeline(handle); return mState.mPipelines->getProgramPipeline(handle);
} }
LabeledObject *Context::getLabeledObject(GLenum identifier, GLuint name) const gl::LabeledObject *Context::getLabeledObject(GLenum identifier, GLuint name) const
{ {
switch (identifier) switch (identifier)
{ {
...@@ -934,14 +945,14 @@ LabeledObject *Context::getLabeledObject(GLenum identifier, GLuint name) const ...@@ -934,14 +945,14 @@ LabeledObject *Context::getLabeledObject(GLenum identifier, GLuint name) const
} }
} }
LabeledObject *Context::getLabeledObjectFromPtr(const void *ptr) const gl::LabeledObject *Context::getLabeledObjectFromPtr(const void *ptr) const
{ {
return getSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr))); return getSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr)));
} }
void Context::objectLabel(GLenum identifier, GLuint name, GLsizei length, const GLchar *label) void Context::objectLabel(GLenum identifier, GLuint name, GLsizei length, const GLchar *label)
{ {
LabeledObject *object = getLabeledObject(identifier, name); gl::LabeledObject *object = getLabeledObject(identifier, name);
ASSERT(object != nullptr); ASSERT(object != nullptr);
std::string labelName = GetObjectLabelFromPointer(length, label); std::string labelName = GetObjectLabelFromPointer(length, label);
...@@ -954,7 +965,7 @@ void Context::objectLabel(GLenum identifier, GLuint name, GLsizei length, const ...@@ -954,7 +965,7 @@ void Context::objectLabel(GLenum identifier, GLuint name, GLsizei length, const
void Context::objectPtrLabel(const void *ptr, GLsizei length, const GLchar *label) void Context::objectPtrLabel(const void *ptr, GLsizei length, const GLchar *label)
{ {
LabeledObject *object = getLabeledObjectFromPtr(ptr); gl::LabeledObject *object = getLabeledObjectFromPtr(ptr);
ASSERT(object != nullptr); ASSERT(object != nullptr);
std::string labelName = GetObjectLabelFromPointer(length, label); std::string labelName = GetObjectLabelFromPointer(length, label);
...@@ -967,7 +978,7 @@ void Context::getObjectLabel(GLenum identifier, ...@@ -967,7 +978,7 @@ void Context::getObjectLabel(GLenum identifier,
GLsizei *length, GLsizei *length,
GLchar *label) const GLchar *label) const
{ {
LabeledObject *object = getLabeledObject(identifier, name); gl::LabeledObject *object = getLabeledObject(identifier, name);
ASSERT(object != nullptr); ASSERT(object != nullptr);
const std::string &objectLabel = object->getLabel(); const std::string &objectLabel = object->getLabel();
...@@ -979,7 +990,7 @@ void Context::getObjectPtrLabel(const void *ptr, ...@@ -979,7 +990,7 @@ void Context::getObjectPtrLabel(const void *ptr,
GLsizei *length, GLsizei *length,
GLchar *label) const GLchar *label) const
{ {
LabeledObject *object = getLabeledObjectFromPtr(ptr); gl::LabeledObject *object = getLabeledObjectFromPtr(ptr);
ASSERT(object != nullptr); ASSERT(object != nullptr);
const std::string &objectLabel = object->getLabel(); const std::string &objectLabel = object->getLabel();
......
...@@ -63,7 +63,7 @@ class TransformFeedback; ...@@ -63,7 +63,7 @@ class TransformFeedback;
class VertexArray; class VertexArray;
struct VertexAttribute; struct VertexAttribute;
class Context final : angle::NonCopyable class Context final : public egl::LabeledObject, angle::NonCopyable
{ {
public: public:
Context(rx::EGLImplFactory *implFactory, Context(rx::EGLImplFactory *implFactory,
...@@ -78,6 +78,9 @@ class Context final : angle::NonCopyable ...@@ -78,6 +78,9 @@ class Context final : angle::NonCopyable
egl::Error onDestroy(const egl::Display *display); egl::Error onDestroy(const egl::Display *display);
~Context(); ~Context();
void setLabel(EGLLabelKHR label) override;
EGLLabelKHR getLabel() const override;
egl::Error makeCurrent(egl::Display *display, egl::Surface *surface); egl::Error makeCurrent(egl::Display *display, egl::Surface *surface);
egl::Error releaseSurface(const egl::Display *display); egl::Error releaseSurface(const egl::Display *display);
...@@ -1502,8 +1505,8 @@ class Context final : angle::NonCopyable ...@@ -1502,8 +1505,8 @@ class Context final : angle::NonCopyable
void updateCaps(); void updateCaps();
void initWorkarounds(); void initWorkarounds();
LabeledObject *getLabeledObject(GLenum identifier, GLuint name) const; gl::LabeledObject *getLabeledObject(GLenum identifier, GLuint name) const;
LabeledObject *getLabeledObjectFromPtr(const void *ptr) const; gl::LabeledObject *getLabeledObjectFromPtr(const void *ptr) const;
ContextState mState; ContextState mState;
bool mSkipValidation; bool mSkipValidation;
...@@ -1519,6 +1522,8 @@ class Context final : angle::NonCopyable ...@@ -1519,6 +1522,8 @@ class Context final : angle::NonCopyable
std::unique_ptr<rx::ContextImpl> mImplementation; std::unique_ptr<rx::ContextImpl> mImplementation;
EGLLabelKHR mLabel;
// Caps to use for validation // Caps to use for validation
Caps mCaps; Caps mCaps;
TextureCapsMap mTextureCaps; TextureCapsMap mTextureCaps;
......
...@@ -325,3 +325,64 @@ void Debug::pushDefaultGroup() ...@@ -325,3 +325,64 @@ void Debug::pushDefaultGroup()
mGroups.push_back(std::move(g)); mGroups.push_back(std::move(g));
} }
} // namespace gl } // namespace gl
namespace egl
{
namespace
{
angle::PackedEnumBitSet<MessageType> GetDefaultMessageTypeBits()
{
angle::PackedEnumBitSet<MessageType> result;
result.set(MessageType::Critical);
result.set(MessageType::Error);
return result;
}
} // anonymous namespace
Debug::Debug() : mCallback(nullptr), mEnabledMessageTypes(GetDefaultMessageTypeBits())
{
}
void Debug::setCallback(EGLDEBUGPROCKHR callback, const AttributeMap &attribs)
{
mCallback = callback;
const angle::PackedEnumBitSet<MessageType> defaultMessageTypes = GetDefaultMessageTypeBits();
if (mCallback != nullptr)
{
for (MessageType messageType : angle::AllEnums<MessageType>())
{
mEnabledMessageTypes[messageType] =
(attribs.getAsInt(egl::ToEGLenum(messageType), defaultMessageTypes[messageType]) ==
EGL_TRUE);
}
}
}
EGLDEBUGPROCKHR Debug::getCallback() const
{
return mCallback;
}
bool Debug::isMessageTypeEnabled(MessageType type) const
{
return mEnabledMessageTypes[type];
}
void Debug::insertMessage(EGLenum error,
const char *command,
MessageType messageType,
EGLLabelKHR threadLabel,
EGLLabelKHR objectLabel,
const std::string &message) const
{
// TODO(geofflang): Lock before checking the callback. http://anglebug.com/2464
if (mCallback && isMessageTypeEnabled(messageType))
{
mCallback(error, command, egl::ToEGLenum(messageType), threadLabel, objectLabel,
message.c_str());
}
}
} // namespace egl
...@@ -10,7 +10,9 @@ ...@@ -10,7 +10,9 @@
#define LIBANGLE_DEBUG_H_ #define LIBANGLE_DEBUG_H_
#include "angle_gl.h" #include "angle_gl.h"
#include "common/PackedEnums.h"
#include "common/angleutils.h" #include "common/angleutils.h"
#include "libANGLE/AttributeMap.h"
#include <deque> #include <deque>
#include <string> #include <string>
...@@ -126,4 +128,35 @@ class Debug : angle::NonCopyable ...@@ -126,4 +128,35 @@ class Debug : angle::NonCopyable
}; };
} // namespace gl } // namespace gl
namespace egl
{
class LabeledObject
{
public:
virtual ~LabeledObject() {}
virtual void setLabel(EGLLabelKHR label) = 0;
virtual EGLLabelKHR getLabel() const = 0;
};
class Debug : angle::NonCopyable
{
public:
Debug();
void setCallback(EGLDEBUGPROCKHR callback, const AttributeMap &attribs);
EGLDEBUGPROCKHR getCallback() const;
bool isMessageTypeEnabled(MessageType type) const;
void insertMessage(EGLenum error,
const char *command,
MessageType messageType,
EGLLabelKHR threadLabel,
EGLLabelKHR objectLabel,
const std::string &message) const;
private:
EGLDEBUGPROCKHR mCallback;
angle::PackedEnumBitSet<MessageType> mEnabledMessageTypes;
};
} // namespace egl
#endif // LIBANGLE_DEBUG_H_ #endif // LIBANGLE_DEBUG_H_
...@@ -70,14 +70,14 @@ egl::Error Device::CreateDevice(EGLint deviceType, void *nativeDevice, Device ** ...@@ -70,14 +70,14 @@ egl::Error Device::CreateDevice(EGLint deviceType, void *nativeDevice, Device **
return NoError(); return NoError();
} }
bool Device::IsValidDevice(Device *device) bool Device::IsValidDevice(const Device *device)
{ {
const DeviceSet *deviceSet = GetDeviceSet(); const DeviceSet *deviceSet = GetDeviceSet();
return deviceSet->find(device) != deviceSet->end(); return deviceSet->find(const_cast<Device *>(device)) != deviceSet->end();
} }
Device::Device(Display *owningDisplay, rx::DeviceImpl *impl) Device::Device(Display *owningDisplay, rx::DeviceImpl *impl)
: mOwningDisplay(owningDisplay), mImplementation(impl) : mLabel(nullptr), mOwningDisplay(owningDisplay), mImplementation(impl)
{ {
ASSERT(GetDeviceSet()->find(this) == GetDeviceSet()->end()); ASSERT(GetDeviceSet()->find(this) == GetDeviceSet()->end());
GetDeviceSet()->insert(this); GetDeviceSet()->insert(this);
...@@ -90,6 +90,16 @@ Device::~Device() ...@@ -90,6 +90,16 @@ Device::~Device()
GetDeviceSet()->erase(this); GetDeviceSet()->erase(this);
} }
void Device::setLabel(EGLLabelKHR label)
{
mLabel = label;
}
EGLLabelKHR Device::getLabel() const
{
return mLabel;
}
Error Device::getDevice(EGLAttrib *value) Error Device::getDevice(EGLAttrib *value)
{ {
void *nativeDevice = nullptr; void *nativeDevice = nullptr;
......
...@@ -23,12 +23,15 @@ class DeviceImpl; ...@@ -23,12 +23,15 @@ class DeviceImpl;
namespace egl namespace egl
{ {
class Device final : angle::NonCopyable class Device final : public LabeledObject, angle::NonCopyable
{ {
public: public:
Device(Display *owningDisplay, rx::DeviceImpl *impl); Device(Display *owningDisplay, rx::DeviceImpl *impl);
virtual ~Device(); virtual ~Device();
void setLabel(EGLLabelKHR label) override;
EGLLabelKHR getLabel() const override;
Error getDevice(EGLAttrib *value); Error getDevice(EGLAttrib *value);
Display *getOwningDisplay() { return mOwningDisplay; }; Display *getOwningDisplay() { return mOwningDisplay; };
EGLint getType(); EGLint getType();
...@@ -39,11 +42,13 @@ class Device final : angle::NonCopyable ...@@ -39,11 +42,13 @@ class Device final : angle::NonCopyable
rx::DeviceImpl *getImplementation() { return mImplementation.get(); } rx::DeviceImpl *getImplementation() { return mImplementation.get(); }
static egl::Error CreateDevice(EGLint deviceType, void *nativeDevice, Device **outDevice); static egl::Error CreateDevice(EGLint deviceType, void *nativeDevice, Device **outDevice);
static bool IsValidDevice(Device *device); static bool IsValidDevice(const Device *device);
private: private:
void initDeviceExtensions(); void initDeviceExtensions();
EGLLabelKHR mLabel;
Display *mOwningDisplay; Display *mOwningDisplay;
std::unique_ptr<rx::DeviceImpl> mImplementation; std::unique_ptr<rx::DeviceImpl> mImplementation;
......
...@@ -273,7 +273,7 @@ void ANGLESetDefaultDisplayPlatform(angle::EGLDisplayType display) ...@@ -273,7 +273,7 @@ void ANGLESetDefaultDisplayPlatform(angle::EGLDisplayType display)
} // anonymous namespace } // anonymous namespace
DisplayState::DisplayState() DisplayState::DisplayState() : label(nullptr)
{ {
} }
...@@ -425,6 +425,16 @@ Display::~Display() ...@@ -425,6 +425,16 @@ Display::~Display()
SafeDelete(mImplementation); SafeDelete(mImplementation);
} }
void Display::setLabel(EGLLabelKHR label)
{
mState.label = label;
}
EGLLabelKHR Display::getLabel() const
{
return mState.label;
}
void Display::setAttributes(rx::DisplayImpl *impl, const AttributeMap &attribMap) void Display::setAttributes(rx::DisplayImpl *impl, const AttributeMap &attribMap)
{ {
ASSERT(!mInitialized); ASSERT(!mInitialized);
...@@ -1020,6 +1030,7 @@ static ClientExtensions GenerateClientExtensions() ...@@ -1020,6 +1030,7 @@ static ClientExtensions GenerateClientExtensions()
extensions.clientGetAllProcAddresses = true; extensions.clientGetAllProcAddresses = true;
extensions.explicitContext = true; extensions.explicitContext = true;
extensions.debug = true;
return extensions; return extensions;
} }
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include "libANGLE/AttributeMap.h" #include "libANGLE/AttributeMap.h"
#include "libANGLE/Caps.h" #include "libANGLE/Caps.h"
#include "libANGLE/Config.h" #include "libANGLE/Config.h"
#include "libANGLE/Debug.h"
#include "libANGLE/Error.h" #include "libANGLE/Error.h"
#include "libANGLE/LoggingAnnotator.h" #include "libANGLE/LoggingAnnotator.h"
#include "libANGLE/MemoryProgramCache.h" #include "libANGLE/MemoryProgramCache.h"
...@@ -48,17 +49,21 @@ struct DisplayState final : private angle::NonCopyable ...@@ -48,17 +49,21 @@ struct DisplayState final : private angle::NonCopyable
DisplayState(); DisplayState();
~DisplayState(); ~DisplayState();
EGLLabelKHR label;
SurfaceSet surfaceSet; SurfaceSet surfaceSet;
}; };
// Constant coded here as a sanity limit. // Constant coded here as a sanity limit.
constexpr EGLAttrib kProgramCacheSizeAbsoluteMax = 0x4000000; constexpr EGLAttrib kProgramCacheSizeAbsoluteMax = 0x4000000;
class Display final : angle::NonCopyable class Display final : public LabeledObject, angle::NonCopyable
{ {
public: public:
~Display(); ~Display();
void setLabel(EGLLabelKHR label) override;
EGLLabelKHR getLabel() const override;
Error initialize(); Error initialize();
Error terminate(); Error terminate();
......
...@@ -118,7 +118,7 @@ void ImageSibling::setSourceEGLImageInitState(gl::InitState initState) const ...@@ -118,7 +118,7 @@ void ImageSibling::setSourceEGLImageInitState(gl::InitState initState) const
} }
ImageState::ImageState(EGLenum target, ImageSibling *buffer, const AttributeMap &attribs) ImageState::ImageState(EGLenum target, ImageSibling *buffer, const AttributeMap &attribs)
: imageIndex(GetImageIndex(target, attribs)), source(buffer), targets() : label(nullptr), imageIndex(GetImageIndex(target, attribs)), source(buffer), targets()
{ {
} }
...@@ -161,6 +161,16 @@ Image::~Image() ...@@ -161,6 +161,16 @@ Image::~Image()
SafeDelete(mImplementation); SafeDelete(mImplementation);
} }
void Image::setLabel(EGLLabelKHR label)
{
mState.label = label;
}
EGLLabelKHR Image::getLabel() const
{
return mState.label;
}
void Image::addTargetSibling(ImageSibling *sibling) void Image::addTargetSibling(ImageSibling *sibling)
{ {
mState.targets.insert(sibling); mState.targets.insert(sibling);
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "common/angleutils.h" #include "common/angleutils.h"
#include "libANGLE/AttributeMap.h" #include "libANGLE/AttributeMap.h"
#include "libANGLE/Debug.h"
#include "libANGLE/Error.h" #include "libANGLE/Error.h"
#include "libANGLE/FramebufferAttachment.h" #include "libANGLE/FramebufferAttachment.h"
#include "libANGLE/RefCountObject.h" #include "libANGLE/RefCountObject.h"
...@@ -66,12 +67,13 @@ struct ImageState : private angle::NonCopyable ...@@ -66,12 +67,13 @@ struct ImageState : private angle::NonCopyable
ImageState(EGLenum target, ImageSibling *buffer, const AttributeMap &attribs); ImageState(EGLenum target, ImageSibling *buffer, const AttributeMap &attribs);
~ImageState(); ~ImageState();
EGLLabelKHR label;
gl::ImageIndex imageIndex; gl::ImageIndex imageIndex;
gl::BindingPointer<ImageSibling> source; gl::BindingPointer<ImageSibling> source;
std::set<ImageSibling *> targets; std::set<ImageSibling *> targets;
}; };
class Image final : public gl::RefCountObject class Image final : public gl::RefCountObject, public LabeledObject
{ {
public: public:
Image(rx::EGLImplFactory *factory, Image(rx::EGLImplFactory *factory,
...@@ -82,6 +84,9 @@ class Image final : public gl::RefCountObject ...@@ -82,6 +84,9 @@ class Image final : public gl::RefCountObject
gl::Error onDestroy(const gl::Context *context) override; gl::Error onDestroy(const gl::Context *context) override;
~Image() override; ~Image() override;
void setLabel(EGLLabelKHR label) override;
EGLLabelKHR getLabel() const override;
gl::Format getFormat() const; gl::Format getFormat() const;
size_t getWidth() const; size_t getWidth() const;
size_t getHeight() const; size_t getHeight() const;
......
...@@ -25,7 +25,8 @@ namespace egl ...@@ -25,7 +25,8 @@ namespace egl
{ {
Stream::Stream(Display *display, const AttributeMap &attribs) Stream::Stream(Display *display, const AttributeMap &attribs)
: mDisplay(display), : mLabel(nullptr),
mDisplay(display),
mProducerImplementation(nullptr), mProducerImplementation(nullptr),
mState(EGL_STREAM_STATE_CREATED_KHR), mState(EGL_STREAM_STATE_CREATED_KHR),
mProducerFrame(0), mProducerFrame(0),
...@@ -55,6 +56,16 @@ Stream::~Stream() ...@@ -55,6 +56,16 @@ Stream::~Stream()
} }
} }
void Stream::setLabel(EGLLabelKHR label)
{
mLabel = label;
}
EGLLabelKHR Stream::getLabel() const
{
return mLabel;
}
void Stream::setConsumerLatency(EGLint latency) void Stream::setConsumerLatency(EGLint latency)
{ {
mConsumerLatency = latency; mConsumerLatency = latency;
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include "common/angleutils.h" #include "common/angleutils.h"
#include "libANGLE/AttributeMap.h" #include "libANGLE/AttributeMap.h"
#include "libANGLE/Debug.h"
namespace rx namespace rx
{ {
...@@ -35,12 +36,15 @@ class Display; ...@@ -35,12 +36,15 @@ class Display;
class Error; class Error;
class Thread; class Thread;
class Stream final : angle::NonCopyable class Stream final : public LabeledObject, angle::NonCopyable
{ {
public: public:
Stream(Display *display, const AttributeMap &attribs); Stream(Display *display, const AttributeMap &attribs);
~Stream(); ~Stream();
void setLabel(EGLLabelKHR label) override;
EGLLabelKHR getLabel() const override;
enum class ConsumerType enum class ConsumerType
{ {
NoConsumer, NoConsumer,
...@@ -100,6 +104,8 @@ class Stream final : angle::NonCopyable ...@@ -100,6 +104,8 @@ class Stream final : angle::NonCopyable
Error postD3D11Texture(void *texture, const AttributeMap &attributes); Error postD3D11Texture(void *texture, const AttributeMap &attributes);
private: private:
EGLLabelKHR mLabel;
// Associated display // Associated display
Display *mDisplay; Display *mDisplay;
......
...@@ -25,7 +25,7 @@ namespace egl ...@@ -25,7 +25,7 @@ namespace egl
{ {
SurfaceState::SurfaceState(const egl::Config *configIn, const AttributeMap &attributesIn) SurfaceState::SurfaceState(const egl::Config *configIn, const AttributeMap &attributesIn)
: config(configIn), attributes(attributesIn) : label(nullptr), config(configIn), attributes(attributesIn)
{ {
} }
...@@ -212,6 +212,16 @@ Error Surface::onDestroy(const Display *display) ...@@ -212,6 +212,16 @@ Error Surface::onDestroy(const Display *display)
return NoError(); return NoError();
} }
void Surface::setLabel(EGLLabelKHR label)
{
mState.label = label;
}
EGLLabelKHR Surface::getLabel() const
{
return mState.label;
}
EGLint Surface::getType() const EGLint Surface::getType() const
{ {
return mType; return mType;
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "common/PackedEnums.h" #include "common/PackedEnums.h"
#include "common/angleutils.h" #include "common/angleutils.h"
#include "libANGLE/AttributeMap.h" #include "libANGLE/AttributeMap.h"
#include "libANGLE/Debug.h"
#include "libANGLE/Error.h" #include "libANGLE/Error.h"
#include "libANGLE/FramebufferAttachment.h" #include "libANGLE/FramebufferAttachment.h"
#include "libANGLE/RefCountObject.h" #include "libANGLE/RefCountObject.h"
...@@ -43,15 +44,19 @@ struct SurfaceState final : private angle::NonCopyable ...@@ -43,15 +44,19 @@ struct SurfaceState final : private angle::NonCopyable
{ {
SurfaceState(const egl::Config *configIn, const AttributeMap &attributesIn); SurfaceState(const egl::Config *configIn, const AttributeMap &attributesIn);
EGLLabelKHR label;
const egl::Config *config; const egl::Config *config;
AttributeMap attributes; AttributeMap attributes;
}; };
class Surface : public gl::FramebufferAttachmentObject class Surface : public LabeledObject, public gl::FramebufferAttachmentObject
{ {
public: public:
rx::SurfaceImpl *getImplementation() const { return mImplementation; } rx::SurfaceImpl *getImplementation() const { return mImplementation; }
void setLabel(EGLLabelKHR label) override;
EGLLabelKHR getLabel() const override;
EGLint getType() const; EGLint getType() const;
Error initialize(const Display *display); Error initialize(const Display *display);
......
...@@ -9,20 +9,48 @@ ...@@ -9,20 +9,48 @@
#include "libANGLE/Thread.h" #include "libANGLE/Thread.h"
#include "libANGLE/Context.h" #include "libANGLE/Context.h"
#include "libANGLE/Debug.h"
#include "libANGLE/Error.h" #include "libANGLE/Error.h"
namespace egl namespace egl
{ {
Thread::Thread() Thread::Thread()
: mError(EGL_SUCCESS), : mLabel(nullptr),
mError(EGL_SUCCESS),
mAPI(EGL_OPENGL_ES_API), mAPI(EGL_OPENGL_ES_API),
mContext(static_cast<gl::Context *>(EGL_NO_CONTEXT)) mContext(static_cast<gl::Context *>(EGL_NO_CONTEXT))
{ {
} }
void Thread::setError(const Error &error) void Thread::setLabel(EGLLabelKHR label)
{
mLabel = label;
}
EGLLabelKHR Thread::getLabel() const
{
return mLabel;
}
void Thread::setSuccess()
{ {
mError = EGL_SUCCESS;
}
void Thread::setError(const Error &error,
const Debug *debug,
const char *command,
const LabeledObject *object)
{
ASSERT(debug != nullptr);
mError = error.getCode(); mError = error.getCode();
if (error.isError() && !error.getMessage().empty())
{
debug->insertMessage(error.getCode(), command, ErrorCodeToMessageType(error.getCode()),
getLabel(), object ? object->getLabel() : nullptr, error.getMessage());
}
} }
EGLint Thread::getError() const EGLint Thread::getError() const
......
...@@ -11,6 +11,8 @@ ...@@ -11,6 +11,8 @@
#include <EGL/egl.h> #include <EGL/egl.h>
#include "libANGLE/Debug.h"
namespace gl namespace gl
{ {
class Context; class Context;
...@@ -19,15 +21,23 @@ class Context; ...@@ -19,15 +21,23 @@ class Context;
namespace egl namespace egl
{ {
class Error; class Error;
class Debug;
class Display; class Display;
class Surface; class Surface;
class Thread class Thread : public LabeledObject
{ {
public: public:
Thread(); Thread();
void setError(const Error &error); void setLabel(EGLLabelKHR label) override;
EGLLabelKHR getLabel() const override;
void setSuccess();
void setError(const Error &error,
const Debug *debug,
const char *command,
const LabeledObject *object);
EGLint getError() const; EGLint getError() const;
void setAPI(EGLenum api); void setAPI(EGLenum api);
...@@ -41,6 +51,7 @@ class Thread ...@@ -41,6 +51,7 @@ class Thread
Display *getCurrentDisplay() const; Display *getCurrentDisplay() const;
private: private:
EGLLabelKHR mLabel;
EGLint mError; EGLint mError;
EGLenum mAPI; EGLenum mAPI;
gl::Context *mContext; gl::Context *mContext;
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include "libANGLE/Stream.h" #include "libANGLE/Stream.h"
#include "libANGLE/Surface.h" #include "libANGLE/Surface.h"
#include "libANGLE/Texture.h" #include "libANGLE/Texture.h"
#include "libANGLE/Thread.h"
#include "libANGLE/formatutils.h" #include "libANGLE/formatutils.h"
#include <EGL/eglext.h> #include <EGL/eglext.h>
...@@ -493,6 +494,100 @@ Error ValidateGetPlatformDisplayCommon(EGLenum platform, ...@@ -493,6 +494,100 @@ Error ValidateGetPlatformDisplayCommon(EGLenum platform,
return NoError(); return NoError();
} }
Error ValidateStream(const Display *display, const Stream *stream)
{
ANGLE_TRY(ValidateDisplay(display));
const DisplayExtensions &displayExtensions = display->getExtensions();
if (!displayExtensions.stream)
{
return EglBadAccess() << "Stream extension not active";
}
if (stream == EGL_NO_STREAM_KHR || !display->isValidStream(stream))
{
return EglBadStream() << "Invalid stream";
}
return NoError();
}
Error ValidateLabeledObject(Thread *thread,
const Display *display,
ObjectType objectType,
EGLObjectKHR object,
LabeledObject **outLabeledObject)
{
switch (objectType)
{
case ObjectType::Context:
{
gl::Context *context = static_cast<gl::Context *>(object);
ANGLE_TRY(ValidateContext(display, context));
*outLabeledObject = context;
break;
}
case ObjectType::Display:
{
ANGLE_TRY(ValidateDisplay(display));
if (display != object)
{
return EglBadParameter() << "when object type is EGL_OBJECT_DISPLAY_KHR, the "
"object must be the same as the display.";
}
*outLabeledObject = static_cast<Display *>(object);
break;
}
case ObjectType::Image:
{
Image *image = static_cast<Image *>(object);
ANGLE_TRY(ValidateImage(display, image));
*outLabeledObject = image;
break;
}
case ObjectType::Stream:
{
Stream *stream = static_cast<Stream *>(object);
ANGLE_TRY(ValidateStream(display, stream));
*outLabeledObject = stream;
break;
}
case ObjectType::Surface:
{
Surface *surface = static_cast<Surface *>(object);
ANGLE_TRY(ValidateSurface(display, surface));
*outLabeledObject = surface;
break;
}
case ObjectType::Sync:
{
ANGLE_TRY(ValidateDisplay(display));
// TODO(geofflang): Implement sync objects. http://anglebug.com/2466
UNIMPLEMENTED();
return EglBadDisplay() << "Sync objects are unimplemented.";
break;
}
case ObjectType::Thread:
{
*outLabeledObject = thread;
break;
}
default:
return EglBadParameter() << "unknown object type.";
}
return NoError();
}
} // namespace } // namespace
Error ValidateDisplay(const Display *display) Error ValidateDisplay(const Display *display)
...@@ -568,24 +663,101 @@ Error ValidateImage(const Display *display, const Image *image) ...@@ -568,24 +663,101 @@ Error ValidateImage(const Display *display, const Image *image)
return NoError(); return NoError();
} }
Error ValidateStream(const Display *display, const Stream *stream) Error ValidateDevice(const Device *device)
{ {
ANGLE_TRY(ValidateDisplay(display)); if (device == EGL_NO_DEVICE_EXT)
const DisplayExtensions &displayExtensions = display->getExtensions();
if (!displayExtensions.stream)
{ {
return EglBadAccess() << "Stream extension not active"; return EglBadAccess() << "device is EGL_NO_DEVICE.";
} }
if (stream == EGL_NO_STREAM_KHR || !display->isValidStream(stream)) if (!Device::IsValidDevice(device))
{ {
return EglBadStream() << "Invalid stream"; return EglBadAccess() << "device is not valid.";
} }
return NoError(); return NoError();
} }
const Thread *GetThreadIfValid(const Thread *thread)
{
// Threads should always be valid
return thread;
}
const Display *GetDisplayIfValid(const Display *display)
{
if (ValidateDisplay(display).isError())
{
return nullptr;
}
return display;
}
const Surface *GetSurfaceIfValid(const Display *display, const Surface *surface)
{
if (ValidateSurface(display, surface).isError())
{
return nullptr;
}
return surface;
}
const Image *GetImageIfValid(const Display *display, const Image *image)
{
if (ValidateImage(display, image).isError())
{
return nullptr;
}
return image;
}
const Stream *GetStreamIfValid(const Display *display, const Stream *stream)
{
if (ValidateStream(display, stream).isError())
{
return nullptr;
}
return stream;
}
const gl::Context *GetContextIfValid(const Display *display, const gl::Context *context)
{
if (ValidateContext(display, context).isError())
{
return nullptr;
}
return context;
}
const Device *GetDeviceIfValid(const Device *device)
{
if (ValidateDevice(device).isError())
{
return nullptr;
}
return device;
}
LabeledObject *GetLabeledObjectIfValid(Thread *thread,
const Display *display,
ObjectType objectType,
EGLObjectKHR object)
{
LabeledObject *labeledObject = nullptr;
if (ValidateLabeledObject(thread, display, objectType, object, &labeledObject).isError())
{
return nullptr;
}
return labeledObject;
}
Error ValidateCreateContext(Display *display, Error ValidateCreateContext(Display *display,
Config *configuration, Config *configuration,
gl::Context *shareContext, gl::Context *shareContext,
...@@ -2715,4 +2887,73 @@ Error ValidateQueryContext(const Display *display, ...@@ -2715,4 +2887,73 @@ Error ValidateQueryContext(const Display *display,
return NoError(); return NoError();
} }
Error ValidateDebugMessageControlKHR(EGLDEBUGPROCKHR callback, const AttributeMap &attribs)
{
const ClientExtensions &clientExtensions = Display::GetClientExtensions();
if (!clientExtensions.debug)
{
return EglBadAccess() << "EGL_KHR_debug extension is not available.";
}
for (const auto &attrib : attribs)
{
switch (attrib.first)
{
case EGL_DEBUG_MSG_CRITICAL_KHR:
case EGL_DEBUG_MSG_ERROR_KHR:
case EGL_DEBUG_MSG_WARN_KHR:
case EGL_DEBUG_MSG_INFO_KHR:
if (attrib.second != EGL_TRUE && attrib.second != EGL_FALSE)
{
return EglBadAttribute() << "message controls must be EGL_TRUE or EGL_FALSE.";
}
break;
}
}
return NoError();
}
Error ValidateQueryDebugKHR(EGLint attribute, EGLAttrib *value)
{
const ClientExtensions &clientExtensions = Display::GetClientExtensions();
if (!clientExtensions.debug)
{
return EglBadAccess() << "EGL_KHR_debug extension is not available.";
}
switch (attribute)
{
case EGL_DEBUG_MSG_CRITICAL_KHR:
case EGL_DEBUG_MSG_ERROR_KHR:
case EGL_DEBUG_MSG_WARN_KHR:
case EGL_DEBUG_MSG_INFO_KHR:
case EGL_DEBUG_CALLBACK_KHR:
break;
default:
return EglBadAttribute() << "unknown attribute.";
}
return NoError();
}
Error ValidateLabelObjectKHR(Thread *thread,
const Display *display,
ObjectType objectType,
EGLObjectKHR object,
EGLLabelKHR label)
{
const ClientExtensions &clientExtensions = Display::GetClientExtensions();
if (!clientExtensions.debug)
{
return EglBadAccess() << "EGL_KHR_debug extension is not available.";
}
LabeledObject *labeledObject = nullptr;
ANGLE_TRY(ValidateLabeledObject(thread, display, objectType, object, &labeledObject));
return NoError();
}
} // namespace egl } // namespace egl
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#ifndef LIBANGLE_VALIDATIONEGL_H_ #ifndef LIBANGLE_VALIDATIONEGL_H_
#define LIBANGLE_VALIDATIONEGL_H_ #define LIBANGLE_VALIDATIONEGL_H_
#include "common/PackedEnums.h"
#include "libANGLE/Error.h" #include "libANGLE/Error.h"
#include <EGL/egl.h> #include <EGL/egl.h>
...@@ -30,6 +31,8 @@ class Display; ...@@ -30,6 +31,8 @@ class Display;
class Image; class Image;
class Stream; class Stream;
class Surface; class Surface;
class Thread;
class LabeledObject;
// Object validation // Object validation
Error ValidateDisplay(const Display *display); Error ValidateDisplay(const Display *display);
...@@ -37,6 +40,20 @@ Error ValidateSurface(const Display *display, const Surface *surface); ...@@ -37,6 +40,20 @@ Error ValidateSurface(const Display *display, const Surface *surface);
Error ValidateConfig(const Display *display, const Config *config); Error ValidateConfig(const Display *display, const Config *config);
Error ValidateContext(const Display *display, const gl::Context *context); Error ValidateContext(const Display *display, const gl::Context *context);
Error ValidateImage(const Display *display, const Image *image); Error ValidateImage(const Display *display, const Image *image);
Error ValidateDevice(const Device *device);
// 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);
LabeledObject *GetLabeledObjectIfValid(Thread *thread,
const Display *display,
ObjectType objectType,
EGLObjectKHR object);
// Entry point validation // Entry point validation
Error ValidateCreateContext(Display *display, Error ValidateCreateContext(Display *display,
...@@ -181,23 +198,34 @@ Error ValidateQueryContext(const Display *display, ...@@ -181,23 +198,34 @@ Error ValidateQueryContext(const Display *display,
EGLint attribute, EGLint attribute,
EGLint *value); EGLint *value);
// EGL_KHR_debug
Error ValidateDebugMessageControlKHR(EGLDEBUGPROCKHR callback, const AttributeMap &attribs);
Error ValidateQueryDebugKHR(EGLint attribute, EGLAttrib *value);
Error ValidateLabelObjectKHR(Thread *thread,
const Display *display,
ObjectType objectType,
EGLObjectKHR object,
EGLLabelKHR label);
} // namespace egl } // namespace egl
#define ANGLE_EGL_TRY(THREAD, EXPR) \ #define ANGLE_EGL_TRY(THREAD, EXPR, FUNCNAME, LABELOBJECT) \
{ \ { \
auto ANGLE_LOCAL_VAR = (EXPR); \ auto ANGLE_LOCAL_VAR = (EXPR); \
if (ANGLE_LOCAL_VAR.isError()) \ if (ANGLE_LOCAL_VAR.isError()) \
return THREAD->setError(ANGLE_LOCAL_VAR); \ return THREAD->setError(ANGLE_LOCAL_VAR, GetDebug(), FUNCNAME, LABELOBJECT); \
} }
#define ANGLE_EGL_TRY_RETURN(THREAD, EXPR, RETVAL) \ #define ANGLE_EGL_TRY_RETURN(THREAD, EXPR, FUNCNAME, LABELOBJECT, RETVAL) \
{ \ { \
auto ANGLE_LOCAL_VAR = (EXPR); \ auto ANGLE_LOCAL_VAR = (EXPR); \
if (ANGLE_LOCAL_VAR.isError()) \ if (ANGLE_LOCAL_VAR.isError()) \
{ \ { \
THREAD->setError(ANGLE_LOCAL_VAR); \ THREAD->setError(ANGLE_LOCAL_VAR, GetDebug(), FUNCNAME, LABELOBJECT); \
return RETVAL; \ return RETVAL; \
} \ } \
} }
#endif // LIBANGLE_VALIDATIONEGL_H_ #endif // LIBANGLE_VALIDATIONEGL_H_
...@@ -493,4 +493,22 @@ EGLint EGLAPIENTRY eglProgramCacheResizeANGLE(EGLDisplay dpy, EGLint limit, EGLe ...@@ -493,4 +493,22 @@ EGLint EGLAPIENTRY eglProgramCacheResizeANGLE(EGLDisplay dpy, EGLint limit, EGLe
return egl::ProgramCacheResizeANGLE(dpy, limit, mode); return egl::ProgramCacheResizeANGLE(dpy, limit, mode);
} }
EGLint EGLAPIENTRY eglDebugMessageControlKHR(EGLDEBUGPROCKHR callback, const EGLAttrib *attrib_list)
{
return egl::DebugMessageControlKHR(callback, attrib_list);
}
EGLBoolean EGLAPIENTRY eglQueryDebugKHR(EGLint attribute, EGLAttrib *value)
{
return egl::QueryDebugKHR(attribute, value);
}
EGLint EGLAPIENTRY eglLabelObjectKHR(EGLDisplay dpy,
EGLenum objectType,
EGLObjectKHR object,
EGLLabelKHR label)
{
return egl::LabelObjectKHR(dpy, objectType, object, label);
}
} // extern "C" } // extern "C"
...@@ -66,6 +66,9 @@ EXPORTS ...@@ -66,6 +66,9 @@ EXPORTS
eglCreatePlatformWindowSurfaceEXT @72 eglCreatePlatformWindowSurfaceEXT @72
eglCreatePlatformPixmapSurfaceEXT @73 eglCreatePlatformPixmapSurfaceEXT @73
eglPresentationTimeANDROID @74 eglPresentationTimeANDROID @74
eglDebugMessageControlKHR @75
eglQueryDebugKHR @76
eglLabelObjectKHR @77
; 1.5 entry points ; 1.5 entry points
eglCreateSync @38 eglCreateSync @38
......
...@@ -120,7 +120,7 @@ ANGLE_EXPORT EGLBoolean EGLAPIENTRY PresentationTimeANDROID(EGLDisplay dpy, ...@@ -120,7 +120,7 @@ ANGLE_EXPORT EGLBoolean EGLAPIENTRY PresentationTimeANDROID(EGLDisplay dpy,
EGLSurface surface, EGLSurface surface,
EGLnsecsANDROID time); EGLnsecsANDROID time);
// // EGL_ANGLE_program_cache_control
ANGLE_EXPORT EGLint EGLAPIENTRY ProgramCacheGetAttribANGLE(EGLDisplay dpy, EGLenum attrib); ANGLE_EXPORT EGLint EGLAPIENTRY ProgramCacheGetAttribANGLE(EGLDisplay dpy, EGLenum attrib);
ANGLE_EXPORT void EGLAPIENTRY ProgramCacheQueryANGLE(EGLDisplay dpy, ANGLE_EXPORT void EGLAPIENTRY ProgramCacheQueryANGLE(EGLDisplay dpy,
EGLint index, EGLint index,
...@@ -135,6 +135,17 @@ ANGLE_EXPORT void EGLAPIENTRY ProgramCachePopulateANGLE(EGLDisplay dpy, ...@@ -135,6 +135,17 @@ ANGLE_EXPORT void EGLAPIENTRY ProgramCachePopulateANGLE(EGLDisplay dpy,
EGLint binarysize); EGLint binarysize);
ANGLE_EXPORT EGLint EGLAPIENTRY ProgramCacheResizeANGLE(EGLDisplay dpy, EGLint limit, EGLenum mode); ANGLE_EXPORT EGLint EGLAPIENTRY ProgramCacheResizeANGLE(EGLDisplay dpy, EGLint limit, EGLenum mode);
// EGL_KHR_debug
ANGLE_EXPORT EGLint EGLAPIENTRY DebugMessageControlKHR(EGLDEBUGPROCKHR callback,
const EGLAttrib *attrib_list);
ANGLE_EXPORT EGLBoolean EGLAPIENTRY QueryDebugKHR(EGLint attribute, EGLAttrib *value);
ANGLE_EXPORT EGLint EGLAPIENTRY LabelObjectKHR(EGLDisplay display,
EGLenum objectType,
EGLObjectKHR object,
EGLLabelKHR label);
} // namespace egl } // namespace egl
#endif // LIBGLESV2_ENTRYPOINTSEGLEXT_H_ #endif // LIBGLESV2_ENTRYPOINTSEGLEXT_H_
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "common/platform.h" #include "common/platform.h"
#include "common/tls.h" #include "common/tls.h"
#include "libANGLE/Debug.h"
#include "libANGLE/Thread.h" #include "libANGLE/Thread.h"
namespace gl namespace gl
...@@ -38,6 +39,7 @@ namespace ...@@ -38,6 +39,7 @@ namespace
{ {
static TLSIndex threadTLS = TLS_INVALID_INDEX; static TLSIndex threadTLS = TLS_INVALID_INDEX;
Debug *g_Debug = nullptr;
Thread *AllocateCurrentThread() Thread *AllocateCurrentThread()
{ {
...@@ -57,6 +59,15 @@ Thread *AllocateCurrentThread() ...@@ -57,6 +59,15 @@ Thread *AllocateCurrentThread()
return thread; return thread;
} }
void AllocateDebug()
{
// TODO(geofflang): Lock around global allocation. http://anglebug.com/2464
if (g_Debug == nullptr)
{
g_Debug = new Debug();
}
}
} // anonymous namespace } // anonymous namespace
Thread *GetCurrentThread() Thread *GetCurrentThread()
...@@ -74,6 +85,12 @@ Thread *GetCurrentThread() ...@@ -74,6 +85,12 @@ Thread *GetCurrentThread()
return (current ? current : AllocateCurrentThread()); return (current ? current : AllocateCurrentThread());
} }
Debug *GetDebug()
{
AllocateDebug();
return g_Debug;
}
} // namespace egl } // namespace egl
#ifdef ANGLE_PLATFORM_WINDOWS #ifdef ANGLE_PLATFORM_WINDOWS
...@@ -90,8 +107,16 @@ bool DeallocateCurrentThread() ...@@ -90,8 +107,16 @@ bool DeallocateCurrentThread()
return SetTLSValue(threadTLS, nullptr); return SetTLSValue(threadTLS, nullptr);
} }
void DealocateDebug()
{
SafeDelete(g_Debug);
}
bool InitializeProcess() bool InitializeProcess()
{ {
ASSERT(g_Debug == nullptr);
AllocateDebug();
threadTLS = CreateTLSIndex(); threadTLS = CreateTLSIndex();
if (threadTLS == TLS_INVALID_INDEX) if (threadTLS == TLS_INVALID_INDEX)
{ {
...@@ -103,6 +128,8 @@ bool InitializeProcess() ...@@ -103,6 +128,8 @@ bool InitializeProcess()
bool TerminateProcess() bool TerminateProcess()
{ {
DealocateDebug();
if (!DeallocateCurrentThread()) if (!DeallocateCurrentThread())
{ {
return false; return false;
......
...@@ -20,9 +20,11 @@ Context *GetValidGlobalContext(); ...@@ -20,9 +20,11 @@ Context *GetValidGlobalContext();
namespace egl namespace egl
{ {
class Debug;
class Thread; class Thread;
Thread *GetCurrentThread(); Thread *GetCurrentThread();
Debug *GetDebug();
} // namespace egl } // namespace egl
......
...@@ -47,6 +47,7 @@ ProcEntry g_procTable[] = { ...@@ -47,6 +47,7 @@ ProcEntry g_procTable[] = {
{"eglCreateStreamProducerD3DTextureANGLE", P(egl::CreateStreamProducerD3DTextureANGLE)}, {"eglCreateStreamProducerD3DTextureANGLE", P(egl::CreateStreamProducerD3DTextureANGLE)},
{"eglCreateSync", P(egl::CreateSync)}, {"eglCreateSync", P(egl::CreateSync)},
{"eglCreateWindowSurface", P(egl::CreateWindowSurface)}, {"eglCreateWindowSurface", P(egl::CreateWindowSurface)},
{"eglDebugMessageControlKHR", P(egl::DebugMessageControlKHR)},
{"eglDestroyContext", P(egl::DestroyContext)}, {"eglDestroyContext", P(egl::DestroyContext)},
{"eglDestroyImage", P(egl::DestroyImage)}, {"eglDestroyImage", P(egl::DestroyImage)},
{"eglDestroyImageKHR", P(egl::DestroyImageKHR)}, {"eglDestroyImageKHR", P(egl::DestroyImageKHR)},
...@@ -66,6 +67,7 @@ ProcEntry g_procTable[] = { ...@@ -66,6 +67,7 @@ ProcEntry g_procTable[] = {
{"eglGetSyncAttrib", P(egl::GetSyncAttrib)}, {"eglGetSyncAttrib", P(egl::GetSyncAttrib)},
{"eglGetSyncValuesCHROMIUM", P(egl::GetSyncValuesCHROMIUM)}, {"eglGetSyncValuesCHROMIUM", P(egl::GetSyncValuesCHROMIUM)},
{"eglInitialize", P(egl::Initialize)}, {"eglInitialize", P(egl::Initialize)},
{"eglLabelObjectKHR", P(egl::LabelObjectKHR)},
{"eglMakeCurrent", P(egl::MakeCurrent)}, {"eglMakeCurrent", P(egl::MakeCurrent)},
{"eglPostSubBufferNV", P(egl::PostSubBufferNV)}, {"eglPostSubBufferNV", P(egl::PostSubBufferNV)},
{"eglPresentationTimeANDROID", P(egl::PresentationTimeANDROID)}, {"eglPresentationTimeANDROID", P(egl::PresentationTimeANDROID)},
...@@ -75,6 +77,7 @@ ProcEntry g_procTable[] = { ...@@ -75,6 +77,7 @@ ProcEntry g_procTable[] = {
{"eglProgramCacheResizeANGLE", P(egl::ProgramCacheResizeANGLE)}, {"eglProgramCacheResizeANGLE", P(egl::ProgramCacheResizeANGLE)},
{"eglQueryAPI", P(egl::QueryAPI)}, {"eglQueryAPI", P(egl::QueryAPI)},
{"eglQueryContext", P(egl::QueryContext)}, {"eglQueryContext", P(egl::QueryContext)},
{"eglQueryDebugKHR", P(egl::QueryDebugKHR)},
{"eglQueryDeviceAttribEXT", P(egl::QueryDeviceAttribEXT)}, {"eglQueryDeviceAttribEXT", P(egl::QueryDeviceAttribEXT)},
{"eglQueryDeviceStringEXT", P(egl::QueryDeviceStringEXT)}, {"eglQueryDeviceStringEXT", P(egl::QueryDeviceStringEXT)},
{"eglQueryDisplayAttribEXT", P(egl::QueryDisplayAttribEXT)}, {"eglQueryDisplayAttribEXT", P(egl::QueryDisplayAttribEXT)},
...@@ -1234,5 +1237,5 @@ ProcEntry g_procTable[] = { ...@@ -1234,5 +1237,5 @@ ProcEntry g_procTable[] = {
{"glWeightPointerOES", P(gl::WeightPointerOES)}, {"glWeightPointerOES", P(gl::WeightPointerOES)},
{"glWeightPointerOESContextANGLE", P(gl::WeightPointerOESContextANGLE)}}; {"glWeightPointerOESContextANGLE", P(gl::WeightPointerOESContextANGLE)}};
size_t g_numProcs = 1166; size_t g_numProcs = 1169;
} // namespace egl } // namespace egl
...@@ -839,6 +839,12 @@ ...@@ -839,6 +839,12 @@
"eglProgramCacheResizeANGLE" "eglProgramCacheResizeANGLE"
], ],
"EGL_KHR_debug": [
"eglDebugMessageControlKHR",
"eglQueryDebugKHR",
"eglLabelObjectKHR"
],
"angle::Platform related entry points": [ "angle::Platform related entry points": [
"ANGLEGetDisplayPlatform", "ANGLEGetDisplayPlatform",
"ANGLEResetDisplayPlatform" "ANGLEResetDisplayPlatform"
......
...@@ -127,6 +127,7 @@ ...@@ -127,6 +127,7 @@
'<(angle_path)/src/tests/gl_tests/WebGLReadOutsideFramebufferTest.cpp', '<(angle_path)/src/tests/gl_tests/WebGLReadOutsideFramebufferTest.cpp',
'<(angle_path)/src/tests/egl_tests/EGLContextCompatibilityTest.cpp', '<(angle_path)/src/tests/egl_tests/EGLContextCompatibilityTest.cpp',
'<(angle_path)/src/tests/egl_tests/EGLContextSharingTest.cpp', '<(angle_path)/src/tests/egl_tests/EGLContextSharingTest.cpp',
'<(angle_path)/src/tests/egl_tests/EGLDebugTest.cpp',
'<(angle_path)/src/tests/egl_tests/EGLProgramCacheControlTest.cpp', '<(angle_path)/src/tests/egl_tests/EGLProgramCacheControlTest.cpp',
'<(angle_path)/src/tests/egl_tests/EGLQueryContextTest.cpp', '<(angle_path)/src/tests/egl_tests/EGLQueryContextTest.cpp',
'<(angle_path)/src/tests/egl_tests/EGLRobustnessTest.cpp', '<(angle_path)/src/tests/egl_tests/EGLRobustnessTest.cpp',
......
//
// Copyright (c) 2018 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.
//
// EGLDebugTest.cpp:
// Tests of EGL_KHR_debug extension
#include <gtest/gtest.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include "test_utils/ANGLETest.h"
#include "test_utils/angle_test_configs.h"
namespace angle
{
class EGLDebugTest : public ANGLETest
{
protected:
bool hasExtension() const { return eglClientExtensionEnabled("EGL_KHR_debug"); }
static void EGLAPIENTRY StubCallback(EGLenum error,
const char *command,
EGLint messageType,
EGLLabelKHR threadLabel,
EGLLabelKHR objectLabel,
const char *message)
{
}
static void EGLAPIENTRY CheckBadBindAPIError(EGLenum error,
const char *command,
EGLint messageType,
EGLLabelKHR threadLabel,
EGLLabelKHR objectLabel,
const char *message)
{
EXPECT_STREQ("eglBindAPI", command);
ASSERT_EGLENUM_EQ(EGL_BAD_PARAMETER, error);
EXPECT_STREQ("Thread", static_cast<const char *>(threadLabel));
}
static EGLDEBUGPROCKHR EGLAttribToDebugCallback(EGLAttrib attrib)
{
return reinterpret_cast<EGLDEBUGPROCKHR>(static_cast<uintptr_t>(attrib));
}
static EGLAttrib DebugCallbackToEGLAttrib(EGLDEBUGPROCKHR callback)
{
return static_cast<EGLAttrib>(reinterpret_cast<intptr_t>(callback));
}
};
// Test that the extension is always available (it is implemented in ANGLE's frontend).
TEST_P(EGLDebugTest, ExtensionAlwaysAvailable)
{
ASSERT_TRUE(hasExtension());
}
// Check that the default message filters and callbacks are correct
TEST_P(EGLDebugTest, DefaultParameters)
{
ANGLE_SKIP_TEST_IF(!hasExtension());
EXPECT_EQ(static_cast<EGLint>(EGL_SUCCESS), eglDebugMessageControlKHR(nullptr, nullptr));
EGLAttrib result = 0;
EXPECT_EGL_TRUE(eglQueryDebugKHR(EGL_DEBUG_MSG_ERROR_KHR, &result));
EXPECT_EGL_TRUE(result);
EXPECT_EGL_TRUE(eglQueryDebugKHR(EGL_DEBUG_MSG_WARN_KHR, &result));
EXPECT_EGL_FALSE(result);
EXPECT_EGL_TRUE(eglQueryDebugKHR(EGL_DEBUG_MSG_INFO_KHR, &result));
EXPECT_EGL_FALSE(result);
EXPECT_EGL_TRUE(eglQueryDebugKHR(EGL_DEBUG_CALLBACK_KHR, &result));
EXPECT_EQ(nullptr, EGLAttribToDebugCallback(result));
}
// Check that the message control and callback parameters can be set and then queried back
TEST_P(EGLDebugTest, SetMessageControl)
{
ANGLE_SKIP_TEST_IF(!hasExtension());
EGLAttrib controls[] = {
EGL_DEBUG_MSG_CRITICAL_KHR, EGL_FALSE,
// EGL_DEBUG_MSG_ERROR_KHR left unset
EGL_DEBUG_MSG_WARN_KHR, EGL_TRUE, EGL_DEBUG_MSG_INFO_KHR, EGL_FALSE, EGL_NONE, EGL_NONE,
};
EXPECT_EQ(static_cast<EGLint>(EGL_SUCCESS), eglDebugMessageControlKHR(&StubCallback, controls));
EGLAttrib result = 0;
EXPECT_EGL_TRUE(eglQueryDebugKHR(EGL_DEBUG_MSG_CRITICAL_KHR, &result));
EXPECT_EGL_FALSE(result);
EXPECT_EGL_TRUE(eglQueryDebugKHR(EGL_DEBUG_MSG_ERROR_KHR, &result));
EXPECT_EGL_TRUE(result);
EXPECT_EGL_TRUE(eglQueryDebugKHR(EGL_DEBUG_MSG_WARN_KHR, &result));
EXPECT_EGL_TRUE(result);
EXPECT_EGL_TRUE(eglQueryDebugKHR(EGL_DEBUG_MSG_INFO_KHR, &result));
EXPECT_EGL_FALSE(result);
EXPECT_EGL_TRUE(eglQueryDebugKHR(EGL_DEBUG_CALLBACK_KHR, &result));
EXPECT_EQ(DebugCallbackToEGLAttrib(&StubCallback), result);
}
// Set a thread label and then trigger a callback to verify the callback parameters are correct
TEST_P(EGLDebugTest, CorrectCallbackParameters)
{
ANGLE_SKIP_TEST_IF(!hasExtension());
EXPECT_EQ(static_cast<EGLint>(EGL_SUCCESS), eglDebugMessageControlKHR(nullptr, nullptr));
EXPECT_EQ(EGL_SUCCESS, eglLabelObjectKHR(EGL_NO_DISPLAY, EGL_OBJECT_THREAD_KHR, nullptr,
const_cast<char *>("Thread")));
// Enable all messages
EGLAttrib controls[] = {
EGL_DEBUG_MSG_CRITICAL_KHR,
EGL_TRUE,
EGL_DEBUG_MSG_ERROR_KHR,
EGL_TRUE,
EGL_DEBUG_MSG_WARN_KHR,
EGL_TRUE,
EGL_DEBUG_MSG_INFO_KHR,
EGL_TRUE,
EGL_NONE,
EGL_NONE,
};
EXPECT_EQ(static_cast<EGLint>(EGL_SUCCESS),
eglDebugMessageControlKHR(&CheckBadBindAPIError, controls));
// Generate an error and trigger the callback
EXPECT_EGL_FALSE(eglBindAPI(0xBADDBADD));
}
// Test that labels can be set and that errors are generated if the wrong object type is used
TEST_P(EGLDebugTest, SetLabel)
{
ANGLE_SKIP_TEST_IF(!hasExtension());
EXPECT_EQ(static_cast<EGLint>(EGL_SUCCESS), eglDebugMessageControlKHR(nullptr, nullptr));
// Display display and object must be equal when setting a display label
EXPECT_EQ(static_cast<EGLint>(EGL_SUCCESS),
eglLabelObjectKHR(getEGLWindow()->getDisplay(), EGL_OBJECT_DISPLAY_KHR,
getEGLWindow()->getDisplay(), const_cast<char *>("Display")));
EXPECT_NE(static_cast<EGLint>(EGL_SUCCESS),
eglLabelObjectKHR(nullptr, EGL_OBJECT_DISPLAY_KHR, getEGLWindow()->getDisplay(),
const_cast<char *>("Display")));
// Set a surface label
EXPECT_EQ(static_cast<EGLint>(EGL_SUCCESS),
eglLabelObjectKHR(getEGLWindow()->getDisplay(), EGL_OBJECT_SURFACE_KHR,
getEGLWindow()->getSurface(), const_cast<char *>("Surface")));
EXPECT_EGL_ERROR(EGL_SUCCESS);
// Provide a surface but use an image label type
EXPECT_EQ(static_cast<EGLint>(EGL_BAD_PARAMETER),
eglLabelObjectKHR(getEGLWindow()->getDisplay(), EGL_OBJECT_IMAGE_KHR,
getEGLWindow()->getSurface(), const_cast<char *>("Image")));
EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
}
ANGLE_INSTANTIATE_TEST(EGLDebugTest,
ES2_D3D9(),
ES2_D3D11(),
ES3_D3D11(),
ES2_OPENGL(),
ES3_OPENGL());
} // namespace angle
...@@ -37,10 +37,12 @@ ...@@ -37,10 +37,12 @@
#define EXPECT_EGL_SUCCESS() EXPECT_EGL_ERROR(EGL_SUCCESS) #define EXPECT_EGL_SUCCESS() EXPECT_EGL_ERROR(EGL_SUCCESS)
// EGLBoolean is |unsigned int| but EGL_TRUE is 0, not 0u. // EGLBoolean is |unsigned int| but EGL_TRUE is 0, not 0u.
#define ASSERT_EGL_TRUE(a) ASSERT_EQ(static_cast<EGLBoolean>(EGL_TRUE), (a)) #define ASSERT_EGL_TRUE(a) ASSERT_EQ(static_cast<EGLBoolean>(EGL_TRUE), static_cast<EGLBoolean>(a))
#define ASSERT_EGL_FALSE(a) ASSERT_EQ(static_cast<EGLBoolean>(EGL_FALSE), (a)) #define ASSERT_EGL_FALSE(a) \
#define EXPECT_EGL_TRUE(a) EXPECT_EQ(static_cast<EGLBoolean>(EGL_TRUE), (a)) ASSERT_EQ(static_cast<EGLBoolean>(EGL_FALSE), static_cast<EGLBoolean>(a))
#define EXPECT_EGL_FALSE(a) EXPECT_EQ(static_cast<EGLBoolean>(EGL_FALSE), (a)) #define EXPECT_EGL_TRUE(a) EXPECT_EQ(static_cast<EGLBoolean>(EGL_TRUE), static_cast<EGLBoolean>(a))
#define EXPECT_EGL_FALSE(a) \
EXPECT_EQ(static_cast<EGLBoolean>(EGL_FALSE), static_cast<EGLBoolean>(a))
#define ASSERT_EGL_ERROR(err) ASSERT_EQ((err), eglGetError()) #define ASSERT_EGL_ERROR(err) ASSERT_EQ((err), eglGetError())
#define ASSERT_EGL_SUCCESS() ASSERT_EGL_ERROR(EGL_SUCCESS) #define ASSERT_EGL_SUCCESS() ASSERT_EGL_ERROR(EGL_SUCCESS)
...@@ -54,6 +56,11 @@ ...@@ -54,6 +56,11 @@
#define EXPECT_GLENUM_NE(expected, actual) \ #define EXPECT_GLENUM_NE(expected, actual) \
EXPECT_NE(static_cast<GLenum>(expected), static_cast<GLenum>(actual)) EXPECT_NE(static_cast<GLenum>(expected), static_cast<GLenum>(actual))
#define ASSERT_EGLENUM_EQ(expected, actual) \
ASSERT_EQ(static_cast<EGLenum>(expected), static_cast<EGLenum>(actual))
#define EXPECT_EGLENUM_EQ(expected, actual) \
EXPECT_EQ(static_cast<EGLenum>(expected), static_cast<EGLenum>(actual))
namespace angle namespace angle
{ {
struct GLColorRGB struct GLColorRGB
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment