KHR_debug

Name

KHR_debug

Name Strings

EGL_KHR_debug

Contributors

Jeff Vigil, Qualcomm
Brian Ellis, Qualcomm
(Original contributors of Gl_KHR_debug extension for OpenGL/GL_ES)
Mark Callow, HI
John Leech, Khronos
Ray Smith, ARM
Prabindh Sundareson, Texas Instruments
James Jones, NVIDIA
Jesse Hall, Google

Contact

Jeff Vigil (jvigil 'at' qualcomm.com)

Notice

Copyright (c) 2012-2015 The Khronos Group Inc. Copyright terms at
    http://www.khronos.org/registry/speccopyright.html

Status

Complete. Approved by the EGL Working Group on 2015/04/24.
Approved by the Khronos Board of Promoters on 2015/06/26.

Version

Version 18, Modified Date: September 28, 2016

Number

EGL Extension #92

Extension Type

EGL client extension

Dependencies

Applicable to any version of EGL 1.x, but written in relationship
to EGL 1.5.

Overview

This extension allows EGL to notify applications when various events
occur that may be useful during application development and debugging.

These events are represented in the form of debug messages with a
human-readable string representation. Examples of debug events include
errors due to incorrect use of the EGL API, warnings of undefined behavior,
and performance warnings.

The "type" of the message roughly identifies the nature of the event that
caused the message. Examples include input errors, performance
information, or warnings about undefined behavior.

Messages are communicated to the application through an application-
defined callback function that is called by the EGL implementation on
each debug message. The motivation for the callback routine is to free
application developers from actively having to query whether an EGL error,
or any other debuggable event has happened after each call to a EGL
function. With a callback, developers can keep their code free of debug
checks, set breakpoints in the callback function, and only have to react
to messages as they occur. The callback also offers much more information
than just an error code.

To control the volume of debug output, types of messages can be enabled or
disabled. The mechanism is controlled by attributes passed to EGL. The
state of the message type control can be queried.

Debug output can be enabled and disabled by changing the callback function.
NULL will disable the feature while a valid function pointer will enable
it.

Finally, this extension defines a mechanism for EGL applications to
label their objects (contexts, surfaces, syncs, etc.) with a pointer
to an application provided structure. This pointer can be a descriptive
string, identifier or pointer to a structure. This enables the application
to associate the EGL object with application information. EGL will not
interpret this pointer as a string or any other meaning - just attach to
the object and pass back in the callback when that object is the primary
object of an event.

IP Status

No known IP claims.

New Procedures and Functions

EGLint eglDebugMessageControlKHR(
        EGLDEBUGPROCKHR callback,
        const EGLAttrib* attrib_list);

EGLBoolean eglQueryDebugKHR(
        EGLint attribute,
        EGLAttrib* value);

EGLInt eglLabelObjectKHR(
        EGLDisplay display,
        EGLenum objectType,
        EGLObjectKHR object,
        EGLLabelKHR label);

New Types

A general type to identify EGL objects, such as EGLSurface or EGLContext.

    typedef void* EGLObjectKHR;

A label is a string, ID or pointer to a structure that the application
can attach to an EGL object.

    typedef void* EGLLabelKHR;

The callback function that applications can define, and is accepted by
eglDebugMessageControlKHR, is defined as:

    typedef void (APIENTRY *EGLDEBUGPROCKHR)(
            EGLenum error,
            const char *command,
            EGLint messageType,
            EGLLabelKHR threadLabel,
            EGLLabelKHR objectLabel,
            const char* message);

New Tokens

Tokens accepted by the <objectType> parameter of function
eglLabelObjectKHR:

    EGL_OBJECT_THREAD_KHR                            0x33B0
    EGL_OBJECT_DISPLAY_KHR                           0x33B1
    EGL_OBJECT_CONTEXT_KHR                           0x33B2
    EGL_OBJECT_SURFACE_KHR                           0x33B3
    EGL_OBJECT_IMAGE_KHR                             0x33B4
    EGL_OBJECT_SYNC_KHR                              0x33B5
    EGL_OBJECT_STREAM_KHR                            0x33B6

Tokens provided by the <messageType> parameter of EGLDEBUGPROCKHR
or the attributes input to eglControlDebugMessageKHR or attribute
of eglQueryDebugKHR:

    EGL_DEBUG_MSG_CRITICAL_KHR                       0x33B9
    EGL_DEBUG_MSG_ERROR_KHR                          0x33BA
    EGL_DEBUG_MSG_WARN_KHR                           0x33BB
    EGL_DEBUG_MSG_INFO_KHR                           0x33BC

Tokens provided by the input attribute to eglQueryDebugKHR:

    EGL_DEBUG_CALLBACK_KHR                           0x33B8

Additions to Chapter 3 of the EGL 1.5 Specification (EGL Functions and Errors)

Add new Section 3.13:

"3.13 - Debug Output

Application developers can obtain more information from EGL runtime in
the form of debug output.  This information can include details about EGL
errors, undefined behavior, implementation-dependent performance warnings,
or other useful hints.

This information is communicated through a stream of debug messages that
are generated as EGL commands are executed.  The application can
receive these messages through a callback routine.

Controls are provided for disabling classes of messages that the
application does not care about.

Debug output functionality is controlled with:

    EGLint eglDebugMessageControlKHR(
            EGLDEBUGPROCKHR callback,
            const EGLAttrib* attrib_list);

If the <callback> parameter is NULL, then no messages are sent to the
callback function and the debug message generation is disabled. If the
<callback> parameter is a pointer to a valid callback function, as defined
by EGLDEBUGPROCKHR, then messages will be sent to that callback function.

The attribute list <attrib_list> contains a set of message type enums,
and each has a value of EGL_TRUE to enable that class of messages,
or value EGL_FALSE to disable that class of message.

If the <attrib_list> contains an unknown attribute or value the function
will return a EGL_BAD_ATTRIBUTE error.

If there is no error, then the function will set the updated callback,
set the updated message types and return EGL_SUCCESS.

The messages types, their purpose and initial states are given in
table 13.1 below. The parameter <attrib_list> needs only contain the
attributes to change; an application can call eglDebugMessageControl more
than once with a valid callback, and change the message type states as
desired.

When the callback is set to NULL; the attributes are reset to their
default values.

Debug Output Message Type     Informs about                   Initial/Default state
-------------------------     -------------                   ---------------------
EGL_DEBUG_MSG_CRITICAL_KHR    Internal EGL driver failures    ENABLED
                              i.e. EGL_BAD_ALLOC,
                              EGL_CONTEXT_LOST

EGL_DEBUG_MSG_ERROR_KHR       Input and bad match errors      ENABLED
                              i.e. EGL_BAD_CONTEXT,
                              EGL_BAD_PARAMETER...

EGL_DEBUG_MSG_WARN_KHR        Warnings, code is EGL_SUCCESS,  DISABLED
                              but message indicates
                              deprecated or inefficient
                              operation.

EGL_DEBUG_MSG_INFO_KHR        Verbose operation               DISABLED
                              Messages such as object
                              creation and destruction
                              or change in state.

---------------------------------------------------------------------------
Table 13.1: Types of debug output messages. Each debug message is associated
with one of these types that describes the nature or class of the message.

3.13.1 - Debug Message Callback

Applications must provide a callback function for receiving debug messages
of the following type:

    typedef void (APIENTRY *EGLDEBUGPROCKHR)(
            EGLenum error,
            const char *command,
            EGLint messageType,
            EGLLabelKHR threadLabel,
            EGLLabelKHR objectLabel,
            const char* message);

The function's prototype must follow the type definition of EGLDEBUGPROCKHR.
Only one debug callback can be in-use for the application, and
further calls overwrite the previous callback. Specifying NULL as the
value of <callback> clears the current callback and disables message
output.

The callback will receive the following in its parameters:

    <error> will contain an EGL error code, or EGL_SUCCESS, as applicable.

    <command> will contain a pointer to a string. Example "eglBindApi".

    <messageType> will contain one of the debug message types listed in
    table 13.1.

    <threadLabel> will contain the label attached to the current thread.
    The <threadLabel> will be NULL if not set by the application. If the
    message is from an internal thread, the label will be NULL.

    <objectLabel> will contain the label attached to the primary object
    of the message; Labels will be NULL if not set by the application.
    The primary object should be the object the function operates on, see
    table 13.2 which provides the recommended mapping between functions and
    their primary object. This <objectLabel> may be NULL even though the
    application labeled the object. This is because it is possible an error
    was raised while executing the command before the primary object was
    validated, therefore its label cannot be included in the callback.

    <message> will contain a platform specific debug string message;
    This string should provide added information to the application
    developer regarding the condition that generated the message.
    The format of a message is implementation-defined, although it should
    represent a concise description of the event that caused the message
    to be generated. Message strings can be NULL and should not be assumed
    otherwise.

EGL Command                             Primary object
-------------------------               -------------

  eglBindAPI                             thread
  eglBindTexImage                        surface
  eglChooseConfig                        display
  eglClientWaitSync                      sync
  eglCopyBuffers                         surface
  eglCreateContext                       display
  eglCreateImage                         display
  eglCreatePbufferFromClientBuffer       display
  eglCreatePbufferSurface                display
  eglCreatePixmapSurface                 display
  eglCreatePlatformWindowSurface         display
  eglCreatePlatformPixmapSurface         display
  eglCreateSync                          display
  eglCreateWindowSurface                 display
  eglDestroyContext                      context
  eglDestroyImage                        image
  eglDestroySurface                      surface
  eglDestroySync                         sync
  eglGetConfigAttrib                     display
  eglGetConfigs                          display
  eglGetCurrentContext                   context
  eglGetCurrentDisplay                   display
  eglGetCurrentSurface                   surface
  eglGetDisplay                          thread
  eglGetError                            thread
  eglGetPlatformDisplay                  thread
  eglGetSyncAttrib                       sync
  eglInitialize                          display
  eglMakeCurrent                         context
  eglQueryAPI                            context
  eglQueryContext                        context
  eglQueryString                         display
  eglQuerySurface                        surface
  eglReleaseTexImage                     surface
  eglReleaseThread                       thread
  eglSurfaceAttrib                       surface
  eglSwapBuffers                         surface
  eglSwapInterval                        surface
  eglTerminate                           display
  eglWaitClient                          context
  eglWaitGL                              context
  eglWaitNative                          thread
  eglWaitSync                            sync
  eglDebugMessageControlKHR              -none-
  eglQueryDebugKHR                       -none-
  eglLabelObjectKHR                      labeled object

---------------------------------------------------------------------------
Table 13.2: Recommendation of primary object in a callback as result
of various EGL commands.

If the application has specified a <callback> function for receiving debug
output, the implementation will call that function whenever any enabled
message is generated. A message must be posted for every error since
debug messages can be used as an alternative to eglGetError() for error
detection and handling. Specifying a callback function does not affect the
behavior of eglGetError; errors are reported through both mechanisms.

Applications that specify a callback function must be aware of certain
special conditions when executing code inside a callback when it is
called by EGL. The memory for <message> is read-only, owned and managed
by EGL, and should only be considered valid for the duration of the
function call. Likewise the <command> string is read-only EGL managed
memory and should be considered valid only for the duration of the
callback.

Setting the label for EGL objects is optional and only intended for
applications to correlate application structures with EGL objects.
All object labels are initially NULL.

The behavior of calling any EGL operation, its client APIs, or window system
functions from within the callback function is undefined and may lead
to program termination. It should not be considered reentrant.

Only one debug callback may be registered at a time; registering a new
callback will replace the previous callback. The callback is used by any
thread that calls EGL, so if the application calls into EGL concurrently
from multiple threads it must ensure the callback is thread-safe.

EGL may employ internal threads to execute EGL commands. These threads can
post debug messages to the callback function. The labels for these
internal threads will be NULL.

3.13.2 Debug Labels:

Debug labels provide a method for annotating any object (context, surface,
sync, etc.) with an application provided label. These labels may then be
used by the debug output or an external tool such as a debugger or profiler
to describe labeled objects.

 The command

    EGLint eglLabelObjectKHR(
        EGLDisplay display,
        EGLenum objectType,
        EGLObjectKHR object,
        EGLLabelKHR label);

enables the application to attach a label to a specified object.
The <display>, <objectType>, and <object> identify the object to be
labeled.

The <label> contains a pointer sized variable to attach to the
object. This label can be a integer identifier, string or pointer to a
application defined structure. EGL will not interpret this value;
it will merely provide it when the object is involved in a callback
message. The label for any object will initially be NULL until set by
the application.

An EGL_BAD_PARAMETER error is returned by eglLabelObjectKHR if <objectType>
doesn't match one of the object type enums. An EGL_BAD_PARAMETER is also
returned if the <objectType> is not a supported type; such as no support
for streams.

An EGL_BAD_PARAMETER error is returned by eglLabelObjectKHR if <object> is
invalid, unknown, NULL, or is not an object created with
EGLDisplay <display>.

When the <objectType> is EGL_OBJECT_THREAD_KHR, the <object> parameter
will be ignored by EGL. The thread is implicitly the active thread. It is
recommended that the application pass a NULL for the <object> parameter in
this case.

When the <objectType> is EGL_OBJECT_DISPLAY_KHR, the <object> parameter
must be the same as the <display> parameter - the Display to label. If
these do not match, in this case, a EGL_BAD_PARAMETER is generated.

The <display> does not need to be initialized for <objectType>
EGL_OBJECT_THREAD_KHR, or EGL_OBJECT_DISPLAY_KHR; However for all other
types it must be initialized in order to validate the <object> for
attaching a label.

If there is no error, then the function will set the label and return
EGL_SUCCESS.

3.13.3 Debug Queries:

 The command

EGLBoolean eglQueryDebugKHR(
        EGLint attribute,
        EGLAttrib* value);

enables the application to query the current value for the debug
attributes. On success the function returns EGL_TRUE.

If <attribute> is a message type enum, the value returned will
be either EGL_TRUE or EGL_FALSE to indicate whether the specified types of
messages are enabled or disabled respectively.

Querying for attribute EGL_DEBUG_CALLBACK_KHR will return the current
callback pointer. This feature is intended to enable layering of the
callback with helper libraries.

Querying for an unknown attribute will result in an EGL_BAD_ATTRIBUTE error
and a return of EGL_FALSE.

Usage Examples

This example shows starting debug messaging and attaching string labels to
newly created objects.

void MyCallBack(EGLenum error,
                const char *command,
                EGLint messageType,
                EGLLabelKHR threadLabel,
                EGLLabelKHR objectLabel,
                const char* message)
{
    printf("Error: %x, With command %s, Type: %d,"
        "Thread: %s, Object: %s, Message: %s.",
        error, command, messageType, threadLabel, objectLabel, message);
}

EGLint result;

// DEBUG_MSG_ERROR and CRITICAL are enabled by default
EGLAttrib debugAttribs = {EGL_DEBUG_MSG_WARN_KHR, EGL_TRUE, EGL_NONE};
// Start up debug messaging:
result = eglDebugMessageControl(MyCallBack, debugAttribs);

// Label for the rendering thread.
EGLLabelKHR renderThreadLabel = (EGLLabelKHR)"Render thread";
result = eglLabelObject(NULL, EGL_OBJECT_THREAD_KHR, NULL, renderThreadLabel);

EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
EGLLabelKHR myDisplay = (EGLLabelKHR)"Default display";
result = eglLabelObject(dpy, EGL_OBJECT_DISPLAY_KHR, dpy, myDisplay);

eglInitialize(dpy);

EGLLabelKHR renderContextLabel = (EGLLabelKHR)"Render context";
EGLContext ctx = eglCreateContext(dpy, config, NULL, contextAttribs);
result = eglLabelObject(dpy, EGL_OBJECT_CONTEXT_KHR, ctx, renderContextLabel);

Issues

  1. Why not use GL_KHR_debug?

    RESOLVED: Most EGL use and object creation happens before creating a GL context. And since EGL operations are thread related - the debug messages should be too.

  2. Is the callback expected only to be called from the thread which it's registered?

    RESOLVED: In most cases when an application thread calls an EGL function, it is expected that EGL upon detecting an error will callback using that application thread. However, EGL may have internal helper threads that execute operations. These threads can callback but will have no threadLabel. It is the responsibility of EGL to ensure that if these threads are blocked in the application's callback by a breakpoint; that EGL does not fail. Internal threads are an implementation detail and are not required.

Revision History

Revision 18, 2016-07-28 (Jeff Vigil)
  - Clarify return values/error codes.

Revision 17, 2015-09-23 (Jeff Vigil)
  - Correct type name to "EGLDEBUGPROCKHR". Updated example code.

Revision 16, 2015-04-15 (Jeff Vigil)
  - Clarified that <objectLabel> maybe NULL in the callback, if an error
  is raised before the primary object handle is validated.

Revision 15, 2015-03-30 (Jeff Vigil)
  - Further details to labeling of EGL_OBJECT_DISPLAY_KHR.

Revision 14, 2015-03-27 (Jeff Vigil)
  - Further clarification of returns and errors. Add further details to
  labeling of EGL_OBJECT_THREAD_KHR and EGL_OBJECT_DISPLAY_KHR.

Revision 13, 2015-03-26 (Jeff Vigil)
  - Clarified returns and errors.

Revision 12, 2015-03-24 (Jeff Vigil)
  - Improve readability. Add assigned enum values.

Revision 11, 2015-03-02 (Jeff Vigil)
  - Clarify text regarding parameter attribute_list and its persistence.

Revision 10, 2015-02-25 (Jeff Vigil)
  - Clarify text regarding callback blocking.
  - The implementation must provide errors and success in callbacks so
  that the callback replaces the use of eglGetError.
  - <command> strings are read-only EGL memory.
  - Specify default values for attributes.
  - Fix typos.

Revision 9, 2015-02-03 (Jeff Vigil)
  - Updated contributors.
  - Add extension type.
  - Add "KHR" to token and function names.
  - Fix typos.
  - Add query to get current callback pointer.

Revision 8, 2014-12-03 (Jeff Vigil)
  - Add table containing recommendation for primary object in the callback.

Revision 7, 2014-10-21 (Jeff Vigil)
  - Remove configs as a label-able object.
  - Remove redundant text.
  - Simplify to one callback per process, not per thread.

Revision 6, 2014-10-17 (Jeff Vigil)
  - Add issues.
  - Address internal EGL threads posting messages.

Revision 5, 2014-05-27 (Jeff Vigil)
  - Add missing text for eglQueryDebug.
  - Clarify threading model.

Revision 4, 2014-04-14 (Jeff Vigil)
  - Fix due to feedback from EGL WG face-to-face conference.

Revision 3, 2014-04-10 (Jeff Vigil)
  - Refinements.

Revision 2, 2014-02-21 (Jeff Vigil)
  - Simplify API.

Revision 1, 2013-09-08 (Jeff Vigil)
  - Work in progress for F2F, Based on GL_KHR_debug, replace GL with EGL
  and remove GL spec specific text.