/* * Copyright (c) 2016-2017, 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. */ /** * @file * * NVIDIA Multimedia API: DRM Renderer API * * @b Description: Helper class for rendering using LibDRM. */ #ifndef __NV_DRM_RENDERER_H__ #define __NV_DRM_RENDERER_H__ #include "NvElement.h" #include #include #include #include /** * * @defgroup l4t_mm_nvdrmrenderer_group DRM Renderer API * * @ingroup aa_framework_api_group * @{ */ /** Holds a buffer object handle. */ typedef struct _NvDrmBO { uint32_t bo_handle; /**< Holds DRM buffer index. */ int width; /**< Holds width of the DRM buffer, in pixels. */ int height; /**< Holds height of the DRM buffer, in pixels. */ int pitch; /**< Holds stride/pitch of the DRM buffer. */ uint8_t* data; /**< Holds mapped CPU accessible address. */ } NvDrmBO; /** Holds information about the frame. */ typedef struct _NvDrmFB { uint32_t fb_id; /**< Holds the frame ID. */ int width; /**< Holds width of the frame, in pixels. */ int height; /**< Holds height of the frame, in pixels. */ int format; /**< Holds frame format, such as @c DRM_FORMAT_RGB332. This class supports a subset of the formats defined in @c drm_fourcc.h, the standard DRM header. */ NvDrmBO bo[4]; /**< Holds DRM buffer handles. */ int num_buffers; /**< Holds the number of DRM buffers, which depends on the buffer format. */ } NvDrmFB; /** * @brief Helper class for rendering using LibDRM. * * The renderer requires the file descriptor of a buffer as an input. The caller * must set the rendering rate in terms of frames per second (FPS). * * The caller specifies the width, height connector, and CRTC index. * Based on the connector and CRTC index, the renderer finds a suitable encoder * and configures the CRTC mode. */ class NvDrmRenderer:public NvElement { public: /** * Creates a new DRM based renderer named @a name. * * @param[in] name Unique name to identity the element instance. * @param[in] width Width of the window in pixels. * @param[in] height Height of the window in pixels. * @param[in] w_x x offset of window location. * @param[in] w_y y offset of window location. * @param[in] connector Index of connector to use. * @param[in] crtc Index of CRTC to use. * @param[in] metadata Contains HDR metadata. * @param[in] streamHDR Flag indicating that the current stream has HDR * metadata, and hence @a metadata is set. * @returns Reference to the newly created renderer object if successful, * or NULL if initialization failed. */ static 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); ~NvDrmRenderer(); /** * Enqueues a buffer file descriptor for rendering. * * This is a non-blocking call. The function waits for the estimated * rendering time of the next buffer. The estimated rendering time is * calculated based on the rendering time of the last buffer and the * rendering rate. * * @param[in] fd File descriptor of the exported buffer to render. * @returns 0 for success, or -1 otherwise. */ int enqueBuffer(int fd); /** * Dequeues a previously rendered buffer. * * This is blocking function that waits until a free buffer is available. * The renderer retains one buffer, which must not be overwritten * by any other component. This buffer can be used when the renderer * is closed or after sending an EOS to the component. * * @returns File descriptor of the previously rendered buffer. */ int dequeBuffer(); /** * Sets the rendering rate in terms of frames per second. * * \warning @a fps may not be set to zero. * * @param[in] fps Rendering rate in frames per second. * @returns 0 for success, or -1 otherwise. */ int setFPS(float fps); /** * Enables/disables DRM universal planes client caps, * such as @c DRM_CLIENT_CAP_UNIVERSAL_PLANES. * * @param[in] enable 1 to enable the caps, or 0 to disable them. * @returns true if successful, or false otherwise. */ bool enableUniversalPlanes(int enable); /** * Allocates a framebuffer of size (w, h). * * @post If the call is successful, the application must remove (free) the * framebuffer by calling removeFB(). * * @param[in] width Framebuffer width in pixels. * @param[in] height Framebuffer height in pixels. * @param[in] drm_format DRM format of @a _NvDrmBO::bo_handle in @a *fb. * @param[out] fb A pointer to an \ref NvDrmFB structure that * contains the framebuffer ID and the buffer * mapping. * * @return 1 if successful, or 0 otherwise. */ uint32_t createDumbFB(uint32_t width, uint32_t height, uint32_t drm_format, NvDrmFB *fb); /** * Destroys (frees) a framebuffer previously allocated by createDumbFB(). * * @param fb_id The ID of the framebuffer to destroy. * @return 0 if the framebuffer is successfully destroyed, or @c -ENOENT * if the framebuffer is not found. */ int removeFB(uint32_t fb_id); /** * Close GEM (Graphics Execution Manager) handles. * * @param fd FD of the buffer. * @param bo_handle the gem-handle to be closed. * * @return 1 for success, 0 for failure. */ int drmUtilCloseGemBo(int fd, uint32_t bo_handle); /** * Changes a plane's framebuffer and position. * * @note The @a crtc_... and @a src_... parameters accept the special input * value -1, which indicates that the hardware offset value is not to be * changed. (Kernel-based DRM drivers return the error code @c -ERANGE when * given this value.) * * @note All @c %setPlane() operations are synced to vblank and are * blocking. * * @param pl_index Plane index of the plane to be changed. * @param fb_id Framebuffer ID of the framebuffer to display on the * plane, or -1 to leave the framebuffer unchanged. * @param crtc_x Offset from left of active display region to show plane. * @param crtc_y Offset from top of active display region to show plane. * @param crtc_w Width of output rectangle on display. * @param crtc_h Height of output rectangle on display. * @param src_x Clip offset from left of source framebuffer * (Q16.16 fixed point). * @param src_y Clip offset from top of source framebuffer * (Q16.16 fixed point). * @param src_w Width of source rectangle (Q16.16 fixed point). * @param src_h Height of source rectangle (Q16.16 fixed point). * @retval 0 if successful. * @retval -EINVAL if @a pl_index is invalid. * @retval -errno otherwise. */ int 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); /** * Gets total number of planes available. * * By default, the count returned includes only "Overlay" type (regular) * planes -- not "Primary" and "Cursor" planes. If * @c DRM_CLIENT_CAP_UNIVERSAL_PLANES has been enabled with * enableUniversalPlanes(), the count returned includes "Primary" * and "Cursor" planes as well. * * @return Count of total planes available. */ int getPlaneCount(); /** * Gets the plane indexes supported by the given * crtc index. * * @param[in] crtc_index Index of crtc for which the * plane indexes to be found. * @param[in,out] plane_index Pointer to an array which * contains plane indexes. This array should be allocated * by the caller for the size of plane count returned * by getPlaneCount() API. * * @return Count of the indexes written in the given array. * */ int getPlaneIndex(uint32_t crtc_index, int32_t* plane_index); /** * Gets count of available CRTCs. * * @return Count of available CRTCs. */ int getCrtcCount(); /** * Gets count of available encoders. * * @return Count of available encoders. */ int getEncoderCount(); /** * Checks whether the DRM renderer supports HDR mode. * * @return True if the DRM renderer supports HDR mode, or FALSE otherwise. */ bool hdrSupported(); /** * Sets the HDR metadata retrieved from the decoder. * * @return 0 if successful, or -1 otherwise. */ int setHDRMetadataSmpte2086(struct drm_tegra_hdr_metadata_smpte_2086); private: struct timespec last_render_time; /**< Rendering time of the last buffer. */ int drm_fd; /**< File descriptor of opened DRM device. */ int conn, crtc; uint32_t width, height; uint32_t drm_conn_id; /**< DRM connector ID. */ uint32_t drm_enc_id; /**< DRM encoder ID. */ uint32_t drm_crtc_id; /**< DRM CRTC ID. */ uint32_t last_fb; int activeFd; int flippedFd; bool flipPending; bool renderingStarted; bool is_nvidia_drm; uint32_t hdrBlobId; bool hdrBlobCreated; std::queue freeBuffers; std::queue pendingBuffers; std::unordered_map map_list; bool stop_thread; /**< Boolean variable used to signal rendering thread to stop. */ pthread_t render_thread; /**< pthread ID of the rendering thread. */ pthread_mutex_t render_lock; /**< Used for synchronization. */ pthread_cond_t render_cond; /**< Used for synchronization. */ pthread_mutex_t enqueue_lock; /**< Used for synchronization. */ pthread_cond_t enqueue_cond; /**< Used for synchronization. */ pthread_mutex_t dequeue_lock; /**< Used for synchronization. */ pthread_cond_t dequeue_cond; /**< Used for synchronization. */ float fps; /**< Rendering rate in frames per second. */ uint64_t render_time_sec; /**< Seconds part of the time for which a frame should be displayed. */ uint64_t render_time_nsec; /**< Nanoseconds part of the time for which a frame should be displayed. */ /** * Constructor called by the wrapper createDrmRenderer(). * * \param[in] name A pointer to a unique name that identifies * the element instance. * \param[in] width Width of the window in pixels. * \param[in] height Height of the window in pixels. * \param[in] w_x X coordinate of the window's upper left corner. * \param[in] w_y Y coordinate of the window's upper left corner. * \param[in] connector Index of the connector to use. * \param[in] crtc Index of the CRTC to use. * \param[in] metadata A pointer to HDR metadata. * \param[in] streamHDR TRUE if the current stream has HDR metadata, * or FALSE otherwise. If TRUE, * @a metadata must be set. */ NvDrmRenderer(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); /** * Function executed by the renderThread. * * This function is executed repeatedly until signalled to stop * by the @c stop_thread variable. The function contains a while loop * which calls renderInternal(). * * \param[in] arg A pointer to an NvDrmRenderer object. */ static void * renderThread(void *arg); static void * renderThreadOrin(void *arg); /** * Callback function for DRM flip event. */ static void page_flip_handler(int fd, unsigned int frame, unsigned int sec, unsigned int usec, void *data); /** * Implements the logic of rendering a buffer * and waiting until the buffer render time. * * \param[in] fd Identifier for the buffer to be rendered. */ int renderInternal(int fd); /* * Returns a DRM buffer_object handle. * * \param[in] w Width of the window in pixels. * \param[in] h Height of the window in pixels. * \param[in] bpp Bits per pixel in the window. * \param[in] bo A pointer to a buffer object handle. * \return An allocated DRM buffer_object handle of size (w,h) */ int createDumbBO(int w, int h, int bpp, NvDrmBO *bo); static const NvElementProfiler::ProfilerField valid_fields = NvElementProfiler::PROFILER_FIELD_TOTAL_UNITS | NvElementProfiler::PROFILER_FIELD_FPS | NvElementProfiler::PROFILER_FIELD_LATE_UNITS; }; /** @} */ #endif