1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180 |
- /*
- * Copyright (c) 2016-2023, NVIDIA CORPORATION. All rights reserved.
- * NVIDIA CORPORATION and its licensors retain all intellectual property
- * and proprietary rights in and to this software, related documentation
- * and any modifications thereto. Any use, reproduction, disclosure or
- * distribution of this software and related documentation without an express
- * license agreement from NVIDIA CORPORATION is strictly prohibited.
- */
- #include "NvDrmRenderer.h"
- #include "NvLogging.h"
- #include "nvbufsurface.h"
- #include <sys/time.h>
- #include <sys/poll.h>
- #include <unistd.h>
- #include <string.h>
- #include <xf86drm.h>
- #include <xf86drmMode.h>
- #include <drm_fourcc.h>
- #include <fcntl.h>
- #include "tegra_drm.h"
- #include <sys/mman.h>
- #ifndef DOWNSTREAM_TEGRA_DRM
- #include "tegra_drm_nvdc.h"
- #endif
- using namespace std;
- #define CAT_NAME "DrmRenderer"
- #define DRM_DEVICE_NAME "drm-nvdc"
- #define ZERO_FD 0x0
- struct NvBufDrmParams
- {
- uint32_t num_planes;
- uint32_t pitch[4];
- uint32_t offset[4];
- uint32_t pixel_format;
- };
- struct NvBOFormat {
- uint32_t drm_format;
- int num_buffers;
- struct {
- int w; // width divisor from overall fb_width (luma size)
- int h; // height divisor from overall fb_height (luma size)
- int bpp;
- } buffers[3];
- };
- const NvBOFormat NvBOFormats[] = {
- // drm fourcc type #buffers w1 h1 bpp1 w2 h2 bpp2 w3 h3 bpp3
- {DRM_FORMAT_RGB332, 1, {{1, 1, 8}, {0, 0, 0}, {0, 0, 0}}},
- {DRM_FORMAT_BGR233, 1, {{1, 1, 8}, {0, 0, 0}, {0, 0, 0}}},
- {DRM_FORMAT_XRGB4444, 1, {{1, 1, 16}, {0, 0, 0}, {0, 0, 0}}},
- {DRM_FORMAT_ARGB4444, 1, {{1, 1, 16}, {0, 0, 0}, {0, 0, 0}}},
- {DRM_FORMAT_XBGR4444, 1, {{1, 1, 16}, {0, 0, 0}, {0, 0, 0}}},
- {DRM_FORMAT_ABGR4444, 1, {{1, 1, 16}, {0, 0, 0}, {0, 0, 0}}},
- {DRM_FORMAT_RGBX4444, 1, {{1, 1, 16}, {0, 0, 0}, {0, 0, 0}}},
- {DRM_FORMAT_RGBA4444, 1, {{1, 1, 16}, {0, 0, 0}, {0, 0, 0}}},
- {DRM_FORMAT_BGRX4444, 1, {{1, 1, 16}, {0, 0, 0}, {0, 0, 0}}},
- {DRM_FORMAT_BGRA4444, 1, {{1, 1, 16}, {0, 0, 0}, {0, 0, 0}}},
- {DRM_FORMAT_XRGB1555, 1, {{1, 1, 16}, {0, 0, 0}, {0, 0, 0}}},
- {DRM_FORMAT_ARGB1555, 1, {{1, 1, 16}, {0, 0, 0}, {0, 0, 0}}},
- {DRM_FORMAT_XBGR1555, 1, {{1, 1, 16}, {0, 0, 0}, {0, 0, 0}}},
- {DRM_FORMAT_ABGR1555, 1, {{1, 1, 16}, {0, 0, 0}, {0, 0, 0}}},
- {DRM_FORMAT_RGBX5551, 1, {{1, 1, 16}, {0, 0, 0}, {0, 0, 0}}},
- {DRM_FORMAT_RGBA5551, 1, {{1, 1, 16}, {0, 0, 0}, {0, 0, 0}}},
- {DRM_FORMAT_BGRX5551, 1, {{1, 1, 16}, {0, 0, 0}, {0, 0, 0}}},
- {DRM_FORMAT_BGRA5551, 1, {{1, 1, 16}, {0, 0, 0}, {0, 0, 0}}},
- {DRM_FORMAT_RGB565, 1, {{1, 1, 16}, {0, 0, 0}, {0, 0, 0}}},
- {DRM_FORMAT_BGR565, 1, {{1, 1, 16}, {0, 0, 0}, {0, 0, 0}}},
- {DRM_FORMAT_RGB888, 1, {{1, 1, 24}, {0, 0, 0}, {0, 0, 0}}},
- {DRM_FORMAT_BGR888, 1, {{1, 1, 24}, {0, 0, 0}, {0, 0, 0}}},
- {DRM_FORMAT_XRGB8888, 1, {{1, 1, 32}, {0, 0, 0}, {0, 0, 0}}},
- {DRM_FORMAT_ARGB8888, 1, {{1, 1, 32}, {0, 0, 0}, {0, 0, 0}}},
- {DRM_FORMAT_XBGR8888, 1, {{1, 1, 32}, {0, 0, 0}, {0, 0, 0}}},
- {DRM_FORMAT_ABGR8888, 1, {{1, 1, 32}, {0, 0, 0}, {0, 0, 0}}},
- {DRM_FORMAT_RGBX8888, 1, {{1, 1, 32}, {0, 0, 0}, {0, 0, 0}}},
- {DRM_FORMAT_RGBA8888, 1, {{1, 1, 32}, {0, 0, 0}, {0, 0, 0}}},
- {DRM_FORMAT_BGRX8888, 1, {{1, 1, 32}, {0, 0, 0}, {0, 0, 0}}},
- {DRM_FORMAT_BGRA8888, 1, {{1, 1, 32}, {0, 0, 0}, {0, 0, 0}}},
- {DRM_FORMAT_ARGB2101010,1, {{1, 1, 32}, {0, 0, 0}, {0, 0, 0}}},
- {DRM_FORMAT_ABGR2101010,1, {{1, 1, 32}, {0, 0, 0}, {0, 0, 0}}},
- {DRM_FORMAT_YUYV, 1, {{1, 1, 16}, {0, 0, 0}, {0, 0, 0}}},
- {DRM_FORMAT_YVYU, 1, {{1, 1, 16}, {0, 0, 0}, {0, 0, 0}}},
- {DRM_FORMAT_UYVY, 1, {{1, 1, 16}, {0, 0, 0}, {0, 0, 0}}},
- {DRM_FORMAT_VYUY, 1, {{1, 1, 16}, {0, 0, 0}, {0, 0, 0}}},
- {DRM_FORMAT_NV12, 2, {{1, 1, 8}, {2, 2, 16}, {0, 0, 0}}},
- {DRM_FORMAT_NV21, 2, {{1, 1, 8}, {2, 2, 16}, {0, 0, 0}}},
- {DRM_FORMAT_NV16, 2, {{1, 1, 8}, {2, 1, 16}, {0, 0, 0}}},
- {DRM_FORMAT_NV61, 2, {{1, 1, 8}, {2, 1, 16}, {0, 0, 0}}},
- {DRM_FORMAT_YUV410, 3, {{1, 1, 8}, {4, 4, 8}, {4, 4, 8}}},
- {DRM_FORMAT_YVU410, 3, {{1, 1, 8}, {4, 4, 8}, {4, 4, 8}}},
- {DRM_FORMAT_YUV411, 3, {{1, 1, 8}, {4, 1, 8}, {4, 1, 8}}},
- {DRM_FORMAT_YVU411, 3, {{1, 1, 8}, {4, 1, 8}, {4, 1, 8}}},
- {DRM_FORMAT_YUV420, 3, {{1, 1, 8}, {2, 2, 8}, {2, 2, 8}}},
- {DRM_FORMAT_YVU420, 3, {{1, 1, 8}, {2, 2, 8}, {2, 2, 8}}},
- {DRM_FORMAT_YUV422, 3, {{1, 1, 8}, {2, 1, 8}, {2, 1, 8}}},
- {DRM_FORMAT_YVU422, 3, {{1, 1, 8}, {2, 1, 8}, {2, 1, 8}}},
- {DRM_FORMAT_YUV444, 3, {{1, 1, 8}, {1, 1, 8}, {1, 1, 8}}},
- {DRM_FORMAT_YVU444, 3, {{1, 1, 8}, {1, 1, 8}, {1, 1, 8}}},
- };
- static int NvBufGetDrmParams(NvBufSurface *nvbuf_surface, NvBufDrmParams *dParams)
- {
- unsigned int i;
- if (nvbuf_surface == NULL || dParams == NULL)
- goto error;
- memset(dParams, 0 , sizeof(NvBufDrmParams));
- dParams->num_planes = nvbuf_surface->surfaceList[0].planeParams.num_planes;
- for (i = 0; i < nvbuf_surface->surfaceList[0].planeParams.num_planes; i++) {
- dParams->pitch[i] = nvbuf_surface->surfaceList[0].planeParams.pitch[i];
- dParams->offset[i] = nvbuf_surface->surfaceList[0].planeParams.offset[i];
- }
- switch (nvbuf_surface->surfaceList[0].colorFormat) {
- case NVBUF_COLOR_FORMAT_YUV420:
- dParams->pixel_format = DRM_FORMAT_YUV420;
- break;
- case NVBUF_COLOR_FORMAT_YVU420:
- dParams->pixel_format = DRM_FORMAT_YVU420;
- break;
- case NVBUF_COLOR_FORMAT_NV12:
- dParams->pixel_format = DRM_FORMAT_NV12;
- break;
- case NVBUF_COLOR_FORMAT_NV21:
- dParams->pixel_format = DRM_FORMAT_NV21;
- break;
- case NVBUF_COLOR_FORMAT_UYVY:
- dParams->pixel_format = DRM_FORMAT_UYVY;
- break;
- case NVBUF_COLOR_FORMAT_NV12_10LE_2020:
- dParams->pixel_format = DRM_FORMAT_TEGRA_P010_2020;
- break;
- case NVBUF_COLOR_FORMAT_NV12_10LE_709:
- dParams->pixel_format = DRM_FORMAT_TEGRA_P010_709;
- break;
- case NVBUF_COLOR_FORMAT_NV12_10LE:
- dParams->pixel_format = DRM_FORMAT_P010;
- break;
- case NVBUF_COLOR_FORMAT_INVALID:
- default:
- goto error;
- }
- return 0;
- error:
- ERROR_MSG("Error in transforming buffer information ");
- return -1;
- }
- static int get_format_info(uint32_t drm_format, NvBOFormat *bo)
- {
- unsigned int i;
- for (i = 0; i < sizeof(NvBOFormats) / sizeof(NvBOFormats[0]); i++) {
- if (NvBOFormats[i].drm_format == drm_format) {
- *bo = NvBOFormats[i];
- return 1;
- }
- }
- return 0;
- }
- NvDrmRenderer::NvDrmRenderer(const char *name, uint32_t w, uint32_t h,
- uint32_t w_x, uint32_t w_y, uint32_t aconn, uint32_t acrtc,
- struct drm_tegra_hdr_metadata_smpte_2086 metadata,
- bool streamHDR)
- :NvElement(name, valid_fields)
- {
- drmModeRes* drm_res_info = NULL;
- drmModeConnector* drm_conn_info = NULL;
- drmModeEncoder* drm_enc_info = NULL;
- drmModeCrtc* drm_crtc_info = NULL;
- uint32_t crtc_mask;
- int i;
- conn = aconn;
- crtc = acrtc;
- width = w;
- height = h;
- stop_thread = false;
- flipPending = false;
- renderingStarted = false;
- is_nvidia_drm = false;
- activeFd = flippedFd = -1;
- last_fb = 0;
- int ret =0;
- log_level = LOG_LEVEL_ERROR;
- last_render_time.tv_sec = 0;
- drmVersion *version;
- drm_fd = drmOpen(DRM_DEVICE_NAME, NULL);
- if (drm_fd < 0)
- drm_fd = open("/dev/dri/card0", O_RDWR, 0);
- if (drm_fd == -1) {
- COMP_ERROR_MSG("Couldn't open device");
- goto error;
- }
- version = drmGetVersion(drm_fd);
- if (version == NULL) {
- COMP_ERROR_MSG("Failed to get drm version\n");
- goto error;
- }
- if (!strcmp(version->name, "nvidia-drm")) {
- is_nvidia_drm = true;
- }
- drmFreeVersion(version);
- // Obtain DRM-KMS resources
- drm_res_info = drmModeGetResources(drm_fd);
- if (!drm_res_info) {
- COMP_ERROR_MSG("Couldn't obtain DRM-KMS resources ");
- goto error;
- }
- COMP_DEBUG_MSG("Obtained device information ");
- // If a specific crtc was requested, make sure it exists
- if (crtc >= drm_res_info->count_crtcs) {
- COMP_ERROR_MSG("Requested crtc index " << crtc << " exceeds count " << drm_res_info->count_crtcs);
- goto error;
- }
- crtc_mask = (crtc >= 0) ? (1<<crtc) : ((1<<drm_res_info->count_crtcs)-1);
- if (conn >= 0) {
- // Query info for requested connector
- if (conn >= drm_res_info->count_connectors) {
- COMP_ERROR_MSG("Requested connector index " << conn << " exceeds count " << drm_res_info->count_connectors);
- goto error;
- }
- drm_conn_id = drm_res_info->connectors[conn];
- drm_conn_info = drmModeGetConnector(drm_fd, drm_conn_id);
- if (!drm_conn_info) {
- COMP_ERROR_MSG("Unable to obtain info for connector " << drm_conn_id);
- goto error;
- } else if (drm_conn_info->connection != DRM_MODE_CONNECTED) {
- COMP_ERROR_MSG("Requested connnector is not connected ");
- goto error;
- } else if (drm_conn_info->count_modes <= 0) {
- COMP_ERROR_MSG("Requested connnector has no available modes ");
- goto error;
- }
- } else {
- for (i=0; i<drm_res_info->count_connectors; ++i) {
- // Query info for requested connector
- drm_conn_id = drm_res_info->connectors[i];
- drm_conn_info = drmModeGetConnector(drm_fd, drm_conn_id);
- if (!drm_conn_info) {
- COMP_ERROR_MSG("Unable to obtain info for connector " << drm_conn_id);
- goto error;
- } else if (drm_conn_info->connection != DRM_MODE_CONNECTED) {
- drmModeFreeConnector(drm_conn_info);
- continue;
- } else if (drm_conn_info->count_modes <= 0) {
- COMP_ERROR_MSG("Requested connnector has no available modes ");
- goto error;
- } else if (drm_conn_info->connection == DRM_MODE_CONNECTED) {
- break;
- }
- }
- if (i > drm_res_info->count_connectors) {
- COMP_ERROR_MSG("Requested connector index " << i << " exceeds count " << drm_res_info->count_connectors);
- goto error;
- }
- }
- COMP_DEBUG_MSG("Obtained connector information\n");
- // If there is already an encoder attached to the connector, choose
- // it unless not compatible with crtc/plane
- drm_enc_id = drm_conn_info->encoder_id;
- drm_enc_info = drmModeGetEncoder(drm_fd, drm_enc_id);
- if (drm_enc_info) {
- if (!(drm_enc_info->possible_crtcs & crtc_mask)) {
- drmModeFreeEncoder(drm_enc_info);
- drm_enc_info = NULL;
- }
- }
- // If we didn't have a suitable encoder, find one
- if (!drm_enc_info) {
- for (i=0; i<drm_conn_info->count_encoders; ++i) {
- drm_enc_id = drm_conn_info->encoders[i];
- drm_enc_info = drmModeGetEncoder(drm_fd, drm_enc_id);
- if (drm_enc_info) {
- if (crtc_mask & drm_enc_info->possible_crtcs) {
- crtc_mask &= drm_enc_info->possible_crtcs;
- break;
- }
- drmModeFreeEncoder(drm_enc_info);
- drm_enc_info = NULL;
- }
- }
- if (i == drm_conn_info->count_encoders) {
- COMP_ERROR_MSG("Unable to find suitable encoder ");
- goto error;
- }
- }
- COMP_DEBUG_MSG("Obtained encoder information ");
- // Select a suitable crtc. Give preference to one that's already
- // attached to the encoder.
- for (i=0; i<drm_res_info->count_crtcs; ++i) {
- if (crtc_mask & (1 << i)) {
- drm_crtc_id = drm_res_info->crtcs[i];
- if (drm_enc_info && drm_res_info->crtcs[i] == drm_enc_info->crtc_id) {
- break;
- }
- }
- }
- if (streamHDR && hdrSupported()) {
- ret = setHDRMetadataSmpte2086(metadata);
- if(ret!=0)
- COMP_DEBUG_MSG("Error while getting HDR mastering display data\n");
- }
- else {
- COMP_DEBUG_MSG("APP_INFO : HDR not supported \n");
- }
- // Query info for crtc
- drm_crtc_info = drmModeGetCrtc(drm_fd, drm_crtc_id);
- if (!drm_crtc_info) {
- COMP_ERROR_MSG("Unable to obtain info for crtc " << drm_crtc_id);
- goto error;
- }
- COMP_DEBUG_MSG("Obtained crtc information\n");
- #if 0
- if ((drm_conn_info->encoder_id != drm_enc_id) ||
- (drm_enc_info->crtc_id != drm_crtc_id) ||
- !drm_crtc_info->mode_valid) {
- drmModeSetCrtc(drm_fd, drm_crtc_id, -1, 0, 0, &drm_conn_id, 1, NULL);
- }
- #endif
- drmModeModeInfoPtr mode;
- mode = NULL;
- int area, current_area;
- area = 0;
- current_area = 0;
- /* Find the mode with highest resolution */
- for (int i = 0; i < drm_conn_info->count_modes; i++) {
- drmModeModeInfoPtr current_mode = &(drm_conn_info)->modes[i];
- current_area = current_mode->hdisplay * current_mode->vdisplay;
- if (current_area > area) {
- mode = current_mode;
- area = current_area;
- }
- }
- NvDrmFB fb;
- createDumbFB(mode->hdisplay, mode->vdisplay, DRM_FORMAT_NV12, &fb);
- drmModeSetCrtc(drm_fd, drm_crtc_id, fb.fb_id, w_x, w_y, &drm_conn_id, 1, mode);
- pthread_mutex_init(&enqueue_lock, NULL);
- pthread_cond_init(&enqueue_cond, NULL);
- pthread_mutex_init(&dequeue_lock, NULL);
- pthread_mutex_init(&render_lock, NULL);
- pthread_cond_init(&render_cond, NULL);
- pthread_cond_init(&dequeue_cond, NULL);
- setFPS(30);
- if (is_nvidia_drm)
- pthread_create(&render_thread, NULL, renderThreadOrin, this);
- else
- pthread_create(&render_thread, NULL, renderThread, this);
- pthread_setname_np(render_thread, "DrmRenderer");
- error_crtc:
- drmModeFreeCrtc(drm_crtc_info);
- error_enc:
- drmModeFreeEncoder(drm_enc_info);
- error_conn:
- drmModeFreeConnector(drm_conn_info);
- error_res:
- drmModeFreeResources(drm_res_info);
- return;
- error:
- is_in_error = 1;
- if (drm_fd != -1)
- drmClose(drm_fd);
- if (drm_crtc_info)
- goto error_crtc;
- if (drm_enc_info)
- goto error_enc;
- if (drm_conn_info)
- goto error_conn;
- if (drm_res_info)
- goto error_res;
- return;
- }
- int
- NvDrmRenderer::drmUtilCloseGemBo (int fd, uint32_t bo_handle)
- {
- struct drm_gem_close gemCloseArgs;
- memset (&gemCloseArgs, 0, sizeof (gemCloseArgs));
- gemCloseArgs.handle = bo_handle;
- drmIoctl (fd, DRM_IOCTL_GEM_CLOSE, &gemCloseArgs);
- return 1;
- }
- void NvDrmRenderer::page_flip_handler(int drm_fd, unsigned int frame,
- unsigned int sec, unsigned int usec, void *data)
- {
- NvDrmRenderer *renderer = (NvDrmRenderer *) data;
- int fd;
- int ret;
- pthread_mutex_lock(&renderer->dequeue_lock);
- if (renderer->activeFd != -1) {
- renderer->freeBuffers.push(renderer->activeFd);
- pthread_cond_signal(&renderer->dequeue_cond);
- }
- renderer->activeFd = renderer->flippedFd;
- pthread_mutex_unlock(&renderer->dequeue_lock);
- pthread_mutex_lock(&renderer->enqueue_lock);
- if (renderer->pendingBuffers.empty()) {
- renderer->flipPending = false;
- pthread_mutex_unlock(&renderer->enqueue_lock);
- return;
- } else {
- fd = (int)renderer->pendingBuffers.front();
- renderer->pendingBuffers.pop();
- if (fd == -1) {
- // drmModeSetCrtc with a ZERO FD will walk through the path that
- // disable the windows.
- // Note: drmModePageFlip doesn't support this trick.
- ret = drmModeSetCrtc(drm_fd, renderer->drm_crtc_id,
- ZERO_FD, 0, 0, &renderer->drm_conn_id, 1, NULL);
- if (ret) {
- std::cout << "Failed to disable windows before exiting" << std::endl;
- pthread_mutex_unlock(&renderer->enqueue_lock);
- return;
- }
- // EOS buffer. Release last buffer held.
- renderer->stop_thread = true;
- pthread_mutex_lock(&renderer->dequeue_lock);
- renderer->freeBuffers.push(renderer->activeFd);
- pthread_cond_signal(&renderer->dequeue_cond);
- pthread_mutex_unlock(&renderer->dequeue_lock);
- renderer->flipPending = false;
- pthread_mutex_unlock(&renderer->enqueue_lock);
- return;
- }
- pthread_mutex_unlock(&renderer->enqueue_lock);
- renderer->renderInternal(fd);
- }
- }
- void *
- NvDrmRenderer::renderThread(void *arg)
- {
- NvDrmRenderer *renderer = (NvDrmRenderer *) arg;
- drmEventContext evctx;
- struct pollfd fds;
- int ret;
- int timeout = 500; // 500ms
- memset(&fds, 0, sizeof(fds));
- fds.fd = renderer->drm_fd;
- fds.events = POLLIN;
- pthread_mutex_lock(&renderer->enqueue_lock);
- while (renderer->pendingBuffers.empty()) {
- if (renderer->stop_thread) {
- pthread_mutex_unlock(&renderer->enqueue_lock);
- return NULL;
- }
- pthread_cond_wait(&renderer->enqueue_cond, &renderer->enqueue_lock);
- }
- int fd = (int)renderer->pendingBuffers.front();
- renderer->pendingBuffers.pop();
- pthread_mutex_unlock(&renderer->enqueue_lock);
- ret = renderer->renderInternal(fd);
- if (ret < 0) {
- renderer->is_in_error = 1;
- return NULL;
- }
- renderer->renderingStarted = true;
- while (!renderer->isInError() || !renderer->stop_thread) {
- ret = poll(&fds, 1, timeout);
- if (ret > 0) {
- if (fds.revents & POLLIN) {
- memset(&evctx, 0, sizeof evctx);
- evctx.version = DRM_EVENT_CONTEXT_VERSION;
- evctx.page_flip_handler = page_flip_handler;
- drmHandleEvent(renderer->drm_fd, &evctx);
- }
- } else if (ret < 0) {
- renderer->is_in_error = 1;
- return NULL;
- } else {
- // Timeout
- return NULL;
- }
- }
- return NULL;
- }
- void *
- NvDrmRenderer::renderThreadOrin(void *arg)
- {
- NvDrmRenderer *renderer = (NvDrmRenderer *) arg;
- int ret;
- pthread_mutex_lock(&renderer->enqueue_lock);
- while (renderer->pendingBuffers.empty()) {
- if (renderer->stop_thread) {
- pthread_mutex_unlock(&renderer->enqueue_lock);
- return NULL;
- }
- pthread_cond_wait(&renderer->enqueue_cond, &renderer->enqueue_lock);
- }
- int fd = (int)renderer->pendingBuffers.front();
- renderer->pendingBuffers.pop();
- pthread_mutex_unlock(&renderer->enqueue_lock);
- ret = renderer->renderInternal(fd);
- if (ret < 0) {
- renderer->is_in_error = 1;
- return NULL;
- }
- renderer->renderingStarted = true;
- while (!renderer->stop_thread) {
- page_flip_handler (renderer->drm_fd, 0, 0, 0, renderer);
- }
- return NULL;
- }
- bool NvDrmRenderer::hdrSupported()
- {
- uint32_t i;
- bool hdr_supported = 0;
- drmModeObjectProperties *props;
- drmModePropertyRes **props_info;
- props = drmModeObjectGetProperties(drm_fd, drm_crtc_id, DRM_MODE_OBJECT_CRTC);
- props_info = (drmModePropertyRes **) calloc(props->count_props, sizeof(props_info));
- for (i = 0; i < props->count_props; i++) {
- props_info[i] = drmModeGetProperty(drm_fd, props->props[i]);
- }
- for (i = 0; i < props->count_props; i++) {
- if (strcmp(props_info[i]->name, "HDR_SUPPORTED") == 0) {
- hdr_supported = props_info[i]->values[0];
- break;
- }
- }
- drmModeFreeObjectProperties(props);
- drmModeFreeProperty(*props_info);
- return hdr_supported;
- }
- int NvDrmRenderer::setHDRMetadataSmpte2086(struct drm_tegra_hdr_metadata_smpte_2086 metadata)
- {
- int prop_id = -1;
- uint32_t i;
- drmModeObjectProperties *props;
- drmModePropertyRes **props_info;
- if (hdrBlobCreated) {
- drmModeDestroyPropertyBlob(drm_fd, hdrBlobId);
- hdrBlobCreated = 0;
- }
- if (drmModeCreatePropertyBlob(drm_fd, &metadata, sizeof(metadata), &hdrBlobId) != 0) {
- return -1;
- }
- hdrBlobCreated = 1;
- props = drmModeObjectGetProperties(drm_fd, drm_crtc_id, DRM_MODE_OBJECT_CRTC);
- props_info = (drmModePropertyRes **) calloc(props->count_props, sizeof(props_info));
- for (i = 0; i < props->count_props; i++) {
- props_info[i] = drmModeGetProperty(drm_fd, props->props[i]);
- }
- for (i = 0; i < props->count_props; i++) {
- if (strcmp(props_info[i]->name, "HDR_METADATA_SMPTE_2086_ID") == 0) {
- prop_id = props_info[i]->prop_id;
- break;
- }
- }
- if (prop_id < 0) {
- return -1;
- }
- return drmModeObjectSetProperty(drm_fd, drm_crtc_id, DRM_MODE_OBJECT_CRTC, prop_id, hdrBlobId);
- }
- NvDrmRenderer::~NvDrmRenderer()
- {
- uint32_t fb;
- stop_thread = true;
- pthread_mutex_lock(&enqueue_lock);
- pthread_cond_broadcast(&enqueue_cond);
- pthread_mutex_unlock(&enqueue_lock);
- pthread_join(render_thread, NULL);
- pthread_mutex_destroy(&enqueue_lock);
- pthread_cond_destroy(&enqueue_cond);
- pthread_mutex_lock(&dequeue_lock);
- pthread_cond_broadcast(&dequeue_cond);
- pthread_mutex_unlock(&dequeue_lock);
- pthread_mutex_destroy(&dequeue_lock);
- pthread_cond_destroy(&dequeue_cond);
- pthread_mutex_destroy(&render_lock);
- pthread_cond_destroy(&render_cond);
- for (auto map_entry = map_list.begin();
- map_entry != map_list.end(); ++map_entry) {
- fb = (uint32_t) map_entry->second;
- drmModeRmFB(drm_fd, fb);
- }
- if(last_fb)
- drmModeRmFB(drm_fd, last_fb);
- if (hdrBlobCreated) {
- drmModeDestroyPropertyBlob(drm_fd, hdrBlobId);
- hdrBlobCreated = 0;
- }
- if (drm_fd != -1)
- drmClose(drm_fd);
- }
- int
- NvDrmRenderer::dequeBuffer()
- {
- int fd = -1;
- // if (stop_thread)
- // return fd;
- // usleep(15000);
- pthread_mutex_lock(&dequeue_lock);
- while (freeBuffers.empty()) {
- if (stop_thread) {
- pthread_mutex_unlock(&dequeue_lock);
- return fd;
- }
- pthread_cond_wait (&dequeue_cond, &dequeue_lock);
- }
- fd = (int) freeBuffers.front();
- freeBuffers.pop();
- pthread_mutex_unlock(&dequeue_lock);
- return fd;
- }
- int
- NvDrmRenderer::enqueBuffer(int fd)
- {
- int ret = -1;
- int tmpFd;
- if (is_in_error)
- return ret;
- pthread_mutex_lock(&enqueue_lock);
- pendingBuffers.push(fd);
- if (renderingStarted && !flipPending) {
- tmpFd = (int) pendingBuffers.front();
- pendingBuffers.pop();
- if (tmpFd == -1) {
- // drmModeSetCrtc with a ZERO FD will walk through the path that
- // disable the windows.
- // Note: drmModePageFlip doesn't support this trick.
- ret = drmModeSetCrtc(drm_fd, drm_crtc_id,
- ZERO_FD, 0, 0, &drm_conn_id, 1, NULL);
- if (ret) {
- COMP_ERROR_MSG("Failed to disable windows before exiting ");
- pthread_mutex_unlock(&enqueue_lock);
- return ret;
- }
- // This is EOS and it is assumed to be last buffer.
- // No buffer will be processed after this.
- // Release last buffer held.
- stop_thread = true;
- pthread_mutex_lock(&dequeue_lock);
- if (activeFd != -1)
- freeBuffers.push(activeFd);
- pthread_cond_signal(&dequeue_cond);
- pthread_mutex_unlock(&dequeue_lock);
- pthread_mutex_unlock(&enqueue_lock);
- return 0;
- }
- pthread_mutex_unlock(&enqueue_lock);
- ret = renderInternal(tmpFd);
- } else {
- ret = 0;
- pthread_cond_signal(&enqueue_cond);
- pthread_mutex_unlock(&enqueue_lock);
- }
- return ret;
- }
- int
- NvDrmRenderer::renderInternal(int fd)
- {
- int ret;
- uint32_t i;
- uint32_t handle;
- uint32_t fb;
- uint32_t bo_handles[4] = {0};
- uint32_t flags = 0;
- bool frame_is_late = false;
- NvBufDrmParams dParams;
- struct drm_tegra_gem_set_tiling args;
- auto map_entry = map_list.find (fd);
- if (map_entry != map_list.end()) {
- fb = (uint32_t) map_entry->second;
- } else {
- // Create a new FB.
- NvBufSurface *nvbuf_surf = 0;
- NvBufSurfaceFromFd(fd, (void**)(&nvbuf_surf));
- if (nvbuf_surf == NULL) {
- COMP_ERROR_MSG("NvBufSurfaceFromFd Failed ");
- goto error;
- }
- ret = NvBufGetDrmParams(nvbuf_surf, &dParams);
- if (ret < 0) {
- COMP_ERROR_MSG("Failed to convert to DRM params ");
- goto error;
- }
- for (i = 0; i < dParams.num_planes; i++) {
- ret = drmPrimeFDToHandle(drm_fd, fd, &handle);
- if (ret)
- {
- COMP_ERROR_MSG("Failed to import buffer object. ");
- goto error;
- }
- if (!is_nvidia_drm) {
- memset(&args, 0, sizeof(args));
- args.handle = handle;
- args.mode = DRM_TEGRA_GEM_TILING_MODE_PITCH;
- args.value = 1;
- ret = drmIoctl(drm_fd, DRM_IOCTL_TEGRA_GEM_SET_TILING, &args);
- if (ret < 0)
- {
- COMP_ERROR_MSG("Failed to set tiling parameters ");
- goto error;
- }
- }
- bo_handles[i] = handle;
- }
- if (is_nvidia_drm) {
- static uint64_t modifiers[NVBUF_MAX_PLANES] = { 0 };
- uint64_t hm = 0;
- for (hm = 0; hm < dParams.num_planes; hm++) {
- modifiers[hm] = DRM_FORMAT_MOD_LINEAR;
- //modifiers[hm] = DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 1, 2, 0x06, 0x01);
- }
- if (drmModeAddFB2WithModifiers (drm_fd, width, height,
- dParams.pixel_format, bo_handles, dParams.pitch, dParams.offset,
- modifiers, &fb,
- DRM_MODE_FB_MODIFIERS)) {
- COMP_ERROR_MSG ("Failed to create frame buffer\n");
- goto error;
- }
- } else {
- ret = drmModeAddFB2(drm_fd, width, height, dParams.pixel_format, bo_handles,
- dParams.pitch, dParams.offset, &fb, flags);
- if (ret)
- {
- COMP_ERROR_MSG("Failed to create fb ");
- goto error;
- }
- }
- ret = setPlane(0, fb, 0, 0, width, height, 0, 0, width << 16, height << 16);
- if(ret) {
- COMP_ERROR_MSG("FAILED TO SET PLANE ");
- goto error;
- }
- /* TODO:
- * We get new FDs from camera consumer. Don't do mapping until
- * we can resolve that.
- */
- // map_list.insert(std::make_pair(fd, fb));
- }
- if (last_render_time.tv_sec != 0)
- {
- pthread_mutex_lock(&render_lock);
- last_render_time.tv_sec += render_time_sec;
- last_render_time.tv_nsec += render_time_nsec;
- last_render_time.tv_sec += last_render_time.tv_nsec / 1000000000UL;
- last_render_time.tv_nsec %= 1000000000UL;
- if (isProfilingEnabled())
- {
- struct timeval cur_time;
- gettimeofday(&cur_time, NULL);
- if ((cur_time.tv_sec * 1000000.0 + cur_time.tv_usec) >
- (last_render_time.tv_sec * 1000000.0 +
- last_render_time.tv_nsec / 1000.0))
- {
- frame_is_late = true;
- }
- }
- pthread_cond_timedwait(&render_cond, &render_lock,
- &last_render_time);
- pthread_mutex_unlock(&render_lock);
- }
- else
- {
- struct timeval now;
- gettimeofday(&now, NULL);
- last_render_time.tv_sec = now.tv_sec;
- last_render_time.tv_nsec = now.tv_usec * 1000L;
- }
- flippedFd = fd;
- flipPending = true;
- if (!is_nvidia_drm) {
- ret = drmModePageFlip(drm_fd, drm_crtc_id, fb,
- DRM_MODE_PAGE_FLIP_EVENT,
- this);
- if (ret)
- {
- COMP_ERROR_MSG("Failed to flip");
- flipPending = false;
- goto error;
- }
- }
- /* TODO:
- * Don't create/remove fb for each frame but maintain mapping.
- * We will do that once new FD for each frame from consumer is resolved.
- */
- for (i = 0; i < dParams.num_planes; i++)
- {
- drmUtilCloseGemBo (drm_fd,bo_handles[i]);
- }
- if(last_fb)
- drmModeRmFB(drm_fd, last_fb);
- last_fb = fb;
- profiler.finishProcessing(0, frame_is_late);
- return 0;
- error:
- COMP_ERROR_MSG("Error in rendering frame ");
- return -1;
- }
- int
- NvDrmRenderer::createDumbBO(int width, int height, int bpp, NvDrmBO *bo)
- {
- struct drm_mode_create_dumb creq;
- struct drm_mode_destroy_dumb dreq;
- struct drm_mode_map_dumb mreq;
- int ret;
- uint8_t* map = NULL;
- /* create dumb buffer */
- memset(&creq, 0, sizeof(creq));
- creq.width = width;
- creq.height = height;
- creq.bpp = bpp;
- ret = drmIoctl(drm_fd, DRM_IOCTL_MODE_CREATE_DUMB, &creq);
- if (ret < 0) {
- COMP_ERROR_MSG("cannot create dumb buffer\n");
- return 0;
- }
- /* prepare buffer for memory mapping */
- memset(&mreq, 0, sizeof(mreq));
- mreq.handle = creq.handle;
- ret = drmIoctl(drm_fd, DRM_IOCTL_MODE_MAP_DUMB, &mreq);
- if (ret) {
- COMP_ERROR_MSG("cannot map dumb buffer\n");
- ret = -errno;
- goto err_destroy;
- }
- if (is_nvidia_drm) {
- map = (uint8_t*)mmap(0, creq.size, PROT_READ | PROT_WRITE, MAP_SHARED, drm_fd,
- mreq.offset);
- if (map == MAP_FAILED) {
- COMP_ERROR_MSG("cannot mmap dumb buffer\n");
- return 0;
- }
- } else {
- map = (uint8_t *) (mreq.offset);
- }
- /* clear the buffer object */
- memset(map, 0x00, creq.size);
- bo->bo_handle = creq.handle;
- bo->width = width;
- bo->height = height;
- bo->pitch = creq.pitch;
- bo->data = map;
- return 1;
- err_destroy:
- memset(&dreq, 0, sizeof(dreq));
- dreq.handle = creq.handle;
- drmIoctl(drm_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &dreq);
- return 0;
- }
- int
- NvDrmRenderer::setFPS(float fps)
- {
- uint64_t render_time_usec;
- if (fps == 0)
- {
- COMP_WARN_MSG("Fps 0 is not allowed. Not changing fps");
- return -1;
- }
- pthread_mutex_lock(&render_lock);
- this->fps = fps;
- render_time_usec = 1000000L / fps;
- render_time_sec = render_time_usec / 1000000;
- render_time_nsec = (render_time_usec % 1000000) * 1000L;
- pthread_mutex_unlock(&render_lock);
- return 0;
- }
- bool NvDrmRenderer::enableUniversalPlanes (int enable)
- {
- return !drmSetClientCap(drm_fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, enable);
- }
- uint32_t
- NvDrmRenderer::createDumbFB(uint32_t width, uint32_t height,
- uint32_t drm_format, NvDrmFB *fb)
- {
- int buf_count;
- int i = 0;
- struct drm_mode_destroy_dumb dreq;
- int ret;
- struct NvBOFormat boFormat = {0};
- if (!get_format_info(drm_format, &boFormat)) {
- COMP_ERROR_MSG("Can't make a FB of type " << drm_format);
- return 0;
- }
- buf_count = boFormat.num_buffers;
- uint32_t buf_id;
- uint32_t bo_handles[4] = {0};
- uint32_t pitches[4] = {0};
- uint32_t offsets[4] = {0};
- /* create dumb buffers */
- for (i = 0; i < buf_count; i++) {
- NvDrmBO *bo = &(fb->bo[i]);
- ret = createDumbBO(width / boFormat.buffers[i].w,
- height / boFormat.buffers[i].h,
- boFormat.buffers[i].bpp, bo);
- if (ret < 0) {
- COMP_ERROR_MSG("cannot create dumb buffer ");
- return 0;
- }
- bo_handles[i] = fb->bo[i].bo_handle;
- pitches[i] = fb->bo[i].pitch;
- offsets[i] = 0;
- }
- /* create framebuffer object for the dumb-buffer */
- ret = drmModeAddFB2(drm_fd, width, height, drm_format, bo_handles,
- pitches, offsets, &buf_id, 0);
- if (ret) {
- COMP_ERROR_MSG("cannot create framebuffer ");
- goto err_destroy;
- }
- fb->fb_id = buf_id;
- fb->width = width;
- fb->height = height;
- fb->format = drm_format;
- return 1;
- err_destroy:
- for (i = 0; i < buf_count; i++) {
- memset(&dreq, 0, sizeof(dreq));
- dreq.handle = fb->bo[i].bo_handle;
- drmIoctl(drm_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &dreq);
- }
- return 0;
- }
- int NvDrmRenderer::removeFB(uint32_t fb_id)
- {
- return drmModeRmFB(drm_fd, fb_id);
- }
- int NvDrmRenderer::setPlane(uint32_t pl_index,
- uint32_t fb_id,
- uint32_t crtc_x,
- uint32_t crtc_y,
- uint32_t crtc_w,
- uint32_t crtc_h,
- uint32_t src_x,
- uint32_t src_y,
- uint32_t src_w,
- uint32_t src_h)
- {
- int ret = -1;
- drmModePlaneResPtr pl = NULL;
- drmModePlanePtr plane = NULL;
- pl = drmModeGetPlaneResources(drm_fd);
- if (pl) {
- if (pl_index < pl->count_planes) {
- plane = drmModeGetPlane(drm_fd, pl->planes[pl_index]);
- if (plane) {
- ret = drmModeSetPlane(drm_fd, plane->plane_id, drm_crtc_id,
- fb_id, 0, crtc_x, crtc_y, crtc_w,
- crtc_h, src_x, src_y,
- src_w, src_h);
- drmModeFreePlane(plane);
- }
- } else {
- ret = -EINVAL;
- }
- drmModeFreePlaneResources(pl);
- return ret;
- }
- COMP_ERROR_MSG("No plane resource available ");
- return ret;
- }
- int NvDrmRenderer::getPlaneCount()
- {
- drmModePlaneResPtr pl = NULL;
- int count = 0;
- pl = drmModeGetPlaneResources(drm_fd);
- if (pl) {
- count = pl->count_planes;
- drmModeFreePlaneResources(pl);
- }
- return count;
- }
- int32_t NvDrmRenderer::getPlaneIndex(uint32_t crtc_index,
- int32_t* plane_index)
- {
- drmModePlaneResPtr pl = NULL;
- uint32_t count = 0;
- if (!plane_index)
- return 0;
- pl = drmModeGetPlaneResources(drm_fd);
- if (pl) {
- for (uint32_t i = 0; i < pl->count_planes; i++) {
- drmModePlanePtr plane;
- plane = drmModeGetPlane(drm_fd, pl->planes[i]);
- plane_index[i] = -1;
- if (plane) {
- //Find the plane is with the given crtc
- if (plane->possible_crtcs & (1 << crtc_index)) {
- plane_index[count] = i;
- count++;
- }
- drmModeFreePlane(plane);
- }
- }
- drmModeFreePlaneResources(pl);
- }
- return count;
- }
- int NvDrmRenderer::getCrtcCount()
- {
- drmModeResPtr resPtr = NULL;
- int count = 0;
- resPtr = drmModeGetResources(drm_fd);
- if (resPtr) {
- count = resPtr->count_crtcs;
- drmModeFreeResources(resPtr);
- }
- return count;
- }
- int NvDrmRenderer::getEncoderCount()
- {
- drmModeResPtr resPtr = NULL;
- int count = 0;
- resPtr = drmModeGetResources(drm_fd);
- if (resPtr) {
- count = resPtr->count_encoders;
- drmModeFreeResources(resPtr);
- }
- return count;
- }
- NvDrmRenderer *
- NvDrmRenderer::createDrmRenderer(const char *name, uint32_t width,
- uint32_t height, uint32_t w_x, uint32_t w_y,
- uint32_t connector, uint32_t crtc,
- struct drm_tegra_hdr_metadata_smpte_2086 metadata,
- bool streamHDR)
- {
- if (!width || ! height) {
- width = 640;
- height = 480;
- }
- NvDrmRenderer* renderer = new NvDrmRenderer(name, width, height, w_x, w_y, connector, crtc, metadata, streamHDR);
- if (renderer && renderer->isInError())
- {
- delete renderer;
- return NULL;
- }
- return renderer;
- }
|