From 70b67f4466e3e13841c3ede3bb7574eb84660576 Mon Sep 17 00:00:00 2001 From: jojo61 Date: Tue, 7 Jan 2020 22:22:07 +0100 Subject: [PATCH] Fix DETA/ATTA with DRM (hopefully) --- drm.c | 57 ++++++++----- hdr.c | 17 ++-- video.c | 260 ++++++++++++++++++++++++++++++++------------------------ 3 files changed, 196 insertions(+), 138 deletions(-) diff --git a/drm.c b/drm.c index 5547522..75347bc 100644 --- a/drm.c +++ b/drm.c @@ -23,6 +23,7 @@ struct _Drm_Render_ uint32_t connector_id, crtc_id, video_plane; uint32_t hdr_metadata; uint32_t mmWidth,mmHeight; // Size in mm + uint32_t hdr_blob_id; }; typedef struct _Drm_Render_ VideoRender; @@ -207,10 +208,10 @@ static int FindDevice(VideoRender * render) fprintf(stderr, "FindDevice: cannot open /dev/dri/card0: %m\n"); return -errno; } - + drmSetMaster(render->fd_drm); version = drmGetVersion(render->fd_drm); - fprintf(stderr, "FindDevice: open /dev/dri/card0: %i %s\n", version->name_len, version->name); + fprintf(stderr, "FindDevice: open /dev/dri/card0: %s\n", version->name); // check capability if (drmGetCap(render->fd_drm, DRM_CAP_DUMB_BUFFER, &has_dumb) < 0 || has_dumb == 0) @@ -375,8 +376,6 @@ static int FindDevice(VideoRender * render) return 0; } - - /// /// Initialize video output module. /// @@ -384,6 +383,7 @@ void VideoInitDrm() { int i; + if (!(render = calloc(1, sizeof(*render)))) { Fatal(_("video/DRM: out of memory\n")); return; @@ -392,13 +392,13 @@ void VideoInitDrm() if (FindDevice(render)){ Fatal(_( "VideoInit: FindDevice() failed\n")); } - + gbm.dev = gbm_create_device (render->fd_drm); assert (gbm.dev != NULL); PFNEGLGETPLATFORMDISPLAYEXTPROC get_platform_display = NULL; get_platform_display = - (void *) eglGetProcAddress("eglGetPlatformDisplayEXT"); + (void *) eglGetProcAddress("eglGetPlatformDisplay"); assert(get_platform_display != NULL); eglDisplay = get_platform_display(EGL_PLATFORM_GBM_KHR, gbm.dev, NULL); @@ -418,7 +418,7 @@ void VideoInitDrm() fprintf(stderr, "cannot allocate atomic request (%d): %m\n", errno); return; } - + printf("set CRTC %d of Connector %d aktiv\n",render->crtc_id,render->connector_id); SetPropertyRequest(ModeReq, render->fd_drm, render->crtc_id, DRM_MODE_OBJECT_CRTC, "MODE_ID", modeID); SetPropertyRequest(ModeReq, render->fd_drm, render->connector_id, @@ -430,7 +430,7 @@ void VideoInitDrm() fprintf(stderr, "cannot set atomic mode (%d): %m\n", errno); if (drmModeDestroyPropertyBlob(render->fd_drm, modeID) != 0) - fprintf(stderr, "cannot destroy prperty blob (%d): %m\n", errno); + fprintf(stderr, "cannot destroy property blob (%d): %m\n", errno); drmModeAtomicFree(ModeReq); @@ -438,6 +438,7 @@ void VideoInitDrm() void get_drm_aspect(int *num,int *den) { + Debug(3,"mmHeight %d mmWidth %d VideoHeight %d VideoWidth %d\n",render->mmHeight,render->mmWidth,VideoWindowHeight,VideoWindowWidth); *num = VideoWindowWidth * render->mmHeight; *den = VideoWindowHeight * render->mmWidth; } @@ -456,6 +457,7 @@ void InitBo(int bpp) { assert(gbm.surface != NULL); eglSurface = eglCreateWindowSurface (eglDisplay, eglConfig, gbm.surface, NULL); assert(eglSurface != NULL); + } static struct gbm_bo *previous_bo = NULL; @@ -526,27 +528,44 @@ static void drm_swap_buffers () { } previous_bo = bo; previous_fb = fb; + } static void drm_clean_up () { // set the previous crtc - + if (!render) return; - - drmModeSetCrtc (render->fd_drm, render->saved_crtc->crtc_id, render->saved_crtc->buffer_id, - render->saved_crtc->x, render->saved_crtc->y, &render->connector_id, 1, &render->saved_crtc->mode); - drmModeFreeCrtc (render->saved_crtc); - - if (previous_bo) { + Debug(3,"drm clean up\n"); + + if (previous_bo) { drmModeRmFB (render->fd_drm, previous_fb); gbm_surface_release_buffer (gbm.surface, previous_bo); } - -// eglDestroySurface (display, eglSurface); + + drmModeSetCrtc (render->fd_drm, render->saved_crtc->crtc_id, render->saved_crtc->buffer_id, + render->saved_crtc->x, render->saved_crtc->y, &render->connector_id, 1, &render->saved_crtc->mode); + drmModeFreeCrtc (render->saved_crtc); + + if (render->hdr_blob_id) + drmModeDestroyPropertyBlob(render->fd_drm, render->hdr_blob_id); + render->hdr_blob_id = 0; + + eglDestroySurface (eglDisplay, eglSurface); + EglCheck(); gbm_surface_destroy (gbm.surface); -// eglDestroyContext (display, context); -// eglTerminate (display); + eglDestroyContext (eglDisplay, eglContext); + EglCheck(); + eglDestroyContext (eglDisplay, eglSharedContext); + EglCheck(); + + eglTerminate (eglDisplay); + EglCheck(); + gbm_device_destroy (gbm.dev); + drmDropMaster(render->fd_drm); close (render->fd_drm); + + free(render); + } diff --git a/hdr.c b/hdr.c index 37351df..b4b9238 100644 --- a/hdr.c +++ b/hdr.c @@ -330,7 +330,6 @@ static void set_hdr_metadata(int color,int trc, AVFrameSideData *sd1, AVFrameSid struct weston_colorspace *cs; enum hdr_metadata_eotf eotf; struct hdr_output_metadata data; - static uint32_t blob_id = 0; int ret,MaxCLL=1500,MaxFALL=400; int max_lum=4000,min_lum=0050; struct AVMasteringDisplayMetadata *md = NULL; @@ -378,8 +377,8 @@ static void set_hdr_metadata(int color,int trc, AVFrameSideData *sd1, AVFrameSid old_color = color; old_trc = trc; - if (blob_id) - drmModeDestroyPropertyBlob(render->fd_drm, blob_id); + if (render->hdr_blob_id) + drmModeDestroyPropertyBlob(render->fd_drm, render->hdr_blob_id); switch(trc) { case AVCOL_TRC_BT709: // 1 @@ -468,21 +467,21 @@ static void set_hdr_metadata(int color,int trc, AVFrameSideData *sd1, AVFrameSid - ret = drmModeCreatePropertyBlob(render->fd_drm, &data, sizeof(data), &blob_id); + ret = drmModeCreatePropertyBlob(render->fd_drm, &data, sizeof(data), &render->hdr_blob_id); if (ret) { printf("DRM: HDR metadata: failed blob create \n"); - blob_id = 0; + render->hdr_blob_id = 0; return; } ret = drmModeConnectorSetProperty(render->fd_drm, render->connector_id, - render->hdr_metadata, blob_id); + render->hdr_metadata, render->hdr_blob_id); if (ret) { printf("DRM: HDR metadata: failed property set %d\n",ret); - if (blob_id) - drmModeDestroyPropertyBlob(render->fd_drm, blob_id); - blob_id = 0; + if (render->hdr_blob_id) + drmModeDestroyPropertyBlob(render->fd_drm, render->hdr_blob_id); + render->hdr_blob_id = 0; return; } m_need_modeset = 1; diff --git a/video.c b/video.c index cbea387..2ad7eb2 100644 --- a/video.c +++ b/video.c @@ -551,6 +551,56 @@ static void X11DPMSReenable(xcb_connection_t *); static void X11DPMSDisable(xcb_connection_t *); #endif + +char *eglErrorString(EGLint error) +{ + switch (error) { + case EGL_SUCCESS: + return "No error"; + case EGL_NOT_INITIALIZED: + return "EGL not initialized or failed to initialize"; + case EGL_BAD_ACCESS: + return "Resource inaccessible"; + case EGL_BAD_ALLOC: + return "Cannot allocate resources"; + case EGL_BAD_ATTRIBUTE: + return "Unrecognized attribute or attribute value"; + case EGL_BAD_CONTEXT: + return "Invalid EGL context"; + case EGL_BAD_CONFIG: + return "Invalid EGL frame buffer configuration"; + case EGL_BAD_CURRENT_SURFACE: + return "Current surface is no longer valid"; + case EGL_BAD_DISPLAY: + return "Invalid EGL display"; + case EGL_BAD_SURFACE: + return "Invalid surface"; + case EGL_BAD_MATCH: + return "Inconsistent arguments"; + case EGL_BAD_PARAMETER: + return "Invalid argument"; + case EGL_BAD_NATIVE_PIXMAP: + return "Invalid native pixmap"; + case EGL_BAD_NATIVE_WINDOW: + return "Invalid native window"; + case EGL_CONTEXT_LOST: + return "Context lost"; + } + return "Unknown error "; +} + +/// +/// egl check error. +/// +#define EglCheck(void) \ +{\ + EGLint err;\ +\ + if ((err = eglGetError()) != EGL_SUCCESS) {\ + Debug(3, "video/egl: %s:%d error %d %s\n", __FILE__,__LINE__,err,eglErrorString(err));\ + }\ +} + //---------------------------------------------------------------------------- // DRM Helper Functions //---------------------------------------------------------------------------- @@ -657,6 +707,8 @@ static void VideoUpdateOutput(AVRational input_aspect_ratio, int input_width, in #ifdef USE_DRM get_drm_aspect(&display_aspect_ratio.num,&display_aspect_ratio.den); #else + Debug(3,"mmHeight %d mm Width %d VideoHeight %d VideoWidth %d\n",VideoScreen->height_in_millimeters,VideoScreen->width_in_millimeters, + VideoScreen->height_in_pixels,VideoScreen->width_in_pixels); display_aspect_ratio.num = VideoScreen->width_in_pixels * VideoScreen->height_in_millimeters; display_aspect_ratio.den = VideoScreen->height_in_pixels * VideoScreen->width_in_millimeters; #endif @@ -829,54 +881,6 @@ static PFNGLXSWAPINTERVALSGIPROC GlxSwapIntervalSGI; }\ } -char *eglErrorString(EGLint error) -{ - switch (error) { - case EGL_SUCCESS: - return "No error"; - case EGL_NOT_INITIALIZED: - return "EGL not initialized or failed to initialize"; - case EGL_BAD_ACCESS: - return "Resource inaccessible"; - case EGL_BAD_ALLOC: - return "Cannot allocate resources"; - case EGL_BAD_ATTRIBUTE: - return "Unrecognized attribute or attribute value"; - case EGL_BAD_CONTEXT: - return "Invalid EGL context"; - case EGL_BAD_CONFIG: - return "Invalid EGL frame buffer configuration"; - case EGL_BAD_CURRENT_SURFACE: - return "Current surface is no longer valid"; - case EGL_BAD_DISPLAY: - return "Invalid EGL display"; - case EGL_BAD_SURFACE: - return "Invalid surface"; - case EGL_BAD_MATCH: - return "Inconsistent arguments"; - case EGL_BAD_PARAMETER: - return "Invalid argument"; - case EGL_BAD_NATIVE_PIXMAP: - return "Invalid native pixmap"; - case EGL_BAD_NATIVE_WINDOW: - return "Invalid native window"; - case EGL_CONTEXT_LOST: - return "Context lost"; - } - return "Unknown error "; -} - -/// -/// egl check error. -/// -#define EglCheck(void) \ -{\ - EGLint err;\ -\ - if ((err = eglGetError()) != EGL_SUCCESS) {\ - Debug(3, "video/egl: %s:%d error %d %s\n", __FILE__,__LINE__,err,eglErrorString(err));\ - }\ -} @@ -978,10 +982,11 @@ static void EglInit(void) XVisualInfo *vi = NULL; + #ifdef PLACEBO return; #endif - + // The desired 30-bit color visual int attributeList10[] = { GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, @@ -1016,7 +1021,7 @@ static void EglInit(void) if (!glXQueryVersion(XlibDisplay, &major, &minor)) { Fatal(_("video/glx: no GLX support\n")); } - Info(_("video/glx: glx version %d.%d\n"), major, minor); + Debug(3,"video/glx: glx version %d.%d\n", major, minor); // // check which extension are supported @@ -1154,7 +1159,8 @@ static void EglInit(void) static void EglInit(void) { int redSize, greenSize, blueSize, alphaSize; - + static int glewdone = 0; + #ifdef PLACEBO return; #endif @@ -1163,12 +1169,15 @@ static void EglInit(void) // create egl context setenv("MESA_GL_VERSION_OVERRIDE","3.3",0); make_egl(); - GLenum err = glewInit(); - - if (err != GLEW_OK) { - Debug(3, "Error: %s\n", glewGetErrorString(err)); - } - + + if (!glewdone) { + GLenum err = glewInit(); + glewdone = 1; + if (err != GLEW_OK) { + Debug(3, "Error: %s\n", glewGetErrorString(err)); + } + } + eglGetConfigAttrib(eglDisplay, eglConfig, EGL_BLUE_SIZE, &blueSize); eglGetConfigAttrib(eglDisplay, eglConfig, EGL_RED_SIZE, &redSize); eglGetConfigAttrib(eglDisplay, eglConfig, EGL_GREEN_SIZE, &greenSize); @@ -1192,7 +1201,7 @@ static void EglInit(void) static void EglExit(void) { Debug(3, "video/egl: %s\n", __FUNCTION__); -#ifdef PLACEBO +#if defined PLACEBO return; #endif @@ -1215,11 +1224,7 @@ static void EglExit(void) GlxCheck(); glxContext = NULL; } - if (glxThreadContext) { - glXDestroyContext(XlibDisplay, glxThreadContext); - GlxCheck(); - glxThreadContext = NULL; - } + if (glxSharedContext) { glXDestroyContext(XlibDisplay, glxSharedContext); GlxCheck(); @@ -1230,20 +1235,26 @@ static void EglExit(void) // if currently used, set to none eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); } +#ifndef USE_DRM if (eglSharedContext) { eglDestroyContext(eglDisplay, eglSharedContext); EglCheck(); } + if (eglContext) { eglDestroyContext(eglDisplay, eglContext); EglCheck(); + eglContext = NULL; } - if (eglThreadContext) { - eglDestroyContext(eglDisplay, eglThreadContext); - EglCheck(); - } + eglTerminate(eglDisplay); #endif + +#ifdef USE_DRM + drm_clean_up(); +#endif + +#endif } #endif @@ -2112,6 +2123,7 @@ static void CuvidDelHwDecoder(CuvidDecoder * decoder) static int CuvidGlxInit( __attribute__((unused)) const char *display_name) { + #ifndef PLACEBO EglInit(); @@ -4889,6 +4901,7 @@ void VideoOsdExit(void) { OsdDirtyWidth = 0; OsdDirtyHeight = 0; + VideoOsdClear(); } //---------------------------------------------------------------------------- @@ -5077,29 +5090,7 @@ void pl_log_intern(void *stream, enum pl_log_level level, const char *msg) printf("%5s: %s\n", prefix[level], msg); } -void delete_placebo() -{ - Debug(3, "delete placebo\n"); - if (p == NULL) - return; - if (osdoverlay.plane.texture) - pl_tex_destroy(p->gpu, &osdoverlay.plane.texture); - - pl_renderer_destroy(&p->renderer); - if (p->renderertest) { - pl_renderer_destroy(&p->renderertest); - p->renderertest = NULL; - } - pl_swapchain_destroy(&p->swapchain); - - vkDestroySurfaceKHR(p->vk_inst->instance, p->pSurface, NULL); - pl_vk_inst_destroy(&p->vk_inst); - // pl_vulkan_destroy(&p->vk); - pl_context_destroy(&p->ctx); - free(p); - p = NULL; -} void InitPlacebo() { @@ -5199,11 +5190,17 @@ void InitPlacebo() /// /// Video render thread. /// + +void delete_decode() { + Debug(3,"decoder thread exit\n"); +} + static void *VideoDisplayHandlerThread(void *dummy) { - prctl(PR_SET_NAME, "cuvid video", 0, 0, 0); + prctl(PR_SET_NAME, "video decode", 0, 0, 0); sleep(2); + pthread_cleanup_push(delete_decode, NULL); for (;;) { // fix dead-lock with CuvidExit pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); @@ -5212,11 +5209,50 @@ static void *VideoDisplayHandlerThread(void *dummy) VideoUsedModule->DisplayHandlerThread(); } - + pthread_cleanup_pop(NULL); return dummy; } +void exit_display() +{ +#ifdef PLACEBO + Debug(3, "delete placebo\n"); + if (p == NULL) + return; + if (osdoverlay.plane.texture) + pl_tex_destroy(p->gpu, &osdoverlay.plane.texture); + + pl_renderer_destroy(&p->renderer); + if (p->renderertest) { + pl_renderer_destroy(&p->renderertest); + p->renderertest = NULL; + } + pl_swapchain_destroy(&p->swapchain); + + vkDestroySurfaceKHR(p->vk_inst->instance, p->pSurface, NULL); + pl_vk_inst_destroy(&p->vk_inst); + // pl_vulkan_destroy(&p->vk); + pl_context_destroy(&p->ctx); + free(p); + p = NULL; +#endif +#ifdef CUVID + if (glxThreadContext) { + glXDestroyContext(XlibDisplay, glxThreadContext); + GlxCheck(); + glxThreadContext = NULL; + } +#else + if (eglThreadContext) { + eglDestroyContext(eglDisplay, eglThreadContext); + EglCheck(); + eglThreadContext = NULL; + } +#endif + Debug(3,"display thread exit\n"); +} + static void *VideoHandlerThread(void *dummy) { EGLint contextAttrs[] = { @@ -5224,12 +5260,10 @@ static void *VideoHandlerThread(void *dummy) EGL_NONE }; - prctl(PR_SET_NAME, "cuvid video display", 0, 0, 0); - + prctl(PR_SET_NAME, "video display", 0, 0, 0); + #ifdef PLACEBO InitPlacebo(); - pthread_cleanup_push(delete_placebo, NULL); - #else #ifdef CUVID if (EglEnabled) { @@ -5247,22 +5281,22 @@ static void *VideoHandlerThread(void *dummy) eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglThreadContext); #endif #endif + pthread_cleanup_push(exit_display, NULL); for (;;) { pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); pthread_testcancel(); pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); - +#ifndef USE_DRM VideoPollEvent(); - +#endif // first_time = GetusTicks(); CuvidSyncDisplayFrame(); // printf("syncdisplayframe exec %d\n",(GetusTicks()-first_time)/1000); } -#ifdef PLACEBO - pthread_cleanup_pop(NULL); -#endif + pthread_cleanup_pop(NULL); + return dummy; } @@ -5276,7 +5310,7 @@ static void VideoThreadInit(void) #ifdef CUVID glXMakeCurrent(XlibDisplay, None, NULL); #else - eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, eglContext); +// eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, eglContext); #endif #endif pthread_mutex_init(&VideoMutex, NULL); @@ -5301,19 +5335,20 @@ static void VideoThreadExit(void) // FIXME: can't cancel locked if (pthread_cancel(VideoThread)) { - Error(_("video: can't queue cancel video display thread\n")); + Debug(3,"video: can't queue cancel video display thread\n"); } - + usleep(200000); // 200ms if (pthread_join(VideoThread, &retval) || retval != PTHREAD_CANCELED) { - Error(_("video: can't cancel video display thread\n")); + Debug(3,"video: can't cancel video decoder thread\n"); } + if (VideoDisplayThread) { if (pthread_cancel(VideoDisplayThread)) { - Error(_("video: can't queue cancel video display thread\n")); - } + Debug(3,"video: can't queue cancel video display thread\n"); + } usleep(200000); // 200ms if (pthread_join(VideoDisplayThread, &retval) || retval != PTHREAD_CANCELED) { - Error(_("video: can't cancel video display thread\n")); + Debug(3,"video: can't cancel video display thread\n"); } VideoDisplayThread = 0; } @@ -5324,8 +5359,10 @@ static void VideoThreadExit(void) pthread_mutex_destroy(&OSDMutex); #ifndef PLACEBO + if (OSDtexture) glDeleteTextures(1, &OSDtexture); + if (gl_prog_osd) { glDeleteProgram(gl_prog_osd); gl_prog_osd = 0; @@ -5334,7 +5371,9 @@ static void VideoThreadExit(void) glDeleteProgram(gl_prog); gl_prog = 0; } + #endif + } } @@ -6699,6 +6738,7 @@ void VideoExit(void) if (!XlibDisplay) { // no init or failed return; } + // // Reenable screensaver / DPMS. // @@ -6751,9 +6791,7 @@ void VideoExit(void) Connection = 0; } #endif -#ifdef USE_DRM - drm_clean_up(); -#endif + } #ifdef USE_DRM @@ -6762,6 +6800,8 @@ int GlxInitopengl () { EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE }; + while (!eglSharedContext) + sleep(1); if (!eglOSDContext) { eglOSDContext = eglCreateContext(eglDisplay, eglConfig, eglSharedContext, contextAttrs);