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: Jamie Madill <jmadill@chromium.org>
diff --git a/src/common/PackedEGLEnums_autogen.cpp b/src/common/PackedEGLEnums_autogen.cpp
index 77fb3d4..e09a9a6 100644
--- a/src/common/PackedEGLEnums_autogen.cpp
+++ b/src/common/PackedEGLEnums_autogen.cpp
@@ -16,6 +16,90 @@
{
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)
{
switch (from)
diff --git a/src/common/PackedEGLEnums_autogen.h b/src/common/PackedEGLEnums_autogen.h
index 16856aa..fd3d719 100644
--- a/src/common/PackedEGLEnums_autogen.h
+++ b/src/common/PackedEGLEnums_autogen.h
@@ -24,6 +24,39 @@
template <typename Enum>
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
{
NoTexture = 0,
diff --git a/src/common/PackedEnums.cpp b/src/common/PackedEnums.cpp
index 4843c4e..517c443 100644
--- a/src/common/PackedEnums.cpp
+++ b/src/common/PackedEnums.cpp
@@ -149,6 +149,41 @@
} // 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
{
diff --git a/src/common/PackedEnums.h b/src/common/PackedEnums.h
index d649cf4..c53d3e5 100644
--- a/src/common/PackedEnums.h
+++ b/src/common/PackedEnums.h
@@ -189,6 +189,11 @@
} // namespace gl
+namespace egl
+{
+MessageType ErrorCodeToMessageType(EGLint errorCode);
+} // namespace egl
+
namespace egl_gl
{
gl::TextureTarget EGLCubeMapTargetToCubeMapTarget(EGLenum eglTarget);
diff --git a/src/common/packed_egl_enums.json b/src/common/packed_egl_enums.json
index dc946b6..04d67d4 100644
--- a/src/common/packed_egl_enums.json
+++ b/src/common/packed_egl_enums.json
@@ -4,5 +4,22 @@
"NoTexture": "EGL_NO_TEXTURE",
"RGB": "EGL_TEXTURE_RGB",
"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"
}
}
diff --git a/src/libANGLE/Caps.cpp b/src/libANGLE/Caps.cpp
index 293693e..016d712 100644
--- a/src/libANGLE/Caps.cpp
+++ b/src/libANGLE/Caps.cpp
@@ -1387,7 +1387,8 @@
x11Visual(false),
experimentalPresentPath(false),
clientGetAllProcAddresses(false),
- explicitContext(false)
+ explicitContext(false),
+ debug(false)
{
}
@@ -1413,6 +1414,7 @@
InsertExtensionString("EGL_ANGLE_experimental_present_path", experimentalPresentPath, &extensionStrings);
InsertExtensionString("EGL_KHR_client_get_all_proc_addresses", clientGetAllProcAddresses, &extensionStrings);
InsertExtensionString("EGL_ANGLE_explicit_context", explicitContext, &extensionStrings);
+ InsertExtensionString("EGL_KHR_debug", debug, &extensionStrings);
// clang-format on
return extensionStrings;
diff --git a/src/libANGLE/Caps.h b/src/libANGLE/Caps.h
index f783364..0589d00 100644
--- a/src/libANGLE/Caps.h
+++ b/src/libANGLE/Caps.h
@@ -826,6 +826,9 @@
// EGL_ANGLE_explicit_context
bool explicitContext;
+
+ // EGL_KHR_debug
+ bool debug;
};
} // namespace egl
diff --git a/src/libANGLE/Context.cpp b/src/libANGLE/Context.cpp
index 0ec0bfc..e62be2a 100644
--- a/src/libANGLE/Context.cpp
+++ b/src/libANGLE/Context.cpp
@@ -280,6 +280,7 @@
mDisplayTextureShareGroup(shareTextures != nullptr),
mSavedArgsType(nullptr),
mImplementation(implFactory->createContext(mState)),
+ mLabel(nullptr),
mCompiler(),
mGLState(GetDebug(attribs),
GetBindGeneratesResource(attribs),
@@ -518,6 +519,16 @@
{
}
+void Context::setLabel(EGLLabelKHR label)
+{
+ mLabel = label;
+}
+
+EGLLabelKHR Context::getLabel() const
+{
+ return mLabel;
+}
+
egl::Error Context::makeCurrent(egl::Display *display, egl::Surface *surface)
{
mCurrentDisplay = display;
@@ -904,7 +915,7 @@
return mState.mPipelines->getProgramPipeline(handle);
}
-LabeledObject *Context::getLabeledObject(GLenum identifier, GLuint name) const
+gl::LabeledObject *Context::getLabeledObject(GLenum identifier, GLuint name) const
{
switch (identifier)
{
@@ -934,14 +945,14 @@
}
}
-LabeledObject *Context::getLabeledObjectFromPtr(const void *ptr) const
+gl::LabeledObject *Context::getLabeledObjectFromPtr(const void *ptr) const
{
return getSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr)));
}
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);
std::string labelName = GetObjectLabelFromPointer(length, label);
@@ -954,7 +965,7 @@
void Context::objectPtrLabel(const void *ptr, GLsizei length, const GLchar *label)
{
- LabeledObject *object = getLabeledObjectFromPtr(ptr);
+ gl::LabeledObject *object = getLabeledObjectFromPtr(ptr);
ASSERT(object != nullptr);
std::string labelName = GetObjectLabelFromPointer(length, label);
@@ -967,7 +978,7 @@
GLsizei *length,
GLchar *label) const
{
- LabeledObject *object = getLabeledObject(identifier, name);
+ gl::LabeledObject *object = getLabeledObject(identifier, name);
ASSERT(object != nullptr);
const std::string &objectLabel = object->getLabel();
@@ -979,7 +990,7 @@
GLsizei *length,
GLchar *label) const
{
- LabeledObject *object = getLabeledObjectFromPtr(ptr);
+ gl::LabeledObject *object = getLabeledObjectFromPtr(ptr);
ASSERT(object != nullptr);
const std::string &objectLabel = object->getLabel();
diff --git a/src/libANGLE/Context.h b/src/libANGLE/Context.h
index bcd4361..2d14caf 100644
--- a/src/libANGLE/Context.h
+++ b/src/libANGLE/Context.h
@@ -63,7 +63,7 @@
class VertexArray;
struct VertexAttribute;
-class Context final : angle::NonCopyable
+class Context final : public egl::LabeledObject, angle::NonCopyable
{
public:
Context(rx::EGLImplFactory *implFactory,
@@ -78,6 +78,9 @@
egl::Error onDestroy(const egl::Display *display);
~Context();
+ void setLabel(EGLLabelKHR label) override;
+ EGLLabelKHR getLabel() const override;
+
egl::Error makeCurrent(egl::Display *display, egl::Surface *surface);
egl::Error releaseSurface(const egl::Display *display);
@@ -1502,8 +1505,8 @@
void updateCaps();
void initWorkarounds();
- LabeledObject *getLabeledObject(GLenum identifier, GLuint name) const;
- LabeledObject *getLabeledObjectFromPtr(const void *ptr) const;
+ gl::LabeledObject *getLabeledObject(GLenum identifier, GLuint name) const;
+ gl::LabeledObject *getLabeledObjectFromPtr(const void *ptr) const;
ContextState mState;
bool mSkipValidation;
@@ -1519,6 +1522,8 @@
std::unique_ptr<rx::ContextImpl> mImplementation;
+ EGLLabelKHR mLabel;
+
// Caps to use for validation
Caps mCaps;
TextureCapsMap mTextureCaps;
diff --git a/src/libANGLE/Debug.cpp b/src/libANGLE/Debug.cpp
index c742fe1..4619235 100644
--- a/src/libANGLE/Debug.cpp
+++ b/src/libANGLE/Debug.cpp
@@ -325,3 +325,64 @@
mGroups.push_back(std::move(g));
}
} // 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
diff --git a/src/libANGLE/Debug.h b/src/libANGLE/Debug.h
index 261ca54..544512a 100644
--- a/src/libANGLE/Debug.h
+++ b/src/libANGLE/Debug.h
@@ -10,7 +10,9 @@
#define LIBANGLE_DEBUG_H_
#include "angle_gl.h"
+#include "common/PackedEnums.h"
#include "common/angleutils.h"
+#include "libANGLE/AttributeMap.h"
#include <deque>
#include <string>
@@ -126,4 +128,35 @@
};
} // 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_
diff --git a/src/libANGLE/Device.cpp b/src/libANGLE/Device.cpp
index fe37558..51d4524 100644
--- a/src/libANGLE/Device.cpp
+++ b/src/libANGLE/Device.cpp
@@ -70,14 +70,14 @@
return NoError();
}
-bool Device::IsValidDevice(Device *device)
+bool Device::IsValidDevice(const Device *device)
{
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)
- : mOwningDisplay(owningDisplay), mImplementation(impl)
+ : mLabel(nullptr), mOwningDisplay(owningDisplay), mImplementation(impl)
{
ASSERT(GetDeviceSet()->find(this) == GetDeviceSet()->end());
GetDeviceSet()->insert(this);
@@ -90,6 +90,16 @@
GetDeviceSet()->erase(this);
}
+void Device::setLabel(EGLLabelKHR label)
+{
+ mLabel = label;
+}
+
+EGLLabelKHR Device::getLabel() const
+{
+ return mLabel;
+}
+
Error Device::getDevice(EGLAttrib *value)
{
void *nativeDevice = nullptr;
diff --git a/src/libANGLE/Device.h b/src/libANGLE/Device.h
index ce6d4ee..9625fe6 100644
--- a/src/libANGLE/Device.h
+++ b/src/libANGLE/Device.h
@@ -23,12 +23,15 @@
namespace egl
{
-class Device final : angle::NonCopyable
+class Device final : public LabeledObject, angle::NonCopyable
{
public:
Device(Display *owningDisplay, rx::DeviceImpl *impl);
virtual ~Device();
+ void setLabel(EGLLabelKHR label) override;
+ EGLLabelKHR getLabel() const override;
+
Error getDevice(EGLAttrib *value);
Display *getOwningDisplay() { return mOwningDisplay; };
EGLint getType();
@@ -39,11 +42,13 @@
rx::DeviceImpl *getImplementation() { return mImplementation.get(); }
static egl::Error CreateDevice(EGLint deviceType, void *nativeDevice, Device **outDevice);
- static bool IsValidDevice(Device *device);
+ static bool IsValidDevice(const Device *device);
private:
void initDeviceExtensions();
+ EGLLabelKHR mLabel;
+
Display *mOwningDisplay;
std::unique_ptr<rx::DeviceImpl> mImplementation;
diff --git a/src/libANGLE/Display.cpp b/src/libANGLE/Display.cpp
index f936dd2..1c83a45 100644
--- a/src/libANGLE/Display.cpp
+++ b/src/libANGLE/Display.cpp
@@ -273,7 +273,7 @@
} // anonymous namespace
-DisplayState::DisplayState()
+DisplayState::DisplayState() : label(nullptr)
{
}
@@ -425,6 +425,16 @@
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)
{
ASSERT(!mInitialized);
@@ -1020,6 +1030,7 @@
extensions.clientGetAllProcAddresses = true;
extensions.explicitContext = true;
+ extensions.debug = true;
return extensions;
}
diff --git a/src/libANGLE/Display.h b/src/libANGLE/Display.h
index ed8770a..9d56478 100644
--- a/src/libANGLE/Display.h
+++ b/src/libANGLE/Display.h
@@ -17,6 +17,7 @@
#include "libANGLE/AttributeMap.h"
#include "libANGLE/Caps.h"
#include "libANGLE/Config.h"
+#include "libANGLE/Debug.h"
#include "libANGLE/Error.h"
#include "libANGLE/LoggingAnnotator.h"
#include "libANGLE/MemoryProgramCache.h"
@@ -48,17 +49,21 @@
DisplayState();
~DisplayState();
+ EGLLabelKHR label;
SurfaceSet surfaceSet;
};
// Constant coded here as a sanity limit.
constexpr EGLAttrib kProgramCacheSizeAbsoluteMax = 0x4000000;
-class Display final : angle::NonCopyable
+class Display final : public LabeledObject, angle::NonCopyable
{
public:
~Display();
+ void setLabel(EGLLabelKHR label) override;
+ EGLLabelKHR getLabel() const override;
+
Error initialize();
Error terminate();
diff --git a/src/libANGLE/Image.cpp b/src/libANGLE/Image.cpp
index 4adbeff..34e8d7a 100644
--- a/src/libANGLE/Image.cpp
+++ b/src/libANGLE/Image.cpp
@@ -118,7 +118,7 @@
}
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 @@
SafeDelete(mImplementation);
}
+void Image::setLabel(EGLLabelKHR label)
+{
+ mState.label = label;
+}
+
+EGLLabelKHR Image::getLabel() const
+{
+ return mState.label;
+}
+
void Image::addTargetSibling(ImageSibling *sibling)
{
mState.targets.insert(sibling);
diff --git a/src/libANGLE/Image.h b/src/libANGLE/Image.h
index 844aee8..86012fd 100644
--- a/src/libANGLE/Image.h
+++ b/src/libANGLE/Image.h
@@ -11,6 +11,7 @@
#include "common/angleutils.h"
#include "libANGLE/AttributeMap.h"
+#include "libANGLE/Debug.h"
#include "libANGLE/Error.h"
#include "libANGLE/FramebufferAttachment.h"
#include "libANGLE/RefCountObject.h"
@@ -66,12 +67,13 @@
ImageState(EGLenum target, ImageSibling *buffer, const AttributeMap &attribs);
~ImageState();
+ EGLLabelKHR label;
gl::ImageIndex imageIndex;
gl::BindingPointer<ImageSibling> source;
std::set<ImageSibling *> targets;
};
-class Image final : public gl::RefCountObject
+class Image final : public gl::RefCountObject, public LabeledObject
{
public:
Image(rx::EGLImplFactory *factory,
@@ -82,6 +84,9 @@
gl::Error onDestroy(const gl::Context *context) override;
~Image() override;
+ void setLabel(EGLLabelKHR label) override;
+ EGLLabelKHR getLabel() const override;
+
gl::Format getFormat() const;
size_t getWidth() const;
size_t getHeight() const;
diff --git a/src/libANGLE/Stream.cpp b/src/libANGLE/Stream.cpp
index a2db4d5..320e06f 100644
--- a/src/libANGLE/Stream.cpp
+++ b/src/libANGLE/Stream.cpp
@@ -25,7 +25,8 @@
{
Stream::Stream(Display *display, const AttributeMap &attribs)
- : mDisplay(display),
+ : mLabel(nullptr),
+ mDisplay(display),
mProducerImplementation(nullptr),
mState(EGL_STREAM_STATE_CREATED_KHR),
mProducerFrame(0),
@@ -55,6 +56,16 @@
}
}
+void Stream::setLabel(EGLLabelKHR label)
+{
+ mLabel = label;
+}
+
+EGLLabelKHR Stream::getLabel() const
+{
+ return mLabel;
+}
+
void Stream::setConsumerLatency(EGLint latency)
{
mConsumerLatency = latency;
diff --git a/src/libANGLE/Stream.h b/src/libANGLE/Stream.h
index 2319355..7fac4f8 100644
--- a/src/libANGLE/Stream.h
+++ b/src/libANGLE/Stream.h
@@ -17,6 +17,7 @@
#include "common/angleutils.h"
#include "libANGLE/AttributeMap.h"
+#include "libANGLE/Debug.h"
namespace rx
{
@@ -35,12 +36,15 @@
class Error;
class Thread;
-class Stream final : angle::NonCopyable
+class Stream final : public LabeledObject, angle::NonCopyable
{
public:
Stream(Display *display, const AttributeMap &attribs);
~Stream();
+ void setLabel(EGLLabelKHR label) override;
+ EGLLabelKHR getLabel() const override;
+
enum class ConsumerType
{
NoConsumer,
@@ -100,6 +104,8 @@
Error postD3D11Texture(void *texture, const AttributeMap &attributes);
private:
+ EGLLabelKHR mLabel;
+
// Associated display
Display *mDisplay;
diff --git a/src/libANGLE/Surface.cpp b/src/libANGLE/Surface.cpp
index bf4861f..3822d45 100644
--- a/src/libANGLE/Surface.cpp
+++ b/src/libANGLE/Surface.cpp
@@ -25,7 +25,7 @@
{
SurfaceState::SurfaceState(const egl::Config *configIn, const AttributeMap &attributesIn)
- : config(configIn), attributes(attributesIn)
+ : label(nullptr), config(configIn), attributes(attributesIn)
{
}
@@ -212,6 +212,16 @@
return NoError();
}
+void Surface::setLabel(EGLLabelKHR label)
+{
+ mState.label = label;
+}
+
+EGLLabelKHR Surface::getLabel() const
+{
+ return mState.label;
+}
+
EGLint Surface::getType() const
{
return mType;
diff --git a/src/libANGLE/Surface.h b/src/libANGLE/Surface.h
index 3107aa2..ea09341 100644
--- a/src/libANGLE/Surface.h
+++ b/src/libANGLE/Surface.h
@@ -16,6 +16,7 @@
#include "common/PackedEnums.h"
#include "common/angleutils.h"
#include "libANGLE/AttributeMap.h"
+#include "libANGLE/Debug.h"
#include "libANGLE/Error.h"
#include "libANGLE/FramebufferAttachment.h"
#include "libANGLE/RefCountObject.h"
@@ -43,15 +44,19 @@
{
SurfaceState(const egl::Config *configIn, const AttributeMap &attributesIn);
+ EGLLabelKHR label;
const egl::Config *config;
AttributeMap attributes;
};
-class Surface : public gl::FramebufferAttachmentObject
+class Surface : public LabeledObject, public gl::FramebufferAttachmentObject
{
public:
rx::SurfaceImpl *getImplementation() const { return mImplementation; }
+ void setLabel(EGLLabelKHR label) override;
+ EGLLabelKHR getLabel() const override;
+
EGLint getType() const;
Error initialize(const Display *display);
diff --git a/src/libANGLE/Thread.cpp b/src/libANGLE/Thread.cpp
index d346db1..a7c5045 100644
--- a/src/libANGLE/Thread.cpp
+++ b/src/libANGLE/Thread.cpp
@@ -9,20 +9,48 @@
#include "libANGLE/Thread.h"
#include "libANGLE/Context.h"
+#include "libANGLE/Debug.h"
#include "libANGLE/Error.h"
namespace egl
{
+
Thread::Thread()
- : mError(EGL_SUCCESS),
+ : mLabel(nullptr),
+ mError(EGL_SUCCESS),
mAPI(EGL_OPENGL_ES_API),
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();
+ 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
diff --git a/src/libANGLE/Thread.h b/src/libANGLE/Thread.h
index 6406dad..8f37895 100644
--- a/src/libANGLE/Thread.h
+++ b/src/libANGLE/Thread.h
@@ -11,6 +11,8 @@
#include <EGL/egl.h>
+#include "libANGLE/Debug.h"
+
namespace gl
{
class Context;
@@ -19,15 +21,23 @@
namespace egl
{
class Error;
+class Debug;
class Display;
class Surface;
-class Thread
+class Thread : public LabeledObject
{
public:
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;
void setAPI(EGLenum api);
@@ -41,6 +51,7 @@
Display *getCurrentDisplay() const;
private:
+ EGLLabelKHR mLabel;
EGLint mError;
EGLenum mAPI;
gl::Context *mContext;
diff --git a/src/libANGLE/validationEGL.cpp b/src/libANGLE/validationEGL.cpp
index 2e6e502..dcd4edb 100644
--- a/src/libANGLE/validationEGL.cpp
+++ b/src/libANGLE/validationEGL.cpp
@@ -17,6 +17,7 @@
#include "libANGLE/Stream.h"
#include "libANGLE/Surface.h"
#include "libANGLE/Texture.h"
+#include "libANGLE/Thread.h"
#include "libANGLE/formatutils.h"
#include <EGL/eglext.h>
@@ -493,6 +494,100 @@
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
Error ValidateDisplay(const Display *display)
@@ -568,24 +663,101 @@
return NoError();
}
-Error ValidateStream(const Display *display, const Stream *stream)
+Error ValidateDevice(const Device *device)
{
- ANGLE_TRY(ValidateDisplay(display));
-
- const DisplayExtensions &displayExtensions = display->getExtensions();
- if (!displayExtensions.stream)
+ if (device == EGL_NO_DEVICE_EXT)
{
- 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();
}
+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,
Config *configuration,
gl::Context *shareContext,
@@ -2715,4 +2887,73 @@
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
diff --git a/src/libANGLE/validationEGL.h b/src/libANGLE/validationEGL.h
index a0a8169..cb07084 100644
--- a/src/libANGLE/validationEGL.h
+++ b/src/libANGLE/validationEGL.h
@@ -9,6 +9,7 @@
#ifndef LIBANGLE_VALIDATIONEGL_H_
#define LIBANGLE_VALIDATIONEGL_H_
+#include "common/PackedEnums.h"
#include "libANGLE/Error.h"
#include <EGL/egl.h>
@@ -30,6 +31,8 @@
class Image;
class Stream;
class Surface;
+class Thread;
+class LabeledObject;
// Object validation
Error ValidateDisplay(const Display *display);
@@ -37,6 +40,20 @@
Error ValidateConfig(const Display *display, const Config *config);
Error ValidateContext(const Display *display, const gl::Context *context);
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
Error ValidateCreateContext(Display *display,
@@ -181,23 +198,34 @@
EGLint attribute,
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
-#define ANGLE_EGL_TRY(THREAD, EXPR) \
- { \
- auto ANGLE_LOCAL_VAR = (EXPR); \
- if (ANGLE_LOCAL_VAR.isError()) \
- return THREAD->setError(ANGLE_LOCAL_VAR); \
+#define ANGLE_EGL_TRY(THREAD, EXPR, FUNCNAME, LABELOBJECT) \
+ { \
+ auto ANGLE_LOCAL_VAR = (EXPR); \
+ if (ANGLE_LOCAL_VAR.isError()) \
+ return THREAD->setError(ANGLE_LOCAL_VAR, GetDebug(), FUNCNAME, LABELOBJECT); \
}
-#define ANGLE_EGL_TRY_RETURN(THREAD, EXPR, RETVAL) \
- { \
- auto ANGLE_LOCAL_VAR = (EXPR); \
- if (ANGLE_LOCAL_VAR.isError()) \
- { \
- THREAD->setError(ANGLE_LOCAL_VAR); \
- return RETVAL; \
- } \
+#define ANGLE_EGL_TRY_RETURN(THREAD, EXPR, FUNCNAME, LABELOBJECT, RETVAL) \
+ { \
+ auto ANGLE_LOCAL_VAR = (EXPR); \
+ if (ANGLE_LOCAL_VAR.isError()) \
+ { \
+ THREAD->setError(ANGLE_LOCAL_VAR, GetDebug(), FUNCNAME, LABELOBJECT); \
+ return RETVAL; \
+ } \
}
#endif // LIBANGLE_VALIDATIONEGL_H_
diff --git a/src/libEGL/libEGL.cpp b/src/libEGL/libEGL.cpp
index 0498336..98822d0 100644
--- a/src/libEGL/libEGL.cpp
+++ b/src/libEGL/libEGL.cpp
@@ -493,4 +493,22 @@
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"
diff --git a/src/libEGL/libEGL.def b/src/libEGL/libEGL.def
index d85cbab..1e5ee63 100644
--- a/src/libEGL/libEGL.def
+++ b/src/libEGL/libEGL.def
@@ -66,6 +66,9 @@
eglCreatePlatformWindowSurfaceEXT @72
eglCreatePlatformPixmapSurfaceEXT @73
eglPresentationTimeANDROID @74
+ eglDebugMessageControlKHR @75
+ eglQueryDebugKHR @76
+ eglLabelObjectKHR @77
; 1.5 entry points
eglCreateSync @38
diff --git a/src/libGLESv2/entry_points_egl.cpp b/src/libGLESv2/entry_points_egl.cpp
index aa445ed..938ec7f 100644
--- a/src/libGLESv2/entry_points_egl.cpp
+++ b/src/libGLESv2/entry_points_egl.cpp
@@ -50,7 +50,6 @@
}
*num_config = result_size;
}
-
} // anonymous namespace
// EGL 1.0
@@ -60,7 +59,7 @@
Thread *thread = GetCurrentThread();
EGLint error = thread->getError();
- thread->setError(NoError());
+ thread->setSuccess();
return error;
}
@@ -80,14 +79,14 @@
Display *display = static_cast<Display *>(dpy);
if (dpy == EGL_NO_DISPLAY || !Display::isValidDisplay(display))
{
- thread->setError(EglBadDisplay());
+ thread->setError(EglBadDisplay(), GetDebug(), "eglInitialize", GetDisplayIfValid(display));
return EGL_FALSE;
}
Error error = display->initialize();
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglInitialize", GetDisplayIfValid(display));
return EGL_FALSE;
}
@@ -96,7 +95,7 @@
if (minor)
*minor = 4;
- thread->setError(NoError());
+ thread->setSuccess();
return EGL_TRUE;
}
@@ -108,7 +107,7 @@
Display *display = static_cast<Display *>(dpy);
if (dpy == EGL_NO_DISPLAY || !Display::isValidDisplay(display))
{
- thread->setError(EglBadDisplay());
+ thread->setError(EglBadDisplay(), GetDebug(), "eglTerminate", GetDisplayIfValid(display));
return EGL_FALSE;
}
@@ -120,11 +119,11 @@
Error error = display->terminate();
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglTerminate", GetDisplayIfValid(display));
return EGL_FALSE;
}
- thread->setError(NoError());
+ thread->setSuccess();
return EGL_TRUE;
}
@@ -139,7 +138,7 @@
Error error = ValidateDisplay(display);
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglQueryString", GetDisplayIfValid(display));
return nullptr;
}
}
@@ -167,11 +166,12 @@
result = "1.4 (ANGLE " ANGLE_VERSION_STRING ")";
break;
default:
- thread->setError(EglBadParameter());
+ thread->setError(EglBadParameter(), GetDebug(), "eglQueryString",
+ GetDisplayIfValid(display));
return nullptr;
}
- thread->setError(NoError());
+ thread->setSuccess();
return result;
}
@@ -191,13 +191,13 @@
Error error = ValidateGetConfigs(display, config_size, num_config);
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglGetConfigs", GetDisplayIfValid(display));
return EGL_FALSE;
}
ClipConfigs(display->getConfigs(AttributeMap()), configs, config_size, num_config);
- thread->setError(NoError());
+ thread->setSuccess();
return EGL_TRUE;
}
@@ -219,13 +219,13 @@
Error error = ValidateChooseConfig(display, attribMap, config_size, num_config);
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglChooseConfig", GetDisplayIfValid(display));
return EGL_FALSE;
}
ClipConfigs(display->getConfigs(attribMap), configs, config_size, num_config);
- thread->setError(NoError());
+ thread->setSuccess();
return EGL_TRUE;
}
@@ -246,13 +246,13 @@
Error error = ValidateGetConfigAttrib(display, configuration, attribute);
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglGetConfigAttrib", GetDisplayIfValid(display));
return EGL_FALSE;
}
QueryConfigAttrib(configuration, attribute, value);
- thread->setError(NoError());
+ thread->setSuccess();
return EGL_TRUE;
}
@@ -274,7 +274,7 @@
Error error = ValidateCreateWindowSurface(display, configuration, win, attributes);
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglCreateWindowSurface", GetDisplayIfValid(display));
return EGL_NO_SURFACE;
}
@@ -282,7 +282,7 @@
error = display->createWindowSurface(configuration, win, attributes, &surface);
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglCreateWindowSurface", GetDisplayIfValid(display));
return EGL_NO_SURFACE;
}
@@ -306,7 +306,7 @@
Error error = ValidateCreatePbufferSurface(display, configuration, attributes);
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglCreatePbufferSurface", GetDisplayIfValid(display));
return EGL_NO_SURFACE;
}
@@ -314,7 +314,7 @@
error = display->createPbufferSurface(configuration, attributes, &surface);
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglCreatePbufferSurface", GetDisplayIfValid(display));
return EGL_NO_SURFACE;
}
@@ -339,13 +339,13 @@
Error error = ValidateConfig(display, configuration);
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglCreatePixmapSurface", GetDisplayIfValid(display));
return EGL_NO_SURFACE;
}
UNIMPLEMENTED(); // FIXME
- thread->setError(NoError());
+ thread->setSuccess();
return EGL_NO_SURFACE;
}
@@ -360,24 +360,27 @@
Error error = ValidateSurface(display, eglSurface);
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglDestroySurface",
+ GetSurfaceIfValid(display, eglSurface));
return EGL_FALSE;
}
if (surface == EGL_NO_SURFACE)
{
- thread->setError(EglBadSurface());
+ thread->setError(EglBadSurface(), GetDebug(), "eglDestroySurface",
+ GetSurfaceIfValid(display, eglSurface));
return EGL_FALSE;
}
- error = display->destroySurface(reinterpret_cast<Surface *>(surface));
+ error = display->destroySurface(eglSurface);
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglDestroySurface",
+ GetSurfaceIfValid(display, eglSurface));
return EGL_FALSE;
}
- thread->setError(NoError());
+ thread->setSuccess();
return EGL_TRUE;
}
@@ -398,13 +401,14 @@
Error error = ValidateQuerySurface(display, eglSurface, attribute, value);
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglQuerySurface",
+ GetSurfaceIfValid(display, eglSurface));
return EGL_FALSE;
}
QuerySurfaceAttrib(eglSurface, attribute, value);
- thread->setError(NoError());
+ thread->setSuccess();
return EGL_TRUE;
}
@@ -428,7 +432,7 @@
Error error = ValidateCreateContext(display, configuration, sharedGLContext, attributes);
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglCreateContext", GetDisplayIfValid(display));
return EGL_NO_CONTEXT;
}
@@ -436,11 +440,11 @@
error = display->createContext(configuration, sharedGLContext, attributes, &context);
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglCreateContext", GetDisplayIfValid(display));
return EGL_NO_CONTEXT;
}
- thread->setError(NoError());
+ thread->setSuccess();
return static_cast<EGLContext>(context);
}
@@ -455,13 +459,15 @@
Error error = ValidateContext(display, context);
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglDestroyContext",
+ GetContextIfValid(display, context));
return EGL_FALSE;
}
if (ctx == EGL_NO_CONTEXT)
{
- thread->setError(EglBadContext());
+ thread->setError(EglBadContext(), GetDebug(), "eglDestroyContext",
+ GetContextIfValid(display, context));
return EGL_FALSE;
}
@@ -473,11 +479,12 @@
error = display->destroyContext(context);
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglDestroyContext",
+ GetContextIfValid(display, context));
return EGL_FALSE;
}
- thread->setError(NoError());
+ thread->setSuccess();
return EGL_TRUE;
}
@@ -495,7 +502,7 @@
gl::Context *context = static_cast<gl::Context *>(ctx);
ANGLE_EGL_TRY_RETURN(thread, ValidateMakeCurrent(display, drawSurface, readSurface, context),
- EGL_FALSE);
+ "eglMakeCurrent", GetContextIfValid(display, context), EGL_FALSE);
Surface *previousDraw = thread->getCurrentDrawSurface();
Surface *previousRead = thread->getCurrentReadSurface();
@@ -505,7 +512,7 @@
if (previousDraw != drawSurface || previousRead != readSurface || previousContext != context)
{
ANGLE_EGL_TRY_RETURN(thread, display->makeCurrent(drawSurface, readSurface, context),
- EGL_FALSE);
+ "eglMakeCurrent", GetContextIfValid(display, context), EGL_FALSE);
thread->setCurrent(context);
@@ -513,11 +520,12 @@
// destroyed surfaces to delete themselves.
if (previousContext != nullptr && context != previousContext)
{
- ANGLE_EGL_TRY_RETURN(thread, previousContext->releaseSurface(display), EGL_FALSE);
+ ANGLE_EGL_TRY_RETURN(thread, previousContext->releaseSurface(display), "eglMakeCurrent",
+ GetContextIfValid(display, context), EGL_FALSE);
}
}
- thread->setError(NoError());
+ thread->setSuccess();
return EGL_TRUE;
}
@@ -528,17 +536,17 @@
if (readdraw == EGL_READ)
{
- thread->setError(NoError());
+ thread->setSuccess();
return thread->getCurrentReadSurface();
}
else if (readdraw == EGL_DRAW)
{
- thread->setError(NoError());
+ thread->setSuccess();
return thread->getCurrentDrawSurface();
}
else
{
- thread->setError(EglBadParameter());
+ thread->setError(EglBadParameter(), GetDebug(), "eglGetCurrentSurface", nullptr);
return EGL_NO_SURFACE;
}
}
@@ -548,7 +556,7 @@
EVENT("()");
Thread *thread = GetCurrentThread();
- thread->setError(NoError());
+ thread->setSuccess();
if (thread->getContext() != nullptr)
{
return thread->getContext()->getCurrentDisplay();
@@ -570,13 +578,13 @@
Error error = ValidateQueryContext(display, context, attribute, value);
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglQueryContext", GetContextIfValid(display, context));
return EGL_FALSE;
}
QueryContextAttrib(context, attribute, value);
- thread->setError(NoError());
+ thread->setSuccess();
return EGL_TRUE;
}
@@ -590,7 +598,7 @@
Error error = ValidateDisplay(display);
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglWaitGL", GetDisplayIfValid(display));
return EGL_FALSE;
}
@@ -599,11 +607,11 @@
error = display->waitClient(thread->getContext());
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglWaitGL", GetDisplayIfValid(display));
return EGL_FALSE;
}
- thread->setError(NoError());
+ thread->setSuccess();
return EGL_TRUE;
}
@@ -617,23 +625,24 @@
Error error = ValidateDisplay(display);
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglWaitNative", GetThreadIfValid(thread));
return EGL_FALSE;
}
if (engine != EGL_CORE_NATIVE_ENGINE)
{
- thread->setError(EglBadParameter() << "the 'engine' parameter has an unrecognized value");
+ thread->setError(EglBadParameter() << "the 'engine' parameter has an unrecognized value",
+ GetDebug(), "eglWaitNative", GetDisplayIfValid(display));
}
error = display->waitNative(thread->getContext(), engine);
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglWaitNative", GetThreadIfValid(thread));
return EGL_FALSE;
}
- thread->setError(NoError());
+ thread->setSuccess();
return EGL_TRUE;
}
@@ -648,36 +657,41 @@
Error error = ValidateSurface(display, eglSurface);
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglSwapBuffers",
+ GetSurfaceIfValid(display, eglSurface));
return EGL_FALSE;
}
if (display->isDeviceLost())
{
- thread->setError(EglContextLost());
+ thread->setError(EglContextLost(), GetDebug(), "eglSwapBuffers",
+ GetSurfaceIfValid(display, eglSurface));
return EGL_FALSE;
}
if (surface == EGL_NO_SURFACE)
{
- thread->setError(EglBadSurface());
+ thread->setError(EglBadSurface(), GetDebug(), "eglSwapBuffers",
+ GetSurfaceIfValid(display, eglSurface));
return EGL_FALSE;
}
if (!thread->getContext() || thread->getCurrentDrawSurface() != eglSurface)
{
- thread->setError(EglBadSurface());
+ thread->setError(EglBadSurface(), GetDebug(), "eglSwapBuffers",
+ GetSurfaceIfValid(display, eglSurface));
return EGL_FALSE;
}
error = eglSurface->swap(thread->getContext());
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglSwapBuffers",
+ GetSurfaceIfValid(display, eglSurface));
return EGL_FALSE;
}
- thread->setError(NoError());
+ thread->setSuccess();
return EGL_TRUE;
}
@@ -695,19 +709,21 @@
Error error = ValidateSurface(display, eglSurface);
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglCopyBuffers",
+ GetSurfaceIfValid(display, eglSurface));
return EGL_FALSE;
}
if (display->testDeviceLost())
{
- thread->setError(EglContextLost());
+ thread->setError(EglContextLost(), GetDebug(), "eglCopyBuffers",
+ GetSurfaceIfValid(display, eglSurface));
return EGL_FALSE;
}
UNIMPLEMENTED(); // FIXME
- thread->setError(NoError());
+ thread->setSuccess();
return 0;
}
@@ -724,31 +740,36 @@
Error error = ValidateSurface(display, eglSurface);
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglBindTexImage",
+ GetSurfaceIfValid(display, eglSurface));
return EGL_FALSE;
}
if (buffer != EGL_BACK_BUFFER)
{
- thread->setError(EglBadParameter());
+ thread->setError(EglBadParameter(), GetDebug(), "eglBindTexImage",
+ GetSurfaceIfValid(display, eglSurface));
return EGL_FALSE;
}
if (surface == EGL_NO_SURFACE || eglSurface->getType() == EGL_WINDOW_BIT)
{
- thread->setError(EglBadSurface());
+ thread->setError(EglBadSurface(), GetDebug(), "eglBindTexImage",
+ GetSurfaceIfValid(display, eglSurface));
return EGL_FALSE;
}
if (eglSurface->getBoundTexture())
{
- thread->setError(EglBadAccess());
+ thread->setError(EglBadAccess(), GetDebug(), "eglBindTexImage",
+ GetSurfaceIfValid(display, eglSurface));
return EGL_FALSE;
}
if (eglSurface->getTextureFormat() == TextureFormat::NoTexture)
{
- thread->setError(EglBadMatch());
+ thread->setError(EglBadMatch(), GetDebug(), "eglBindTexImage",
+ GetSurfaceIfValid(display, eglSurface));
return EGL_FALSE;
}
@@ -762,19 +783,21 @@
if (textureObject->getImmutableFormat())
{
- thread->setError(EglBadMatch());
+ thread->setError(EglBadMatch(), GetDebug(), "eglBindTexImage",
+ GetSurfaceIfValid(display, eglSurface));
return EGL_FALSE;
}
error = eglSurface->bindTexImage(context, textureObject, buffer);
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglBindTexImage",
+ GetSurfaceIfValid(display, eglSurface));
return EGL_FALSE;
}
}
- thread->setError(NoError());
+ thread->setSuccess();
return EGL_TRUE;
}
@@ -795,13 +818,14 @@
Error error = ValidateSurfaceAttrib(display, eglSurface, attribute, value);
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglSurfaceAttrib",
+ GetSurfaceIfValid(display, eglSurface));
return EGL_FALSE;
}
SetSurfaceAttrib(eglSurface, attribute, value);
- thread->setError(NoError());
+ thread->setSuccess();
return EGL_TRUE;
}
@@ -817,25 +841,29 @@
Error error = ValidateSurface(display, eglSurface);
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglReleaseTexImage",
+ GetSurfaceIfValid(display, eglSurface));
return EGL_FALSE;
}
if (buffer != EGL_BACK_BUFFER)
{
- thread->setError(EglBadParameter());
+ thread->setError(EglBadParameter(), GetDebug(), "eglReleaseTexImage",
+ GetSurfaceIfValid(display, eglSurface));
return EGL_FALSE;
}
if (surface == EGL_NO_SURFACE || eglSurface->getType() == EGL_WINDOW_BIT)
{
- thread->setError(EglBadSurface());
+ thread->setError(EglBadSurface(), GetDebug(), "eglReleaseTexImage",
+ GetSurfaceIfValid(display, eglSurface));
return EGL_FALSE;
}
if (eglSurface->getTextureFormat() == TextureFormat::NoTexture)
{
- thread->setError(EglBadMatch());
+ thread->setError(EglBadMatch(), GetDebug(), "eglReleaseTexImage",
+ GetSurfaceIfValid(display, eglSurface));
return EGL_FALSE;
}
@@ -846,12 +874,13 @@
error = eglSurface->releaseTexImage(thread->getContext(), buffer);
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglReleaseTexImage",
+ GetSurfaceIfValid(display, eglSurface));
return EGL_FALSE;
}
}
- thread->setError(NoError());
+ thread->setSuccess();
return EGL_TRUE;
}
@@ -865,7 +894,7 @@
Error error = ValidateDisplay(display);
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglSwapInterval", GetDisplayIfValid(display));
return EGL_FALSE;
}
@@ -873,7 +902,8 @@
if (draw_surface == nullptr)
{
- thread->setError(EglBadSurface());
+ thread->setError(EglBadSurface(), GetDebug(), "eglSwapInterval",
+ GetDisplayIfValid(display));
return EGL_FALSE;
}
@@ -883,7 +913,7 @@
draw_surface->setSwapInterval(clampedInterval);
- thread->setError(NoError());
+ thread->setSuccess();
return EGL_TRUE;
}
@@ -897,18 +927,18 @@
{
case EGL_OPENGL_API:
case EGL_OPENVG_API:
- thread->setError(EglBadParameter());
+ thread->setError(EglBadParameter(), GetDebug(), "eglBindAPI", GetThreadIfValid(thread));
return EGL_FALSE; // Not supported by this implementation
case EGL_OPENGL_ES_API:
break;
default:
- thread->setError(EglBadParameter());
+ thread->setError(EglBadParameter(), GetDebug(), "eglBindAPI", GetThreadIfValid(thread));
return EGL_FALSE;
}
thread->setAPI(api);
- thread->setError(NoError());
+ thread->setSuccess();
return EGL_TRUE;
}
@@ -919,7 +949,7 @@
EGLenum API = thread->getAPI();
- thread->setError(NoError());
+ thread->setSuccess();
return API;
}
@@ -943,7 +973,8 @@
ValidateCreatePbufferFromClientBuffer(display, buftype, buffer, configuration, attributes);
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglCreatePbufferFromClientBuffer",
+ GetDisplayIfValid(display));
return EGL_NO_SURFACE;
}
@@ -952,7 +983,8 @@
&surface);
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglCreatePbufferFromClientBuffer",
+ GetDisplayIfValid(display));
return EGL_NO_SURFACE;
}
@@ -966,7 +998,7 @@
MakeCurrent(EGL_NO_DISPLAY, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE);
- thread->setError(NoError());
+ thread->setSuccess();
return EGL_TRUE;
}
@@ -975,23 +1007,24 @@
EVENT("()");
Thread *thread = GetCurrentThread();
- Display *display = thread->getCurrentDisplay();
+ Display *display = thread->getCurrentDisplay();
+ gl::Context *context = thread->getContext();
Error error = ValidateDisplay(display);
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglWaitClient", GetContextIfValid(display, context));
return EGL_FALSE;
}
- error = display->waitClient(thread->getContext());
+ error = display->waitClient(context);
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglWaitClient", GetContextIfValid(display, context));
return EGL_FALSE;
}
- thread->setError(NoError());
+ thread->setSuccess();
return EGL_TRUE;
}
@@ -1003,7 +1036,7 @@
gl::Context *context = thread->getContext();
- thread->setError(NoError());
+ thread->setSuccess();
return static_cast<EGLContext>(context);
}
@@ -1012,10 +1045,13 @@
{
EVENT("(EGLDisplay dpy = 0x%0.8p, EGLenum type = 0x%X, const EGLint* attrib_list = 0x%0.8p)",
dpy, type, attrib_list);
- Thread *thread = GetCurrentThread();
+ Thread *thread = GetCurrentThread();
+ Display *display = static_cast<Display *>(dpy);
UNIMPLEMENTED();
- thread->setError(EglBadDisplay() << "eglCreateSync unimplemented.");
+ // TODO(geofflang): Implement sync objects. http://anglebug.com/2466
+ thread->setError(EglBadDisplay() << "eglCreateSync unimplemented.", GetDebug(), "eglCreateSync",
+ GetDisplayIfValid(display));
return EGL_NO_SYNC;
}
@@ -1025,7 +1061,9 @@
Thread *thread = GetCurrentThread();
UNIMPLEMENTED();
- thread->setError(EglBadDisplay() << "eglDestroySync unimplemented.");
+ // TODO(geofflang): Pass the EGL sync object to the setError function. http://anglebug.com/2466
+ thread->setError(EglBadDisplay() << "eglDestroySync unimplemented.", GetDebug(),
+ "eglDestroySync", nullptr);
return EGL_FALSE;
}
@@ -1038,7 +1076,9 @@
Thread *thread = GetCurrentThread();
UNIMPLEMENTED();
- thread->setError(EglBadDisplay() << "eglClientWaitSync unimplemented.");
+ // TODO(geofflang): Pass the EGL sync object to the setError function. http://anglebug.com/2466
+ thread->setError(EglBadDisplay() << "eglClientWaitSync unimplemented.", GetDebug(),
+ "eglClientWaitSync", nullptr);
return 0;
}
@@ -1054,7 +1094,9 @@
Thread *thread = GetCurrentThread();
UNIMPLEMENTED();
- thread->setError(EglBadDisplay() << "eglSyncAttrib unimplemented.");
+ // TODO(geofflang): Pass the EGL sync object to the setError function. http://anglebug.com/2466
+ thread->setError(EglBadDisplay() << "eglSyncAttrib unimplemented.", GetDebug(),
+ "eglGetSyncAttrib", nullptr);
return EGL_FALSE;
}
@@ -1068,20 +1110,25 @@
"(EGLDisplay dpy = 0x%0.8p, EGLContext ctx = 0x%0.8p, EGLenum target = 0x%X, "
"EGLClientBuffer buffer = 0x%0.8p, const EGLAttrib *attrib_list = 0x%0.8p)",
dpy, ctx, target, buffer, attrib_list);
- Thread *thread = GetCurrentThread();
+ Thread *thread = GetCurrentThread();
+ Display *display = static_cast<Display *>(dpy);
UNIMPLEMENTED();
- thread->setError(EglBadDisplay() << "eglCreateImage unimplemented.");
+ thread->setError(EglBadDisplay() << "eglCreateImage unimplemented.", GetDebug(),
+ "eglCreateImage", GetDisplayIfValid(display));
return EGL_NO_IMAGE;
}
EGLBoolean EGLAPIENTRY DestroyImage(EGLDisplay dpy, EGLImage image)
{
EVENT("(EGLDisplay dpy = 0x%0.8p, EGLImage image = 0x%0.8p)", dpy, image);
- Thread *thread = GetCurrentThread();
+ Thread *thread = GetCurrentThread();
+ Display *display = static_cast<Display *>(dpy);
+ Image *eglImage = static_cast<Image *>(image);
UNIMPLEMENTED();
- thread->setError(EglBadDisplay() << "eglDestroyImage unimplemented.");
+ thread->setError(EglBadDisplay() << "eglDestroyImage unimplemented.", GetDebug(),
+ "eglDestroyImage", GetImageIfValid(display, eglImage));
return EGL_FALSE;
}
@@ -1096,7 +1143,7 @@
Thread *thread = GetCurrentThread();
Error err = ValidateGetPlatformDisplay(platform, native_display, attrib_list);
- thread->setError(err);
+ thread->setError(err, GetDebug(), "eglGetPlatformDisplay", GetThreadIfValid(thread));
if (err.isError())
{
return EGL_NO_DISPLAY;
@@ -1129,10 +1176,12 @@
"(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, void* native_window = 0x%0.8p, "
"const EGLint* attrib_list = 0x%0.8p)",
dpy, config, native_window, attrib_list);
- Thread *thread = GetCurrentThread();
+ Thread *thread = GetCurrentThread();
+ Display *display = static_cast<Display *>(dpy);
UNIMPLEMENTED();
- thread->setError(EglBadDisplay() << "eglCreatePlatformWindowSurface unimplemented.");
+ thread->setError(EglBadDisplay() << "eglCreatePlatformWindowSurface unimplemented.", GetDebug(),
+ "eglCreatePlatformWindowSurface", GetDisplayIfValid(display));
return EGL_NO_SURFACE;
}
@@ -1145,10 +1194,12 @@
"(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, void* native_pixmap = 0x%0.8p, "
"const EGLint* attrib_list = 0x%0.8p)",
dpy, config, native_pixmap, attrib_list);
- Thread *thread = GetCurrentThread();
+ Thread *thread = GetCurrentThread();
+ Display *display = static_cast<Display *>(dpy);
UNIMPLEMENTED();
- thread->setError(EglBadDisplay() << "eglCreatePlatformPixmapSurface unimplemented.");
+ thread->setError(EglBadDisplay() << "eglCreatePlatformPixmapSurface unimplemented.", GetDebug(),
+ "eglCreatePlatformPixmapSurface", GetDisplayIfValid(display));
return EGL_NO_SURFACE;
}
@@ -1156,10 +1207,12 @@
{
EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSync sync = 0x%0.8p, EGLint flags = 0x%X)", dpy, sync,
flags);
- Thread *thread = GetCurrentThread();
+ Thread *thread = GetCurrentThread();
+ Display *display = static_cast<Display *>(dpy);
UNIMPLEMENTED();
- thread->setError(EglBadDisplay() << "eglWaitSync unimplemented.");
+ thread->setError(EglBadDisplay() << "eglWaitSync unimplemented.", GetDebug(), "eglWaitSync",
+ GetDisplayIfValid(display));
return EGL_FALSE;
}
@@ -1171,7 +1224,7 @@
ProcEntry *entry =
std::lower_bound(&g_procTable[0], &g_procTable[g_numProcs], procname, CompareProc);
- thread->setError(NoError());
+ thread->setSuccess();
if (entry == &g_procTable[g_numProcs] || strcmp(entry->first, procname) != 0)
{
diff --git a/src/libGLESv2/entry_points_egl_ext.cpp b/src/libGLESv2/entry_points_egl_ext.cpp
index b0fc1d7..2a1f1b1 100644
--- a/src/libGLESv2/entry_points_egl_ext.cpp
+++ b/src/libGLESv2/entry_points_egl_ext.cpp
@@ -40,19 +40,21 @@
Error error = ValidateSurface(display, eglSurface);
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglQuerySurfacePointerANGLE",
+ GetSurfaceIfValid(display, eglSurface));
return EGL_FALSE;
}
if (!display->getExtensions().querySurfacePointer)
{
- thread->setError(NoError());
+ thread->setSuccess();
return EGL_FALSE;
}
if (surface == EGL_NO_SURFACE)
{
- thread->setError(EglBadSurface());
+ thread->setError(EglBadSurface(), GetDebug(), "eglQuerySurfacePointerANGLE",
+ GetSurfaceIfValid(display, eglSurface));
return EGL_FALSE;
}
@@ -62,25 +64,35 @@
case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE:
if (!display->getExtensions().surfaceD3DTexture2DShareHandle)
{
- thread->setError(EglBadAttribute());
+ thread->setError(EglBadAttribute(), GetDebug(), "eglQuerySurfacePointerANGLE",
+ GetSurfaceIfValid(display, eglSurface));
return EGL_FALSE;
}
break;
case EGL_DXGI_KEYED_MUTEX_ANGLE:
if (!display->getExtensions().keyedMutex)
{
- thread->setError(EglBadAttribute());
+ thread->setError(EglBadAttribute(), GetDebug(), "eglQuerySurfacePointerANGLE",
+ GetSurfaceIfValid(display, eglSurface));
return EGL_FALSE;
}
break;
default:
- thread->setError(EglBadAttribute());
+ thread->setError(EglBadAttribute(), GetDebug(), "eglQuerySurfacePointerANGLE",
+ GetSurfaceIfValid(display, eglSurface));
return EGL_FALSE;
}
error = eglSurface->querySurfacePointerANGLE(attribute, value);
- thread->setError(error);
- return (error.isError() ? EGL_FALSE : EGL_TRUE);
+ if (error.isError())
+ {
+ thread->setError(error, GetDebug(), "eglQuerySurfacePointerANGLE",
+ GetSurfaceIfValid(display, eglSurface));
+ return EGL_FALSE;
+ }
+
+ thread->setSuccess();
+ return EGL_TRUE;
}
// EGL_NV_post_sub_buffer
@@ -91,40 +103,43 @@
"(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint x = %d, EGLint y = %d, "
"EGLint width = %d, EGLint height = %d)",
dpy, surface, x, y, width, height);
- Thread *thread = GetCurrentThread();
+ Thread *thread = GetCurrentThread();
+ Display *display = static_cast<Display *>(dpy);
+ Surface *eglSurface = static_cast<Surface *>(surface);
if (x < 0 || y < 0 || width < 0 || height < 0)
{
- thread->setError(EglBadParameter());
+ thread->setError(EglBadParameter(), GetDebug(), "eglPostSubBufferNV",
+ GetSurfaceIfValid(display, eglSurface));
return EGL_FALSE;
}
- Display *display = static_cast<Display *>(dpy);
- Surface *eglSurface = static_cast<Surface *>(surface);
-
Error error = ValidateSurface(display, eglSurface);
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglPostSubBufferNV",
+ GetSurfaceIfValid(display, eglSurface));
return EGL_FALSE;
}
if (display->testDeviceLost())
{
- thread->setError(EglContextLost());
+ thread->setError(EglContextLost(), GetDebug(), "eglPostSubBufferNV",
+ GetSurfaceIfValid(display, eglSurface));
return EGL_FALSE;
}
if (surface == EGL_NO_SURFACE)
{
- thread->setError(EglBadSurface());
+ thread->setError(EglBadSurface(), GetDebug(), "eglPostSubBufferNV",
+ GetSurfaceIfValid(display, eglSurface));
return EGL_FALSE;
}
if (!display->getExtensions().postSubBuffer)
{
// Spec is not clear about how this should be handled.
- thread->setError(NoError());
+ thread->setSuccess();
return EGL_TRUE;
}
@@ -132,11 +147,12 @@
error = eglSurface->postSubBuffer(thread->getContext(), x, y, width, height);
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglPostSubBufferNV",
+ GetSurfaceIfValid(display, eglSurface));
return EGL_FALSE;
}
- thread->setError(NoError());
+ thread->setSuccess();
return EGL_TRUE;
}
@@ -152,7 +168,7 @@
Thread *thread = GetCurrentThread();
Error err = ValidateGetPlatformDisplayEXT(platform, native_display, attrib_list);
- thread->setError(err);
+ thread->setError(err, GetDebug(), "eglGetPlatformDisplayEXT", GetThreadIfValid(thread));
if (err.isError())
{
return EGL_NO_DISPLAY;
@@ -194,9 +210,10 @@
ANGLE_EGL_TRY_RETURN(
thread,
ValidateCreatePlatformWindowSurfaceEXT(display, configuration, native_window, attributes),
- EGL_NO_SURFACE);
+ "eglCreatePlatformWindowSurfaceEXT", GetDisplayIfValid(display), EGL_NO_SURFACE);
- thread->setError(EglBadDisplay() << "CreatePlatformWindowSurfaceEXT unimplemented.");
+ thread->setError(EglBadDisplay() << "CreatePlatformWindowSurfaceEXT unimplemented.", GetDebug(),
+ "eglCreatePlatformWindowSurfaceEXT", GetDisplayIfValid(display));
return EGL_NO_SURFACE;
}
@@ -218,9 +235,10 @@
ANGLE_EGL_TRY_RETURN(
thread,
ValidateCreatePlatformPixmapSurfaceEXT(display, configuration, native_pixmap, attributes),
- EGL_NO_SURFACE);
+ "eglCreatePlatformPixmapSurfaceEXT", GetDisplayIfValid(display), EGL_NO_SURFACE);
- thread->setError(EglBadDisplay() << "CreatePlatformPixmapSurfaceEXT unimplemented.");
+ thread->setError(EglBadDisplay() << "CreatePlatformPixmapSurfaceEXT unimplemented.", GetDebug(),
+ "eglCreatePlatformPixmapSurfaceEXT", GetDisplayIfValid(display));
return EGL_NO_SURFACE;
}
@@ -232,9 +250,11 @@
Thread *thread = GetCurrentThread();
Device *dev = static_cast<Device *>(device);
- if (dev == EGL_NO_DEVICE_EXT || !Device::IsValidDevice(dev))
+
+ Error error = ValidateDevice(dev);
+ if (error.isError())
{
- thread->setError(EglBadAccess());
+ thread->setError(error, GetDebug(), "eglQueryDeviceAttribEXT", GetDeviceIfValid(dev));
return EGL_FALSE;
}
@@ -245,12 +265,11 @@
{
thread->setError(EglBadAccess() << "Device wasn't created using eglCreateDeviceANGLE, "
"and the Display that created it doesn't support "
- "device querying");
+ "device querying",
+ GetDebug(), "eglQueryDeviceAttribEXT", GetDeviceIfValid(dev));
return EGL_FALSE;
}
- Error error(NoError());
-
// validate the attribute parameter
switch (attribute)
{
@@ -258,18 +277,26 @@
case EGL_D3D9_DEVICE_ANGLE:
if (!dev->getExtensions().deviceD3D || dev->getType() != attribute)
{
- thread->setError(EglBadAttribute());
+ thread->setError(EglBadAttribute(), GetDebug(), "eglQueryDeviceAttribEXT",
+ GetDeviceIfValid(dev));
return EGL_FALSE;
}
error = dev->getDevice(value);
+ if (error.isError())
+ {
+ thread->setError(error, GetDebug(), "eglQueryDeviceAttribEXT",
+ GetDeviceIfValid(dev));
+ return EGL_FALSE;
+ }
break;
default:
- thread->setError(EglBadAttribute());
+ thread->setError(EglBadAttribute(), GetDebug(), "eglQueryDeviceAttribEXT",
+ GetDeviceIfValid(dev));
return EGL_FALSE;
}
- thread->setError(error);
- return (error.isError() ? EGL_FALSE : EGL_TRUE);
+ thread->setSuccess();
+ return EGL_TRUE;
}
// EGL_EXT_device_query
@@ -279,10 +306,12 @@
Thread *thread = GetCurrentThread();
Device *dev = static_cast<Device *>(device);
- if (dev == EGL_NO_DEVICE_EXT || !Device::IsValidDevice(dev))
+
+ Error error = ValidateDevice(dev);
+ if (error.isError())
{
- thread->setError(EglBadDevice());
- return nullptr;
+ thread->setError(error, GetDebug(), "eglQueryDeviceStringEXT", GetDeviceIfValid(dev));
+ return EGL_FALSE;
}
const char *result;
@@ -292,11 +321,12 @@
result = dev->getExtensionString().c_str();
break;
default:
- thread->setError(EglBadDevice());
+ thread->setError(EglBadDevice(), GetDebug(), "eglQueryDeviceStringEXT",
+ GetDeviceIfValid(dev));
return nullptr;
}
- thread->setError(NoError());
+ thread->setSuccess();
return result;
}
@@ -312,13 +342,14 @@
Error error = ValidateDisplay(display);
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglQueryDisplayAttribEXT", GetDisplayIfValid(display));
return EGL_FALSE;
}
if (!display->getExtensions().deviceQuery)
{
- thread->setError(EglBadAccess());
+ thread->setError(EglBadAccess(), GetDebug(), "eglQueryDisplayAttribEXT",
+ GetDisplayIfValid(display));
return EGL_FALSE;
}
@@ -330,12 +361,13 @@
break;
default:
- thread->setError(EglBadAttribute());
+ thread->setError(EglBadAttribute(), GetDebug(), "eglQueryDisplayAttribEXT",
+ GetDisplayIfValid(display));
return EGL_FALSE;
}
- thread->setError(error);
- return (error.isError() ? EGL_FALSE : EGL_TRUE);
+ thread->setSuccess();
+ return EGL_TRUE;
}
ANGLE_EXPORT EGLImageKHR EGLAPIENTRY CreateImageKHR(EGLDisplay dpy,
@@ -357,7 +389,7 @@
Error error = ValidateCreateImageKHR(display, context, target, buffer, attributes);
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglCreateImageKHR", GetDisplayIfValid(display));
return EGL_NO_IMAGE;
}
@@ -365,10 +397,11 @@
error = display->createImage(context, target, buffer, attributes, &image);
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglCreateImageKHR", GetDisplayIfValid(display));
return EGL_NO_IMAGE;
}
+ thread->setSuccess();
return static_cast<EGLImage>(image);
}
@@ -383,12 +416,13 @@
Error error = ValidateDestroyImageKHR(display, img);
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglDestroyImageKHR", GetImageIfValid(display, img));
return EGL_FALSE;
}
display->destroyImage(img);
+ thread->setSuccess();
return EGL_TRUE;
}
@@ -405,7 +439,7 @@
Error error = ValidateCreateDeviceANGLE(device_type, native_device, attrib_list);
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglCreateDeviceANGLE", GetThreadIfValid(thread));
return EGL_NO_DEVICE_EXT;
}
@@ -414,10 +448,11 @@
if (error.isError())
{
ASSERT(device == nullptr);
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglCreateDeviceANGLE", GetThreadIfValid(thread));
return EGL_NO_DEVICE_EXT;
}
+ thread->setSuccess();
return device;
}
@@ -431,12 +466,13 @@
Error error = ValidateReleaseDeviceANGLE(dev);
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglReleaseDeviceANGLE", GetDeviceIfValid(dev));
return EGL_FALSE;
}
SafeDelete(dev);
+ thread->setSuccess();
return EGL_TRUE;
}
@@ -452,7 +488,7 @@
Error error = ValidateCreateStreamKHR(display, attributes);
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglCreateStreamKHR", GetDisplayIfValid(display));
return EGL_NO_STREAM_KHR;
}
@@ -460,11 +496,11 @@
error = display->createStream(attributes, &stream);
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglCreateStreamKHR", GetDisplayIfValid(display));
return EGL_NO_STREAM_KHR;
}
- thread->setError(error);
+ thread->setSuccess();
return static_cast<EGLStreamKHR>(stream);
}
@@ -479,12 +515,14 @@
Error error = ValidateDestroyStreamKHR(display, streamObject);
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglDestroyStreamKHR",
+ GetStreamIfValid(display, streamObject));
return EGL_FALSE;
}
display->destroyStream(streamObject);
- thread->setError(error);
+
+ thread->setSuccess();
return EGL_TRUE;
}
@@ -505,7 +543,8 @@
Error error = ValidateStreamAttribKHR(display, streamObject, attribute, value);
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglStreamAttribKHR",
+ GetStreamIfValid(display, streamObject));
return EGL_FALSE;
}
@@ -521,7 +560,7 @@
UNREACHABLE();
}
- thread->setError(error);
+ thread->setSuccess();
return EGL_TRUE;
}
@@ -542,7 +581,8 @@
Error error = ValidateQueryStreamKHR(display, streamObject, attribute, value);
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglQueryStreamKHR",
+ GetStreamIfValid(display, streamObject));
return EGL_FALSE;
}
@@ -561,7 +601,7 @@
UNREACHABLE();
}
- thread->setError(error);
+ thread->setSuccess();
return EGL_TRUE;
}
@@ -582,7 +622,8 @@
Error error = ValidateQueryStreamu64KHR(display, streamObject, attribute, value);
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglQueryStreamu64KHR",
+ GetStreamIfValid(display, streamObject));
return EGL_FALSE;
}
@@ -598,7 +639,7 @@
UNREACHABLE();
}
- thread->setError(error);
+ thread->setSuccess();
return EGL_TRUE;
}
@@ -614,18 +655,20 @@
Error error = ValidateStreamConsumerGLTextureExternalKHR(display, context, streamObject);
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglStreamConsumerGLTextureExternalKHR",
+ GetStreamIfValid(display, streamObject));
return EGL_FALSE;
}
error = streamObject->createConsumerGLTextureExternal(AttributeMap(), context);
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglStreamConsumerGLTextureExternalKHR",
+ GetStreamIfValid(display, streamObject));
return EGL_FALSE;
}
- thread->setError(error);
+ thread->setSuccess();
return EGL_TRUE;
}
@@ -641,18 +684,20 @@
Error error = ValidateStreamConsumerAcquireKHR(display, context, streamObject);
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglStreamConsumerAcquireKHR",
+ GetStreamIfValid(display, streamObject));
return EGL_FALSE;
}
error = streamObject->consumerAcquire(context);
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglStreamConsumerAcquireKHR",
+ GetStreamIfValid(display, streamObject));
return EGL_FALSE;
}
- thread->setError(error);
+ thread->setSuccess();
return EGL_TRUE;
}
@@ -668,18 +713,20 @@
Error error = ValidateStreamConsumerReleaseKHR(display, context, streamObject);
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglSStreamConsumerReleaseKHR",
+ GetStreamIfValid(display, streamObject));
return EGL_FALSE;
}
error = streamObject->consumerRelease(context);
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglStreamConsumerReleaseKHR",
+ GetStreamIfValid(display, streamObject));
return EGL_FALSE;
}
- thread->setError(error);
+ thread->setSuccess();
return EGL_TRUE;
}
@@ -701,18 +748,20 @@
attributes);
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglStreamConsumerGLTextureExternalAttribsNV",
+ GetStreamIfValid(display, streamObject));
return EGL_FALSE;
}
error = streamObject->createConsumerGLTextureExternal(attributes, context);
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglStreamConsumerGLTextureExternalAttribsNV",
+ GetStreamIfValid(display, streamObject));
return EGL_FALSE;
}
- thread->setError(error);
+ thread->setSuccess();
return EGL_TRUE;
}
@@ -732,18 +781,20 @@
Error error = ValidateCreateStreamProducerD3DTextureANGLE(display, streamObject, attributes);
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglCreateStreamProducerD3DTextureANGLE",
+ GetStreamIfValid(display, streamObject));
return EGL_FALSE;
}
error = streamObject->createProducerD3D11Texture(attributes);
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglCreateStreamProducerD3DTextureANGLE",
+ GetStreamIfValid(display, streamObject));
return EGL_FALSE;
}
- thread->setError(error);
+ thread->setSuccess();
return EGL_TRUE;
}
@@ -765,18 +816,20 @@
Error error = ValidateStreamPostD3DTextureANGLE(display, streamObject, texture, attributes);
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglStreamPostD3DTextureANGLE",
+ GetStreamIfValid(display, streamObject));
return EGL_FALSE;
}
error = streamObject->postD3D11Texture(texture, attributes);
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglStreamPostD3DTextureANGLE",
+ GetStreamIfValid(display, streamObject));
return EGL_FALSE;
}
- thread->setError(error);
+ thread->setSuccess();
return EGL_TRUE;
}
@@ -798,18 +851,20 @@
Error error = ValidateGetSyncValuesCHROMIUM(display, eglSurface, ust, msc, sbc);
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglGetSyncValuesCHROMIUM",
+ GetSurfaceIfValid(display, eglSurface));
return EGL_FALSE;
}
error = eglSurface->getSyncValues(ust, msc, sbc);
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglGetSyncValuesCHROMIUM",
+ GetSurfaceIfValid(display, eglSurface));
return EGL_FALSE;
}
- thread->setError(error);
+ thread->setSuccess();
return EGL_TRUE;
}
@@ -830,17 +885,20 @@
Error error = ValidateSwapBuffersWithDamageKHR(display, eglSurface, rects, n_rects);
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglSwapBuffersWithDamageEXT",
+ GetSurfaceIfValid(display, eglSurface));
return EGL_FALSE;
}
error = eglSurface->swapWithDamage(thread->getContext(), rects, n_rects);
if (error.isError())
{
- thread->setError(error);
+ thread->setError(error, GetDebug(), "eglSwapBuffersWithDamageEXT",
+ GetSurfaceIfValid(display, eglSurface));
return EGL_FALSE;
}
+ thread->setSuccess();
return EGL_TRUE;
}
@@ -856,8 +914,11 @@
Surface *eglSurface = static_cast<Surface *>(surface);
ANGLE_EGL_TRY_RETURN(thread, ValidatePresentationTimeANDROID(display, eglSurface, time),
+ "eglPresentationTimeANDROID", GetSurfaceIfValid(display, eglSurface),
EGL_FALSE);
- ANGLE_EGL_TRY_RETURN(thread, eglSurface->setPresentationTime(time), EGL_FALSE);
+ ANGLE_EGL_TRY_RETURN(thread, eglSurface->setPresentationTime(time),
+ "eglPresentationTimeANDROID", GetSurfaceIfValid(display, eglSurface),
+ EGL_FALSE);
return EGL_TRUE;
}
@@ -869,8 +930,10 @@
Display *display = static_cast<Display *>(dpy);
Thread *thread = GetCurrentThread();
- ANGLE_EGL_TRY_RETURN(thread, ValidateProgramCacheGetAttribANGLE(display, attrib), 0);
+ ANGLE_EGL_TRY_RETURN(thread, ValidateProgramCacheGetAttribANGLE(display, attrib),
+ "eglProgramCacheGetAttribANGLE", GetDisplayIfValid(display), 0);
+ thread->setSuccess();
return display->programCacheGetAttrib(attrib);
}
@@ -890,9 +953,13 @@
Thread *thread = GetCurrentThread();
ANGLE_EGL_TRY(thread,
- ValidateProgramCacheQueryANGLE(display, index, key, keysize, binary, binarysize));
+ ValidateProgramCacheQueryANGLE(display, index, key, keysize, binary, binarysize),
+ "eglProgramCacheQueryANGLE", GetDisplayIfValid(display));
- ANGLE_EGL_TRY(thread, display->programCacheQuery(index, key, keysize, binary, binarysize));
+ ANGLE_EGL_TRY(thread, display->programCacheQuery(index, key, keysize, binary, binarysize),
+ "eglProgramCacheQueryANGLE", GetDisplayIfValid(display));
+
+ thread->setSuccess();
}
void EGLAPIENTRY ProgramCachePopulateANGLE(EGLDisplay dpy,
@@ -910,9 +977,13 @@
Thread *thread = GetCurrentThread();
ANGLE_EGL_TRY(thread,
- ValidateProgramCachePopulateANGLE(display, key, keysize, binary, binarysize));
+ ValidateProgramCachePopulateANGLE(display, key, keysize, binary, binarysize),
+ "eglProgramCachePopulateANGLE", GetDisplayIfValid(display));
- ANGLE_EGL_TRY(thread, display->programCachePopulate(key, keysize, binary, binarysize));
+ ANGLE_EGL_TRY(thread, display->programCachePopulate(key, keysize, binary, binarysize),
+ "eglProgramCachePopulateANGLE", GetDisplayIfValid(display));
+
+ thread->setSuccess();
}
EGLint EGLAPIENTRY ProgramCacheResizeANGLE(EGLDisplay dpy, EGLint limit, EGLenum mode)
@@ -922,9 +993,100 @@
Display *display = static_cast<Display *>(dpy);
Thread *thread = GetCurrentThread();
- ANGLE_EGL_TRY_RETURN(thread, ValidateProgramCacheResizeANGLE(display, limit, mode), 0);
+ ANGLE_EGL_TRY_RETURN(thread, ValidateProgramCacheResizeANGLE(display, limit, mode),
+ "eglProgramCacheResizeANGLE", GetDisplayIfValid(display), 0);
+ thread->setSuccess();
return display->programCacheResize(limit, mode);
}
+EGLint EGLAPIENTRY DebugMessageControlKHR(EGLDEBUGPROCKHR callback, const EGLAttrib *attrib_list)
+{
+ EVENT("(EGLDEBUGPROCKHR callback = 0x%0.8p, EGLAttrib attrib_list = 0x%0.8p)", callback,
+ attrib_list);
+
+ Thread *thread = GetCurrentThread();
+
+ AttributeMap attributes = AttributeMap::CreateFromAttribArray(attrib_list);
+
+ Error error = ValidateDebugMessageControlKHR(callback, attributes);
+ if (error.isError())
+ {
+ thread->setError(error, GetDebug(), "eglDebugMessageControlKHR", nullptr);
+ return error.getCode();
+ }
+
+ Debug *debug = GetDebug();
+ debug->setCallback(callback, attributes);
+
+ thread->setSuccess();
+ return EGL_SUCCESS;
+}
+
+EGLBoolean EGLAPIENTRY QueryDebugKHR(EGLint attribute, EGLAttrib *value)
+{
+ EVENT("(EGLint attribute = 0x%X, EGLAttrib* value = 0x%0.8p)", attribute, value);
+
+ Thread *thread = GetCurrentThread();
+
+ Error error = ValidateQueryDebugKHR(attribute, value);
+ if (error.isError())
+ {
+ thread->setError(error, GetDebug(), "eglQueryDebugKHR", nullptr);
+ return EGL_FALSE;
+ }
+
+ Debug *debug = GetDebug();
+ 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:
+ *value = debug->isMessageTypeEnabled(FromEGLenum<MessageType>(attribute)) ? EGL_TRUE
+ : EGL_FALSE;
+ break;
+ case EGL_DEBUG_CALLBACK_KHR:
+ *value = reinterpret_cast<EGLAttrib>(debug->getCallback());
+ break;
+
+ default:
+ UNREACHABLE();
+ }
+
+ thread->setSuccess();
+ return EGL_TRUE;
+}
+
+EGLint EGLAPIENTRY LabelObjectKHR(EGLDisplay dpy,
+ EGLenum objectType,
+ EGLObjectKHR object,
+ EGLLabelKHR label)
+{
+ EVENT(
+ "(EGLDisplay dpy = 0x%0.8pf, EGLenum objectType = 0x%X, EGLObjectKHR object = 0x%0.8p, "
+ "EGLLabelKHR label = 0x%0.8p)",
+ dpy, objectType, object, label);
+
+ Display *display = static_cast<Display *>(dpy);
+ Thread *thread = GetCurrentThread();
+
+ ObjectType objectTypePacked = FromEGLenum<ObjectType>(objectType);
+ Error error = ValidateLabelObjectKHR(thread, display, objectTypePacked, object, label);
+ if (error.isError())
+ {
+ thread->setError(error, GetDebug(), "eglLabelObjectKHR",
+ GetLabeledObjectIfValid(thread, display, objectTypePacked, object));
+ return error.getCode();
+ }
+
+ LabeledObject *labeledObject =
+ GetLabeledObjectIfValid(thread, display, objectTypePacked, object);
+ ASSERT(labeledObject != nullptr);
+ labeledObject->setLabel(label);
+
+ thread->setSuccess();
+ return EGL_SUCCESS;
+}
+
} // namespace egl
diff --git a/src/libGLESv2/entry_points_egl_ext.h b/src/libGLESv2/entry_points_egl_ext.h
index 98cd457..6a44978 100644
--- a/src/libGLESv2/entry_points_egl_ext.h
+++ b/src/libGLESv2/entry_points_egl_ext.h
@@ -120,7 +120,7 @@
EGLSurface surface,
EGLnsecsANDROID time);
-//
+// EGL_ANGLE_program_cache_control
ANGLE_EXPORT EGLint EGLAPIENTRY ProgramCacheGetAttribANGLE(EGLDisplay dpy, EGLenum attrib);
ANGLE_EXPORT void EGLAPIENTRY ProgramCacheQueryANGLE(EGLDisplay dpy,
EGLint index,
@@ -135,6 +135,17 @@
EGLint binarysize);
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
#endif // LIBGLESV2_ENTRYPOINTSEGLEXT_H_
diff --git a/src/libGLESv2/global_state.cpp b/src/libGLESv2/global_state.cpp
index c5f3dfe..181a029 100644
--- a/src/libGLESv2/global_state.cpp
+++ b/src/libGLESv2/global_state.cpp
@@ -12,6 +12,7 @@
#include "common/platform.h"
#include "common/tls.h"
+#include "libANGLE/Debug.h"
#include "libANGLE/Thread.h"
namespace gl
@@ -38,6 +39,7 @@
{
static TLSIndex threadTLS = TLS_INVALID_INDEX;
+Debug *g_Debug = nullptr;
Thread *AllocateCurrentThread()
{
@@ -57,6 +59,15 @@
return thread;
}
+void AllocateDebug()
+{
+ // TODO(geofflang): Lock around global allocation. http://anglebug.com/2464
+ if (g_Debug == nullptr)
+ {
+ g_Debug = new Debug();
+ }
+}
+
} // anonymous namespace
Thread *GetCurrentThread()
@@ -74,6 +85,12 @@
return (current ? current : AllocateCurrentThread());
}
+Debug *GetDebug()
+{
+ AllocateDebug();
+ return g_Debug;
+}
+
} // namespace egl
#ifdef ANGLE_PLATFORM_WINDOWS
@@ -90,8 +107,16 @@
return SetTLSValue(threadTLS, nullptr);
}
+void DealocateDebug()
+{
+ SafeDelete(g_Debug);
+}
+
bool InitializeProcess()
{
+ ASSERT(g_Debug == nullptr);
+ AllocateDebug();
+
threadTLS = CreateTLSIndex();
if (threadTLS == TLS_INVALID_INDEX)
{
@@ -103,6 +128,8 @@
bool TerminateProcess()
{
+ DealocateDebug();
+
if (!DeallocateCurrentThread())
{
return false;
diff --git a/src/libGLESv2/global_state.h b/src/libGLESv2/global_state.h
index 6442cce..d7dcf56 100644
--- a/src/libGLESv2/global_state.h
+++ b/src/libGLESv2/global_state.h
@@ -20,9 +20,11 @@
namespace egl
{
+class Debug;
class Thread;
Thread *GetCurrentThread();
+Debug *GetDebug();
} // namespace egl
diff --git a/src/libGLESv2/proc_table_autogen.cpp b/src/libGLESv2/proc_table_autogen.cpp
index 7512247..c822309 100644
--- a/src/libGLESv2/proc_table_autogen.cpp
+++ b/src/libGLESv2/proc_table_autogen.cpp
@@ -47,6 +47,7 @@
{"eglCreateStreamProducerD3DTextureANGLE", P(egl::CreateStreamProducerD3DTextureANGLE)},
{"eglCreateSync", P(egl::CreateSync)},
{"eglCreateWindowSurface", P(egl::CreateWindowSurface)},
+ {"eglDebugMessageControlKHR", P(egl::DebugMessageControlKHR)},
{"eglDestroyContext", P(egl::DestroyContext)},
{"eglDestroyImage", P(egl::DestroyImage)},
{"eglDestroyImageKHR", P(egl::DestroyImageKHR)},
@@ -66,6 +67,7 @@
{"eglGetSyncAttrib", P(egl::GetSyncAttrib)},
{"eglGetSyncValuesCHROMIUM", P(egl::GetSyncValuesCHROMIUM)},
{"eglInitialize", P(egl::Initialize)},
+ {"eglLabelObjectKHR", P(egl::LabelObjectKHR)},
{"eglMakeCurrent", P(egl::MakeCurrent)},
{"eglPostSubBufferNV", P(egl::PostSubBufferNV)},
{"eglPresentationTimeANDROID", P(egl::PresentationTimeANDROID)},
@@ -75,6 +77,7 @@
{"eglProgramCacheResizeANGLE", P(egl::ProgramCacheResizeANGLE)},
{"eglQueryAPI", P(egl::QueryAPI)},
{"eglQueryContext", P(egl::QueryContext)},
+ {"eglQueryDebugKHR", P(egl::QueryDebugKHR)},
{"eglQueryDeviceAttribEXT", P(egl::QueryDeviceAttribEXT)},
{"eglQueryDeviceStringEXT", P(egl::QueryDeviceStringEXT)},
{"eglQueryDisplayAttribEXT", P(egl::QueryDisplayAttribEXT)},
@@ -1234,5 +1237,5 @@
{"glWeightPointerOES", P(gl::WeightPointerOES)},
{"glWeightPointerOESContextANGLE", P(gl::WeightPointerOESContextANGLE)}};
-size_t g_numProcs = 1166;
+size_t g_numProcs = 1169;
} // namespace egl
diff --git a/src/libGLESv2/proc_table_data.json b/src/libGLESv2/proc_table_data.json
index 50af45b..80d7d02 100644
--- a/src/libGLESv2/proc_table_data.json
+++ b/src/libGLESv2/proc_table_data.json
@@ -839,6 +839,12 @@
"eglProgramCacheResizeANGLE"
],
+ "EGL_KHR_debug": [
+ "eglDebugMessageControlKHR",
+ "eglQueryDebugKHR",
+ "eglLabelObjectKHR"
+ ],
+
"angle::Platform related entry points": [
"ANGLEGetDisplayPlatform",
"ANGLEResetDisplayPlatform"
diff --git a/src/tests/angle_end2end_tests.gypi b/src/tests/angle_end2end_tests.gypi
index 0265b05..8b60b77 100644
--- a/src/tests/angle_end2end_tests.gypi
+++ b/src/tests/angle_end2end_tests.gypi
@@ -127,6 +127,7 @@
'<(angle_path)/src/tests/gl_tests/WebGLReadOutsideFramebufferTest.cpp',
'<(angle_path)/src/tests/egl_tests/EGLContextCompatibilityTest.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/EGLQueryContextTest.cpp',
'<(angle_path)/src/tests/egl_tests/EGLRobustnessTest.cpp',
diff --git a/src/tests/egl_tests/EGLDebugTest.cpp b/src/tests/egl_tests/EGLDebugTest.cpp
new file mode 100644
index 0000000..558f952
--- /dev/null
+++ b/src/tests/egl_tests/EGLDebugTest.cpp
@@ -0,0 +1,181 @@
+//
+// 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
diff --git a/src/tests/test_utils/ANGLETest.h b/src/tests/test_utils/ANGLETest.h
index c73db9c..f618eeb 100644
--- a/src/tests/test_utils/ANGLETest.h
+++ b/src/tests/test_utils/ANGLETest.h
@@ -37,10 +37,12 @@
#define EXPECT_EGL_SUCCESS() EXPECT_EGL_ERROR(EGL_SUCCESS)
// 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_FALSE(a) ASSERT_EQ(static_cast<EGLBoolean>(EGL_FALSE), (a))
-#define EXPECT_EGL_TRUE(a) EXPECT_EQ(static_cast<EGLBoolean>(EGL_TRUE), (a))
-#define EXPECT_EGL_FALSE(a) EXPECT_EQ(static_cast<EGLBoolean>(EGL_FALSE), (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), static_cast<EGLBoolean>(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_SUCCESS() ASSERT_EGL_ERROR(EGL_SUCCESS)
@@ -54,6 +56,11 @@
#define EXPECT_GLENUM_NE(expected, 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
{
struct GLColorRGB