From: Kyle Brenneman Date: Mon, 12 Sep 2016 21:50:40 +0000 (-0400) Subject: egl: Track EGL_KHR_debug state when going through EGL API calls (v3) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=6a5545d3ba60a19a3bce8f62141e0991a595eeaf;p=mesa.git egl: Track EGL_KHR_debug state when going through EGL API calls (v3) This decorates every EGL entrypoint with _EGL_FUNC_START, which records the function name and primary dispatch object label in the current thread state. It also adds debug report functions and calls them when appropriate. This would be useful enough for debugging on its own, if the user set a breakpoint when the report function was called. We will also need this state tracked in order to expose EGL_KHR_debug. v2: - Clear the object label in more cases in _eglSetFuncName - Pass draw surface (if any) to _EGL_FUNC_START in eglSwapInterval v3: - Set dummy thread's CurrentAPI to EGL_OPENGL_ES_API not zero - Less ?: in _eglSetFuncName Reviewed-by: Adam Jackson Reviewed-by: Emil Velikov --- diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c index 697957eb469..88cdf06121f 100644 --- a/src/egl/main/eglapi.c +++ b/src/egl/main/eglapi.c @@ -250,6 +250,37 @@ _eglUnlockDisplay(_EGLDisplay *dpy) mtx_unlock(&dpy->Mutex); } +static EGLBoolean +_eglSetFuncName(const char *funcName, _EGLDisplay *disp, EGLenum objectType, _EGLResource *object) +{ + _EGLThreadInfo *thr = _eglGetCurrentThread(); + if (!_eglIsCurrentThreadDummy()) { + thr->CurrentFuncName = funcName; + thr->CurrentObjectLabel = NULL; + + if (objectType == EGL_OBJECT_THREAD_KHR) + thr->CurrentObjectLabel = thr->Label; + else if (objectType == EGL_OBJECT_DISPLAY_KHR && disp) + thr->CurrentObjectLabel = disp->Label; + else if (object) + thr->CurrentObjectLabel = object->Label; + + return EGL_TRUE; + } + + _eglDebugReportFull(EGL_BAD_ALLOC, funcName, funcName, + EGL_DEBUG_MSG_CRITICAL_KHR, NULL, NULL); + return EGL_FALSE; +} + +#define _EGL_FUNC_START(disp, objectType, object, ret) \ + do { \ + if (!_eglSetFuncName(__func__, disp, objectType, (_EGLResource *) object)) { \ + if (disp) \ + _eglUnlockDisplay(disp); \ + return ret; \ + } \ + } while(0) /** * Convert an attribute list from EGLint[] to EGLAttrib[]. @@ -328,6 +359,8 @@ eglGetDisplay(EGLNativeDisplayType nativeDisplay) _EGLDisplay *dpy; void *native_display_ptr; + _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_NO_DISPLAY); + STATIC_ASSERT(sizeof(void*) == sizeof(nativeDisplay)); native_display_ptr = (void*) nativeDisplay; @@ -371,6 +404,7 @@ static EGLDisplay EGLAPIENTRY eglGetPlatformDisplayEXT(EGLenum platform, void *native_display, const EGLint *attrib_list) { + _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_NO_DISPLAY); return _eglGetPlatformDisplayCommon(platform, native_display, attrib_list); } @@ -381,6 +415,8 @@ eglGetPlatformDisplay(EGLenum platform, void *native_display, EGLDisplay display; EGLint *int_attribs; + _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_NO_DISPLAY); + int_attribs = _eglConvertAttribsToInt(attrib_list); if (attrib_list && !int_attribs) RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, NULL); @@ -524,6 +560,8 @@ eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) { _EGLDisplay *disp = _eglLockDisplay(dpy); + _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); + if (!disp) RETURN_EGL_ERROR(NULL, EGL_BAD_DISPLAY, EGL_FALSE); @@ -574,6 +612,8 @@ eglTerminate(EGLDisplay dpy) { _EGLDisplay *disp = _eglLockDisplay(dpy); + _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); + if (!disp) RETURN_EGL_ERROR(NULL, EGL_BAD_DISPLAY, EGL_FALSE); @@ -601,6 +641,7 @@ eglQueryString(EGLDisplay dpy, EGLint name) } disp = _eglLockDisplay(dpy); + _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, NULL); _EGL_CHECK_DISPLAY(disp, NULL, drv); switch (name) { @@ -626,6 +667,8 @@ eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, _EGLDriver *drv; EGLBoolean ret; + _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); + _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); ret = drv->API.GetConfigs(drv, disp, configs, config_size, num_config); @@ -641,6 +684,8 @@ eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, _EGLDriver *drv; EGLBoolean ret; + _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); + _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); ret = drv->API.ChooseConfig(drv, disp, attrib_list, configs, config_size, num_config); @@ -658,6 +703,8 @@ eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, _EGLDriver *drv; EGLBoolean ret; + _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); + _EGL_CHECK_CONFIG(disp, conf, EGL_FALSE, drv); ret = drv->API.GetConfigAttrib(drv, disp, conf, attribute, value); @@ -676,6 +723,8 @@ eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_list, _EGLContext *context; EGLContext ret; + _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_CONTEXT); + _EGL_CHECK_DISPLAY(disp, EGL_NO_CONTEXT, drv); if (!config && !disp->Extensions.KHR_no_config_context) @@ -699,6 +748,8 @@ eglDestroyContext(EGLDisplay dpy, EGLContext ctx) _EGLDriver *drv; EGLBoolean ret; + _EGL_FUNC_START(disp, EGL_OBJECT_CONTEXT_KHR, context, EGL_FALSE); + _EGL_CHECK_CONTEXT(disp, context, EGL_FALSE, drv); _eglUnlinkContext(context); ret = drv->API.DestroyContext(drv, disp, context); @@ -718,6 +769,8 @@ eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, _EGLDriver *drv; EGLBoolean ret; + _EGL_FUNC_START(disp, EGL_OBJECT_CONTEXT_KHR, context, EGL_FALSE); + if (!disp) RETURN_EGL_ERROR(disp, EGL_BAD_DISPLAY, EGL_FALSE); drv = disp->Driver; @@ -764,6 +817,8 @@ eglQueryContext(EGLDisplay dpy, EGLContext ctx, _EGLDriver *drv; EGLBoolean ret; + _EGL_FUNC_START(disp, EGL_OBJECT_CONTEXT_KHR, context, EGL_FALSE); + _EGL_CHECK_CONTEXT(disp, context, EGL_FALSE, drv); ret = drv->API.QueryContext(drv, disp, context, attribute, value); @@ -798,6 +853,8 @@ eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType window, const EGLint *attrib_list) { _EGLDisplay *disp = _eglLockDisplay(dpy); + + _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE); STATIC_ASSERT(sizeof(void*) == sizeof(window)); return _eglCreateWindowSurfaceCommon(disp, config, (void*) window, attrib_list); @@ -830,6 +887,7 @@ eglCreatePlatformWindowSurfaceEXT(EGLDisplay dpy, EGLConfig config, native_window = fixupNativeWindow(disp, native_window); + _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE); return _eglCreateWindowSurfaceCommon(disp, config, native_window, attrib_list); } @@ -842,10 +900,13 @@ eglCreatePlatformWindowSurface(EGLDisplay dpy, EGLConfig config, { _EGLDisplay *disp = _eglLockDisplay(dpy); EGLSurface surface; - EGLint *int_attribs = _eglConvertAttribsToInt(attrib_list); + EGLint *int_attribs; + + _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE); + int_attribs = _eglConvertAttribsToInt(attrib_list); if (attrib_list && !int_attribs) - RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, EGL_NO_SURFACE); + RETURN_EGL_ERROR(disp, EGL_BAD_ALLOC, EGL_NO_SURFACE); native_window = fixupNativeWindow(disp, native_window); surface = _eglCreateWindowSurfaceCommon(disp, config, native_window, @@ -894,6 +955,8 @@ eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list) { _EGLDisplay *disp = _eglLockDisplay(dpy); + + _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE); STATIC_ASSERT(sizeof(void*) == sizeof(pixmap)); return _eglCreatePixmapSurfaceCommon(disp, config, (void*) pixmap, attrib_list); @@ -906,6 +969,7 @@ eglCreatePlatformPixmapSurfaceEXT(EGLDisplay dpy, EGLConfig config, { _EGLDisplay *disp = _eglLockDisplay(dpy); + _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE); native_pixmap = fixupNativePixmap(disp, native_pixmap); return _eglCreatePixmapSurfaceCommon(disp, config, native_pixmap, attrib_list); @@ -919,10 +983,13 @@ eglCreatePlatformPixmapSurface(EGLDisplay dpy, EGLConfig config, { _EGLDisplay *disp = _eglLockDisplay(dpy); EGLSurface surface; - EGLint *int_attribs = _eglConvertAttribsToInt(attrib_list); + EGLint *int_attribs; + + _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE); + int_attribs = _eglConvertAttribsToInt(attrib_list); if (attrib_list && !int_attribs) - RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, EGL_NO_SURFACE); + RETURN_EGL_ERROR(disp, EGL_BAD_ALLOC, EGL_NO_SURFACE); native_pixmap = fixupNativePixmap(disp, native_pixmap); surface = _eglCreatePixmapSurfaceCommon(disp, config, native_pixmap, @@ -942,6 +1009,7 @@ eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, _EGLSurface *surf; EGLSurface ret; + _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE); _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv); surf = drv->API.CreatePbufferSurface(drv, disp, conf, attrib_list); @@ -959,6 +1027,7 @@ eglDestroySurface(EGLDisplay dpy, EGLSurface surface) _EGLDriver *drv; EGLBoolean ret; + _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); _eglUnlinkSurface(surf); ret = drv->API.DestroySurface(drv, disp, surf); @@ -975,6 +1044,7 @@ eglQuerySurface(EGLDisplay dpy, EGLSurface surface, _EGLDriver *drv; EGLBoolean ret; + _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); ret = drv->API.QuerySurface(drv, disp, surf, attribute, value); @@ -990,6 +1060,7 @@ eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, _EGLDriver *drv; EGLBoolean ret; + _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); ret = drv->API.SurfaceAttrib(drv, disp, surf, attribute, value); @@ -1005,6 +1076,7 @@ eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) _EGLDriver *drv; EGLBoolean ret; + _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); ret = drv->API.BindTexImage(drv, disp, surf, buffer); @@ -1020,6 +1092,7 @@ eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) _EGLDriver *drv; EGLBoolean ret; + _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); ret = drv->API.ReleaseTexImage(drv, disp, surf, buffer); @@ -1032,17 +1105,17 @@ eglSwapInterval(EGLDisplay dpy, EGLint interval) { _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLContext *ctx = _eglGetCurrentContext(); - _EGLSurface *surf; + _EGLSurface *surf = ctx ? ctx->DrawSurface : NULL; _EGLDriver *drv; EGLBoolean ret; + _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT || ctx->Resource.Display != disp) RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_FALSE); - surf = ctx->DrawSurface; if (_eglGetSurfaceHandle(surf) == EGL_NO_SURFACE) RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE); @@ -1061,6 +1134,7 @@ eglSwapBuffers(EGLDisplay dpy, EGLSurface surface) _EGLDriver *drv; EGLBoolean ret; + _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); /* surface must be bound to current context in EGL 1.4 */ @@ -1086,6 +1160,7 @@ eglSwapBuffersWithDamageEXT(EGLDisplay dpy, EGLSurface surface, _EGLDriver *drv; EGLBoolean ret; + _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); /* surface must be bound to current context in EGL 1.4 */ @@ -1110,6 +1185,7 @@ eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target) EGLBoolean ret; void *native_pixmap_ptr; + _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); STATIC_ASSERT(sizeof(void*) == sizeof(target)); native_pixmap_ptr = (void*) target; @@ -1152,6 +1228,7 @@ _eglWaitClientCommon(void) EGLBoolean EGLAPIENTRY eglWaitClient(void) { + _EGL_FUNC_START(NULL, EGL_OBJECT_CONTEXT_KHR, _eglGetCurrentContext(), EGL_FALSE); return _eglWaitClientCommon(); } @@ -1159,6 +1236,7 @@ EGLBoolean EGLAPIENTRY eglWaitGL(void) { /* Since we only support OpenGL and GLES, eglWaitGL is equivalent to eglWaitClient. */ + _EGL_FUNC_START(NULL, EGL_OBJECT_CONTEXT_KHR, _eglGetCurrentContext(), EGL_FALSE); return _eglWaitClientCommon(); } @@ -1174,6 +1252,8 @@ eglWaitNative(EGLint engine) if (!ctx) RETURN_EGL_SUCCESS(NULL, EGL_TRUE); + _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_FALSE); + disp = ctx->Resource.Display; mtx_lock(&disp->Mutex); @@ -1223,6 +1303,8 @@ eglGetCurrentSurface(EGLint readdraw) _EGLSurface *surf; EGLSurface ret; + _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_NO_SURFACE); + if (!ctx) RETURN_EGL_SUCCESS(NULL, EGL_NO_SURFACE); @@ -1274,8 +1356,11 @@ eglGetError(void) EGLBoolean EGLAPIENTRY eglBindAPI(EGLenum api) { - _EGLThreadInfo *t = _eglGetCurrentThread(); + _EGLThreadInfo *t; + _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_FALSE); + + t = _eglGetCurrentThread(); if (_eglIsCurrentThreadDummy()) RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, EGL_FALSE); @@ -1315,6 +1400,8 @@ eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, _EGLSurface *surf; EGLSurface ret; + _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE); + _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv); surf = drv->API.CreatePbufferFromClientBuffer(drv, disp, buftype, buffer, @@ -1331,8 +1418,10 @@ eglReleaseThread(void) /* unbind current contexts */ if (!_eglIsCurrentThreadDummy()) { _EGLThreadInfo *t = _eglGetCurrentThread(); - _EGLContext *ctx = t->CurrentContext; + + _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_FALSE); + if (ctx) { _EGLDisplay *disp = ctx->Resource.Display; _EGLDriver *drv; @@ -1382,6 +1471,7 @@ eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attr_list) { _EGLDisplay *disp = _eglLockDisplay(dpy); + _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_IMAGE_KHR); return _eglCreateImageCommon(disp, ctx, target, buffer, attr_list); } @@ -1392,8 +1482,11 @@ eglCreateImage(EGLDisplay dpy, EGLContext ctx, EGLenum target, { _EGLDisplay *disp = _eglLockDisplay(dpy); EGLImage image; - EGLint *int_attribs = _eglConvertAttribsToInt(attr_list); + EGLint *int_attribs; + + _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_IMAGE_KHR); + int_attribs = _eglConvertAttribsToInt(attr_list); if (attr_list && !int_attribs) RETURN_EGL_ERROR(disp, EGL_BAD_ALLOC, EGL_NO_IMAGE); @@ -1411,6 +1504,8 @@ eglDestroyImage(EGLDisplay dpy, EGLImage image) _EGLDriver *drv; EGLBoolean ret; + _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE); + _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); if (!disp->Extensions.KHR_image_base) RETURN_EGL_EVAL(disp, EGL_FALSE); @@ -1482,6 +1577,7 @@ static EGLSync EGLAPIENTRY eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list) { _EGLDisplay *disp = _eglLockDisplay(dpy); + _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); return _eglCreateSync(disp, type, attrib_list, NULL, EGL_FALSE, EGL_BAD_ATTRIBUTE); } @@ -1491,6 +1587,7 @@ static EGLSync EGLAPIENTRY eglCreateSync64KHR(EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list) { _EGLDisplay *disp = _eglLockDisplay(dpy); + _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); return _eglCreateSync(disp, type, NULL, attrib_list, EGL_TRUE, EGL_BAD_ATTRIBUTE); } @@ -1500,6 +1597,7 @@ EGLSync EGLAPIENTRY eglCreateSync(EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list) { _EGLDisplay *disp = _eglLockDisplay(dpy); + _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); return _eglCreateSync(disp, type, NULL, attrib_list, EGL_TRUE, EGL_BAD_PARAMETER); } @@ -1513,6 +1611,8 @@ eglDestroySync(EGLDisplay dpy, EGLSync sync) _EGLDriver *drv; EGLBoolean ret; + _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE); + _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv); assert(disp->Extensions.KHR_reusable_sync || disp->Extensions.KHR_fence_sync); @@ -1532,6 +1632,8 @@ eglClientWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout) _EGLDriver *drv; EGLint ret; + _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE); + _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv); assert(disp->Extensions.KHR_reusable_sync || disp->Extensions.KHR_fence_sync); @@ -1588,6 +1690,7 @@ eglWaitSyncKHR(EGLDisplay dpy, EGLSync sync, EGLint flags) { _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLSync *s = _eglLookupSync(sync, disp); + _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE); return _eglWaitSyncCommon(disp, s, flags); } @@ -1601,6 +1704,7 @@ eglWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags) */ _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLSync *s = _eglLookupSync(sync, disp); + _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE); return _eglWaitSyncCommon(disp, s, flags); } @@ -1613,6 +1717,8 @@ eglSignalSyncKHR(EGLDisplay dpy, EGLSync sync, EGLenum mode) _EGLDriver *drv; EGLBoolean ret; + _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE); + _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv); assert(disp->Extensions.KHR_reusable_sync); ret = drv->API.SignalSyncKHR(drv, disp, s, mode); @@ -1640,6 +1746,7 @@ eglGetSyncAttrib(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib *valu { _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLSync *s = _eglLookupSync(sync, disp); + _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE); return _eglGetSyncAttribCommon(disp, s, attribute, value); } @@ -1652,6 +1759,8 @@ eglGetSyncAttribKHR(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLint *valu EGLAttrib attrib; EGLBoolean result; + _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE); + if (!value) RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE); @@ -1680,6 +1789,8 @@ eglSwapBuffersRegionNOK(EGLDisplay dpy, EGLSurface surface, _EGLDriver *drv; EGLBoolean ret; + _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); + _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); if (!disp->Extensions.NOK_swap_region) @@ -1704,6 +1815,8 @@ eglCreateDRMImageMESA(EGLDisplay dpy, const EGLint *attr_list) _EGLImage *img; EGLImage ret; + _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); + _EGL_CHECK_DISPLAY(disp, EGL_NO_IMAGE_KHR, drv); if (!disp->Extensions.MESA_drm_image) RETURN_EGL_EVAL(disp, EGL_NO_IMAGE_KHR); @@ -1723,6 +1836,8 @@ eglExportDRMImageMESA(EGLDisplay dpy, EGLImage image, _EGLDriver *drv; EGLBoolean ret; + _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE); + _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); assert(disp->Extensions.MESA_drm_image); @@ -1744,6 +1859,8 @@ eglBindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display) _EGLDriver *drv; EGLBoolean ret; + _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); + _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); assert(disp->Extensions.WL_bind_wayland_display); @@ -1762,6 +1879,8 @@ eglUnbindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display) _EGLDriver *drv; EGLBoolean ret; + _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); + _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); assert(disp->Extensions.WL_bind_wayland_display); @@ -1781,6 +1900,8 @@ eglQueryWaylandBufferWL(EGLDisplay dpy, struct wl_resource *buffer, _EGLDriver *drv; EGLBoolean ret; + _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); + _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); assert(disp->Extensions.WL_bind_wayland_display); @@ -1801,6 +1922,8 @@ eglCreateWaylandBufferFromImageWL(EGLDisplay dpy, EGLImage image) _EGLDriver *drv; struct wl_buffer *ret; + _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); + _EGL_CHECK_DISPLAY(disp, NULL, drv); assert(disp->Extensions.WL_create_wayland_buffer_from_image); @@ -1823,6 +1946,8 @@ eglPostSubBufferNV(EGLDisplay dpy, EGLSurface surface, _EGLDriver *drv; EGLBoolean ret; + _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); + _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); if (!disp->Extensions.NV_post_sub_buffer) @@ -1843,6 +1968,8 @@ eglGetSyncValuesCHROMIUM(EGLDisplay display, EGLSurface surface, _EGLDriver *drv; EGLBoolean ret; + _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); + _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); if (!disp->Extensions.CHROMIUM_sync_control) RETURN_EGL_EVAL(disp, EGL_FALSE); @@ -1865,6 +1992,8 @@ eglExportDMABUFImageQueryMESA(EGLDisplay dpy, EGLImage image, _EGLDriver *drv; EGLBoolean ret; + _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE); + _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); assert(disp->Extensions.MESA_image_dma_buf_export); @@ -1886,6 +2015,8 @@ eglExportDMABUFImageMESA(EGLDisplay dpy, EGLImage image, _EGLDriver *drv; EGLBoolean ret; + _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE); + _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); assert(disp->Extensions.MESA_image_dma_buf_export); @@ -1984,6 +2115,8 @@ eglGetProcAddress(const char *procname) if (!procname) RETURN_EGL_SUCCESS(NULL, NULL); + _EGL_FUNC_START(NULL, EGL_NONE, NULL, NULL); + ret = NULL; if (strncmp(procname, "egl", 3) == 0) { for (i = 0; egl_functions[i].name; i++) { diff --git a/src/egl/main/eglcurrent.c b/src/egl/main/eglcurrent.c index f093becc7b4..eae7bdcea15 100644 --- a/src/egl/main/eglcurrent.c +++ b/src/egl/main/eglcurrent.c @@ -26,8 +26,10 @@ **************************************************************************/ +#include #include #include +#include #include "c99_compat.h" #include "c11/threads.h" @@ -37,7 +39,7 @@ /* This should be kept in sync with _eglInitThreadInfo() */ #define _EGL_THREAD_INFO_INITIALIZER \ - { EGL_SUCCESS, NULL, 0, NULL, NULL, NULL } + { EGL_SUCCESS, NULL, EGL_OPENGL_ES_API, NULL, NULL, NULL } /* a fallback thread info to guarantee that every thread always has one */ static _EGLThreadInfo dummy_thread = _EGL_THREAD_INFO_INITIALIZER; @@ -217,8 +219,8 @@ _eglGetCurrentContext(void) /** * Record EGL error code and return EGL_FALSE. */ -EGLBoolean -_eglError(EGLint errCode, const char *msg) +static EGLBoolean +_eglInternalError(EGLint errCode, const char *msg) { _EGLThreadInfo *t = _eglGetCurrentThread(); @@ -278,3 +280,86 @@ _eglError(EGLint errCode, const char *msg) return EGL_FALSE; } + +EGLBoolean +_eglError(EGLint errCode, const char *msg) +{ + if (errCode != EGL_SUCCESS) { + EGLint type; + if (errCode == EGL_BAD_ALLOC) { + type = EGL_DEBUG_MSG_CRITICAL_KHR; + } else { + type = EGL_DEBUG_MSG_ERROR_KHR; + } + + _eglDebugReport(errCode, msg, type, NULL); + } else + _eglInternalError(errCode, msg); + + return EGL_FALSE; +} + +/** + * Returns the label set for the current thread. + */ +EGLLabelKHR +_eglGetThreadLabel(void) +{ + _EGLThreadInfo *t = _eglGetCurrentThread(); + return t->Label; +} + +static void +_eglDebugReportFullv(EGLenum error, const char *command, const char *funcName, + EGLint type, EGLLabelKHR objectLabel, const char *message, va_list args) +{ + EGLDEBUGPROCKHR callback = NULL; + + mtx_lock(_eglGlobal.Mutex); + if (_eglGlobal.debugTypesEnabled & DebugBitFromType(type)) { + callback = _eglGlobal.debugCallback; + } + mtx_unlock(_eglGlobal.Mutex); + + if (callback != NULL) { + char *buf = NULL; + + if (message != NULL) { + if (vasprintf(&buf, message, args) < 0) { + buf = NULL; + } + } + callback(error, command, type, _eglGetThreadLabel(), objectLabel, buf); + free(buf); + } + + if (type == EGL_DEBUG_MSG_CRITICAL_KHR || type == EGL_DEBUG_MSG_ERROR_KHR) { + _eglInternalError(error, funcName); + } +} + +void +_eglDebugReportFull(EGLenum error, const char *command, const char *funcName, + EGLint type, EGLLabelKHR objectLabel, const char *message, ...) +{ + va_list args; + va_start(args, message); + _eglDebugReportFullv(error, command, funcName, type, objectLabel, message, args); + va_end(args); +} + +void +_eglDebugReport(EGLenum error, const char *funcName, + EGLint type, const char *message, ...) +{ + _EGLThreadInfo *thr = _eglGetCurrentThread(); + va_list args; + + if (funcName == NULL) { + funcName = thr->CurrentFuncName; + } + + va_start(args, message); + _eglDebugReportFullv(error, thr->CurrentFuncName, funcName, type, thr->CurrentObjectLabel, message, args); + va_end(args); +} diff --git a/src/egl/main/eglcurrent.h b/src/egl/main/eglcurrent.h index b2638fd7ab5..9ec07bac8e6 100644 --- a/src/egl/main/eglcurrent.h +++ b/src/egl/main/eglcurrent.h @@ -99,6 +99,28 @@ _eglGetCurrentContext(void); extern EGLBoolean _eglError(EGLint errCode, const char *msg); +extern EGLLabelKHR +_eglGetThreadLabel(void); + +extern void +_eglDebugReportFull(EGLenum error, const char *command, const char *funcName, + EGLint type, EGLLabelKHR objectLabel, const char *message, ...); + +extern void +_eglDebugReport(EGLenum error, const char *funcName, + EGLint type, const char *message, ...); + +#define _eglReportCritical(error, funcName, ...) \ + _eglDebugReport(error, funcName, EGL_DEBUG_MSG_CRITICAL_KHR, __VA_ARGS__) + +#define _eglReportError(error, funcName, ...) \ + _eglDebugReport(error, funcName, EGL_DEBUG_MSG_ERROR_KHR, __VA_ARGS__) + +#define _eglReportWarn(funcName, ...) \ + _eglDebugReport(EGL_SUCCESS, funcName, EGL_DEBUG_MSG_WARN_KHR, __VA_ARGS__) + +#define _eglReportInfo(funcName, ...) \ + _eglDebugReport(EGL_SUCCESS, funcName, EGL_DEBUG_MSG_INFO_KHR, __VA_ARGS__) #ifdef __cplusplus } diff --git a/src/egl/main/eglglobals.h b/src/egl/main/eglglobals.h index dfa357759b8..ec4f3d04a36 100644 --- a/src/egl/main/eglglobals.h +++ b/src/egl/main/eglglobals.h @@ -70,5 +70,10 @@ extern struct _egl_global _eglGlobal; extern void _eglAddAtExitCall(void (*func)(void)); +static inline unsigned int DebugBitFromType(EGLenum type) +{ + assert(type >= EGL_DEBUG_MSG_CRITICAL_KHR && type <= EGL_DEBUG_MSG_INFO_KHR); + return (1 << (type - EGL_DEBUG_MSG_CRITICAL_KHR)); +} #endif /* EGLGLOBALS_INCLUDED */