diff options
Diffstat (limited to 'include')
43 files changed, 1928 insertions, 2259 deletions
diff --git a/include/NvFBC.h b/include/NvFBC.h deleted file mode 100644 index 8990eea..0000000 --- a/include/NvFBC.h +++ /dev/null @@ -1,2006 +0,0 @@ -/*! - * \file - * - * This file contains the interface constants, structure definitions and - * function prototypes defining the NvFBC API for Linux. - * - * Copyright (c) 2013-2020, NVIDIA CORPORATION. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -#ifndef _NVFBC_H_ -#define _NVFBC_H_ - -#include <stdint.h> - -/*! - * \mainpage NVIDIA Framebuffer Capture (NvFBC) for Linux. - * - * NvFBC is a high performance, low latency API to capture the framebuffer of - * an X server screen. - * - * The output from NvFBC captures everything that would be visible if we were - * directly looking at the monitor. This includes window manager decoration, - * mouse cursor, overlay, etc. - * - * It is ideally suited to desktop or fullscreen application capture and - * remoting. - */ - -/*! - * \defgroup FBC_REQ Requirements - * - * The following requirements are provided by the regular NVIDIA Display Driver - * package: - * - * - OpenGL core >= 4.2: - * Required. NvFBC relies on OpenGL to perform frame capture and - * post-processing. - * - * - Vulkan 1.1: - * Required. - * - * - libcuda.so.1 >= 5.5: - * Optional. Used for capture to video memory with CUDA interop. - * - * The following requirements must be installed separately depending on the - * Linux distribution being used: - * - * - XRandR extension >= 1.2: - * Optional. Used for RandR output tracking. - * - * - libX11-xcb.so.1 >= 1.2: - * Required. NvFBC uses a mix of Xlib and XCB. Xlib is needed to use GLX, - * XCB is needed to make NvFBC more resilient against X server terminations - * while a capture session is active. - * - * - libxcb.so.1 >= 1.3: - * Required. See above. - * - * - xorg-server >= 1.3: - * Optional. Required for push model to work properly. - * - * Note that all optional dependencies are dlopen()'d at runtime. Failure to - * load an optional library is not fatal. - */ - -/*! - * \defgroup FBC_CHANGES ChangeLog - * - * NvFBC Linux API version 0.1 - * - Initial BETA release. - * - * NvFBC Linux API version 0.2 - * - Added 'bEnableMSE' field to NVFBC_H264_HW_ENC_CONFIG. - * - Added 'dwMSE' field to NVFBC_TOH264_GRAB_FRAME_PARAMS. - * - Added 'bEnableAQ' field to NVFBC_H264_HW_ENC_CONFIG. - * - Added 'NVFBC_H264_PRESET_LOSSLESS_HP' enum to NVFBC_H264_PRESET. - * - Added 'NVFBC_BUFFER_FORMAT_YUV444P' enum to NVFBC_BUFFER_FORMAT. - * - Added 'eInputBufferFormat' field to NVFBC_H264_HW_ENC_CONFIG. - * - Added '0' and '244' values for NVFBC_H264_HW_ENC_CONFIG::dwProfile. - * - * NvFBC Linux API version 0.3 - * - Improved multi-threaded support by implementing an API locking mechanism. - * - Added 'nvFBCBindContext' API entry point. - * - Added 'nvFBCReleaseContext' API entry point. - * - * NvFBC Linux API version 1.0 - * - Added codec agnostic interface for HW encoding. - * - Deprecated H.264 interface. - * - Added support for H.265/HEVC HW encoding. - * - * NvFBC Linux API version 1.1 - * - Added 'nvFBCToHwGetCaps' API entry point. - * - Added 'dwDiffMapScalingFactor' field to NVFBC_TOSYS_SETUP_PARAMS. - * - * NvFBC Linux API version 1.2 - * - Deprecated ToHwEnc interface. - * - Added ToGL interface that captures frames to an OpenGL texture in video - * memory. - * - Added 'bDisableAutoModesetRecovery' field to - * NVFBC_CREATE_CAPTURE_SESSION_PARAMS. - * - Added 'bExternallyManagedContext' field to NVFBC_CREATE_HANDLE_PARAMS. - * - * NvFBC Linux API version 1.3 - * - Added NVFBC_BUFFER_FORMAT_RGBA - * - Added 'dwTimeoutMs' field to NVFBC_TOSYS_GRAB_FRAME_PARAMS, - * NVFBC_TOCUDA_GRAB_FRAME_PARAMS, and NVFBC_TOGL_GRAB_FRAME_PARAMS. - * - * NvFBC Linux API version 1.4 - * - Clarified that NVFBC_BUFFER_FORMAT_{ARGB,RGB,RGBA} are byte-order formats. - * - Renamed NVFBC_BUFFER_FORMAT_YUV420P to NVFBC_BUFFER_FORMAT_NV12. - * - Added new requirements. - * - Made NvFBC more resilient against the X server terminating during an active - * capture session. See new comments for ::NVFBC_ERR_X. - * - Relaxed requirement that 'frameSize' must have a width being a multiple of - * 4 and a height being a multiple of 2. - * - Added 'bRoundFrameSize' field to NVFBC_CREATE_CAPTURE_SESSION_PARAMS. - * - Relaxed requirement that the scaling factor for differential maps must be - * a multiple of the size of the frame. - * - Added 'diffMapSize' field to NVFBC_TOSYS_SETUP_PARAMS and - * NVFBC_TOGL_SETUP_PARAMS. - * - * NvFBC Linux API version 1.5 - * - Added NVFBC_BUFFER_FORMAT_BGRA - * - * NvFBC Linux API version 1.6 - * - Added the 'NVFBC_TOSYS_GRAB_FLAGS_NOWAIT_IF_NEW_FRAME_READY', - * 'NVFBC_TOCUDA_GRAB_FLAGS_NOWAIT_IF_NEW_FRAME_READY', and - * 'NVFBC_TOGL_GRAB_FLAGS_NOWAIT_IF_NEW_FRAME_READY' capture flags. - * - Exposed debug and performance logs through the NVFBC_LOG_LEVEL environment - * variable. Setting it to "1" enables performance logs, setting it to "2" - * enables debugging logs, setting it to "3" enables both. - * - Logs are printed to stdout or to the file pointed by the NVFBC_LOG_FILE - * environment variable. - * - Added 'ulTimestampUs' to NVFBC_FRAME_GRAB_INFO. - * - Added 'dwSamplingRateMs' to NVFBC_CREATE_CAPTURE_SESSION_PARAMS. - * - Added 'bPushModel' to NVFBC_CREATE_CAPTURE_SESSION_PARAMS. - * - * NvFBC Linux API version 1.7 - * - Retired the NVFBC_CAPTURE_TO_HW_ENCODER interface. - * This interface has been deprecated since NvFBC 1.2 and has received no - * updates or new features since. We recommend using the NVIDIA Video Codec - * SDK to encode NvFBC frames. - * See: https://developer.nvidia.com/nvidia-video-codec-sdk - * - Added a 'Capture Modes' section to those headers. - * - Added a 'Post Processing' section to those headers. - * - Added an 'Environment Variables' section to those headers. - * - Added 'bInModeset' to NVFBC_GET_STATUS_PARAMS. - * - Added 'bAllowDirectCapture' to NVFBC_CREATE_CAPTURE_SESSION_PARAMS. - * - Added 'bDirectCaptured' to NVFBC_FRAME_GRAB_INFO. - * - Added 'bRequiredPostProcessing' to NVFBC_FRAME_GRAB_INFO. - */ - -/*! - * \defgroup FBC_MODES Capture Modes - * - * When creating a capture session, NvFBC instantiates a capture subsystem - * living in the NVIDIA X driver. - * - * This subsystem listens for damage events coming from applications then - * generates (composites) frames for NvFBC when new content is available. - * - * This capture server can operate on a timer where it periodically checks if - * there are any pending damage events, or it can generate frames as soon as it - * receives a new damage event. - * See NVFBC_CREATE_CAPTURE_SESSION_PARAMS::dwSamplingRateMs, - * and NVFBC_CREATE_CAPTURE_SESSION_PARAMS::bPushModel. - * - * NvFBC can also attach itself to a fullscreen unoccluded application and have - * it copy its frames directly into a buffer owned by NvFBC upon present. This - * mode bypasses the X server. - * See NVFBC_CREATE_CAPTURE_SESSION_PARAMS::bAllowDirectCapture. - * - * NvFBC is designed to capture frames with as few copies as possible. The - * NVIDIA X driver composites frames directly into the NvFBC buffers, and - * direct capture copies frames directly into these buffers as well. - * - * Depending on the configuration of a capture session, an extra copy (rendering - * pass) may be needed. See the 'Post Processing' section. - */ - -/*! - * \defgroup FBC_PP Post Processing - * - * Depending on the configuration of a capture session, NvFBC might require to - * do post processing on frames. - * - * Post processing is required for the following reasons: - * - NvFBC needs to do a pixel format conversion. - * - Diffmaps are requested. - * - Capture to system memory is requested. - * - * NvFBC needs to do a conversion if the requested pixel format does not match - * the native format. The native format is NVFBC_BUFFER_FORMAT_BGRA. - * - * Note: post processing is *not* required for frame scaling and frame cropping. - * - * Skipping post processing can reduce capture latency. An application can know - * whether post processing was required by checking - * NVFBC_FRAME_GRAB_INFO::bRequiredPostProcessing. - */ - -/*! - * \defgroup FBC_ENVVAR Environment Variables - * - * Below are the environment variables supported by NvFBC: - * - * - NVFBC_LOG_LEVEL - * Bitfield where the first bit enables debug logs and the second bit enables - * performance logs. Both can be enabled by setting this envvar to 3. - * - * - NVFBC_LOG_FILE - * Write all NvFBC logs to the given file. - * - * - NVFBC_FORCE_ALLOW_DIRECT_CAPTURE - * Used to override NVFBC_CREATE_CAPTURE_SESSION_PARAMS::bAllowDirectCapture. - * - * - NVFBC_FORCE_POST_PROCESSING - * Used to force the post processing step, even if it could be skipped. - * See the 'Post Processing' section. - */ - -/*! - * \defgroup FBC_STRUCT Structure Definition - * - * @{ - */ - -#ifdef __cplusplus -extern "C" { -#endif - -/*! - * Calling convention. - */ -#define NVFBCAPI - -/*! - * NvFBC API major version. - */ -#define NVFBC_VERSION_MAJOR 1 - -/*! - * NvFBC API minor version. - */ -#define NVFBC_VERSION_MINOR 7 - -/*! - * NvFBC API version. - */ -#define NVFBC_VERSION (uint32_t) (NVFBC_VERSION_MINOR | (NVFBC_VERSION_MAJOR << 8)) - -/*! - * Creates a version number for structure parameters. - */ -#define NVFBC_STRUCT_VERSION(typeName, ver) \ - (uint32_t) (sizeof(typeName) | ((ver) << 16) | (NVFBC_VERSION << 24)) - -/*! - * Defines error codes. - * - * \see NvFBCGetLastErrorStr - */ -typedef enum _NVFBCSTATUS -{ - /*! - * This indicates that the API call returned with no errors. - */ - NVFBC_SUCCESS = 0, - /*! - * This indicates that the API version between the client and the library - * is not compatible. - */ - NVFBC_ERR_API_VERSION = 1, - /*! - * An internal error occurred. - */ - NVFBC_ERR_INTERNAL = 2, - /*! - * This indicates that one or more of the parameter passed to the API call - * is invalid. - */ - NVFBC_ERR_INVALID_PARAM = 3, - /*! - * This indicates that one or more of the pointers passed to the API call - * is invalid. - */ - NVFBC_ERR_INVALID_PTR = 4, - /*! - * This indicates that the handle passed to the API call to identify the - * client is invalid. - */ - NVFBC_ERR_INVALID_HANDLE = 5, - /*! - * This indicates that the maximum number of threaded clients of the same - * process has been reached. The limit is 10 threads per process. - * There is no limit on the number of process. - */ - NVFBC_ERR_MAX_CLIENTS = 6, - /*! - * This indicates that the requested feature is not currently supported - * by the library. - */ - NVFBC_ERR_UNSUPPORTED = 7, - /*! - * This indicates that the API call failed because it was unable to allocate - * enough memory to perform the requested operation. - */ - NVFBC_ERR_OUT_OF_MEMORY = 8, - /*! - * This indicates that the API call was not expected. This happens when - * API calls are performed in a wrong order, such as trying to capture - * a frame prior to creating a new capture session; or trying to set up - * a capture to video memory although a capture session to system memory - * was created. - */ - NVFBC_ERR_BAD_REQUEST = 9, - /*! - * This indicates an X error, most likely meaning that the X server has - * been terminated. When this error is returned, the only resort is to - * create another FBC handle using NvFBCCreateHandle(). - * - * The previous handle should still be freed with NvFBCDestroyHandle(), but - * it might leak resources, in particular X, GLX, and GL resources since - * it is no longer possible to communicate with an X server to free them - * through the driver. - * - * The best course of action to eliminate this potential leak is to close - * the OpenGL driver, close the forked process running the capture, or - * restart the application. - */ - NVFBC_ERR_X = 10, - /*! - * This indicates a GLX error. - */ - NVFBC_ERR_GLX = 11, - /*! - * This indicates an OpenGL error. - */ - NVFBC_ERR_GL = 12, - /*! - * This indicates a CUDA error. - */ - NVFBC_ERR_CUDA = 13, - /*! - * This indicates a HW encoder error. - */ - NVFBC_ERR_ENCODER = 14, - /*! - * This indicates an NvFBC context error. - */ - NVFBC_ERR_CONTEXT = 15, - /*! - * This indicates that the application must recreate the capture session. - * - * This error can be returned if a modeset event occurred while capturing - * frames, and NVFBC_CREATE_HANDLE_PARAMS::bDisableAutoModesetRecovery - * was set to NVFBC_TRUE. - */ - NVFBC_ERR_MUST_RECREATE = 16, - /*! - * This indicates a Vulkan error. - */ - NVFBC_ERR_VULKAN = 17, -} NVFBCSTATUS; - -/*! - * Defines boolean values. - */ -typedef enum _NVFBC_BOOL -{ - /*! - * False value. - */ - NVFBC_FALSE = 0, - /*! - * True value. - */ - NVFBC_TRUE, -} NVFBC_BOOL; - -/*! - * Maximum size in bytes of an error string. - */ -#define NVFBC_ERR_STR_LEN 512 - -/*! - * Capture type. - */ -typedef enum _NVFBC_CAPTURE_TYPE -{ - /*! - * Capture frames to a buffer in system memory. - */ - NVFBC_CAPTURE_TO_SYS = 0, - /*! - * Capture frames to a CUDA device in video memory. - * - * Specifying this will dlopen() libcuda.so.1 and fail if not available. - */ - NVFBC_CAPTURE_SHARED_CUDA, - /*! - * Retired. Do not use. - */ - /* NVFBC_CAPTURE_TO_HW_ENCODER, */ - /*! - * Capture frames to an OpenGL buffer in video memory. - */ - NVFBC_CAPTURE_TO_GL = 3, -} NVFBC_CAPTURE_TYPE; - -/*! - * Tracking type. - * - * NvFBC can track a specific region of the framebuffer to capture. - * - * An X screen corresponds to the entire framebuffer. - * - * An RandR CRTC is a component of the GPU that reads pixels from a region of - * the X screen and sends them through a pipeline to an RandR output. - * A physical monitor can be connected to an RandR output. Tracking an RandR - * output captures the region of the X screen that the RandR CRTC is sending to - * the RandR output. - */ -typedef enum -{ - /*! - * By default, NvFBC tries to track a connected primary output. If none is - * found, then it tries to track the first connected output. If none is - * found then it tracks the entire X screen. - * - * If the XRandR extension is not available, this option has the same effect - * as ::NVFBC_TRACKING_SCREEN. - * - * This default behavior might be subject to changes in the future. - */ - NVFBC_TRACKING_DEFAULT = 0, - /*! - * Track an RandR output specified by its ID in the appropriate field. - * - * The list of connected outputs can be queried via NvFBCGetStatus(). - * This list can also be obtained using e.g., xrandr(1). - * - * If the XRandR extension is not available, setting this option returns an - * error. - */ - NVFBC_TRACKING_OUTPUT, - /*! - * Track the entire X screen. - */ - NVFBC_TRACKING_SCREEN, -} NVFBC_TRACKING_TYPE; - -/*! - * Buffer format. - */ -typedef enum _NVFBC_BUFFER_FORMAT -{ - /*! - * Data will be converted to ARGB8888 byte-order format. 32 bpp. - */ - NVFBC_BUFFER_FORMAT_ARGB = 0, - /*! - * Data will be converted to RGB888 byte-order format. 24 bpp. - */ - NVFBC_BUFFER_FORMAT_RGB, - /*! - * Data will be converted to NV12 format using HDTV weights - * according to ITU-R BT.709. 12 bpp. - */ - NVFBC_BUFFER_FORMAT_NV12, - /*! - * Data will be converted to YUV 444 planar format using HDTV weights - * according to ITU-R BT.709. 24 bpp - */ - NVFBC_BUFFER_FORMAT_YUV444P, - /*! - * Data will be converted to RGBA8888 byte-order format. 32 bpp. - */ - NVFBC_BUFFER_FORMAT_RGBA, - /*! - * Native format. No pixel conversion needed. - * BGRA8888 byte-order format. 32 bpp. - */ - NVFBC_BUFFER_FORMAT_BGRA, -} NVFBC_BUFFER_FORMAT; - -#define NVFBC_BUFFER_FORMAT_YUV420P NVFBC_BUFFER_FORMAT_NV12 - -/*! - * Handle used to identify an NvFBC session. - */ -typedef uint64_t NVFBC_SESSION_HANDLE; - -/*! - * Box used to describe an area of the tracked region to capture. - * - * The coordinates are relative to the tracked region. - * - * E.g., if the size of the X screen is 3520x1200 and the tracked RandR output - * scans a region of 1600x1200+1920+0, then setting a capture box of - * 800x600+100+50 effectively captures a region of 800x600+2020+50 relative to - * the X screen. - */ -typedef struct _NVFBC_BOX -{ - /*! - * [in] X offset of the box. - */ - uint32_t x; - /*! - * [in] Y offset of the box. - */ - uint32_t y; - /*! - * [in] Width of the box. - */ - uint32_t w; - /*! - * [in] Height of the box. - */ - uint32_t h; -} NVFBC_BOX; - -/*! - * Size used to describe the size of a frame. - */ -typedef struct _NVFBC_SIZE -{ - /*! - * [in] Width. - */ - uint32_t w; - /*! - * [in] Height. - */ - uint32_t h; -} NVFBC_SIZE; - -/*! - * Describes information about a captured frame. - */ -typedef struct _NVFBC_FRAME_GRAB_INFO -{ - /*! - * [out] Width of the captured frame. - */ - uint32_t dwWidth; - /*! - * [out] Height of the captured frame. - */ - uint32_t dwHeight; - /*! - * [out] Size of the frame in bytes. - */ - uint32_t dwByteSize; - /*! - * [out] Incremental ID of the current frame. - * - * This can be used to identify a frame. - */ - uint32_t dwCurrentFrame; - /*! - * [out] Whether the captured frame is a new frame. - * - * When using non blocking calls it is possible to capture a frame - * that was already captured before if the display server did not - * render a new frame in the meantime. In that case, this flag - * will be set to NVFBC_FALSE. - * - * When using blocking calls each captured frame will have - * this flag set to NVFBC_TRUE since the blocking mechanism waits for - * the display server to render a new frame. - * - * Note that this flag does not guarantee that the content of - * the frame will be different compared to the previous captured frame. - * - * In particular, some compositing managers report the entire - * framebuffer as damaged when an application refreshes its content. - * - * Consider a single X screen spanned across physical displays A and B - * and an NvFBC application tracking display A. Depending on the - * compositing manager, it is possible that an application refreshing - * itself on display B will trigger a frame capture on display A. - * - * Workarounds include: - * - Using separate X screens - * - Disabling the composite extension - * - Using a compositing manager that properly reports what regions - * are damaged - * - Using NvFBC's diffmaps to find out if the frame changed - */ - NVFBC_BOOL bIsNewFrame; - /*! - * [out] Frame timestamp - * - * Time in micro seconds when the display server started rendering the - * frame. - * - * This does not account for when the frame was captured. If capturing an - * old frame (e.g., bIsNewFrame is NVFBC_FALSE) the reported timestamp - * will reflect the time when the old frame was rendered by the display - * server. - */ - uint64_t ulTimestampUs; - /* - * [out] Number of frames generated since the last capture. - * - * This can help applications tell whether they missed frames or there - * were no frames generated by the server since the last capture. - */ - uint32_t dwMissedFrames; - /* - * [out] Whether the captured frame required post processing. - * - * See the 'Post Processing' section. - */ - NVFBC_BOOL bRequiredPostProcessing; - /* - * [out] Whether this frame was obtained via direct capture. - * - * See NVFBC_CREATE_CAPTURE_SESSION_PARAMS::bAllowDirectCapture. - */ - NVFBC_BOOL bDirectCapture; -} NVFBC_FRAME_GRAB_INFO; - -/*! - * Defines parameters for the CreateHandle() API call. - */ -typedef struct _NVFBC_CREATE_HANDLE_PARAMS -{ - /*! - * [in] Must be set to NVFBC_CREATE_HANDLE_PARAMS_VER - */ - uint32_t dwVersion; - /*! - * [in] Application specific private information passed to the NvFBC - * session. - */ - const void *privateData; - /*! - * [in] Size of the application specific private information passed to the - * NvFBC session. - */ - uint32_t privateDataSize; - /*! - * [in] Whether NvFBC should not create and manage its own graphics context - * - * NvFBC internally uses OpenGL to perfom graphics operations on the - * captured frames. By default, NvFBC will create and manage (e.g., make - * current, detect new threads, etc.) its own OpenGL context. - * - * If set to NVFBC_TRUE, NvFBC will use the application's context. It will - * be the application's responsibility to make sure that a context is - * current on the thread calling into the NvFBC API. - */ - NVFBC_BOOL bExternallyManagedContext; - /*! - * [in] GLX context - * - * GLX context that NvFBC should use internally to create pixmaps and - * make them current when creating a new capture session. - * - * Note: NvFBC expects a context created against a GLX_RGBA_TYPE render - * type. - */ - void *glxCtx; - /*! - * [in] GLX framebuffer configuration - * - * Framebuffer configuration that was used to create the GLX context, and - * that will be used to create pixmaps internally. - * - * Note: NvFBC expects a configuration having at least the following - * attributes: - * GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT - * GLX_BIND_TO_TEXTURE_RGBA_EXT, 1 - * GLX_BIND_TO_TEXTURE_TARGETS_EXT, GLX_TEXTURE_2D_BIT_EXT - */ - void *glxFBConfig; -} NVFBC_CREATE_HANDLE_PARAMS; - -/*! - * NVFBC_CREATE_HANDLE_PARAMS structure version. - */ -#define NVFBC_CREATE_HANDLE_PARAMS_VER NVFBC_STRUCT_VERSION(NVFBC_CREATE_HANDLE_PARAMS, 2) - -/*! - * Defines parameters for the ::NvFBCDestroyHandle() API call. - */ -typedef struct _NVFBC_DESTROY_HANDLE_PARAMS -{ - /*! - * [in] Must be set to NVFBC_DESTROY_HANDLE_PARAMS_VER - */ - uint32_t dwVersion; -} NVFBC_DESTROY_HANDLE_PARAMS; - -/*! - * NVFBC_DESTROY_HANDLE_PARAMS structure version. - */ -#define NVFBC_DESTROY_HANDLE_PARAMS_VER NVFBC_STRUCT_VERSION(NVFBC_DESTROY_HANDLE_PARAMS, 1) - -/*! - * Maximum number of connected RandR outputs to an X screen. - */ -#define NVFBC_OUTPUT_MAX 5 - -/*! - * Maximum size in bytes of an RandR output name. - */ -#define NVFBC_OUTPUT_NAME_LEN 128 - -/*! - * Describes an RandR output. - * - * Filling this structure relies on the XRandR extension. This feature cannot - * be used if the extension is missing or its version is below the requirements. - * - * \see Requirements - */ -typedef struct _NVFBC_OUTPUT -{ - /*! - * Identifier of the RandR output. - */ - uint32_t dwId; - /*! - * Name of the RandR output, as reported by tools such as xrandr(1). - * - * Example: "DVI-I-0" - */ - char name[NVFBC_OUTPUT_NAME_LEN]; - /*! - * Region of the X screen tracked by the RandR CRTC driving this RandR - * output. - */ - NVFBC_BOX trackedBox; -} NVFBC_RANDR_OUTPUT_INFO; - -/*! - * Defines parameters for the ::NvFBCGetStatus() API call. - */ -typedef struct _NVFBC_GET_STATUS_PARAMS -{ - /*! - * [in] Must be set to NVFBC_GET_STATUS_PARAMS_VER - */ - uint32_t dwVersion; - /*! - * [out] Whether or not framebuffer capture is supported by the graphics - * driver. - */ - NVFBC_BOOL bIsCapturePossible; - /*! - * [out] Whether or not there is already a capture session on this system. - */ - NVFBC_BOOL bCurrentlyCapturing; - /*! - * [out] Whether or not it is possible to create a capture session on this - * system. - */ - NVFBC_BOOL bCanCreateNow; - /*! - * [out] Size of the X screen (framebuffer). - */ - NVFBC_SIZE screenSize; - /*! - * [out] Whether the XRandR extension is available. - * - * If this extension is not available then it is not possible to have - * information about RandR outputs. - */ - NVFBC_BOOL bXRandRAvailable; - /*! - * [out] Array of outputs connected to the X screen. - * - * An application can track a specific output by specifying its ID when - * creating a capture session. - * - * Only if XRandR is available. - */ - NVFBC_RANDR_OUTPUT_INFO outputs[NVFBC_OUTPUT_MAX]; - /*! - * [out] Number of outputs connected to the X screen. - * - * This must be used to parse the array of connected outputs. - * - * Only if XRandR is available. - */ - uint32_t dwOutputNum; - /*! - * [out] Version of the NvFBC library running on this system. - */ - uint32_t dwNvFBCVersion; - /*! - * [out] Whether the X server is currently in modeset. - * - * When the X server is in modeset, it must give up all its video - * memory allocations. It is not possible to create a capture - * session until the modeset is over. - * - * Note that VT-switches are considered modesets. - */ - NVFBC_BOOL bInModeset; -} NVFBC_GET_STATUS_PARAMS; - -/*! - * NVFBC_GET_STATUS_PARAMS structure version. - */ -#define NVFBC_GET_STATUS_PARAMS_VER NVFBC_STRUCT_VERSION(NVFBC_GET_STATUS_PARAMS, 2) - -/*! - * Defines parameters for the ::NvFBCCreateCaptureSession() API call. - */ -typedef struct _NVFBC_CREATE_CAPTURE_SESSION_PARAMS -{ - /*! - * [in] Must be set to NVFBC_CREATE_CAPTURE_SESSION_PARAMS_VER - */ - uint32_t dwVersion; - /*! - * [in] Desired capture type. - * - * Note that when specyfing ::NVFBC_CAPTURE_SHARED_CUDA NvFBC will try to - * dlopen() the corresponding libraries. This means that NvFBC can run on - * a system without the CUDA library since it does not link against them. - */ - NVFBC_CAPTURE_TYPE eCaptureType; - /*! - * [in] What region of the framebuffer should be tracked. - */ - NVFBC_TRACKING_TYPE eTrackingType; - /*! - * [in] ID of the output to track if eTrackingType is set to - * ::NVFBC_TRACKING_OUTPUT. - */ - uint32_t dwOutputId; - /*! - * [in] Crop the tracked region. - * - * The coordinates are relative to the tracked region. - * - * It can be set to 0 to capture the entire tracked region. - */ - NVFBC_BOX captureBox; - /*! - * [in] Desired size of the captured frame. - * - * This parameter allow to scale the captured frame. - * - * It can be set to 0 to disable frame resizing. - */ - NVFBC_SIZE frameSize; - /*! - * [in] Whether the mouse cursor should be composited to the frame. - * - * Disabling the cursor will not generate new frames when only the cursor - * is moved. - */ - NVFBC_BOOL bWithCursor; - /*! - * [in] Whether NvFBC should not attempt to recover from modesets. - * - * NvFBC is able to detect when a modeset event occured and can automatically - * re-create a capture session with the same settings as before, then resume - * its frame capture session transparently. - * - * This option allows to disable this behavior. NVFBC_ERR_MUST_RECREATE - * will be returned in that case. - * - * It can be useful in the cases when an application needs to do some work - * between setting up a capture and grabbing the first frame. - * - * For example: an application using the ToGL interface needs to register - * resources with EncodeAPI prior to encoding frames. - * - * Note that during modeset recovery, NvFBC will try to re-create the - * capture session every second until it succeeds. - */ - NVFBC_BOOL bDisableAutoModesetRecovery; - /*! - * [in] Whether NvFBC should round the requested frameSize. - * - * When disabled, NvFBC will not attempt to round the requested resolution. - * - * However, some pixel formats have resolution requirements. E.g., YUV/NV - * formats must have a width being a multiple of 4, and a height being a - * multiple of 2. RGB formats don't have such requirements. - * - * If the resolution doesn't meet the requirements of the format, then NvFBC - * will fail at setup time. - * - * When enabled, NvFBC will round the requested width to the next multiple - * of 4 and the requested height to the next multiple of 2. - * - * In this case, requesting any resolution will always work with every - * format. However, an NvFBC client must be prepared to handle the case - * where the requested resolution is different than the captured resolution. - * - * NVFBC_FRAME_GRAB_INFO::dwWidth and NVFBC_FRAME_GRAB_INFO::dwHeight should - * always be used for getting information about captured frames. - */ - NVFBC_BOOL bRoundFrameSize; - /*! - * [in] Rate in ms at which the display server generates new frames - * - * This controls the frequency at which the display server will generate - * new frames if new content is available. This effectively controls the - * capture rate when using blocking calls. - * - * Note that lower values will increase the CPU and GPU loads. - * - * The default value is 16ms (~ 60 Hz). - */ - uint32_t dwSamplingRateMs; - /*! - * [in] Enable push model for frame capture - * - * When set to NVFBC_TRUE, the display server will generate frames whenever - * it receives a damage event from applications. - * - * Setting this to NVFBC_TRUE will ignore ::dwSamplingRateMs. - * - * Using push model with the NVFBC_*_GRAB_FLAGS_NOWAIT_IF_NEW_FRAME_READY - * capture flag should guarantee the shortest amount of time between an - * application rendering a frame and an NvFBC client capturing it, provided - * that the NvFBC client is able to process the frames quickly enough. - * - * Note that applications running at high frame rates will increase CPU and - * GPU loads. - */ - NVFBC_BOOL bPushModel; - /*! - * [in] Allow direct capture - * - * Direct capture allows NvFBC to attach itself to a fullscreen graphics - * application. Whenever that application presents a frame, it makes a copy - * of it directly into a buffer owned by NvFBC thus bypassing the X server. - * - * When direct capture is *not* enabled, the NVIDIA X driver generates a - * frame for NvFBC when it receives a damage event from an application if push - * model is enabled, or periodically checks if there are any pending damage - * events otherwise (see NVFBC_CREATE_CAPTURE_SESSION_PARAMS::dwSamplingRateMs). - * - * Direct capture is possible under the following conditions: - * - Direct capture is allowed - * - Push model is enabled (see NVFBC_CREATE_CAPTURE_SESSION_PARAMS::bPushModel) - * - The mouse cursor is not composited (see NVFBC_CREATE_CAPTURE_SESSION_PARAMS::bWithCursor) - * - No viewport transformation is required. This happens when the remote - * desktop is e.g. rotated. - * - * When direct capture is possible, NvFBC will automatically attach itself - * to a fullscreen unoccluded application, if such exists. - * - * Notes: - * - This includes compositing desktops such as GNOME (e.g., gnome-shell - * is the fullscreen unoccluded application). - * - There can be only one fullscreen unoccluded application at a time. - * - The NVIDIA X driver monitors which application qualifies or no - * longer qualifies. - * - * For example, if a fullscreen application is launched in GNOME, NvFBC will - * detach from gnome-shell and attach to that application. - * - * Attaching and detaching happens automatically from the perspective of an - * NvFBC client. When detaching from an application, the X driver will - * transparently resume generating frames for NvFBC. - * - * An application can know whether a given frame was obtained through - * direct capture by checking NVFBC_FRAME_GRAB_INFO::bDirectCapture. - */ - NVFBC_BOOL bAllowDirectCapture; -} NVFBC_CREATE_CAPTURE_SESSION_PARAMS; - -/*! - * NVFBC_CREATE_CAPTURE_SESSION_PARAMS structure version. - */ -#define NVFBC_CREATE_CAPTURE_SESSION_PARAMS_VER NVFBC_STRUCT_VERSION(NVFBC_CREATE_CAPTURE_SESSION_PARAMS, 6) - -/*! - * Defines parameters for the ::NvFBCDestroyCaptureSession() API call. - */ -typedef struct _NVFBC_DESTROY_CAPTURE_SESSION_PARAMS -{ - /*! - * [in] Must be set to NVFBC_DESTROY_CAPTURE_SESSION_PARAMS_VER - */ - uint32_t dwVersion; -} NVFBC_DESTROY_CAPTURE_SESSION_PARAMS; - -/*! - * NVFBC_DESTROY_CAPTURE_SESSION_PARAMS structure version. - */ -#define NVFBC_DESTROY_CAPTURE_SESSION_PARAMS_VER NVFBC_STRUCT_VERSION(NVFBC_DESTROY_CAPTURE_SESSION_PARAMS, 1) - -/*! - * Defines parameters for the ::NvFBCBindContext() API call. - */ -typedef struct _NVFBC_BIND_CONTEXT_PARAMS -{ - /*! - * [in] Must be set to NVFBC_BIND_CONTEXT_PARAMS_VER - */ - uint32_t dwVersion; -} NVFBC_BIND_CONTEXT_PARAMS; - -/*! - * NVFBC_BIND_CONTEXT_PARAMS structure version. - */ -#define NVFBC_BIND_CONTEXT_PARAMS_VER NVFBC_STRUCT_VERSION(NVFBC_BIND_CONTEXT_PARAMS, 1) - -/*! - * Defines parameters for the ::NvFBCReleaseContext() API call. - */ -typedef struct _NVFBC_RELEASE_CONTEXT_PARAMS -{ - /*! - * [in] Must be set to NVFBC_RELEASE_CONTEXT_PARAMS_VER - */ - uint32_t dwVersion; -} NVFBC_RELEASE_CONTEXT_PARAMS; - -/*! - * NVFBC_RELEASE_CONTEXT_PARAMS structure version. - */ -#define NVFBC_RELEASE_CONTEXT_PARAMS_VER NVFBC_STRUCT_VERSION(NVFBC_RELEASE_CONTEXT_PARAMS, 1) - -/*! - * Defines flags that can be used when capturing to system memory. - */ -typedef enum -{ - /*! - * Default, capturing waits for a new frame or mouse move. - * - * The default behavior of blocking grabs is to wait for a new frame until - * after the call was made. But it's possible that there is a frame already - * ready that the client hasn't seen. - * \see NVFBC_TOSYS_GRAB_FLAGS_NOWAIT_IF_NEW_FRAME_READY - */ - NVFBC_TOSYS_GRAB_FLAGS_NOFLAGS = 0, - /*! - * Capturing does not wait for a new frame nor a mouse move. - * - * It is therefore possible to capture the same frame multiple times. - * When this occurs, the dwCurrentFrame parameter of the - * NVFBC_FRAME_GRAB_INFO structure is not incremented. - */ - NVFBC_TOSYS_GRAB_FLAGS_NOWAIT = (1 << 0), - /*! - * Forces the destination buffer to be refreshed even if the frame has not - * changed since previous capture. - * - * By default, if the captured frame is identical to the previous one, NvFBC - * will omit one copy and not update the destination buffer. - * - * Setting that flag will prevent this behavior. This can be useful e.g., - * if the application has modified the buffer in the meantime. - */ - NVFBC_TOSYS_GRAB_FLAGS_FORCE_REFRESH = (1 << 1), - /*! - * Similar to NVFBC_TOSYS_GRAB_FLAGS_NOFLAGS, except that the capture will - * not wait if there is already a frame available that the client has - * never seen yet. - */ - NVFBC_TOSYS_GRAB_FLAGS_NOWAIT_IF_NEW_FRAME_READY = (1 << 2), -} NVFBC_TOSYS_GRAB_FLAGS; - -/*! - * Defines parameters for the ::NvFBCToSysSetUp() API call. - */ -typedef struct _NVFBC_TOSYS_SETUP_PARAMS -{ - /*! - * [in] Must be set to NVFBC_TOSYS_SETUP_PARAMS_VER - */ - uint32_t dwVersion; - /*! - * [in] Desired buffer format. - */ - NVFBC_BUFFER_FORMAT eBufferFormat; - /*! - * [out] Pointer to a pointer to a buffer in system memory. - * - * This buffer contains the pixel value of the requested format. Refer to - * the description of the buffer formats to understand the memory layout. - * - * The application does not need to allocate memory for this buffer. It - * should not free this buffer either. This buffer is automatically - * re-allocated when needed (e.g., when the resolution changes). - * - * This buffer is allocated by the NvFBC library to the proper size. This - * size is returned in the dwByteSize field of the - * ::NVFBC_FRAME_GRAB_INFO structure. - */ - void **ppBuffer; - /*! - * [in] Whether differential maps should be generated. - */ - NVFBC_BOOL bWithDiffMap; - /*! - * [out] Pointer to a pointer to a buffer in system memory. - * - * This buffer contains the differential map of two frames. It must be read - * as an array of unsigned char. Each unsigned char is either 0 or - * non-zero. 0 means that the pixel value at the given location has not - * changed since the previous captured frame. Non-zero means that the pixel - * value has changed. - * - * The application does not need to allocate memory for this buffer. It - * should not free this buffer either. This buffer is automatically - * re-allocated when needed (e.g., when the resolution changes). - * - * This buffer is allocated by the NvFBC library to the proper size. The - * size of the differential map is returned in ::diffMapSize. - * - * This option is not compatible with the ::NVFBC_BUFFER_FORMAT_YUV420P and - * ::NVFBC_BUFFER_FORMAT_YUV444P buffer formats. - */ - void **ppDiffMap; - /*! - * [in] Scaling factor of the differential maps. - * - * For example, a scaling factor of 16 means that one pixel of the diffmap - * will represent 16x16 pixels of the original frames. - * - * If any of these 16x16 pixels is different between the current and the - * previous frame, then the corresponding pixel in the diffmap will be set - * to non-zero. - * - * The default scaling factor is 1. A dwDiffMapScalingFactor of 0 will be - * set to 1. - */ - uint32_t dwDiffMapScalingFactor; - /*! - * [out] Size of the differential map. - * - * Only set if bWithDiffMap is set to NVFBC_TRUE. - */ - NVFBC_SIZE diffMapSize; -} NVFBC_TOSYS_SETUP_PARAMS; - -/*! - * NVFBC_TOSYS_SETUP_PARAMS structure version. - */ -#define NVFBC_TOSYS_SETUP_PARAMS_VER NVFBC_STRUCT_VERSION(NVFBC_TOSYS_SETUP_PARAMS, 3) - -/*! - * Defines parameters for the ::NvFBCToSysGrabFrame() API call. - */ -typedef struct _NVFBC_TOSYS_GRAB_FRAME_PARAMS -{ - /*! - * [in] Must be set to NVFBC_TOSYS_GRAB_FRAME_PARAMS_VER - */ - uint32_t dwVersion; - /*! - * [in] Flags defining the behavior of this frame capture. - */ - uint32_t dwFlags; - /*! - * [out] Information about the captured frame. - * - * Can be NULL. - */ - NVFBC_FRAME_GRAB_INFO *pFrameGrabInfo; - /*! - * [in] Wait timeout in milliseconds. - * - * When capturing frames with the NVFBC_TOSYS_GRAB_FLAGS_NOFLAGS or - * NVFBC_TOSYS_GRAB_FLAGS_NOWAIT_IF_NEW_FRAME_READY flags, - * NvFBC will wait for a new frame or mouse move until the below timer - * expires. - * - * When timing out, the last captured frame will be returned. Note that as - * long as the NVFBC_TOSYS_GRAB_FLAGS_FORCE_REFRESH flag is not set, - * returning an old frame will incur no performance penalty. - * - * NvFBC clients can use the return value of the grab frame operation to - * find out whether a new frame was captured, or the timer expired. - * - * Note that the behavior of blocking calls is to wait for a new frame - * *after* the call has been made. When using timeouts, it is possible - * that NvFBC will return a new frame (e.g., it has never been captured - * before) even though no new frame was generated after the grab call. - * - * For the precise definition of what constitutes a new frame, see - * ::bIsNewFrame. - * - * Set to 0 to disable timeouts. - */ - uint32_t dwTimeoutMs; -} NVFBC_TOSYS_GRAB_FRAME_PARAMS; - -/*! - * NVFBC_TOSYS_GRAB_FRAME_PARAMS structure version. - */ -#define NVFBC_TOSYS_GRAB_FRAME_PARAMS_VER NVFBC_STRUCT_VERSION(NVFBC_TOSYS_GRAB_FRAME_PARAMS, 2) - -/*! - * Defines flags that can be used when capturing to a CUDA buffer in video memory. - */ -typedef enum -{ - /*! - * Default, capturing waits for a new frame or mouse move. - * - * The default behavior of blocking grabs is to wait for a new frame until - * after the call was made. But it's possible that there is a frame already - * ready that the client hasn't seen. - * \see NVFBC_TOCUDA_GRAB_FLAGS_NOWAIT_IF_NEW_FRAME_READY - */ - NVFBC_TOCUDA_GRAB_FLAGS_NOFLAGS = 0, - /*! - * Capturing does not wait for a new frame nor a mouse move. - * - * It is therefore possible to capture the same frame multiple times. - * When this occurs, the dwCurrentFrame parameter of the - * NVFBC_FRAME_GRAB_INFO structure is not incremented. - */ - NVFBC_TOCUDA_GRAB_FLAGS_NOWAIT = (1 << 0), - /*! - * [in] Forces the destination buffer to be refreshed even if the frame - * has not changed since previous capture. - * - * By default, if the captured frame is identical to the previous one, NvFBC - * will omit one copy and not update the destination buffer. - * - * Setting that flag will prevent this behavior. This can be useful e.g., - * if the application has modified the buffer in the meantime. - */ - NVFBC_TOCUDA_GRAB_FLAGS_FORCE_REFRESH = (1 << 1), - /*! - * Similar to NVFBC_TOCUDA_GRAB_FLAGS_NOFLAGS, except that the capture will - * not wait if there is already a frame available that the client has - * never seen yet. - */ - NVFBC_TOCUDA_GRAB_FLAGS_NOWAIT_IF_NEW_FRAME_READY = (1 << 2), -} NVFBC_TOCUDA_FLAGS; - -/*! - * Defines parameters for the ::NvFBCToCudaSetUp() API call. - */ -typedef struct _NVFBC_TOCUDA_SETUP_PARAMS -{ - /*! - * [in] Must be set to NVFBC_TOCUDA_SETUP_PARAMS_VER - */ - uint32_t dwVersion; - /*! - * [in] Desired buffer format. - */ - NVFBC_BUFFER_FORMAT eBufferFormat; -} NVFBC_TOCUDA_SETUP_PARAMS; - -/*! - * NVFBC_TOCUDA_SETUP_PARAMS structure version. - */ -#define NVFBC_TOCUDA_SETUP_PARAMS_VER NVFBC_STRUCT_VERSION(NVFBC_TOCUDA_SETUP_PARAMS, 1) - -/*! - * Defines parameters for the ::NvFBCToCudaGrabFrame() API call. - */ -typedef struct _NVFBC_TOCUDA_GRAB_FRAME_PARAMS -{ - /*! - * [in] Must be set to NVFBC_TOCUDA_GRAB_FRAME_PARAMS_VER. - */ - uint32_t dwVersion; - /*! - * [in] Flags defining the behavior of this frame capture. - */ - uint32_t dwFlags; - /*! - * [out] Pointer to a ::CUdeviceptr - * - * The application does not need to allocate memory for this CUDA device. - * - * The application does need to create its own CUDA context to use this - * CUDA device. - * - * This ::CUdeviceptr will be mapped to a segment in video memory containing - * the frame. It is not possible to process a CUDA device while capturing - * a new frame. If the application wants to do so, it must copy the CUDA - * device using ::cuMemcpyDtoD or ::cuMemcpyDtoH beforehand. - */ - void *pCUDADeviceBuffer; - /*! - * [out] Information about the captured frame. - * - * Can be NULL. - */ - NVFBC_FRAME_GRAB_INFO *pFrameGrabInfo; - /*! - * [in] Wait timeout in milliseconds. - * - * When capturing frames with the NVFBC_TOCUDA_GRAB_FLAGS_NOFLAGS or - * NVFBC_TOCUDA_GRAB_FLAGS_NOWAIT_IF_NEW_FRAME_READY flags, - * NvFBC will wait for a new frame or mouse move until the below timer - * expires. - * - * When timing out, the last captured frame will be returned. Note that as - * long as the NVFBC_TOCUDA_GRAB_FLAGS_FORCE_REFRESH flag is not set, - * returning an old frame will incur no performance penalty. - * - * NvFBC clients can use the return value of the grab frame operation to - * find out whether a new frame was captured, or the timer expired. - * - * Note that the behavior of blocking calls is to wait for a new frame - * *after* the call has been made. When using timeouts, it is possible - * that NvFBC will return a new frame (e.g., it has never been captured - * before) even though no new frame was generated after the grab call. - * - * For the precise definition of what constitutes a new frame, see - * ::bIsNewFrame. - * - * Set to 0 to disable timeouts. - */ - uint32_t dwTimeoutMs; -} NVFBC_TOCUDA_GRAB_FRAME_PARAMS; - -/*! - * NVFBC_TOCUDA_GRAB_FRAME_PARAMS structure version. - */ -#define NVFBC_TOCUDA_GRAB_FRAME_PARAMS_VER NVFBC_STRUCT_VERSION(NVFBC_TOCUDA_GRAB_FRAME_PARAMS, 2) - -/*! - * Defines flags that can be used when capturing to an OpenGL buffer in video memory. - */ -typedef enum -{ - /*! - * Default, capturing waits for a new frame or mouse move. - * - * The default behavior of blocking grabs is to wait for a new frame until - * after the call was made. But it's possible that there is a frame already - * ready that the client hasn't seen. - * \see NVFBC_TOGL_GRAB_FLAGS_NOWAIT_IF_NEW_FRAME_READY - */ - NVFBC_TOGL_GRAB_FLAGS_NOFLAGS = 0, - /*! - * Capturing does not wait for a new frame nor a mouse move. - * - * It is therefore possible to capture the same frame multiple times. - * When this occurs, the dwCurrentFrame parameter of the - * NVFBC_FRAME_GRAB_INFO structure is not incremented. - */ - NVFBC_TOGL_GRAB_FLAGS_NOWAIT = (1 << 0), - /*! - * [in] Forces the destination buffer to be refreshed even if the frame - * has not changed since previous capture. - * - * By default, if the captured frame is identical to the previous one, NvFBC - * will omit one copy and not update the destination buffer. - * - * Setting that flag will prevent this behavior. This can be useful e.g., - * if the application has modified the buffer in the meantime. - */ - NVFBC_TOGL_GRAB_FLAGS_FORCE_REFRESH = (1 << 1), - /*! - * Similar to NVFBC_TOGL_GRAB_FLAGS_NOFLAGS, except that the capture will - * not wait if there is already a frame available that the client has - * never seen yet. - */ - NVFBC_TOGL_GRAB_FLAGS_NOWAIT_IF_NEW_FRAME_READY = (1 << 2), -} NVFBC_TOGL_FLAGS; - -/*! - * Maximum number of GL textures that can be used to store frames. - */ -#define NVFBC_TOGL_TEXTURES_MAX 2 - -/*! - * Defines parameters for the ::NvFBCToGLSetUp() API call. - */ -typedef struct _NVFBC_TOGL_SETUP_PARAMS -{ - /*! - * [in] Must be set to NVFBC_TOGL_SETUP_PARAMS_VER - */ - uint32_t dwVersion; - /*! - * [in] Desired buffer format. - */ - NVFBC_BUFFER_FORMAT eBufferFormat; - /*! - * [in] Whether differential maps should be generated. - */ - NVFBC_BOOL bWithDiffMap; - /*! - * [out] Pointer to a pointer to a buffer in system memory. - * - * \see NVFBC_TOSYS_SETUP_PARAMS::ppDiffMap - */ - void **ppDiffMap; - /*! - * [in] Scaling factor of the differential maps. - * - * \see NVFBC_TOSYS_SETUP_PARAMS::dwDiffMapScalingFactor - */ - uint32_t dwDiffMapScalingFactor; - /*! - * [out] List of GL textures that will store the captured frames. - * - * This array is 0 terminated. The number of textures varies depending on - * the capture settings (such as whether diffmaps are enabled). - * - * An application wishing to interop with, for example, EncodeAPI will need - * to register these textures prior to start encoding frames. - * - * After each frame capture, the texture holding the current frame will be - * returned in NVFBC_TOGL_GRAB_FRAME_PARAMS::dwTexture. - */ - uint32_t dwTextures[NVFBC_TOGL_TEXTURES_MAX]; - /*! - * [out] GL target to which the texture should be bound. - */ - uint32_t dwTexTarget; - /*! - * [out] GL format of the textures. - */ - uint32_t dwTexFormat; - /*! - * [out] GL type of the textures. - */ - uint32_t dwTexType; - /*! - * [out] Size of the differential map. - * - * Only set if bWithDiffMap is set to NVFBC_TRUE. - */ - NVFBC_SIZE diffMapSize; -} NVFBC_TOGL_SETUP_PARAMS; - -/*! - * NVFBC_TOGL_SETUP_PARAMS structure version. - */ -#define NVFBC_TOGL_SETUP_PARAMS_VER NVFBC_STRUCT_VERSION(NVFBC_TOGL_SETUP_PARAMS, 2) - -/*! - * Defines parameters for the ::NvFBCToGLGrabFrame() API call. - */ -typedef struct _NVFBC_TOGL_GRAB_FRAME_PARAMS -{ - /*! - * [in] Must be set to NVFBC_TOGL_GRAB_FRAME_PARAMS_VER. - */ - uint32_t dwVersion; - /*! - * [in] Flags defining the behavior of this frame capture. - */ - uint32_t dwFlags; - /*! - * [out] Index of the texture storing the current frame. - * - * This is an index in the NVFBC_TOGL_SETUP_PARAMS::dwTextures array. - */ - uint32_t dwTextureIndex; - /*! - * [out] Information about the captured frame. - * - * Can be NULL. - */ - NVFBC_FRAME_GRAB_INFO *pFrameGrabInfo; - /*! - * [in] Wait timeout in milliseconds. - * - * When capturing frames with the NVFBC_TOGL_GRAB_FLAGS_NOFLAGS or - * NVFBC_TOGL_GRAB_FLAGS_NOWAIT_IF_NEW_FRAME_READY flags, - * NvFBC will wait for a new frame or mouse move until the below timer - * expires. - * - * When timing out, the last captured frame will be returned. Note that as - * long as the NVFBC_TOGL_GRAB_FLAGS_FORCE_REFRESH flag is not set, - * returning an old frame will incur no performance penalty. - * - * NvFBC clients can use the return value of the grab frame operation to - * find out whether a new frame was captured, or the timer expired. - * - * Note that the behavior of blocking calls is to wait for a new frame - * *after* the call has been made. When using timeouts, it is possible - * that NvFBC will return a new frame (e.g., it has never been captured - * before) even though no new frame was generated after the grab call. - * - * For the precise definition of what constitutes a new frame, see - * ::bIsNewFrame. - * - * Set to 0 to disable timeouts. - */ - uint32_t dwTimeoutMs; -} NVFBC_TOGL_GRAB_FRAME_PARAMS; - -/*! - * NVFBC_TOGL_GRAB_FRAME_PARAMS structure version. - */ -#define NVFBC_TOGL_GRAB_FRAME_PARAMS_VER NVFBC_STRUCT_VERSION(NVFBC_TOGL_GRAB_FRAME_PARAMS, 2) - -/*! @} FBC_STRUCT */ - -/*! - * \defgroup FBC_FUNC API Entry Points - * - * Entry points are thread-safe and can be called concurrently. - * - * The locking model includes a global lock that protects session handle - * management (\see NvFBCCreateHandle, \see NvFBCDestroyHandle). - * - * Each NvFBC session uses a local lock to protect other entry points. Note - * that in certain cases, a thread can hold the local lock for an undefined - * amount of time, such as grabbing a frame using a blocking call. - * - * Note that a context is associated with each session. NvFBC clients wishing - * to share a session between different threads are expected to release and - * bind the context appropriately (\see NvFBCBindContext, - * \see NvFBCReleaseContext). This is not required when each thread uses its - * own NvFBC session. - * - * @{ - */ - -/*! - * Gets the last error message that got recorded for a client. - * - * When NvFBC returns an error, it will save an error message that can be - * queried through this API call. Only the last message is saved. - * The message and the return code should give enough information about - * what went wrong. - * - * \param [in] sessionHandle - * Handle to the NvFBC client. - * \return - * A NULL terminated error message, or an empty string. Its maximum length - * is NVFBC_ERROR_STR_LEN. - */ -const char* NVFBCAPI NvFBCGetLastErrorStr(const NVFBC_SESSION_HANDLE sessionHandle); - -/*! - * \brief Allocates a new handle for an NvFBC client. - * - * This function allocates a session handle used to identify an FBC client. - * - * This function implicitly calls NvFBCBindContext(). - * - * \param [out] pSessionHandle - * Pointer that will hold the allocated session handle. - * \param [in] pParams - * ::NVFBC_CREATE_HANDLE_PARAMS - * - * \return - * ::NVFBC_SUCCESS \n - * ::NVFBC_ERR_INVALID_PTR \n - * ::NVFBC_ERR_API_VERSION \n - * ::NVFBC_ERR_INTERNAL \n - * ::NVFBC_ERR_OUT_OF_MEMORY \n - * ::NVFBC_ERR_MAX_CLIENTS \n - * ::NVFBC_ERR_X \n - * ::NVFBC_ERR_GLX \n - * ::NVFBC_ERR_GL - * - */ -NVFBCSTATUS NVFBCAPI NvFBCCreateHandle(NVFBC_SESSION_HANDLE *pSessionHandle, NVFBC_CREATE_HANDLE_PARAMS *pParams); - -/*! - * \brief Destroys the handle of an NvFBC client. - * - * This function uninitializes an FBC client. - * - * This function implicitly calls NvFBCReleaseContext(). - * - * After this fucntion returns, it is not possible to use this session handle - * for any further API call. - * - * \param [in] sessionHandle - * FBC session handle. - * \param [in] pParams - * ::NVFBC_DESTROY_HANDLE_PARAMS - * - * \return - * ::NVFBC_SUCCESS \n - * ::NVFBC_ERR_INVALID_HANDLE \n - * ::NVFBC_ERR_API_VERSION \n - * ::NVFBC_ERR_BAD_REQUEST \n - * ::NVFBC_ERR_INTERNAL \n - * ::NVFBC_ERR_CONTEXT \n - * ::NVFBC_ERR_X - */ -NVFBCSTATUS NVFBCAPI NvFBCDestroyHandle(const NVFBC_SESSION_HANDLE sessionHandle, NVFBC_DESTROY_HANDLE_PARAMS *pParams); - -/*! - * \brief Gets the current status of the display driver. - * - * This function queries the display driver for various information. - * - * \param [in] sessionHandle - * FBC session handle. - * \param [in] pParams - * ::NVFBC_GET_STATUS_PARAMS - * - * \return - * ::NVFBC_SUCCESS \n - * ::NVFBC_ERR_INVALID_HANDLE \n - * ::NVFBC_ERR_API_VERSION \n - * ::NVFBC_ERR_INTERNAL \n - * ::NVFBC_ERR_X - */ -NVFBCSTATUS NVFBCAPI NvFBCGetStatus(const NVFBC_SESSION_HANDLE sessionHandle, NVFBC_GET_STATUS_PARAMS *pParams); - -/*! - * \brief Binds the FBC context to the calling thread. - * - * The NvFBC library internally relies on objects that must be bound to a - * thread. Such objects are OpenGL contexts and CUDA contexts. - * - * This function binds these objects to the calling thread. - * - * The FBC context must be bound to the calling thread for most NvFBC entry - * points, otherwise ::NVFBC_ERR_CONTEXT is returned. - * - * If the FBC context is already bound to a different thread, - * ::NVFBC_ERR_CONTEXT is returned. The other thread must release the context - * first by calling the ReleaseContext() entry point. - * - * If the FBC context is already bound to the current thread, this function has - * no effects. - * - * \param [in] sessionHandle - * FBC session handle. - * \param [in] pParams - * ::NVFBC_DESTROY_CAPTURE_SESSION_PARAMS - * - * \return - * ::NVFBC_SUCCESS \n - * ::NVFBC_ERR_INVALID_HANDLE \n - * ::NVFBC_ERR_API_VERSION \n - * ::NVFBC_ERR_BAD_REQUEST \n - * ::NVFBC_ERR_CONTEXT \n - * ::NVFBC_ERR_INTERNAL \n - * ::NVFBC_ERR_X - */ -NVFBCSTATUS NVFBCAPI NvFBCBindContext(const NVFBC_SESSION_HANDLE sessionHandle, NVFBC_BIND_CONTEXT_PARAMS *pParams); - -/*! - * \brief Releases the FBC context from the calling thread. - * - * If the FBC context is bound to a different thread, ::NVFBC_ERR_CONTEXT is - * returned. - * - * If the FBC context is already released, this functino has no effects. - * - * \param [in] sessionHandle - * FBC session handle. - * \param [in] pParams - * ::NVFBC_SUCCESS \n - * ::NVFBC_ERR_INVALID_HANDLE \n - * ::NVFBC_ERR_API_VERSION \n - * ::NVFBC_ERR_BAD_REQUEST \n - * ::NVFBC_ERR_CONTEXT \n - * ::NVFBC_ERR_INTERNAL \n - * ::NVFBC_ERR_X - */ -NVFBCSTATUS NVFBCAPI NvFBCReleaseContext(const NVFBC_SESSION_HANDLE sessionHandle, NVFBC_RELEASE_CONTEXT_PARAMS *pParams); - -/*! - * \brief Creates a capture session for an FBC client. - * - * This function starts a capture session of the desired type (system memory, - * video memory with CUDA interop, or H.264 compressed frames in system memory). - * - * Not all types are supported on all systems. Also, it is possible to use - * NvFBC without having the CUDA library. In this case, requesting a capture - * session of the concerned type will return an error. - * - * After this function returns, the display driver will start generating frames - * that can be captured using the corresponding API call. - * - * \param [in] sessionHandle - * FBC session handle. - * \param [in] pParams - * ::NVFBC_CREATE_CAPTURE_SESSION_PARAMS - * - * \return - * ::NVFBC_SUCCESS \n - * ::NVFBC_ERR_INVALID_HANDLE \n - * ::NVFBC_ERR_API_VERSION \n - * ::NVFBC_ERR_BAD_REQUEST \n - * ::NVFBC_ERR_CONTEXT \n - * ::NVFBC_ERR_INVALID_PARAM \n - * ::NVFBC_ERR_OUT_OF_MEMORY \n - * ::NVFBC_ERR_X \n - * ::NVFBC_ERR_GLX \n - * ::NVFBC_ERR_GL \n - * ::NVFBC_ERR_CUDA \n - * ::NVFBC_ERR_MUST_RECREATE \n - * ::NVFBC_ERR_INTERNAL - */ -NVFBCSTATUS NVFBCAPI NvFBCCreateCaptureSession(const NVFBC_SESSION_HANDLE sessionHandle, NVFBC_CREATE_CAPTURE_SESSION_PARAMS *pParams); - -/*! - * \brief Destroys a capture session for an FBC client. - * - * This function stops a capture session and frees allocated objects. - * - * After this function returns, it is possible to create another capture - * session using the corresponding API call. - * - * \param [in] sessionHandle - * FBC session handle. - * \param [in] pParams - * ::NVFBC_DESTROY_CAPTURE_SESSION_PARAMS - * - * \return - * ::NVFBC_SUCCESS \n - * ::NVFBC_ERR_INVALID_HANDLE \n - * ::NVFBC_ERR_API_VERSION \n - * ::NVFBC_ERR_BAD_REQUEST \n - * ::NVFBC_ERR_CONTEXT \n - * ::NVFBC_ERR_INTERNAL \n - * ::NVFBC_ERR_X - */ -NVFBCSTATUS NVFBCAPI NvFBCDestroyCaptureSession(const NVFBC_SESSION_HANDLE sessionHandle, NVFBC_DESTROY_CAPTURE_SESSION_PARAMS *pParams); - -/*! - * \brief Sets up a capture to system memory session. - * - * This function configures how the capture to system memory should behave. It - * can be called anytime and several times after the capture session has been - * created. However, it must be called at least once prior to start capturing - * frames. - * - * This function allocates the buffer that will contain the captured frame. - * The application does not need to free this buffer. The size of this buffer - * is returned in the ::NVFBC_FRAME_GRAB_INFO structure. - * - * \param [in] sessionHandle - * FBC session handle. - * \param [in] pParams - * ::NVFBC_TOSYS_SETUP_PARAMS - * - * \return - * ::NVFBC_SUCCESS \n - * ::NVFBC_ERR_INVALID_HANDLE \n - * ::NVFBC_ERR_API_VERSION \n - * ::NVFBC_ERR_BAD_REQUEST \n - * ::NVFBC_ERR_INTERNAL \n - * ::NVFBC_ERR_CONTEXT \n - * ::NVFBC_ERR_UNSUPPORTED \n - * ::NVFBC_ERR_INVALID_PTR \n - * ::NVFBC_ERR_INVALID_PARAM \n - * ::NVFBC_ERR_OUT_OF_MEMORY \n - * ::NVFBC_ERR_X - */ -NVFBCSTATUS NVFBCAPI NvFBCToSysSetUp(const NVFBC_SESSION_HANDLE sessionHandle, NVFBC_TOSYS_SETUP_PARAMS *pParams); - -/*! - * \brief Captures a frame to a buffer in system memory. - * - * This function triggers a frame capture to a buffer in system memory that was - * registered with the ToSysSetUp() API call. - * - * Note that it is possible that the resolution of the desktop changes while - * capturing frames. This should be transparent for the application. - * - * When the resolution changes, the capture session is recreated using the same - * parameters, and necessary buffers are re-allocated. The frame counter is not - * reset. - * - * An application can detect that the resolution changed by comparing the - * dwByteSize member of the ::NVFBC_FRAME_GRAB_INFO against a previous - * frame and/or dwWidth and dwHeight. - * - * During a change of resolution the capture is paused even in asynchronous - * mode. - * - * \param [in] sessionHandle - * FBC session handle. - * \param [in] pParams - * ::NVFBC_TOSYS_GRAB_FRAME_PARAMS - * - * \return - * ::NVFBC_SUCCESS \n - * ::NVFBC_ERR_INVALID_HANDLE \n - * ::NVFBC_ERR_API_VERSION \n - * ::NVFBC_ERR_BAD_REQUEST \n - * ::NVFBC_ERR_CONTEXT \n - * ::NVFBC_ERR_INVALID_PTR \n - * ::NVFBC_ERR_INTERNAL \n - * ::NVFBC_ERR_X \n - * ::NVFBC_ERR_MUST_RECREATE \n - * \see NvFBCCreateCaptureSession \n - * \see NvFBCToSysSetUp - */ -NVFBCSTATUS NVFBCAPI NvFBCToSysGrabFrame(const NVFBC_SESSION_HANDLE sessionHandle, NVFBC_TOSYS_GRAB_FRAME_PARAMS *pParams); - -/*! - * \brief Sets up a capture to video memory session. - * - * This function configures how the capture to video memory with CUDA interop - * should behave. It can be called anytime and several times after the capture - * session has been created. However, it must be called at least once prior - * to start capturing frames. - * - * \param [in] sessionHandle - * FBC session handle. - * - * \param [in] pParams - * ::NVFBC_TOCUDA_SETUP_PARAMS - * - * \return - * ::NVFBC_SUCCESS \n - * ::NVFBC_ERR_INVALID_HANDLE \n - * ::NVFBC_ERR_API_VERSION \n - * ::NVFBC_ERR_BAD_REQUEST \n - * ::NVFBC_ERR_INTERNAL \n - * ::NVFBC_ERR_CONTEXT \n - * ::NVFBC_ERR_UNSUPPORTED \n - * ::NVFBC_ERR_GL \n - * ::NVFBC_ERR_X - */ -NVFBCSTATUS NVFBCAPI NvFBCToCudaSetUp(const NVFBC_SESSION_HANDLE sessionHandle, NVFBC_TOCUDA_SETUP_PARAMS *pParams); - -/*! - * \brief Captures a frame to a CUDA device in video memory. - * - * This function triggers a frame capture to a CUDA device in video memory. - * - * Note about changes of resolution: \see NvFBCToSysGrabFrame - * - * \param [in] sessionHandle - * FBC session handle. - * - * \param [in] pParams - * ::NVFBC_TOCUDA_GRAB_FRAME_PARAMS - * - * \return - * ::NVFBC_SUCCESS \n - * ::NVFBC_ERR_INVALID_HANDLE \n - * ::NVFBC_ERR_API_VERSION \n - * ::NVFBC_ERR_BAD_REQUEST \n - * ::NVFBC_ERR_CONTEXT \n - * ::NVFBC_ERR_INVALID_PTR \n - * ::NVFBC_ERR_CUDA \n - * ::NVFBC_ERR_INTERNAL \n - * ::NVFBC_ERR_X \n - * ::NVFBC_ERR_MUST_RECREATE \n - * \see NvFBCCreateCaptureSession \n - * \see NvFBCToCudaSetUp - */ -NVFBCSTATUS NVFBCAPI NvFBCToCudaGrabFrame(const NVFBC_SESSION_HANDLE sessionHandle, NVFBC_TOCUDA_GRAB_FRAME_PARAMS *pParams); - -/*! - * \brief Sets up a capture to OpenGL buffer in video memory session. - * - * This function configures how the capture to video memory should behave. - * It can be called anytime and several times after the capture session has been - * created. However, it must be called at least once prior to start capturing - * frames. - * - * \param [in] sessionHandle - * FBC session handle. - * - * \param [in] pParams - * ::NVFBC_TOGL_SETUP_PARAMS - * - * \return - * ::NVFBC_SUCCESS \n - * ::NVFBC_ERR_INVALID_HANDLE \n - * ::NVFBC_ERR_API_VERSION \n - * ::NVFBC_ERR_BAD_REQUEST \n - * ::NVFBC_ERR_INTERNAL \n - * ::NVFBC_ERR_CONTEXT \n - * ::NVFBC_ERR_UNSUPPORTED \n - * ::NVFBC_ERR_GL \n - * ::NVFBC_ERR_X - */ -NVFBCSTATUS NVFBCAPI NvFBCToGLSetUp(const NVFBC_SESSION_HANDLE sessionHandle, NVFBC_TOGL_SETUP_PARAMS *pParams); - -/*! - * \brief Captures a frame to an OpenGL buffer in video memory. - * - * This function triggers a frame capture to a selected resource in video memory. - * - * Note about changes of resolution: \see NvFBCToSysGrabFrame - * - * \param [in] sessionHandle - * FBC session handle. - * - * \param [in] pParams - * ::NVFBC_TOGL_GRAB_FRAME_PARAMS - * - * \return - * ::NVFBC_SUCCESS \n - * ::NVFBC_ERR_INVALID_HANDLE \n - * ::NVFBC_ERR_API_VERSION \n - * ::NVFBC_ERR_BAD_REQUEST \n - * ::NVFBC_ERR_CONTEXT \n - * ::NVFBC_ERR_INVALID_PTR \n - * ::NVFBC_ERR_INTERNAL \n - * ::NVFBC_ERR_X \n - * ::NVFBC_ERR_MUST_RECREATE \n - * \see NvFBCCreateCaptureSession \n - * \see NvFBCToCudaSetUp - */ -NVFBCSTATUS NVFBCAPI NvFBCToGLGrabFrame(const NVFBC_SESSION_HANDLE sessionHandle, NVFBC_TOGL_GRAB_FRAME_PARAMS *pParams); - -/*! - * \cond FBC_PFN - * - * Defines API function pointers - */ -typedef const char* (NVFBCAPI* PNVFBCGETLASTERRORSTR)(const NVFBC_SESSION_HANDLE sessionHandle); -typedef NVFBCSTATUS (NVFBCAPI* PNVFBCCREATEHANDLE)(NVFBC_SESSION_HANDLE *pSessionHandle, NVFBC_CREATE_HANDLE_PARAMS *pParams); -typedef NVFBCSTATUS (NVFBCAPI* PNVFBCDESTROYHANDLE)(const NVFBC_SESSION_HANDLE sessionHandle, NVFBC_DESTROY_HANDLE_PARAMS *pParams); -typedef NVFBCSTATUS (NVFBCAPI* PNVFBCBINDCONTEXT)(const NVFBC_SESSION_HANDLE sessionHandle, NVFBC_BIND_CONTEXT_PARAMS *pParams); -typedef NVFBCSTATUS (NVFBCAPI* PNVFBCRELEASECONTEXT)(const NVFBC_SESSION_HANDLE sessionHandle, NVFBC_RELEASE_CONTEXT_PARAMS *pParams); -typedef NVFBCSTATUS (NVFBCAPI* PNVFBCGETSTATUS)(const NVFBC_SESSION_HANDLE sessionHandle, NVFBC_GET_STATUS_PARAMS *pParams); -typedef NVFBCSTATUS (NVFBCAPI* PNVFBCCREATECAPTURESESSION)(const NVFBC_SESSION_HANDLE sessionHandle, NVFBC_CREATE_CAPTURE_SESSION_PARAMS *pParams); -typedef NVFBCSTATUS (NVFBCAPI* PNVFBCDESTROYCAPTURESESSION)(const NVFBC_SESSION_HANDLE sessionHandle, NVFBC_DESTROY_CAPTURE_SESSION_PARAMS *pParams); -typedef NVFBCSTATUS (NVFBCAPI* PNVFBCTOSYSSETUP)(const NVFBC_SESSION_HANDLE sessionHandle, NVFBC_TOSYS_SETUP_PARAMS *pParams); -typedef NVFBCSTATUS (NVFBCAPI* PNVFBCTOSYSGRABFRAME)(const NVFBC_SESSION_HANDLE sessionHandle, NVFBC_TOSYS_GRAB_FRAME_PARAMS *pParams); -typedef NVFBCSTATUS (NVFBCAPI* PNVFBCTOCUDASETUP)(const NVFBC_SESSION_HANDLE sessionHandle, NVFBC_TOCUDA_SETUP_PARAMS *pParams); -typedef NVFBCSTATUS (NVFBCAPI* PNVFBCTOCUDAGRABFRAME)(const NVFBC_SESSION_HANDLE sessionHandle, NVFBC_TOCUDA_GRAB_FRAME_PARAMS *pParams); -typedef NVFBCSTATUS (NVFBCAPI* PNVFBCTOGLSETUP)(const NVFBC_SESSION_HANDLE sessionHandle, NVFBC_TOGL_SETUP_PARAMS *pParams); -typedef NVFBCSTATUS (NVFBCAPI* PNVFBCTOGLGRABFRAME)(const NVFBC_SESSION_HANDLE sessionHandle, NVFBC_TOGL_GRAB_FRAME_PARAMS *pParams); - -/// \endcond - -/*! @} FBC_FUNC */ - -/*! - * \ingroup FBC_STRUCT - * - * Structure populated with API function pointers. - */ -typedef struct -{ - uint32_t dwVersion; //!< [in] Must be set to NVFBC_VERSION. - PNVFBCGETLASTERRORSTR nvFBCGetLastErrorStr; //!< [out] Pointer to ::NvFBCGetLastErrorStr(). - PNVFBCCREATEHANDLE nvFBCCreateHandle; //!< [out] Pointer to ::NvFBCCreateHandle(). - PNVFBCDESTROYHANDLE nvFBCDestroyHandle; //!< [out] Pointer to ::NvFBCDestroyHandle(). - PNVFBCGETSTATUS nvFBCGetStatus; //!< [out] Pointer to ::NvFBCGetStatus(). - PNVFBCCREATECAPTURESESSION nvFBCCreateCaptureSession; //!< [out] Pointer to ::NvFBCCreateCaptureSession(). - PNVFBCDESTROYCAPTURESESSION nvFBCDestroyCaptureSession; //!< [out] Pointer to ::NvFBCDestroyCaptureSession(). - PNVFBCTOSYSSETUP nvFBCToSysSetUp; //!< [out] Pointer to ::NvFBCToSysSetUp(). - PNVFBCTOSYSGRABFRAME nvFBCToSysGrabFrame; //!< [out] Pointer to ::NvFBCToSysGrabFrame(). - PNVFBCTOCUDASETUP nvFBCToCudaSetUp; //!< [out] Pointer to ::NvFBCToCudaSetUp(). - PNVFBCTOCUDAGRABFRAME nvFBCToCudaGrabFrame; //!< [out] Pointer to ::NvFBCToCudaGrabFrame(). - void* pad1; //!< [out] Retired. Do not use. - void* pad2; //!< [out] Retired. Do not use. - void* pad3; //!< [out] Retired. Do not use. - PNVFBCBINDCONTEXT nvFBCBindContext; //!< [out] Pointer to ::NvFBCBindContext(). - PNVFBCRELEASECONTEXT nvFBCReleaseContext; //!< [out] Pointer to ::NvFBCReleaseContext(). - void* pad4; //!< [out] Retired. Do not use. - void* pad5; //!< [out] Retired. Do not use. - void* pad6; //!< [out] Retired. Do not use. - void* pad7; //!< [out] Retired. Do not use. - PNVFBCTOGLSETUP nvFBCToGLSetUp; //!< [out] Pointer to ::nvFBCToGLSetup(). - PNVFBCTOGLGRABFRAME nvFBCToGLGrabFrame; //!< [out] Pointer to ::nvFBCToGLGrabFrame(). -} NVFBC_API_FUNCTION_LIST; - -/*! - * \ingroup FBC_FUNC - * - * \brief Entry Points to the NvFBC interface. - * - * Creates an instance of the NvFBC interface, and populates the - * pFunctionList with function pointers to the API routines implemented by - * the NvFBC interface. - * - * \param [out] pFunctionList - * - * \return - * ::NVFBC_SUCCESS \n - * ::NVFBC_ERR_INVALID_PTR \n - * ::NVFBC_ERR_API_VERSION - */ -NVFBCSTATUS NVFBCAPI NvFBCCreateInstance(NVFBC_API_FUNCTION_LIST *pFunctionList); -/*! - * \ingroup FBC_FUNC - * - * Defines function pointer for the ::NvFBCCreateInstance() API call. - */ -typedef NVFBCSTATUS (NVFBCAPI* PNVFBCCREATEINSTANCE)(NVFBC_API_FUNCTION_LIST *pFunctionList); - -#ifdef __cplusplus -} -#endif - -#endif // _NVFBC_H_ diff --git a/include/NvFBCLibrary.hpp b/include/NvFBCLibrary.hpp deleted file mode 100644 index 6d115a4..0000000 --- a/include/NvFBCLibrary.hpp +++ /dev/null @@ -1,246 +0,0 @@ -#pragma once - -#include "NvFBC.h" -#include <cuda.h> - -#include <dlfcn.h> -#include <string.h> -#include <stdio.h> - -class NvFBCLibrary { -public: - ~NvFBCLibrary() { - if(fbc_handle_created) { - NVFBC_DESTROY_CAPTURE_SESSION_PARAMS destroy_capture_params; - memset(&destroy_capture_params, 0, sizeof(destroy_capture_params)); - destroy_capture_params.dwVersion = NVFBC_DESTROY_CAPTURE_SESSION_PARAMS_VER; - nv_fbc_function_list.nvFBCDestroyCaptureSession(nv_fbc_handle, &destroy_capture_params); - - NVFBC_DESTROY_HANDLE_PARAMS destroy_params; - memset(&destroy_params, 0, sizeof(destroy_params)); - destroy_params.dwVersion = NVFBC_DESTROY_HANDLE_PARAMS_VER; - nv_fbc_function_list.nvFBCDestroyHandle(nv_fbc_handle, &destroy_params); - } - - if(library) - dlclose(library); - } - - bool load() { - if(library) - return true; - - dlerror(); // clear - void *lib = dlopen("libnvidia-fbc.so.1", RTLD_NOW); - if(!lib) { - fprintf(stderr, "Error: failed to load libnvidia-fbc.so.1, error: %s\n", dlerror()); - return false; - } - - nv_fbc_create_instance = (PNVFBCCREATEINSTANCE)dlsym(lib, "NvFBCCreateInstance"); - if(!nv_fbc_create_instance) { - fprintf(stderr, "Error: unable to resolve symbol 'NvFBCCreateInstance'\n"); - dlclose(lib); - return false; - } - - memset(&nv_fbc_function_list, 0, sizeof(nv_fbc_function_list)); - nv_fbc_function_list.dwVersion = NVFBC_VERSION; - NVFBCSTATUS status = nv_fbc_create_instance(&nv_fbc_function_list); - if(status != NVFBC_SUCCESS) { - fprintf(stderr, "Error: failed to create NvFBC instance (status: %d)\n", status); - dlclose(lib); - return false; - } - - library = lib; - return true; - } - - // If |display_to_capture| is "screen", then the entire x11 screen is captured (all displays) - bool create(const char *display_to_capture, uint32_t fps, /*out*/ uint32_t *display_width, /*out*/ uint32_t *display_height, uint32_t x = 0, uint32_t y = 0, uint32_t width = 0, uint32_t height = 0, bool direct_capture = false) { - if(!library || !display_to_capture || !display_width || !display_height || fbc_handle_created) - return false; - - const bool capture_region = (x > 0 || y > 0 || width > 0 || height > 0); - - NVFBCSTATUS status; - NVFBC_TRACKING_TYPE tracking_type; - bool capture_session_created = false; - uint32_t output_id = 0; - fbc_handle_created = false; - - NVFBC_CREATE_HANDLE_PARAMS create_params; - memset(&create_params, 0, sizeof(create_params)); - create_params.dwVersion = NVFBC_CREATE_HANDLE_PARAMS_VER; - - status = nv_fbc_function_list.nvFBCCreateHandle(&nv_fbc_handle, &create_params); - if(status != NVFBC_SUCCESS) { - fprintf(stderr, "Error: %s\n", nv_fbc_function_list.nvFBCGetLastErrorStr(nv_fbc_handle)); - return false; - } - fbc_handle_created = true; - - NVFBC_GET_STATUS_PARAMS status_params; - memset(&status_params, 0, sizeof(status_params)); - status_params.dwVersion = NVFBC_GET_STATUS_PARAMS_VER; - - status = nv_fbc_function_list.nvFBCGetStatus(nv_fbc_handle, &status_params); - if(status != NVFBC_SUCCESS) { - fprintf(stderr, "Error: %s\n", nv_fbc_function_list.nvFBCGetLastErrorStr(nv_fbc_handle)); - goto error_cleanup; - } - - if(status_params.bCanCreateNow == NVFBC_FALSE) { - fprintf(stderr, "Error: it's not possible to create a capture session on this system\n"); - goto error_cleanup; - } - - tracking_type = strcmp(display_to_capture, "screen") == 0 ? NVFBC_TRACKING_SCREEN : NVFBC_TRACKING_OUTPUT; - if(tracking_type == NVFBC_TRACKING_OUTPUT) { - if(!status_params.bXRandRAvailable) { - fprintf(stderr, "Error: the xrandr extension is not available\n"); - goto error_cleanup; - } - - if(status_params.bInModeset) { - fprintf(stderr, "Error: the x server is in modeset, unable to record\n"); - goto error_cleanup; - } - - output_id = get_output_id_from_display_name(status_params.outputs, status_params.dwOutputNum, display_to_capture, display_width, display_height); - if(output_id == 0) { - fprintf(stderr, "Error: display '%s' not found\n", display_to_capture); - goto error_cleanup; - } - } else { - *display_width = status_params.screenSize.w; - *display_height = status_params.screenSize.h; - } - - NVFBC_CREATE_CAPTURE_SESSION_PARAMS create_capture_params; - memset(&create_capture_params, 0, sizeof(create_capture_params)); - create_capture_params.dwVersion = NVFBC_CREATE_CAPTURE_SESSION_PARAMS_VER; - create_capture_params.eCaptureType = NVFBC_CAPTURE_SHARED_CUDA; - create_capture_params.bWithCursor = direct_capture ? NVFBC_FALSE : NVFBC_TRUE; - if(capture_region) { - create_capture_params.captureBox = { x, y, width, height }; - *display_width = width; - *display_height = height; - } - create_capture_params.eTrackingType = tracking_type; - create_capture_params.dwSamplingRateMs = 1000 / fps; - create_capture_params.bAllowDirectCapture = direct_capture ? NVFBC_TRUE : NVFBC_FALSE; - create_capture_params.bPushModel = direct_capture ? NVFBC_TRUE : NVFBC_FALSE; - if(tracking_type == NVFBC_TRACKING_OUTPUT) - create_capture_params.dwOutputId = output_id; - - status = nv_fbc_function_list.nvFBCCreateCaptureSession(nv_fbc_handle, &create_capture_params); - if(status != NVFBC_SUCCESS) { - fprintf(stderr, "Error: %s\n", nv_fbc_function_list.nvFBCGetLastErrorStr(nv_fbc_handle)); - goto error_cleanup; - } - capture_session_created = true; - - NVFBC_TOCUDA_SETUP_PARAMS setup_params; - memset(&setup_params, 0, sizeof(setup_params)); - setup_params.dwVersion = NVFBC_TOCUDA_SETUP_PARAMS_VER; - setup_params.eBufferFormat = NVFBC_BUFFER_FORMAT_BGRA; - - status = nv_fbc_function_list.nvFBCToCudaSetUp(nv_fbc_handle, &setup_params); - if(status != NVFBC_SUCCESS) { - fprintf(stderr, "Error: %s\n", nv_fbc_function_list.nvFBCGetLastErrorStr(nv_fbc_handle)); - goto error_cleanup; - } - - return true; - - error_cleanup: - if(fbc_handle_created) { - if(capture_session_created) { - NVFBC_DESTROY_CAPTURE_SESSION_PARAMS destroy_capture_params; - memset(&destroy_capture_params, 0, sizeof(destroy_capture_params)); - destroy_capture_params.dwVersion = NVFBC_DESTROY_CAPTURE_SESSION_PARAMS_VER; - nv_fbc_function_list.nvFBCDestroyCaptureSession(nv_fbc_handle, &destroy_capture_params); - } - - NVFBC_DESTROY_HANDLE_PARAMS destroy_params; - memset(&destroy_params, 0, sizeof(destroy_params)); - destroy_params.dwVersion = NVFBC_DESTROY_HANDLE_PARAMS_VER; - nv_fbc_function_list.nvFBCDestroyHandle(nv_fbc_handle, &destroy_params); - fbc_handle_created = false; - } - output_id = 0; - return false; - } - - bool capture(/*out*/ CUdeviceptr *cu_device_ptr, uint32_t *byte_size) { - if(!library || !fbc_handle_created || !cu_device_ptr || !byte_size) - return false; - - NVFBCSTATUS status; - NVFBC_FRAME_GRAB_INFO frame_info; - memset(&frame_info, 0, sizeof(frame_info)); - - NVFBC_TOCUDA_GRAB_FRAME_PARAMS grab_params; - memset(&grab_params, 0, sizeof(grab_params)); - grab_params.dwVersion = NVFBC_TOCUDA_GRAB_FRAME_PARAMS_VER; - grab_params.dwFlags = NVFBC_TOCUDA_GRAB_FLAGS_NOWAIT; - grab_params.pFrameGrabInfo = &frame_info; - grab_params.pCUDADeviceBuffer = cu_device_ptr; - - status = nv_fbc_function_list.nvFBCToCudaGrabFrame(nv_fbc_handle, &grab_params); - if(status != NVFBC_SUCCESS) { - fprintf(stderr, "Error: %s\n", nv_fbc_function_list.nvFBCGetLastErrorStr(nv_fbc_handle)); - return false; - } - - *byte_size = frame_info.dwByteSize; - // TODO: Check bIsNewFrame - // TODO: Check dwWidth and dwHeight and update size in video output in ffmpeg. This can happen when xrandr is used to change monitor resolution - - return true; - } -private: - static char to_upper(char c) { - if(c >= 'a' && c <= 'z') - return c - 32; - else - return c; - } - - static bool strcase_equals(const char *str1, const char *str2) { - for(;;) { - char c1 = to_upper(*str1); - char c2 = to_upper(*str2); - if(c1 != c2) - return false; - if(c1 == '\0' || c2 == '\0') - return true; - ++str1; - ++str2; - } - } - - // Returns 0 on failure - uint32_t get_output_id_from_display_name(NVFBC_RANDR_OUTPUT_INFO *outputs, uint32_t num_outputs, const char *display_name, uint32_t *display_width, uint32_t *display_height) { - if(!outputs) - return 0; - - for(uint32_t i = 0; i < num_outputs; ++i) { - if(strcase_equals(outputs[i].name, display_name)) { - *display_width = outputs[i].trackedBox.w; - *display_height = outputs[i].trackedBox.h; - return outputs[i].dwId; - } - } - - return 0; - } -private: - void *library = nullptr; - PNVFBCCREATEINSTANCE nv_fbc_create_instance = nullptr; - NVFBC_API_FUNCTION_LIST nv_fbc_function_list; - NVFBC_SESSION_HANDLE nv_fbc_handle; - bool fbc_handle_created = false; -};
\ No newline at end of file diff --git a/include/args_parser.h b/include/args_parser.h new file mode 100644 index 0000000..e2fa46e --- /dev/null +++ b/include/args_parser.h @@ -0,0 +1,106 @@ +#ifndef GSR_ARGS_PARSER_H +#define GSR_ARGS_PARSER_H + +#include <stdbool.h> +#include <stdint.h> +#include "defs.h" +#include "vec2.h" + +typedef struct gsr_egl gsr_egl; + +#define NUM_ARGS 30 + +typedef enum { + ARG_TYPE_STRING, + ARG_TYPE_BOOLEAN, + ARG_TYPE_ENUM, + ARG_TYPE_I64, + ARG_TYPE_DOUBLE, +} ArgType; + +typedef struct { + const char *name; + int value; +} ArgEnum; + +typedef struct { + ArgType type; + const char **values; + int capacity_num_values; + int num_values; + + const char *key; + bool optional; + bool list; + + const ArgEnum *enum_values; + int num_enum_values; + + int64_t integer_value_min; + int64_t integer_value_max; + + union { + bool boolean; + int enum_value; + int64_t i64_value; + double d_value; + } typed_value; +} Arg; + +typedef struct { + void (*version)(void *userdata); + void (*info)(void *userdata); + void (*list_audio_devices)(void *userdata); + void (*list_application_audio)(void *userdata); + void (*list_capture_options)(const char *card_path, void *userdata); +} args_handlers; + +typedef struct { + Arg args[NUM_ARGS]; + + gsr_video_encoder_hardware video_encoder; + gsr_pixel_format pixel_format; + gsr_framerate_mode framerate_mode; + gsr_color_range color_range; + gsr_tune tune; + gsr_video_codec video_codec; + gsr_audio_codec audio_codec; + gsr_bitrate_mode bitrate_mode; + gsr_video_quality video_quality; + gsr_replay_storage replay_storage; + char window[64]; + const char *container_format; + const char *filename; + const char *replay_recording_directory; + const char *portal_session_token_filepath; + const char *recording_saved_script; + bool verbose; + bool gl_debug; + bool record_cursor; + bool date_folders; + bool restore_portal_session; + bool restart_replay_on_save; + bool overclock; + bool is_livestream; + bool is_output_piped; + bool low_latency_recording; + bool very_old_gpu; + int64_t video_bitrate; + int64_t audio_bitrate; + int64_t fps; + int64_t replay_buffer_size_secs; + double keyint; + vec2i output_resolution; + vec2i region_size; + vec2i region_position; +} args_parser; + +/* |argv| is stored as a reference */ +bool args_parser_parse(args_parser *self, int argc, char **argv, const args_handlers *args_handlers, void *userdata); +void args_parser_deinit(args_parser *self); + +bool args_parser_validate_with_gl_info(args_parser *self, gsr_egl *egl); +void args_parser_print_usage(void); +Arg* args_parser_get_arg(args_parser *self, const char *arg_name); + +#endif /* GSR_ARGS_PARSER_H */ diff --git a/include/capture/capture.h b/include/capture/capture.h new file mode 100644 index 0000000..c2128c5 --- /dev/null +++ b/include/capture/capture.h @@ -0,0 +1,52 @@ +#ifndef GSR_CAPTURE_CAPTURE_H +#define GSR_CAPTURE_CAPTURE_H + +#include "../color_conversion.h" +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +typedef struct AVCodecContext AVCodecContext; +typedef struct AVStream AVStream; +typedef struct AVFrame AVFrame; +typedef struct AVMasteringDisplayMetadata AVMasteringDisplayMetadata; +typedef struct AVContentLightMetadata AVContentLightMetadata; +typedef struct gsr_capture gsr_capture; + +typedef struct { + int width; + int height; + int fps; + AVCodecContext *video_codec_context; /* can be NULL */ + AVFrame *frame; /* can be NULL, but will never be NULL if |video_codec_context| is set */ +} gsr_capture_metadata; + +struct gsr_capture { + /* These methods should not be called manually. Call gsr_capture_* instead. |capture_metdata->width| and |capture_metadata->height| should be set by this function */ + int (*start)(gsr_capture *cap, gsr_capture_metadata *capture_metadata); + void (*on_event)(gsr_capture *cap, gsr_egl *egl); /* can be NULL */ + void (*tick)(gsr_capture *cap); /* can be NULL. If there is an event then |on_event| is called before this */ + bool (*should_stop)(gsr_capture *cap, bool *err); /* can be NULL. If NULL, return false */ + bool (*capture_has_synchronous_task)(gsr_capture *cap); /* can be NULL. If this returns true then the time spent in |capture| is ignored for video/audio (capture is paused while the synchronous task happens) */ + int (*capture)(gsr_capture *cap, gsr_capture_metadata *capture_metadata, gsr_color_conversion *color_conversion); /* Return 0 if the frame was captured */ + bool (*uses_external_image)(gsr_capture *cap); /* can be NULL. If NULL, return false */ + bool (*set_hdr_metadata)(gsr_capture *cap, AVMasteringDisplayMetadata *mastering_display_metadata, AVContentLightMetadata *light_metadata); /* can be NULL. If NULL, return false */ + uint64_t (*get_window_id)(gsr_capture *cap); /* can be NULL. Returns 0 if unknown */ + bool (*is_damaged)(gsr_capture *cap); /* can be NULL */ + void (*clear_damage)(gsr_capture *cap); /* can be NULL */ + void (*destroy)(gsr_capture *cap); + + void *priv; /* can be NULL */ + bool started; +}; + +int gsr_capture_start(gsr_capture *cap, gsr_capture_metadata *capture_metadata); +void gsr_capture_on_event(gsr_capture *cap, gsr_egl *egl); +void gsr_capture_tick(gsr_capture *cap); +bool gsr_capture_should_stop(gsr_capture *cap, bool *err); +int gsr_capture_capture(gsr_capture *cap, gsr_capture_metadata *capture_metadata, gsr_color_conversion *color_conversion); +bool gsr_capture_uses_external_image(gsr_capture *cap); +bool gsr_capture_set_hdr_metadata(gsr_capture *cap, AVMasteringDisplayMetadata *mastering_display_metadata, AVContentLightMetadata *light_metadata); +void gsr_capture_destroy(gsr_capture *cap); + +#endif /* GSR_CAPTURE_CAPTURE_H */ diff --git a/include/capture/kms.h b/include/capture/kms.h new file mode 100644 index 0000000..ce09817 --- /dev/null +++ b/include/capture/kms.h @@ -0,0 +1,19 @@ +#ifndef GSR_CAPTURE_KMS_H +#define GSR_CAPTURE_KMS_H + +#include "capture.h" + +typedef struct { + gsr_egl *egl; + const char *display_to_capture; /* A copy is made of this */ + bool hdr; + bool record_cursor; + int fps; + vec2i output_resolution; + vec2i region_size; + vec2i region_position; +} gsr_capture_kms_params; + +gsr_capture* gsr_capture_kms_create(const gsr_capture_kms_params *params); + +#endif /* GSR_CAPTURE_KMS_H */ diff --git a/include/capture/nvfbc.h b/include/capture/nvfbc.h new file mode 100644 index 0000000..7e30d01 --- /dev/null +++ b/include/capture/nvfbc.h @@ -0,0 +1,20 @@ +#ifndef GSR_CAPTURE_NVFBC_H +#define GSR_CAPTURE_NVFBC_H + +#include "capture.h" +#include "../vec2.h" + +typedef struct { + gsr_egl *egl; + const char *display_to_capture; /* if this is "screen", then the entire x11 screen is captured (all displays). A copy is made of this */ + int fps; + bool direct_capture; + bool record_cursor; + vec2i output_resolution; + vec2i region_size; + vec2i region_position; +} gsr_capture_nvfbc_params; + +gsr_capture* gsr_capture_nvfbc_create(const gsr_capture_nvfbc_params *params); + +#endif /* GSR_CAPTURE_NVFBC_H */ diff --git a/include/capture/portal.h b/include/capture/portal.h new file mode 100644 index 0000000..74cdba9 --- /dev/null +++ b/include/capture/portal.h @@ -0,0 +1,17 @@ +#ifndef GSR_CAPTURE_PORTAL_H +#define GSR_CAPTURE_PORTAL_H + +#include "capture.h" + +typedef struct { + gsr_egl *egl; + bool record_cursor; + bool restore_portal_session; + /* If this is set to NULL then this defaults to $XDG_CONFIG_HOME/gpu-screen-recorder/restore_token ($XDG_CONFIG_HOME defaults to $HOME/.config) */ + const char *portal_session_token_filepath; + vec2i output_resolution; +} gsr_capture_portal_params; + +gsr_capture* gsr_capture_portal_create(const gsr_capture_portal_params *params); + +#endif /* GSR_CAPTURE_PORTAL_H */ diff --git a/include/capture/xcomposite.h b/include/capture/xcomposite.h new file mode 100644 index 0000000..bf6532e --- /dev/null +++ b/include/capture/xcomposite.h @@ -0,0 +1,17 @@ +#ifndef GSR_CAPTURE_XCOMPOSITE_H +#define GSR_CAPTURE_XCOMPOSITE_H + +#include "capture.h" +#include "../vec2.h" + +typedef struct { + gsr_egl *egl; + unsigned long window; + bool follow_focused; /* If this is set then |window| is ignored */ + bool record_cursor; + vec2i output_resolution; +} gsr_capture_xcomposite_params; + +gsr_capture* gsr_capture_xcomposite_create(const gsr_capture_xcomposite_params *params); + +#endif /* GSR_CAPTURE_XCOMPOSITE_H */ diff --git a/include/capture/ximage.h b/include/capture/ximage.h new file mode 100644 index 0000000..e6c3607 --- /dev/null +++ b/include/capture/ximage.h @@ -0,0 +1,18 @@ +#ifndef GSR_CAPTURE_XIMAGE_H +#define GSR_CAPTURE_XIMAGE_H + +#include "capture.h" +#include "../vec2.h" + +typedef struct { + gsr_egl *egl; + const char *display_to_capture; /* A copy is made of this */ + bool record_cursor; + vec2i output_resolution; + vec2i region_size; + vec2i region_position; +} gsr_capture_ximage_params; + +gsr_capture* gsr_capture_ximage_create(const gsr_capture_ximage_params *params); + +#endif /* GSR_CAPTURE_XIMAGE_H */ diff --git a/include/codec_query/codec_query.h b/include/codec_query/codec_query.h new file mode 100644 index 0000000..316217d --- /dev/null +++ b/include/codec_query/codec_query.h @@ -0,0 +1,23 @@ +#ifndef GSR_CODEC_QUERY_H +#define GSR_CODEC_QUERY_H + +#include <stdbool.h> + +typedef struct { + bool supported; + bool low_power; +} gsr_supported_video_codec; + +typedef struct { + gsr_supported_video_codec h264; + gsr_supported_video_codec hevc; + gsr_supported_video_codec hevc_hdr; + gsr_supported_video_codec hevc_10bit; + gsr_supported_video_codec av1; + gsr_supported_video_codec av1_hdr; + gsr_supported_video_codec av1_10bit; + gsr_supported_video_codec vp8; + gsr_supported_video_codec vp9; +} gsr_supported_video_codecs; + +#endif /* GSR_CODEC_QUERY_H */ diff --git a/include/codec_query/nvenc.h b/include/codec_query/nvenc.h new file mode 100644 index 0000000..c01acf6 --- /dev/null +++ b/include/codec_query/nvenc.h @@ -0,0 +1,8 @@ +#ifndef GSR_CODEC_QUERY_NVENC_H +#define GSR_CODEC_QUERY_NVENC_H + +#include "codec_query.h" + +bool gsr_get_supported_video_codecs_nvenc(gsr_supported_video_codecs *video_codecs, bool cleanup); + +#endif /* GSR_CODEC_QUERY_NVENC_H */ diff --git a/include/codec_query/vaapi.h b/include/codec_query/vaapi.h new file mode 100644 index 0000000..60bdeca --- /dev/null +++ b/include/codec_query/vaapi.h @@ -0,0 +1,8 @@ +#ifndef GSR_CODEC_QUERY_VAAPI_H +#define GSR_CODEC_QUERY_VAAPI_H + +#include "codec_query.h" + +bool gsr_get_supported_video_codecs_vaapi(gsr_supported_video_codecs *video_codecs, const char *card_path, bool cleanup); + +#endif /* GSR_CODEC_QUERY_VAAPI_H */ diff --git a/include/codec_query/vulkan.h b/include/codec_query/vulkan.h new file mode 100644 index 0000000..bb06c6b --- /dev/null +++ b/include/codec_query/vulkan.h @@ -0,0 +1,8 @@ +#ifndef GSR_CODEC_QUERY_VULKAN_H +#define GSR_CODEC_QUERY_VULKAN_H + +#include "codec_query.h" + +bool gsr_get_supported_video_codecs_vulkan(gsr_supported_video_codecs *video_codecs, const char *card_path, bool cleanup); + +#endif /* GSR_CODEC_QUERY_VULKAN_H */ diff --git a/include/color_conversion.h b/include/color_conversion.h new file mode 100644 index 0000000..cb074a1 --- /dev/null +++ b/include/color_conversion.h @@ -0,0 +1,85 @@ +#ifndef GSR_COLOR_CONVERSION_H +#define GSR_COLOR_CONVERSION_H + +#include "shader.h" +#include "defs.h" +#include "vec2.h" +#include <stdbool.h> + +#define GSR_COLOR_CONVERSION_MAX_COMPUTE_SHADERS 12 +#define GSR_COLOR_CONVERSION_MAX_GRAPHICS_SHADERS 6 +#define GSR_COLOR_CONVERSION_MAX_FRAMEBUFFERS 2 + +typedef enum { + GSR_SOURCE_COLOR_RGB, + GSR_SOURCE_COLOR_BGR +} gsr_source_color; + +typedef enum { + GSR_DESTINATION_COLOR_NV12, /* YUV420, BT709, 8-bit */ + GSR_DESTINATION_COLOR_P010, /* YUV420, BT2020, 10-bit */ + GSR_DESTINATION_COLOR_RGB8 +} gsr_destination_color; + +typedef enum { + GSR_ROT_0, + GSR_ROT_90, + GSR_ROT_180, + GSR_ROT_270 +} gsr_rotation; + +typedef struct { + int rotation_matrix; + int offset; +} gsr_color_graphics_uniforms; + +typedef struct { + int rotation_matrix; + int source_position; + int target_position; + int scale; +} gsr_color_compute_uniforms; + +typedef struct { + gsr_egl *egl; + + gsr_destination_color destination_color; + + unsigned int destination_textures[2]; + int num_destination_textures; + + gsr_color_range color_range; + bool load_external_image_shader; + bool force_graphics_shader; +} gsr_color_conversion_params; + +typedef struct { + gsr_color_conversion_params params; + gsr_color_compute_uniforms compute_uniforms[GSR_COLOR_CONVERSION_MAX_COMPUTE_SHADERS]; + gsr_shader compute_shaders[GSR_COLOR_CONVERSION_MAX_COMPUTE_SHADERS]; + + /* These are only loader if compute shaders (of the same type) fail to load */ + gsr_color_graphics_uniforms graphics_uniforms[GSR_COLOR_CONVERSION_MAX_GRAPHICS_SHADERS]; + gsr_shader graphics_shaders[GSR_COLOR_CONVERSION_MAX_GRAPHICS_SHADERS]; + + bool compute_shaders_failed_to_load; + bool external_compute_shaders_failed_to_load; + + unsigned int framebuffers[GSR_COLOR_CONVERSION_MAX_FRAMEBUFFERS]; + + unsigned int vertex_array_object_id; + unsigned int vertex_buffer_object_id; + + int max_local_size_dim; +} gsr_color_conversion; + +int gsr_color_conversion_init(gsr_color_conversion *self, const gsr_color_conversion_params *params); +void gsr_color_conversion_deinit(gsr_color_conversion *self); + +void gsr_color_conversion_draw(gsr_color_conversion *self, unsigned int texture_id, vec2i destination_pos, vec2i destination_size, vec2i source_pos, vec2i source_size, vec2i texture_size, gsr_rotation rotation, gsr_source_color source_color, bool external_texture, bool alpha_blending); +void gsr_color_conversion_clear(gsr_color_conversion *self); +void gsr_color_conversion_read_destination_texture(gsr_color_conversion *self, int destination_texture_index, int x, int y, int width, int height, unsigned int color_format, unsigned int data_format, void *pixels); + +gsr_rotation gsr_monitor_rotation_to_rotation(gsr_monitor_rotation monitor_rotation); + +#endif /* GSR_COLOR_CONVERSION_H */ diff --git a/include/cuda.h b/include/cuda.h new file mode 100644 index 0000000..fd1f9f9 --- /dev/null +++ b/include/cuda.h @@ -0,0 +1,108 @@ +#ifndef GSR_CUDA_H +#define GSR_CUDA_H + +#include "overclock.h" +#include <stddef.h> +#include <stdbool.h> + +// To prevent hwcontext_cuda.h from including cuda.h +#define CUDA_VERSION 11070 + +#define CU_CTX_SCHED_AUTO 0 + +#if defined(_WIN64) || defined(__LP64__) +typedef unsigned long long CUdeviceptr_v2; +#else +typedef unsigned int CUdeviceptr_v2; +#endif +typedef CUdeviceptr_v2 CUdeviceptr; + +typedef int CUresult; +typedef int CUdevice_v1; +typedef CUdevice_v1 CUdevice; +typedef struct CUctx_st *CUcontext; +typedef struct CUstream_st *CUstream; +typedef struct CUarray_st *CUarray; + +#define CUDA_SUCCESS 0 + +typedef enum CUgraphicsMapResourceFlags_enum { + CU_GRAPHICS_MAP_RESOURCE_FLAGS_NONE = 0x00, + CU_GRAPHICS_MAP_RESOURCE_FLAGS_READ_ONLY = 0x01, + CU_GRAPHICS_MAP_RESOURCE_FLAGS_WRITE_DISCARD = 0x02 +} CUgraphicsMapResourceFlags; + +typedef enum CUgraphicsRegisterFlags_enum { + CU_GRAPHICS_REGISTER_FLAGS_NONE = 0x00, + CU_GRAPHICS_REGISTER_FLAGS_READ_ONLY = 0x01, + CU_GRAPHICS_REGISTER_FLAGS_WRITE_DISCARD = 0x02, + CU_GRAPHICS_REGISTER_FLAGS_SURFACE_LDST = 0x04, + CU_GRAPHICS_REGISTER_FLAGS_TEXTURE_GATHER = 0x08 +} CUgraphicsRegisterFlags; + +typedef enum CUmemorytype_enum { + CU_MEMORYTYPE_HOST = 0x01, /**< Host memory */ + CU_MEMORYTYPE_DEVICE = 0x02, /**< Device memory */ + CU_MEMORYTYPE_ARRAY = 0x03, /**< Array memory */ + CU_MEMORYTYPE_UNIFIED = 0x04 /**< Unified device or host memory */ +} CUmemorytype; + +typedef struct CUDA_MEMCPY2D_st { + size_t srcXInBytes; /**< Source X in bytes */ + size_t srcY; /**< Source Y */ + + CUmemorytype srcMemoryType; /**< Source memory type (host, device, array) */ + const void *srcHost; /**< Source host pointer */ + CUdeviceptr srcDevice; /**< Source device pointer */ + CUarray srcArray; /**< Source array reference */ + size_t srcPitch; /**< Source pitch (ignored when src is array) */ + + size_t dstXInBytes; /**< Destination X in bytes */ + size_t dstY; /**< Destination Y */ + + CUmemorytype dstMemoryType; /**< Destination memory type (host, device, array) */ + void *dstHost; /**< Destination host pointer */ + CUdeviceptr dstDevice; /**< Destination device pointer */ + CUarray dstArray; /**< Destination array reference */ + size_t dstPitch; /**< Destination pitch (ignored when dst is array) */ + + size_t WidthInBytes; /**< Width of 2D memory copy in bytes */ + size_t Height; /**< Height of 2D memory copy */ +} CUDA_MEMCPY2D_v2; +typedef CUDA_MEMCPY2D_v2 CUDA_MEMCPY2D; + +typedef struct CUgraphicsResource_st *CUgraphicsResource; + +typedef struct gsr_cuda gsr_cuda; +struct gsr_cuda { + gsr_overclock overclock; + bool do_overclock; + + void *library; + CUcontext cu_ctx; + + CUresult (*cuInit)(unsigned int Flags); + CUresult (*cuDeviceGetCount)(int *count); + CUresult (*cuDeviceGet)(CUdevice *device, int ordinal); + CUresult (*cuCtxCreate_v2)(CUcontext *pctx, unsigned int flags, CUdevice dev); + CUresult (*cuCtxDestroy_v2)(CUcontext ctx); + CUresult (*cuCtxPushCurrent_v2)(CUcontext ctx); + CUresult (*cuCtxPopCurrent_v2)(CUcontext *pctx); + CUresult (*cuGetErrorString)(CUresult error, const char **pStr); + CUresult (*cuMemcpy2D_v2)(const CUDA_MEMCPY2D *pCopy); + CUresult (*cuMemcpy2DAsync_v2)(const CUDA_MEMCPY2D *pcopy, CUstream hStream); + CUresult (*cuStreamSynchronize)(CUstream hStream); + + CUresult (*cuGraphicsGLRegisterImage)(CUgraphicsResource *pCudaResource, unsigned int image, unsigned int target, unsigned int flags); + CUresult (*cuGraphicsEGLRegisterImage)(CUgraphicsResource *pCudaResource, void *image, unsigned int flags); + CUresult (*cuGraphicsResourceSetMapFlags)(CUgraphicsResource resource, unsigned int flags); + CUresult (*cuGraphicsMapResources)(unsigned int count, CUgraphicsResource *resources, CUstream hStream); + CUresult (*cuGraphicsUnmapResources)(unsigned int count, CUgraphicsResource *resources, CUstream hStream); + CUresult (*cuGraphicsUnregisterResource)(CUgraphicsResource resource); + CUresult (*cuGraphicsSubResourceGetMappedArray)(CUarray *pArray, CUgraphicsResource resource, unsigned int arrayIndex, unsigned int mipLevel); +}; + +bool gsr_cuda_load(gsr_cuda *self, Display *display, bool overclock); +void gsr_cuda_unload(gsr_cuda *self); + +#endif /* GSR_CUDA_H */ diff --git a/include/cursor.h b/include/cursor.h new file mode 100644 index 0000000..1564714 --- /dev/null +++ b/include/cursor.h @@ -0,0 +1,28 @@ +#ifndef GSR_CURSOR_H +#define GSR_CURSOR_H + +#include "egl.h" +#include "vec2.h" + +typedef struct { + gsr_egl *egl; + Display *display; + int x_fixes_event_base; + + unsigned int texture_id; + vec2i size; + vec2i hotspot; + vec2i position; + + bool cursor_image_set; + bool visible; +} gsr_cursor; + +int gsr_cursor_init(gsr_cursor *self, gsr_egl *egl, Display *display); +void gsr_cursor_deinit(gsr_cursor *self); + +/* Returns true if the cursor image has updated or if the cursor has moved */ +bool gsr_cursor_on_event(gsr_cursor *self, XEvent *xev); +void gsr_cursor_tick(gsr_cursor *self, Window relative_to); + +#endif /* GSR_CURSOR_H */ diff --git a/include/damage.h b/include/damage.h new file mode 100644 index 0000000..4b10e58 --- /dev/null +++ b/include/damage.h @@ -0,0 +1,52 @@ +#ifndef GSR_DAMAGE_H +#define GSR_DAMAGE_H + +#include "cursor.h" +#include "utils.h" +#include <stdbool.h> +#include <stdint.h> + +typedef struct _XDisplay Display; +typedef union _XEvent XEvent; + +typedef enum { + GSR_DAMAGE_TRACK_NONE, + GSR_DAMAGE_TRACK_WINDOW, + GSR_DAMAGE_TRACK_MONITOR +} gsr_damage_track_type; + +typedef struct { + gsr_egl *egl; + Display *display; + bool track_cursor; + gsr_damage_track_type track_type; + + int damage_event; + int damage_error; + uint64_t damage; + bool damaged; + + int randr_event; + int randr_error; + + uint64_t window; + //vec2i window_pos; + vec2i window_size; + + gsr_cursor cursor; /* Relative to |window| */ + gsr_monitor monitor; + char monitor_name[32]; +} gsr_damage; + +bool gsr_damage_init(gsr_damage *self, gsr_egl *egl, bool track_cursor); +void gsr_damage_deinit(gsr_damage *self); + +bool gsr_damage_set_target_window(gsr_damage *self, uint64_t window); +bool gsr_damage_set_target_monitor(gsr_damage *self, const char *monitor_name); +void gsr_damage_on_event(gsr_damage *self, XEvent *xev); +void gsr_damage_tick(gsr_damage *self); +/* Also returns true if damage tracking is not available */ +bool gsr_damage_is_damaged(gsr_damage *self); +void gsr_damage_clear(gsr_damage *self); + +#endif /* GSR_DAMAGE_H */ diff --git a/include/dbus.h b/include/dbus.h new file mode 100644 index 0000000..229f7ea --- /dev/null +++ b/include/dbus.h @@ -0,0 +1,49 @@ +#ifndef GSR_DBUS_H +#define GSR_DBUS_H + +#include <stdbool.h> +#include <stdint.h> +#include <dbus/dbus.h> + +#define DBUS_RANDOM_STR_SIZE 16 + +typedef enum { + GSR_PORTAL_CAPTURE_TYPE_MONITOR = 1 << 0, + GSR_PORTAL_CAPTURE_TYPE_WINDOW = 1 << 1, + GSR_PORTAL_CAPTURE_TYPE_VIRTUAL = 1 << 2, + GSR_PORTAL_CAPTURE_TYPE_ALL = GSR_PORTAL_CAPTURE_TYPE_MONITOR | GSR_PORTAL_CAPTURE_TYPE_WINDOW | GSR_PORTAL_CAPTURE_TYPE_VIRTUAL +} gsr_portal_capture_type; + +typedef enum { + GSR_PORTAL_CURSOR_MODE_HIDDEN = 1 << 0, + GSR_PORTAL_CURSOR_MODE_EMBEDDED = 1 << 1, + GSR_PORTAL_CURSOR_MODE_METADATA = 1 << 2 +} gsr_portal_cursor_mode; + +typedef struct { + DBusConnection *con; + DBusError err; + char random_str[DBUS_RANDOM_STR_SIZE + 1]; + unsigned int handle_counter; + bool desktop_portal_rule_added; + uint32_t screencast_version; + char *screencast_restore_token; +} gsr_dbus; + +/* Blocking. TODO: Make non-blocking */ +bool gsr_dbus_init(gsr_dbus *self, const char *screencast_restore_token); +void gsr_dbus_deinit(gsr_dbus *self); + +/* The follow functions should be called in order to setup ScreenCast properly */ +/* These functions that return an int return the response status code */ +int gsr_dbus_screencast_create_session(gsr_dbus *self, char **session_handle); +/* + |capture_type| is a bitmask of gsr_portal_capture_type values. gsr_portal_capture_type values that are not supported by the desktop portal will be ignored. + |gsr_portal_cursor_mode| is a bitmask of gsr_portal_cursor_mode values. gsr_portal_cursor_mode values that are not supported will be ignored. +*/ +int gsr_dbus_screencast_select_sources(gsr_dbus *self, const char *session_handle, uint32_t capture_type, uint32_t cursor_mode); +int gsr_dbus_screencast_start(gsr_dbus *self, const char *session_handle, uint32_t *pipewire_node); +bool gsr_dbus_screencast_open_pipewire_remote(gsr_dbus *self, const char *session_handle, int *pipewire_fd); +const char* gsr_dbus_screencast_get_restore_token(gsr_dbus *self); + +#endif /* GSR_DBUS_H */ diff --git a/include/defs.h b/include/defs.h new file mode 100644 index 0000000..d780005 --- /dev/null +++ b/include/defs.h @@ -0,0 +1,112 @@ +#ifndef GSR_DEFS_H +#define GSR_DEFS_H + +#include <stdbool.h> + +#define GSR_VIDEO_CODEC_AUTO -1 +#define GSR_BITRATE_MODE_AUTO -1 + +typedef enum { + GSR_GPU_VENDOR_AMD, + GSR_GPU_VENDOR_INTEL, + GSR_GPU_VENDOR_NVIDIA, + GSR_GPU_VENDOR_BROADCOM, +} gsr_gpu_vendor; + +typedef struct { + gsr_gpu_vendor vendor; + int gpu_version; /* 0 if unknown */ + bool is_steam_deck; +} gsr_gpu_info; + +typedef enum { + GSR_MONITOR_ROT_0, + GSR_MONITOR_ROT_90, + GSR_MONITOR_ROT_180, + GSR_MONITOR_ROT_270, +} gsr_monitor_rotation; + +typedef enum { + GSR_CONNECTION_X11, + GSR_CONNECTION_WAYLAND, + GSR_CONNECTION_DRM, +} gsr_connection_type; + +typedef enum { + GSR_VIDEO_QUALITY_MEDIUM, + GSR_VIDEO_QUALITY_HIGH, + GSR_VIDEO_QUALITY_VERY_HIGH, + GSR_VIDEO_QUALITY_ULTRA, +} gsr_video_quality; + +typedef enum { + GSR_VIDEO_CODEC_H264, + GSR_VIDEO_CODEC_HEVC, + GSR_VIDEO_CODEC_HEVC_HDR, + GSR_VIDEO_CODEC_HEVC_10BIT, + GSR_VIDEO_CODEC_AV1, + GSR_VIDEO_CODEC_AV1_HDR, + GSR_VIDEO_CODEC_AV1_10BIT, + GSR_VIDEO_CODEC_VP8, + GSR_VIDEO_CODEC_VP9, + GSR_VIDEO_CODEC_H264_VULKAN, + GSR_VIDEO_CODEC_HEVC_VULKAN, +} gsr_video_codec; + +typedef enum { + GSR_AUDIO_CODEC_AAC, + GSR_AUDIO_CODEC_OPUS, + GSR_AUDIO_CODEC_FLAC, +} gsr_audio_codec; + +typedef enum { + GSR_PIXEL_FORMAT_YUV420, + GSR_PIXEL_FORMAT_YUV444, +} gsr_pixel_format; + +typedef enum { + GSR_FRAMERATE_MODE_CONSTANT, + GSR_FRAMERATE_MODE_VARIABLE, + GSR_FRAMERATE_MODE_CONTENT, +} gsr_framerate_mode; + +typedef enum { + GSR_BITRATE_MODE_QP, + GSR_BITRATE_MODE_VBR, + GSR_BITRATE_MODE_CBR, +} gsr_bitrate_mode; + +typedef enum { + GSR_TUNE_PERFORMANCE, + GSR_TUNE_QUALITY, +} gsr_tune; + +typedef enum { + GSR_VIDEO_ENCODER_HW_GPU, + GSR_VIDEO_ENCODER_HW_CPU, +} gsr_video_encoder_hardware; + +typedef enum { + GSR_COLOR_RANGE_LIMITED, + GSR_COLOR_RANGE_FULL, +} gsr_color_range; + +typedef enum { + GSR_COLOR_DEPTH_8_BITS, + GSR_COLOR_DEPTH_10_BITS, +} gsr_color_depth; + +typedef enum { + GSR_REPLAY_STORAGE_RAM, + GSR_REPLAY_STORAGE_DISK, +} gsr_replay_storage; + +bool video_codec_is_hdr(gsr_video_codec video_codec); +gsr_video_codec hdr_video_codec_to_sdr_video_codec(gsr_video_codec video_codec); +gsr_color_depth video_codec_to_bit_depth(gsr_video_codec video_codec); +const char* video_codec_to_string(gsr_video_codec video_codec); +bool video_codec_is_av1(gsr_video_codec video_codec); +bool video_codec_is_vulkan(gsr_video_codec video_codec); +const char* audio_codec_get_name(gsr_audio_codec audio_codec); + +#endif /* GSR_DEFS_H */ diff --git a/include/egl.h b/include/egl.h new file mode 100644 index 0000000..e11557e --- /dev/null +++ b/include/egl.h @@ -0,0 +1,329 @@ +#ifndef GSR_EGL_H +#define GSR_EGL_H + +/* OpenGL EGL library with a hidden window context (to allow using the opengl functions) */ + +#include <X11/X.h> +#include <X11/Xutil.h> +#include <stdbool.h> +#include <stdint.h> +#include "vec2.h" +#include "defs.h" + +typedef struct gsr_window gsr_window; + +#ifdef _WIN64 +typedef signed long long int khronos_intptr_t; +typedef unsigned long long int khronos_uintptr_t; +typedef signed long long int khronos_ssize_t; +typedef unsigned long long int khronos_usize_t; +#else +typedef signed long int khronos_intptr_t; +typedef unsigned long int khronos_uintptr_t; +typedef signed long int khronos_ssize_t; +typedef unsigned long int khronos_usize_t; +#endif + +typedef void* EGLDisplay; +typedef void* EGLNativeDisplayType; +typedef uintptr_t EGLNativeWindowType; +typedef uintptr_t EGLNativePixmapType; +typedef void* EGLConfig; +typedef void* EGLSurface; +typedef void* EGLContext; +typedef void* EGLClientBuffer; +typedef void* EGLImage; +typedef void* EGLImageKHR; +typedef void *GLeglImageOES; +typedef void (*__eglMustCastToProperFunctionPointerType)(void); +typedef struct __GLXFBConfigRec *GLXFBConfig; +typedef struct __GLXcontextRec *GLXContext; +typedef XID GLXDrawable; +typedef void(*__GLXextFuncPtr)(void); + +#define EGL_SUCCESS 0x3000 +#define EGL_BUFFER_SIZE 0x3020 +#define EGL_RENDERABLE_TYPE 0x3040 +#define EGL_OPENGL_API 0x30A2 +#define EGL_OPENGL_ES_API 0x30A0 +#define EGL_OPENGL_BIT 0x0008 +#define EGL_OPENGL_ES_BIT 0x0001 +#define EGL_OPENGL_ES2_BIT 0x0004 +#define EGL_OPENGL_ES3_BIT 0x00000040 +#define EGL_NONE 0x3038 +#define EGL_CONTEXT_CLIENT_VERSION 0x3098 +#define EGL_BACK_BUFFER 0x3084 +#define EGL_GL_TEXTURE_2D 0x30B1 +#define EGL_TRUE 1 +#define EGL_IMAGE_PRESERVED_KHR 0x30D2 +#define EGL_NATIVE_PIXMAP_KHR 0x30B0 +#define EGL_LINUX_DRM_FOURCC_EXT 0x3271 +#define EGL_WIDTH 0x3057 +#define EGL_HEIGHT 0x3056 +#define EGL_DMA_BUF_PLANE0_FD_EXT 0x3272 +#define EGL_DMA_BUF_PLANE0_OFFSET_EXT 0x3273 +#define EGL_DMA_BUF_PLANE0_PITCH_EXT 0x3274 +#define EGL_DMA_BUF_PLANE1_FD_EXT 0x3275 +#define EGL_DMA_BUF_PLANE1_OFFSET_EXT 0x3276 +#define EGL_DMA_BUF_PLANE1_PITCH_EXT 0x3277 +#define EGL_DMA_BUF_PLANE2_FD_EXT 0x3278 +#define EGL_DMA_BUF_PLANE2_OFFSET_EXT 0x3279 +#define EGL_DMA_BUF_PLANE2_PITCH_EXT 0x327A +#define EGL_DMA_BUF_PLANE3_FD_EXT 0x3440 +#define EGL_DMA_BUF_PLANE3_OFFSET_EXT 0x3441 +#define EGL_DMA_BUF_PLANE3_PITCH_EXT 0x3442 +#define EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT 0x3443 +#define EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT 0x3444 +#define EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT 0x3445 +#define EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT 0x3446 +#define EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT 0x3447 +#define EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT 0x3448 +#define EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT 0x3449 +#define EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT 0x344A +#define EGL_LINUX_DMA_BUF_EXT 0x3270 +#define EGL_RED_SIZE 0x3024 +#define EGL_ALPHA_SIZE 0x3021 +#define EGL_BLUE_SIZE 0x3022 +#define EGL_GREEN_SIZE 0x3023 +#define EGL_CONTEXT_PRIORITY_LEVEL_IMG 0x3100 +#define EGL_CONTEXT_PRIORITY_HIGH_IMG 0x3101 +#define EGL_CONTEXT_PRIORITY_MEDIUM_IMG 0x3102 +#define EGL_CONTEXT_PRIORITY_LOW_IMG 0x3103 +#define EGL_DEVICE_EXT 0x322C +#define EGL_DRM_DEVICE_FILE_EXT 0x3233 + +#define GL_FLOAT 0x1406 +#define GL_FALSE 0 +#define GL_TRUE 1 +#define GL_TRIANGLES 0x0004 +#define GL_TEXTURE_2D 0x0DE1 +#define GL_TEXTURE_EXTERNAL_OES 0x8D65 +#define GL_RED 0x1903 +#define GL_GREEN 0x1904 +#define GL_BLUE 0x1905 +#define GL_ALPHA 0x1906 +#define GL_TEXTURE_SWIZZLE_RGBA 0x8E46 +#define GL_RG 0x8227 +#define GL_RGB 0x1907 +#define GL_RGBA 0x1908 +#define GL_RGB8 0x8051 +#define GL_RGBA8 0x8058 +#define GL_R8 0x8229 +#define GL_RG8 0x822B +#define GL_R16 0x822A +#define GL_RG16 0x822C +#define GL_RGB16 0x8054 +#define GL_RGBA32F 0x8814 +#define GL_UNSIGNED_BYTE 0x1401 +#define GL_COLOR_BUFFER_BIT 0x00004000 +#define GL_TEXTURE_WRAP_S 0x2802 +#define GL_TEXTURE_WRAP_T 0x2803 +#define GL_TEXTURE_MAG_FILTER 0x2800 +#define GL_TEXTURE_MIN_FILTER 0x2801 +#define GL_TEXTURE_WIDTH 0x1000 +#define GL_TEXTURE_HEIGHT 0x1001 +#define GL_NEAREST 0x2600 +#define GL_CLAMP_TO_EDGE 0x812F +#define GL_LINEAR 0x2601 +#define GL_FRAMEBUFFER 0x8D40 +#define GL_COLOR_ATTACHMENT0 0x8CE0 +#define GL_FRAMEBUFFER_COMPLETE 0x8CD5 +#define GL_DYNAMIC_DRAW 0x88E8 +#define GL_ARRAY_BUFFER 0x8892 +#define GL_BLEND 0x0BE2 +#define GL_SRC_ALPHA 0x0302 +#define GL_ONE_MINUS_SRC_ALPHA 0x0303 +#define GL_DEBUG_OUTPUT 0x92E0 +#define GL_SCISSOR_TEST 0x0C11 +#define GL_PACK_ALIGNMENT 0x0D05 +#define GL_UNPACK_ALIGNMENT 0x0CF5 +#define GL_READ_ONLY 0x88B8 +#define GL_WRITE_ONLY 0x88B9 +#define GL_READ_WRITE 0x88BA +#define GL_MAX_COMPUTE_FIXED_GROUP_INVOCATIONS 0x90EB +#define GL_TEXTURE0 0x84C0 +#define GL_TEXTURE1 0x84C1 +#define GL_SHADER_IMAGE_ACCESS_BARRIER_BIT 0x00000020 +#define GL_ALL_BARRIER_BITS 0xFFFFFFFF + +#define GL_VENDOR 0x1F00 +#define GL_RENDERER 0x1F01 +#define GL_VERSION 0x1F02 + +#define GL_COMPILE_STATUS 0x8B81 +#define GL_INFO_LOG_LENGTH 0x8B84 +#define GL_FRAGMENT_SHADER 0x8B30 +#define GL_VERTEX_SHADER 0x8B31 +#define GL_COMPUTE_SHADER 0x91B9 +#define GL_COMPILE_STATUS 0x8B81 +#define GL_LINK_STATUS 0x8B82 + +typedef unsigned int (*FUNC_eglExportDMABUFImageQueryMESA)(EGLDisplay dpy, EGLImageKHR image, int *fourcc, int *num_planes, uint64_t *modifiers); +typedef unsigned int (*FUNC_eglExportDMABUFImageMESA)(EGLDisplay dpy, EGLImageKHR image, int *fds, int32_t *strides, int32_t *offsets); +typedef void (*FUNC_glEGLImageTargetTexture2DOES)(unsigned int target, GLeglImageOES image); +typedef GLXContext (*FUNC_glXCreateContextAttribsARB)(Display *dpy, GLXFBConfig config, GLXContext share_context, Bool direct, const int *attrib_list); +typedef void (*FUNC_glXSwapIntervalEXT)(Display * dpy, GLXDrawable drawable, int interval); +typedef int (*FUNC_glXSwapIntervalMESA)(unsigned int interval); +typedef int (*FUNC_glXSwapIntervalSGI)(int interval); +typedef void (*GLDEBUGPROC)(unsigned int source, unsigned int type, unsigned int id, unsigned int severity, int length, const char *message, const void *userParam); +typedef int (*FUNC_eglQueryDisplayAttribEXT)(EGLDisplay dpy, int32_t attribute, intptr_t *value); +typedef const char* (*FUNC_eglQueryDeviceStringEXT)(void *device, int32_t name); +typedef int (*FUNC_eglQueryDmaBufModifiersEXT)(EGLDisplay dpy, int32_t format, int32_t max_modifiers, uint64_t *modifiers, int *external_only, int32_t *num_modifiers); +typedef void (*FUNC_glCreateMemoryObjectsEXT)(int n, unsigned int *memoryObjects); +typedef void (*FUNC_glImportMemoryFdEXT)(unsigned int memory, uint64_t size, unsigned int handleType, int fd); +typedef unsigned char (*FUNC_glIsMemoryObjectEXT)(unsigned int memoryObject); +typedef void (*FUNC_glTexStorageMem2DEXT)(unsigned int target, int levels, unsigned int internalFormat, int width, int height, unsigned int memory, uint64_t offset); +typedef void (*FUNC_glBufferStorageMemEXT)(unsigned int target, ssize_t size, unsigned int memory, uint64_t offset); +typedef void (*FUNC_glNamedBufferStorageMemEXT)(unsigned int buffer, ssize_t size, unsigned int memory, uint64_t offset); +typedef void (*FUNC_glMemoryObjectParameterivEXT)(unsigned int memoryObject, unsigned int pname, const int *params); + +typedef enum { + GSR_GL_CONTEXT_TYPE_EGL, + GSR_GL_CONTEXT_TYPE_GLX +} gsr_gl_context_type; + +typedef struct gsr_egl gsr_egl; +struct gsr_egl { + void *egl_library; + void *glx_library; + void *gl_library; + + gsr_gl_context_type context_type; + gsr_window *window; + + EGLDisplay egl_display; + EGLSurface egl_surface; + EGLContext egl_context; + const char *dri_card_path; + + void *glx_context; + void *glx_fb_config; + + gsr_gpu_info gpu_info; + + char card_path[128]; + + int32_t (*eglGetError)(void); + EGLDisplay (*eglGetDisplay)(EGLNativeDisplayType display_id); + unsigned int (*eglInitialize)(EGLDisplay dpy, int32_t *major, int32_t *minor); + unsigned int (*eglTerminate)(EGLDisplay dpy); + unsigned int (*eglChooseConfig)(EGLDisplay dpy, const int32_t *attrib_list, EGLConfig *configs, int32_t config_size, int32_t *num_config); + EGLSurface (*eglCreateWindowSurface)(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const int32_t *attrib_list); + EGLContext (*eglCreateContext)(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const int32_t *attrib_list); + unsigned int (*eglMakeCurrent)(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx); + EGLImage (*eglCreateImage)(EGLDisplay dpy, EGLContext ctx, unsigned int target, EGLClientBuffer buffer, const intptr_t *attrib_list); + unsigned int (*eglDestroyContext)(EGLDisplay dpy, EGLContext ctx); + unsigned int (*eglDestroySurface)(EGLDisplay dpy, EGLSurface surface); + unsigned int (*eglDestroyImage)(EGLDisplay dpy, EGLImage image); + unsigned int (*eglSwapInterval)(EGLDisplay dpy, int32_t interval); + unsigned int (*eglSwapBuffers)(EGLDisplay dpy, EGLSurface surface); + unsigned int (*eglBindAPI)(unsigned int api); + __eglMustCastToProperFunctionPointerType (*eglGetProcAddress)(const char *procname); + + FUNC_eglExportDMABUFImageQueryMESA eglExportDMABUFImageQueryMESA; + FUNC_eglExportDMABUFImageMESA eglExportDMABUFImageMESA; + FUNC_glEGLImageTargetTexture2DOES glEGLImageTargetTexture2DOES; + FUNC_eglQueryDisplayAttribEXT eglQueryDisplayAttribEXT; + FUNC_eglQueryDeviceStringEXT eglQueryDeviceStringEXT; + FUNC_eglQueryDmaBufModifiersEXT eglQueryDmaBufModifiersEXT; + FUNC_glCreateMemoryObjectsEXT glCreateMemoryObjectsEXT; + FUNC_glImportMemoryFdEXT glImportMemoryFdEXT; + FUNC_glIsMemoryObjectEXT glIsMemoryObjectEXT; + FUNC_glTexStorageMem2DEXT glTexStorageMem2DEXT; + FUNC_glBufferStorageMemEXT glBufferStorageMemEXT; + FUNC_glNamedBufferStorageMemEXT glNamedBufferStorageMemEXT; + FUNC_glMemoryObjectParameterivEXT glMemoryObjectParameterivEXT; + + __GLXextFuncPtr (*glXGetProcAddress)(const unsigned char *procName); + GLXFBConfig* (*glXChooseFBConfig)(Display *dpy, int screen, const int *attribList, int *nitems); + Bool (*glXMakeContextCurrent)(Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx); + // TODO: Remove + GLXContext (*glXCreateNewContext)(Display *dpy, GLXFBConfig config, int renderType, GLXContext shareList, Bool direct); + void (*glXDestroyContext)(Display *dpy, GLXContext ctx); + void (*glXSwapBuffers)(Display *dpy, GLXDrawable drawable); + FUNC_glXCreateContextAttribsARB glXCreateContextAttribsARB; + + /* Optional */ + FUNC_glXSwapIntervalEXT glXSwapIntervalEXT; + FUNC_glXSwapIntervalMESA glXSwapIntervalMESA; + FUNC_glXSwapIntervalSGI glXSwapIntervalSGI; + + unsigned int (*glGetError)(void); + const unsigned char* (*glGetString)(unsigned int name); + void (*glFlush)(void); + void (*glFinish)(void); + void (*glClear)(unsigned int mask); + void (*glClearColor)(float red, float green, float blue, float alpha); + void (*glGenTextures)(int n, unsigned int *textures); + void (*glDeleteTextures)(int n, const unsigned int *texture); + void (*glActiveTexture)(unsigned int texture); + void (*glBindTexture)(unsigned int target, unsigned int texture); + void (*glBindImageTexture)(unsigned int unit, unsigned int texture, int level, unsigned char layered, int layer, unsigned int access, unsigned int format); + void (*glTexParameteri)(unsigned int target, unsigned int pname, int param); + void (*glTexParameteriv)(unsigned int target, unsigned int pname, const int *params); + void (*glTexParameterfv)(unsigned int target, unsigned int pname, const float *params); + void (*glGetTexLevelParameteriv)(unsigned int target, int level, unsigned int pname, int *params); + void (*glTexImage2D)(unsigned int target, int level, int internalFormat, int width, int height, int border, unsigned int format, unsigned int type, const void *pixels); + void (*glTexSubImage2D)(unsigned int target, int level, int xoffset, int yoffset, int width, int height, unsigned format, unsigned type, const void *pixels); + void (*glTexStorage2D)(unsigned int target, int levels, unsigned int internalformat, int width, int height); + void (*glGetTexImage)(unsigned int target, int level, unsigned int format, unsigned int type, void *pixels); + void (*glGenFramebuffers)(int n, unsigned int *framebuffers); + void (*glBindFramebuffer)(unsigned int target, unsigned int framebuffer); + void (*glDeleteFramebuffers)(int n, const unsigned int *framebuffers); + void (*glDispatchCompute)(unsigned int num_groups_x, unsigned int num_groups_y, unsigned int num_groups_z); + void (*glMemoryBarrier)(unsigned int barriers); + void (*glViewport)(int x, int y, int width, int height); + void (*glFramebufferTexture2D)(unsigned int target, unsigned int attachment, unsigned int textarget, unsigned int texture, int level); + void (*glDrawBuffers)(int n, const unsigned int *bufs); + unsigned int (*glCheckFramebufferStatus)(unsigned int target); + void (*glBindBuffer)(unsigned int target, unsigned int buffer); + void (*glGenBuffers)(int n, unsigned int *buffers); + void (*glBufferData)(unsigned int target, khronos_ssize_t size, const void *data, unsigned int usage); + void (*glBufferSubData)(unsigned int target, khronos_intptr_t offset, khronos_ssize_t size, const void *data); + void (*glDeleteBuffers)(int n, const unsigned int *buffers); + void (*glGenVertexArrays)(int n, unsigned int *arrays); + void (*glBindVertexArray)(unsigned int array); + void (*glDeleteVertexArrays)(int n, const unsigned int *arrays); + unsigned int (*glCreateProgram)(void); + unsigned int (*glCreateShader)(unsigned int type); + void (*glAttachShader)(unsigned int program, unsigned int shader); + void (*glBindAttribLocation)(unsigned int program, unsigned int index, const char *name); + void (*glCompileShader)(unsigned int shader); + void (*glLinkProgram)(unsigned int program); + void (*glShaderSource)(unsigned int shader, int count, const char *const*string, const int *length); + void (*glUseProgram)(unsigned int program); + void (*glGetProgramInfoLog)(unsigned int program, int bufSize, int *length, char *infoLog); + void (*glGetShaderiv)(unsigned int shader, unsigned int pname, int *params); + void (*glGetShaderInfoLog)(unsigned int shader, int bufSize, int *length, char *infoLog); + void (*glDeleteProgram)(unsigned int program); + void (*glDeleteShader)(unsigned int shader); + void (*glGetProgramiv)(unsigned int program, unsigned int pname, int *params); + void (*glVertexAttribPointer)(unsigned int index, int size, unsigned int type, unsigned char normalized, int stride, const void *pointer); + void (*glEnableVertexAttribArray)(unsigned int index); + void (*glDrawArrays)(unsigned int mode, int first, int count); + void (*glEnable)(unsigned int cap); + void (*glDisable)(unsigned int cap); + void (*glBlendFunc)(unsigned int sfactor, unsigned int dfactor); + void (*glPixelStorei)(unsigned int pname, int param); + int (*glGetUniformLocation)(unsigned int program, const char *name); + void (*glUniform1f)(int location, float v0); + void (*glUniform2f)(int location, float v0, float v1); + void (*glUniform1i)(int location, int v0); + void (*glUniform2i)(int location, int v0, int v1); + void (*glUniformMatrix2fv)(int location, int count, unsigned char transpose, const float *value); + void (*glDebugMessageCallback)(GLDEBUGPROC callback, const void *userParam); + void (*glScissor)(int x, int y, int width, int height); + void (*glCreateBuffers)(int n, unsigned int *buffers); + void (*glReadPixels)(int x, int y, int width, int height, unsigned int format, unsigned int type, void *pixels); + void* (*glMapBuffer)(unsigned int target, unsigned int access); + unsigned char (*glUnmapBuffer)(unsigned int target); + void (*glGetIntegerv)(unsigned int pname, int *params); +}; + +bool gsr_egl_load(gsr_egl *self, gsr_window *window, bool is_monitor_capture, bool enable_debug); +void gsr_egl_unload(gsr_egl *self); + +/* Does opengl swap with egl or glx, depending on which one is active */ +void gsr_egl_swap_buffers(gsr_egl *self); + +#endif /* GSR_EGL_H */ diff --git a/include/encoder/encoder.h b/include/encoder/encoder.h new file mode 100644 index 0000000..7e550f6 --- /dev/null +++ b/include/encoder/encoder.h @@ -0,0 +1,43 @@ +#ifndef GSR_ENCODER_H +#define GSR_ENCODER_H + +#include "../replay_buffer/replay_buffer.h" +#include <stdbool.h> +#include <stdint.h> +#include <stddef.h> +#include <pthread.h> + +#define GSR_MAX_RECORDING_DESTINATIONS 128 + +typedef struct AVCodecContext AVCodecContext; +typedef struct AVFormatContext AVFormatContext; +typedef struct AVStream AVStream; + +typedef struct { + size_t id; + AVCodecContext *codec_context; + AVFormatContext *format_context; + AVStream *stream; + int64_t start_pts; + bool has_received_keyframe; +} gsr_encoder_recording_destination; + +typedef struct { + gsr_replay_buffer *replay_buffer; + pthread_mutex_t file_write_mutex; + bool mutex_created; + + gsr_encoder_recording_destination recording_destinations[GSR_MAX_RECORDING_DESTINATIONS]; + size_t num_recording_destinations; + size_t recording_destination_id_counter; +} gsr_encoder; + +bool gsr_encoder_init(gsr_encoder *self, gsr_replay_storage replay_storage, size_t replay_buffer_num_packets, double replay_buffer_time, const char *replay_directory); +void gsr_encoder_deinit(gsr_encoder *self); + +void gsr_encoder_receive_packets(gsr_encoder *self, AVCodecContext *codec_context, int64_t pts, int stream_index); +/* Returns the id to the recording destination, or -1 on error */ +size_t gsr_encoder_add_recording_destination(gsr_encoder *self, AVCodecContext *codec_context, AVFormatContext *format_context, AVStream *stream, int64_t start_pts); +bool gsr_encoder_remove_recording_destination(gsr_encoder *self, size_t id); + +#endif /* GSR_ENCODER_H */ diff --git a/include/encoder/video/nvenc.h b/include/encoder/video/nvenc.h new file mode 100644 index 0000000..d4a906b --- /dev/null +++ b/include/encoder/video/nvenc.h @@ -0,0 +1,16 @@ +#ifndef GSR_ENCODER_VIDEO_NVENC_H +#define GSR_ENCODER_VIDEO_NVENC_H + +#include "video.h" + +typedef struct gsr_egl gsr_egl; + +typedef struct { + gsr_egl *egl; + bool overclock; + gsr_color_depth color_depth; +} gsr_video_encoder_nvenc_params; + +gsr_video_encoder* gsr_video_encoder_nvenc_create(const gsr_video_encoder_nvenc_params *params); + +#endif /* GSR_ENCODER_VIDEO_NVENC_H */ diff --git a/include/encoder/video/software.h b/include/encoder/video/software.h new file mode 100644 index 0000000..fd2dc6b --- /dev/null +++ b/include/encoder/video/software.h @@ -0,0 +1,15 @@ +#ifndef GSR_ENCODER_VIDEO_SOFTWARE_H +#define GSR_ENCODER_VIDEO_SOFTWARE_H + +#include "video.h" + +typedef struct gsr_egl gsr_egl; + +typedef struct { + gsr_egl *egl; + gsr_color_depth color_depth; +} gsr_video_encoder_software_params; + +gsr_video_encoder* gsr_video_encoder_software_create(const gsr_video_encoder_software_params *params); + +#endif /* GSR_ENCODER_VIDEO_SOFTWARE_H */ diff --git a/include/encoder/video/vaapi.h b/include/encoder/video/vaapi.h new file mode 100644 index 0000000..b509f17 --- /dev/null +++ b/include/encoder/video/vaapi.h @@ -0,0 +1,15 @@ +#ifndef GSR_ENCODER_VIDEO_VAAPI_H +#define GSR_ENCODER_VIDEO_VAAPI_H + +#include "video.h" + +typedef struct gsr_egl gsr_egl; + +typedef struct { + gsr_egl *egl; + gsr_color_depth color_depth; +} gsr_video_encoder_vaapi_params; + +gsr_video_encoder* gsr_video_encoder_vaapi_create(const gsr_video_encoder_vaapi_params *params); + +#endif /* GSR_ENCODER_VIDEO_VAAPI_H */ diff --git a/include/encoder/video/video.h b/include/encoder/video/video.h new file mode 100644 index 0000000..7a706b5 --- /dev/null +++ b/include/encoder/video/video.h @@ -0,0 +1,30 @@ +#ifndef GSR_ENCODER_VIDEO_H +#define GSR_ENCODER_VIDEO_H + +#include "../../color_conversion.h" +#include <stdbool.h> + +#define GSR_MAX_RECORDING_DESTINATIONS 128 + +typedef struct gsr_video_encoder gsr_video_encoder; +typedef struct AVCodecContext AVCodecContext; +typedef struct AVFrame AVFrame; + +struct gsr_video_encoder { + bool (*start)(gsr_video_encoder *encoder, AVCodecContext *video_codec_context, AVFrame *frame); + void (*destroy)(gsr_video_encoder *encoder, AVCodecContext *video_codec_context); + void (*copy_textures_to_frame)(gsr_video_encoder *encoder, AVFrame *frame, gsr_color_conversion *color_conversion); /* Can be NULL */ + /* |textures| should be able to fit 2 elements */ + void (*get_textures)(gsr_video_encoder *encoder, unsigned int *textures, int *num_textures, gsr_destination_color *destination_color); + + void *priv; + bool started; +}; + +/* Set |replay_buffer_time_seconds| and |fps| to 0 to disable replay buffer */ +bool gsr_video_encoder_start(gsr_video_encoder *encoder, AVCodecContext *video_codec_context, AVFrame *frame); +void gsr_video_encoder_destroy(gsr_video_encoder *encoder, AVCodecContext *video_codec_context); +void gsr_video_encoder_copy_textures_to_frame(gsr_video_encoder *encoder, AVFrame *frame, gsr_color_conversion *color_conversion); +void gsr_video_encoder_get_textures(gsr_video_encoder *encoder, unsigned int *textures, int *num_textures, gsr_destination_color *destination_color); + +#endif /* GSR_ENCODER_VIDEO_H */ diff --git a/include/encoder/video/vulkan.h b/include/encoder/video/vulkan.h new file mode 100644 index 0000000..383fc4f --- /dev/null +++ b/include/encoder/video/vulkan.h @@ -0,0 +1,15 @@ +#ifndef GSR_ENCODER_VIDEO_VULKAN_H +#define GSR_ENCODER_VIDEO_VULKAN_H + +#include "video.h" + +typedef struct gsr_egl gsr_egl; + +typedef struct { + gsr_egl *egl; + gsr_color_depth color_depth; +} gsr_video_encoder_vulkan_params; + +gsr_video_encoder* gsr_video_encoder_vulkan_create(const gsr_video_encoder_vulkan_params *params); + +#endif /* GSR_ENCODER_VIDEO_VULKAN_H */ diff --git a/include/image_writer.h b/include/image_writer.h new file mode 100644 index 0000000..65e7497 --- /dev/null +++ b/include/image_writer.h @@ -0,0 +1,35 @@ +#ifndef GSR_IMAGE_WRITER_H +#define GSR_IMAGE_WRITER_H + +#include <stdbool.h> + +typedef struct gsr_egl gsr_egl; + +typedef enum { + GSR_IMAGE_FORMAT_JPEG, + GSR_IMAGE_FORMAT_PNG +} gsr_image_format; + +typedef enum { + GSR_IMAGE_WRITER_SOURCE_OPENGL, + GSR_IMAGE_WRITER_SOURCE_MEMORY +} gsr_image_writer_source; + +typedef struct { + gsr_image_writer_source source; + gsr_egl *egl; + int width; + int height; + unsigned int texture; + const void *memory; /* Reference */ +} gsr_image_writer; + +bool gsr_image_writer_init_opengl(gsr_image_writer *self, gsr_egl *egl, int width, int height); +/* |memory| is taken as a reference. The data is expected to be in rgba8 format (8 bit rgba) */ +bool gsr_image_writer_init_memory(gsr_image_writer *self, const void *memory, int width, int height); +void gsr_image_writer_deinit(gsr_image_writer *self); + +/* Quality is between 1 and 100 where 100 is the max quality. Quality doesn't apply to lossless formats */ +bool gsr_image_writer_write_to_file(gsr_image_writer *self, const char *filepath, gsr_image_format image_format, int quality); + +#endif /* GSR_IMAGE_WRITER_H */ diff --git a/include/library_loader.h b/include/library_loader.h new file mode 100644 index 0000000..47bc9f0 --- /dev/null +++ b/include/library_loader.h @@ -0,0 +1,17 @@ +#ifndef GSR_LIBRARY_LOADER_H +#define GSR_LIBRARY_LOADER_H + +#include <stdbool.h> + +typedef struct { + void **func; + const char *name; +} dlsym_assign; + +void* dlsym_print_fail(void *handle, const char *name, bool required); +/* |dlsyms| should be null terminated */ +bool dlsym_load_list(void *handle, const dlsym_assign *dlsyms); +/* |dlsyms| should be null terminated */ +void dlsym_load_list_optional(void *handle, const dlsym_assign *dlsyms); + +#endif /* GSR_LIBRARY_LOADER_H */ diff --git a/include/overclock.h b/include/overclock.h new file mode 100644 index 0000000..d6ff901 --- /dev/null +++ b/include/overclock.h @@ -0,0 +1,17 @@ +#ifndef GSR_OVERCLOCK_H +#define GSR_OVERCLOCK_H + +#include "xnvctrl.h" + +typedef struct { + gsr_xnvctrl xnvctrl; + int num_performance_levels; +} gsr_overclock; + +bool gsr_overclock_load(gsr_overclock *self, Display *display); +void gsr_overclock_unload(gsr_overclock *self); + +bool gsr_overclock_start(gsr_overclock *self); +void gsr_overclock_stop(gsr_overclock *self); + +#endif /* GSR_OVERCLOCK_H */ diff --git a/include/pipewire_audio.h b/include/pipewire_audio.h new file mode 100644 index 0000000..68e5356 --- /dev/null +++ b/include/pipewire_audio.h @@ -0,0 +1,156 @@ +#ifndef GSR_PIPEWIRE_AUDIO_H +#define GSR_PIPEWIRE_AUDIO_H + +#include <pipewire/thread-loop.h> +#include <pipewire/context.h> +#include <pipewire/core.h> +#include <spa/utils/hook.h> + +#include <stdbool.h> + +typedef enum { + GSR_PIPEWIRE_AUDIO_NODE_TYPE_STREAM_OUTPUT, /* Application audio */ + GSR_PIPEWIRE_AUDIO_NODE_TYPE_STREAM_INPUT, /* Audio recording input */ + GSR_PIPEWIRE_AUDIO_NODE_TYPE_SINK_OR_SOURCE /* Audio output or input device or combined (virtual) sink */ +} gsr_pipewire_audio_node_type; + +typedef struct { + uint32_t id; + char *name; + gsr_pipewire_audio_node_type type; +} gsr_pipewire_audio_node; + +typedef enum { + GSR_PIPEWIRE_AUDIO_PORT_DIRECTION_INPUT, + GSR_PIPEWIRE_AUDIO_PORT_DIRECTION_OUTPUT +} gsr_pipewire_audio_port_direction; + +typedef struct { + uint32_t id; + uint32_t node_id; + gsr_pipewire_audio_port_direction direction; + char *name; +} gsr_pipewire_audio_port; + +typedef struct { + uint32_t id; + uint32_t output_node_id; + uint32_t input_node_id; +} gsr_pipewire_audio_link; + +typedef enum { + GSR_PIPEWIRE_AUDIO_LINK_INPUT_TYPE_STREAM, /* Application */ + GSR_PIPEWIRE_AUDIO_LINK_INPUT_TYPE_SINK /* Combined (virtual) sink */ +} gsr_pipewire_audio_link_input_type; + +typedef enum { + GSR_PIPEWIRE_AUDIO_REQUESTED_TYPE_STANDARD, + GSR_PIPEWIRE_AUDIO_REQUESTED_TYPE_DEFAULT_OUTPUT, + GSR_PIPEWIRE_AUDIO_REQUESTED_TYPE_DEFAULT_INPUT +} gsr_pipewire_audio_requested_type; + +typedef struct { + char *name; + gsr_pipewire_audio_requested_type type; +} gsr_pipewire_audio_requested_output; + +typedef struct { + gsr_pipewire_audio_requested_output *outputs; + int num_outputs; + char *input_name; + bool inverted; + gsr_pipewire_audio_node_type output_type; + gsr_pipewire_audio_link_input_type input_type; +} gsr_pipewire_audio_requested_link; + +typedef struct { + struct pw_thread_loop *thread_loop; + struct pw_context *context; + struct pw_core *core; + struct spa_hook core_listener; + struct pw_registry *registry; + struct spa_hook registry_listener; + int server_version_sync; + + struct pw_proxy *metadata_proxy; + struct spa_hook metadata_listener; + struct spa_hook metadata_proxy_listener; + char default_output_device_name[128]; + char default_input_device_name[128]; + + gsr_pipewire_audio_node *stream_nodes; + size_t num_stream_nodes; + size_t stream_nodes_capacity_items; + + gsr_pipewire_audio_port *ports; + size_t num_ports; + size_t ports_capacity_items; + + gsr_pipewire_audio_link *links; + size_t num_links; + size_t links_capacity_items; + + gsr_pipewire_audio_requested_link *requested_links; + size_t num_requested_links; + size_t requested_links_capacity_items; + + struct pw_proxy **virtual_sink_proxies; + size_t num_virtual_sink_proxies; + size_t virtual_sink_proxies_capacity_items; +} gsr_pipewire_audio; + +bool gsr_pipewire_audio_init(gsr_pipewire_audio *self); +void gsr_pipewire_audio_deinit(gsr_pipewire_audio *self); + +bool gsr_pipewire_audio_create_virtual_sink(gsr_pipewire_audio *self, const char *name); + +/* + This function links audio source outputs from applications that match the name |app_names| to the input + that matches the name |stream_name_input|. + If an application or a new application starts outputting audio after this function is called and the app name matches + then it will automatically link the audio sources. + |app_names| and |stream_name_input| are case-insensitive matches. +*/ +bool gsr_pipewire_audio_add_link_from_apps_to_stream(gsr_pipewire_audio *self, const char **app_names, int num_app_names, const char *stream_name_input); +/* + This function links audio source outputs from all applications except the ones that match the name |app_names| to the input + that matches the name |stream_name_input|. + If an application or a new application starts outputting audio after this function is called and the app name doesn't match + then it will automatically link the audio sources. + |app_names| and |stream_name_input| are case-insensitive matches. +*/ +bool gsr_pipewire_audio_add_link_from_apps_to_stream_inverted(gsr_pipewire_audio *self, const char **app_names, int num_app_names, const char *stream_name_input); + +/* + This function links audio source outputs from applications that match the name |app_names| to the input + that matches the name |sink_name_input|. + If an application or a new application starts outputting audio after this function is called and the app name matches + then it will automatically link the audio sources. + |app_names| and |sink_name_input| are case-insensitive matches. +*/ +bool gsr_pipewire_audio_add_link_from_apps_to_sink(gsr_pipewire_audio *self, const char **app_names, int num_app_names, const char *sink_name_input); +/* + This function links audio source outputs from all applications except the ones that match the name |app_names| to the input + that matches the name |sink_name_input|. + If an application or a new application starts outputting audio after this function is called and the app name doesn't match + then it will automatically link the audio sources. + |app_names| and |sink_name_input| are case-insensitive matches. +*/ +bool gsr_pipewire_audio_add_link_from_apps_to_sink_inverted(gsr_pipewire_audio *self, const char **app_names, int num_app_names, const char *sink_name_input); + +/* + This function links audio source outputs from devices that match the name |source_names| to the input + that matches the name |sink_name_input|. + If a device or a new device starts outputting audio after this function is called and the device name matches + then it will automatically link the audio sources. + |source_names| and |sink_name_input| are case-insensitive matches. + |source_names| can include "default_output" or "default_input" to use the default output/input + and it will automatically switch when the default output/input is changed in system audio settings. +*/ +bool gsr_pipewire_audio_add_link_from_sources_to_sink(gsr_pipewire_audio *self, const char **source_names, int num_source_names, const char *sink_name_input); + +/* Return true to continue */ +typedef bool (*gsr_pipewire_audio_app_query_callback)(const char *app_name, void *userdata); +void gsr_pipewire_audio_for_each_app(gsr_pipewire_audio *self, gsr_pipewire_audio_app_query_callback callback, void *userdata); + +#endif /* GSR_PIPEWIRE_AUDIO_H */ diff --git a/include/pipewire_video.h b/include/pipewire_video.h new file mode 100644 index 0000000..d98e43d --- /dev/null +++ b/include/pipewire_video.h @@ -0,0 +1,117 @@ +#ifndef GSR_PIPEWIRE_VIDEO_H +#define GSR_PIPEWIRE_VIDEO_H + +#include <stdbool.h> +#include <stdint.h> +#include <pthread.h> + +#include <spa/utils/hook.h> +#include <spa/param/video/format.h> + +#define GSR_PIPEWIRE_VIDEO_MAX_MODIFIERS 1024 +#define GSR_PIPEWIRE_VIDEO_MAX_VIDEO_FORMATS 6 +#define GSR_PIPEWIRE_VIDEO_DMABUF_MAX_PLANES 4 + +typedef struct gsr_egl gsr_egl; + +typedef struct { + int major; + int minor; + int micro; +} gsr_pipewire_video_data_version; + +typedef struct { + uint32_t fps_num; + uint32_t fps_den; +} gsr_pipewire_video_video_info; + +typedef struct { + int fd; + uint32_t offset; + int32_t stride; +} gsr_pipewire_video_dmabuf_data; + +typedef struct { + int x, y; + int width, height; +} gsr_pipewire_video_region; + +typedef struct { + enum spa_video_format format; + size_t modifiers_index; + size_t modifiers_size; +} gsr_video_format; + +typedef struct { + unsigned int texture_id; + unsigned int external_texture_id; + unsigned int cursor_texture_id; +} gsr_texture_map; + +typedef struct { + gsr_egl *egl; + int fd; + uint32_t node; + pthread_mutex_t mutex; + bool mutex_initialized; + + struct pw_thread_loop *thread_loop; + struct pw_context *context; + struct pw_core *core; + struct spa_hook core_listener; + struct pw_stream *stream; + struct spa_hook stream_listener; + struct spa_source *reneg; + struct spa_video_info format; + int server_version_sync; + bool negotiated; + bool renegotiated; + bool damaged; + + struct { + bool visible; + bool valid; + uint8_t *data; + int x, y; + int hotspot_x, hotspot_y; + int width, height; + } cursor; + + struct { + bool valid; + int x, y; + uint32_t width, height; + } crop; + + gsr_video_format supported_video_formats[GSR_PIPEWIRE_VIDEO_MAX_VIDEO_FORMATS]; + + gsr_pipewire_video_data_version server_version; + gsr_pipewire_video_video_info video_info; + gsr_pipewire_video_dmabuf_data dmabuf_data[GSR_PIPEWIRE_VIDEO_DMABUF_MAX_PLANES]; + size_t dmabuf_num_planes; + + bool no_modifiers_fallback; + bool external_texture_fallback; + + uint64_t modifiers[GSR_PIPEWIRE_VIDEO_MAX_MODIFIERS]; + size_t num_modifiers; + + bool paused; + double paused_start_secs; +} gsr_pipewire_video; + +/* + |capture_cursor| only applies to when capturing a window or region. + In other cases |pipewire_node|'s setup will determine if the cursor is included. + Note that the cursor is not guaranteed to be shown even if set to true, it depends on the wayland compositor. +*/ +bool gsr_pipewire_video_init(gsr_pipewire_video *self, int pipewire_fd, uint32_t pipewire_node, int fps, bool capture_cursor, gsr_egl *egl); +void gsr_pipewire_video_deinit(gsr_pipewire_video *self); + +/* |dmabuf_data| should be at least GSR_PIPEWIRE_VIDEO_DMABUF_MAX_PLANES in size */ +bool gsr_pipewire_video_map_texture(gsr_pipewire_video *self, gsr_texture_map texture_map, gsr_pipewire_video_region *region, gsr_pipewire_video_region *cursor_region, gsr_pipewire_video_dmabuf_data *dmabuf_data, int *num_dmabuf_data, uint32_t *fourcc, uint64_t *modifiers, bool *using_external_image); +bool gsr_pipewire_video_is_damaged(gsr_pipewire_video *self); +void gsr_pipewire_video_clear_damage(gsr_pipewire_video *self); +bool gsr_pipewire_video_should_restart(gsr_pipewire_video *self); + +#endif /* GSR_PIPEWIRE_VIDEO_H */ diff --git a/include/replay_buffer/replay_buffer.h b/include/replay_buffer/replay_buffer.h new file mode 100644 index 0000000..a04a3be --- /dev/null +++ b/include/replay_buffer/replay_buffer.h @@ -0,0 +1,54 @@ +#ifndef GSR_REPLAY_BUFFER_H +#define GSR_REPLAY_BUFFER_H + +#include "../defs.h" +#include <pthread.h> +#include <stdbool.h> +#include <libavcodec/packet.h> + +typedef struct gsr_replay_buffer gsr_replay_buffer; + +typedef struct { + size_t packet_index; + size_t file_index; +} gsr_replay_buffer_iterator; + +struct gsr_replay_buffer { + void (*destroy)(gsr_replay_buffer *self); + bool (*append)(gsr_replay_buffer *self, const AVPacket *av_packet, double timestamp); + void (*clear)(gsr_replay_buffer *self); + AVPacket* (*iterator_get_packet)(gsr_replay_buffer *self, gsr_replay_buffer_iterator iterator); + /* The returned data should be free'd with free */ + uint8_t* (*iterator_get_packet_data)(gsr_replay_buffer *self, gsr_replay_buffer_iterator iterator); + /* The clone has to be destroyed before the replay buffer it clones is destroyed */ + gsr_replay_buffer* (*clone)(gsr_replay_buffer *self); + /* Returns {0, 0} if replay buffer is empty */ + gsr_replay_buffer_iterator (*find_packet_index_by_time_passed)(gsr_replay_buffer *self, int seconds); + /* Returns {-1, 0} if not found */ + gsr_replay_buffer_iterator (*find_keyframe)(gsr_replay_buffer *self, gsr_replay_buffer_iterator start_iterator, int stream_index, bool invert_stream_index); + bool (*iterator_next)(gsr_replay_buffer *self, gsr_replay_buffer_iterator *iterator); + + pthread_mutex_t mutex; + bool mutex_initialized; + gsr_replay_buffer *original_replay_buffer; +}; + +gsr_replay_buffer* gsr_replay_buffer_create(gsr_replay_storage replay_storage, const char *replay_directory, double replay_buffer_time, size_t replay_buffer_num_packets); +void gsr_replay_buffer_destroy(gsr_replay_buffer *self); + +void gsr_replay_buffer_lock(gsr_replay_buffer *self); +void gsr_replay_buffer_unlock(gsr_replay_buffer *self); +bool gsr_replay_buffer_append(gsr_replay_buffer *self, const AVPacket *av_packet, double timestamp); +void gsr_replay_buffer_clear(gsr_replay_buffer *self); +AVPacket* gsr_replay_buffer_iterator_get_packet(gsr_replay_buffer *self, gsr_replay_buffer_iterator iterator); +/* The returned data should be free'd with free */ +uint8_t* gsr_replay_buffer_iterator_get_packet_data(gsr_replay_buffer *self, gsr_replay_buffer_iterator iterator); +/* The clone has to be destroyed before the replay buffer it clones is destroyed */ +gsr_replay_buffer* gsr_replay_buffer_clone(gsr_replay_buffer *self); +/* Returns {0, 0} if replay buffer is empty */ +gsr_replay_buffer_iterator gsr_replay_buffer_find_packet_index_by_time_passed(gsr_replay_buffer *self, int seconds); +/* Returns {-1, 0} if not found */ +gsr_replay_buffer_iterator gsr_replay_buffer_find_keyframe(gsr_replay_buffer *self, gsr_replay_buffer_iterator start_iterator, int stream_index, bool invert_stream_index); +bool gsr_replay_buffer_iterator_next(gsr_replay_buffer *self, gsr_replay_buffer_iterator *iterator); + +#endif /* GSR_REPLAY_BUFFER_H */
\ No newline at end of file diff --git a/include/replay_buffer/replay_buffer_disk.h b/include/replay_buffer/replay_buffer_disk.h new file mode 100644 index 0000000..6873bb0 --- /dev/null +++ b/include/replay_buffer/replay_buffer_disk.h @@ -0,0 +1,44 @@ +#ifndef GSR_REPLAY_BUFFER_DISK_H +#define GSR_REPLAY_BUFFER_DISK_H + +#include "replay_buffer.h" +#include <limits.h> + +#define GSR_REPLAY_BUFFER_CAPACITY_NUM_FILES 1024 + +typedef struct { + AVPacket packet; + size_t data_index; + double timestamp; +} gsr_av_packet_disk; + +typedef struct { + size_t id; + double start_timestamp; + double end_timestamp; + int ref_counter; + int fd; + + gsr_av_packet_disk *packets; + size_t capacity_num_packets; + size_t num_packets; +} gsr_replay_buffer_file; + +typedef struct { + gsr_replay_buffer replay_buffer; + double replay_buffer_time; + + size_t storage_counter; + size_t storage_num_bytes_written; + int storage_fd; + gsr_replay_buffer_file *files[GSR_REPLAY_BUFFER_CAPACITY_NUM_FILES]; // GSR_REPLAY_BUFFER_CAPACITY_NUM_FILES * REPLAY_BUFFER_FILE_SIZE_BYTES = 256gb, should be enough for everybody + size_t num_files; + + char replay_directory[PATH_MAX]; + + bool owns_directory; +} gsr_replay_buffer_disk; + +gsr_replay_buffer* gsr_replay_buffer_disk_create(const char *replay_directory, double replay_buffer_time); + +#endif /* GSR_REPLAY_BUFFER_DISK_H */
\ No newline at end of file diff --git a/include/replay_buffer/replay_buffer_ram.h b/include/replay_buffer/replay_buffer_ram.h new file mode 100644 index 0000000..a43d1b9 --- /dev/null +++ b/include/replay_buffer/replay_buffer_ram.h @@ -0,0 +1,22 @@ +#ifndef GSR_REPLAY_BUFFER_RAM_H +#define GSR_REPLAY_BUFFER_RAM_H + +#include "replay_buffer.h" + +typedef struct { + AVPacket packet; + int ref_counter; + double timestamp; +} gsr_av_packet_ram; + +typedef struct { + gsr_replay_buffer replay_buffer; + gsr_av_packet_ram **packets; + size_t capacity_num_packets; + size_t num_packets; + size_t index; +} gsr_replay_buffer_ram; + +gsr_replay_buffer* gsr_replay_buffer_ram_create(size_t replay_buffer_num_packets); + +#endif /* GSR_REPLAY_BUFFER_RAM_H */
\ No newline at end of file diff --git a/include/shader.h b/include/shader.h new file mode 100644 index 0000000..285758d --- /dev/null +++ b/include/shader.h @@ -0,0 +1,23 @@ +#ifndef GSR_SHADER_H +#define GSR_SHADER_H + +#include <stdbool.h> + +typedef struct gsr_egl gsr_egl; + +typedef struct { + gsr_egl *egl; + unsigned int program_id; +} gsr_shader; + +/* |vertex_shader| or |fragment_shader| may be NULL */ +int gsr_shader_init(gsr_shader *self, gsr_egl *egl, const char *vertex_shader, const char *fragment_shader, const char *compute_shader); +void gsr_shader_deinit(gsr_shader *self); + +int gsr_shader_bind_attribute_location(gsr_shader *self, const char *attribute, int location); +void gsr_shader_use(gsr_shader *self); +void gsr_shader_use_none(gsr_shader *self); + +void gsr_shader_enable_debug_output(bool enable); + +#endif /* GSR_SHADER_H */ diff --git a/include/sound.hpp b/include/sound.hpp index 666d009..87e2e2d 100644 --- a/include/sound.hpp +++ b/include/sound.hpp @@ -18,20 +18,55 @@ #ifndef GPU_SCREEN_RECORDER_H #define GPU_SCREEN_RECORDER_H +#include <vector> +#include <string> + typedef struct { void *handle; - void *buffer; - int buffer_size; unsigned int frames; } SoundDevice; +struct AudioDevice { + std::string name; + std::string description; +}; + +struct AudioDevices { + std::string default_output; + std::string default_input; + std::vector<AudioDevice> audio_inputs; +}; + +enum class AudioInputType { + DEVICE, + APPLICATION +}; + +struct AudioInput { + std::string name; + AudioInputType type = AudioInputType::DEVICE; + bool inverted = false; +}; + +struct MergedAudioInputs { + std::string track_name; + std::vector<AudioInput> audio_inputs; +}; + +typedef enum { + S16, + S32, + F32 +} AudioFormat; + /* - Get a sound device by name, returning the device into the @device parameter. - The device should be closed with @sound_device_close after it has been used - to clean up internal resources. + Get a sound device by name, returning the device into the |device| parameter. + |device_name| can be a device name or "default_output" or "default_input". + If the device name is "default_output" or "default_input" then it will automatically switch which + device is records from when the default output/input is changed in the system audio settings. Returns 0 on success, or a negative value on failure. */ -int sound_device_get_by_name(SoundDevice *device, const char *name = "default", unsigned int num_channels = 2, unsigned int period_frame_size = 32); +int sound_device_get_by_name(SoundDevice *device, const char *device_name, const char *description, unsigned int num_channels, unsigned int period_frame_size, AudioFormat audio_format); void sound_device_close(SoundDevice *device); @@ -39,6 +74,9 @@ void sound_device_close(SoundDevice *device); Returns the next chunk of audio into @buffer. Returns the number of frames read, or a negative value on failure. */ -int sound_device_read_next_chunk(SoundDevice *device, void **buffer); +int sound_device_read_next_chunk(SoundDevice *device, void **buffer, double timeout_sec, double *latency_seconds); + +AudioDevices get_pulseaudio_inputs(); +bool pulseaudio_server_is_pipewire(); #endif /* GPU_SCREEN_RECORDER_H */ diff --git a/include/utils.h b/include/utils.h new file mode 100644 index 0000000..74ccf18 --- /dev/null +++ b/include/utils.h @@ -0,0 +1,61 @@ +#ifndef GSR_UTILS_H +#define GSR_UTILS_H + +#include "vec2.h" +#include "../include/egl.h" +#include "../include/defs.h" +#include <stdbool.h> +#include <stdint.h> + +typedef struct AVCodecContext AVCodecContext; +typedef struct AVFrame AVFrame; + +typedef struct { + const char *name; + int name_len; + vec2i pos; /* This is 0, 0 on wayland. Use |drm_monitor_get_display_server_data| to get the position */ + vec2i size; + uint32_t connector_id; /* Only on x11 and drm */ + gsr_monitor_rotation rotation; /* Only on x11 and wayland */ + uint32_t monitor_identifier; /* On x11 this is the crtc id */ +} gsr_monitor; + +typedef struct { + const char *name; + int name_len; + gsr_monitor *monitor; + bool found_monitor; +} get_monitor_by_name_userdata; + +double clock_get_monotonic_seconds(void); +bool generate_random_characters(char *buffer, int buffer_size, const char *alphabet, size_t alphabet_size); +bool generate_random_characters_standard_alphabet(char *buffer, int buffer_size); + +typedef void (*active_monitor_callback)(const gsr_monitor *monitor, void *userdata); +void for_each_active_monitor_output_x11_not_cached(Display *display, active_monitor_callback callback, void *userdata); +void for_each_active_monitor_output(const gsr_window *window, const char *card_path, gsr_connection_type connection_type, active_monitor_callback callback, void *userdata); +bool get_monitor_by_name(const gsr_egl *egl, gsr_connection_type connection_type, const char *name, gsr_monitor *monitor); +bool drm_monitor_get_display_server_data(const gsr_window *window, const gsr_monitor *monitor, gsr_monitor_rotation *monitor_rotation, vec2i *monitor_position); + +int get_connector_type_by_name(const char *name); +int get_connector_type_id_by_name(const char *name); +uint32_t monitor_identifier_from_type_and_count(int monitor_type_index, int monitor_type_count); + +bool gl_get_gpu_info(gsr_egl *egl, gsr_gpu_info *info); + +bool try_card_has_valid_plane(const char *card_path); +/* |output| should be at least 128 bytes in size */ +bool gsr_get_valid_card_path(gsr_egl *egl, char *output, bool is_monitor_capture); +/* |render_path| should be at least 128 bytes in size */ +bool gsr_card_path_get_render_path(const char *card_path, char *render_path); + +int create_directory_recursive(char *path); + +/* |img_attr| needs to be at least 44 in size */ +void setup_dma_buf_attrs(intptr_t *img_attr, uint32_t format, uint32_t width, uint32_t height, const int *fds, const uint32_t *offsets, const uint32_t *pitches, const uint64_t *modifiers, int num_planes, bool use_modifier); + +vec2i scale_keep_aspect_ratio(vec2i from, vec2i to); + +unsigned int gl_create_texture(gsr_egl *egl, int width, int height, int internal_format, unsigned int format, int filter); + +#endif /* GSR_UTILS_H */ diff --git a/include/vec2.h b/include/vec2.h new file mode 100644 index 0000000..8fd3858 --- /dev/null +++ b/include/vec2.h @@ -0,0 +1,16 @@ +#ifndef VEC2_H +#define VEC2_H + +typedef struct { + int x, y; +} vec2i; + +typedef struct { + float x, y; +} vec2f; + +typedef struct { + double x, y; +} vec2d; + +#endif /* VEC2_H */ diff --git a/include/window/wayland.h b/include/window/wayland.h new file mode 100644 index 0000000..3535b0f --- /dev/null +++ b/include/window/wayland.h @@ -0,0 +1,8 @@ +#ifndef GSR_WINDOW_WAYLAND_H +#define GSR_WINDOW_WAYLAND_H + +#include "window.h" + +gsr_window* gsr_window_wayland_create(void); + +#endif /* GSR_WINDOW_WAYLAND_H */ diff --git a/include/window/window.h b/include/window/window.h new file mode 100644 index 0000000..7839f6a --- /dev/null +++ b/include/window/window.h @@ -0,0 +1,37 @@ +#ifndef GSR_WINDOW_H +#define GSR_WINDOW_H + +#include "../utils.h" +#include <stdbool.h> + +typedef union _XEvent XEvent; +typedef struct gsr_window gsr_window; + +typedef enum { + GSR_DISPLAY_SERVER_X11, + GSR_DISPLAY_SERVER_WAYLAND +} gsr_display_server; + +struct gsr_window { + void (*destroy)(gsr_window *self); + /* Returns true if an event is available */ + bool (*process_event)(gsr_window *self); + XEvent* (*get_event_data)(gsr_window *self); /* can be NULL */ + gsr_display_server (*get_display_server)(void); + void* (*get_display)(gsr_window *self); + void* (*get_window)(gsr_window *self); + void (*for_each_active_monitor_output_cached)(const gsr_window *self, active_monitor_callback callback, void *userdata); + void *priv; +}; + +void gsr_window_destroy(gsr_window *self); + +/* Returns true if an event is available */ +bool gsr_window_process_event(gsr_window *self); +XEvent* gsr_window_get_event_data(gsr_window *self); +gsr_display_server gsr_window_get_display_server(const gsr_window *self); +void* gsr_window_get_display(gsr_window *self); +void* gsr_window_get_window(gsr_window *self); +void gsr_window_for_each_active_monitor_output_cached(const gsr_window *self, active_monitor_callback callback, void *userdata); + +#endif /* GSR_WINDOW_H */ diff --git a/include/window/x11.h b/include/window/x11.h new file mode 100644 index 0000000..e0c2948 --- /dev/null +++ b/include/window/x11.h @@ -0,0 +1,10 @@ +#ifndef GSR_WINDOW_X11_H +#define GSR_WINDOW_X11_H + +#include "window.h" + +typedef struct _XDisplay Display; + +gsr_window* gsr_window_x11_create(Display *display); + +#endif /* GSR_WINDOW_X11_H */ diff --git a/include/window_texture.h b/include/window_texture.h new file mode 100644 index 0000000..6ee5df4 --- /dev/null +++ b/include/window_texture.h @@ -0,0 +1,28 @@ +#ifndef WINDOW_TEXTURE_H +#define WINDOW_TEXTURE_H + +#include "egl.h" + +typedef struct { + Display *display; + Window window; + Pixmap pixmap; + EGLImage image; + unsigned int texture_id; + int redirected; + gsr_egl *egl; +} WindowTexture; + +/* Returns 0 on success */ +int window_texture_init(WindowTexture *window_texture, Display *display, Window window, gsr_egl *egl); +void window_texture_deinit(WindowTexture *self); + +/* + This should ONLY be called when the target window is resized. + Returns 0 on success. +*/ +int window_texture_on_resize(WindowTexture *self); + +unsigned int window_texture_get_opengl_texture_id(WindowTexture *self); + +#endif /* WINDOW_TEXTURE_H */ diff --git a/include/xnvctrl.h b/include/xnvctrl.h new file mode 100644 index 0000000..33fc442 --- /dev/null +++ b/include/xnvctrl.h @@ -0,0 +1,45 @@ +#ifndef GSR_XNVCTRL_H +#define GSR_XNVCTRL_H + +#include <stdbool.h> +#include <stdint.h> + +#define NV_CTRL_GPU_NVCLOCK_OFFSET 409 +#define NV_CTRL_GPU_MEM_TRANSFER_RATE_OFFSET 410 +#define NV_CTRL_GPU_NVCLOCK_OFFSET_ALL_PERFORMANCE_LEVELS 424 +#define NV_CTRL_GPU_MEM_TRANSFER_RATE_OFFSET_ALL_PERFORMANCE_LEVELS 425 + +#define NV_CTRL_TARGET_TYPE_GPU 1 + +#define NV_CTRL_STRING_PERFORMANCE_MODES 29 + +typedef struct _XDisplay Display; + +typedef struct { + int type; + union { + struct { + int64_t min; + int64_t max; + } range; + struct { + unsigned int ints; + } bits; + } u; + unsigned int permissions; +} NVCTRLAttributeValidValuesRec; + +typedef struct { + Display *display; + void *library; + + int (*XNVCTRLQueryExtension)(Display *dpy, int *event_basep, int *error_basep); + int (*XNVCTRLSetTargetAttributeAndGetStatus)(Display *dpy, int target_type, int target_id, unsigned int display_mask, unsigned int attribute, int value); + int (*XNVCTRLQueryValidTargetAttributeValues)(Display *dpy, int target_type, int target_id, unsigned int display_mask, unsigned int attribute, NVCTRLAttributeValidValuesRec *values); + int (*XNVCTRLQueryTargetStringAttribute)(Display *dpy, int target_type, int target_id, unsigned int display_mask, unsigned int attribute, char **ptr); +} gsr_xnvctrl; + +bool gsr_xnvctrl_load(gsr_xnvctrl *self, Display *display); +void gsr_xnvctrl_unload(gsr_xnvctrl *self); + +#endif /* GSR_XNVCTRL_H */ |