mirror of
https://github.com/XITRIX/Moonlight-Switch.git
synced 2026-05-30 11:46:51 +00:00
259 lines
8.4 KiB
C
259 lines
8.4 KiB
C
/*
|
|
* Copyright (c) 2024 averne <averne381@gmail.com>
|
|
*
|
|
* This file is part of FFmpeg.
|
|
*
|
|
* FFmpeg is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* FFmpeg is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with FFmpeg; if not, write to the Free Software Foundation, Inc.,
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*/
|
|
|
|
#ifndef AVUTIL_NVTEGRA_H
|
|
#define AVUTIL_NVTEGRA_H
|
|
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
|
|
#include "buffer.h"
|
|
|
|
#include "nvhost_ioctl.h"
|
|
#include "nvmap_ioctl.h"
|
|
|
|
typedef struct AVNVTegraChannel {
|
|
#ifndef __SWITCH__
|
|
int fd;
|
|
int module_id;
|
|
#else
|
|
NvChannel channel;
|
|
#endif
|
|
|
|
uint32_t syncpt;
|
|
|
|
#ifdef __SWITCH__
|
|
MmuRequest mmu_request;
|
|
#endif
|
|
uint32_t clock;
|
|
} AVNVTegraChannel;
|
|
|
|
typedef struct AVNVTegraMap {
|
|
#ifndef __SWITCH__
|
|
uint32_t handle;
|
|
uint32_t size;
|
|
void *cpu_addr;
|
|
#else
|
|
NvMap map;
|
|
uint32_t iova;
|
|
uint32_t owner;
|
|
#endif
|
|
bool is_linear;
|
|
} AVNVTegraMap;
|
|
|
|
typedef struct AVNVTegraCmdbuf {
|
|
AVNVTegraMap *map;
|
|
|
|
uint32_t mem_offset, mem_size;
|
|
|
|
uint32_t *cur_word;
|
|
|
|
struct nvhost_cmdbuf *cmdbufs;
|
|
#ifndef __SWITCH__
|
|
struct nvhost_cmdbuf_ext *cmdbuf_exts;
|
|
uint32_t *class_ids;
|
|
#endif
|
|
uint32_t num_cmdbufs;
|
|
|
|
#ifndef __SWITCH__
|
|
struct nvhost_reloc *relocs;
|
|
struct nvhost_reloc_type *reloc_types;
|
|
struct nvhost_reloc_shift *reloc_shifts;
|
|
uint32_t num_relocs;
|
|
#endif
|
|
|
|
struct nvhost_syncpt_incr *syncpt_incrs;
|
|
#ifndef __SWITCH__
|
|
uint32_t *fences;
|
|
#endif
|
|
uint32_t num_syncpt_incrs;
|
|
|
|
#ifndef __SWITCH__
|
|
struct nvhost_waitchk *waitchks;
|
|
uint32_t num_waitchks;
|
|
#endif
|
|
} AVNVTegraCmdbuf;
|
|
|
|
typedef struct AVNVTegraJobPool {
|
|
/*
|
|
* Pool object for job allocation
|
|
*/
|
|
AVBufferPool *pool;
|
|
|
|
/*
|
|
* Hardware channel the jobs will be submitted to
|
|
*/
|
|
AVNVTegraChannel *channel;
|
|
|
|
/*
|
|
* Total size of the input memory-mapped buffer
|
|
*/
|
|
size_t input_map_size;
|
|
|
|
/*
|
|
* Offset of the command data within the input map
|
|
*/
|
|
off_t cmdbuf_off;
|
|
|
|
/*
|
|
* Maximum memory usable by the command buffer
|
|
*/
|
|
size_t max_cmdbuf_size;
|
|
} AVNVTegraJobPool;
|
|
|
|
typedef struct AVNVTegraJob {
|
|
/*
|
|
* Memory-mapped buffer for command buffers, metadata structures, ...
|
|
*/
|
|
AVNVTegraMap input_map;
|
|
|
|
/*
|
|
* Object for command recording
|
|
*/
|
|
AVNVTegraCmdbuf cmdbuf;
|
|
|
|
/*
|
|
* Fence indicating completion of the job
|
|
*/
|
|
uint32_t fence;
|
|
} AVNVTegraJob;
|
|
|
|
AVBufferRef *av_nvtegra_driver_init(void);
|
|
|
|
int av_nvtegra_channel_open(AVNVTegraChannel *channel, const char *dev);
|
|
int av_nvtegra_channel_close(AVNVTegraChannel *channel);
|
|
int av_nvtegra_channel_get_clock_rate(AVNVTegraChannel *channel, uint32_t moduleid, uint32_t *clock_rate);
|
|
int av_nvtegra_channel_set_clock_rate(AVNVTegraChannel *channel, uint32_t moduleid, uint32_t clock_rate);
|
|
int av_nvtegra_channel_submit(AVNVTegraChannel *channel, AVNVTegraCmdbuf *cmdbuf, uint32_t *fence);
|
|
int av_nvtegra_channel_set_submit_timeout(AVNVTegraChannel *channel, uint32_t timeout_ms);
|
|
|
|
int av_nvtegra_syncpt_wait(AVNVTegraChannel *channel, uint32_t threshold, int32_t timeout);
|
|
|
|
int av_nvtegra_map_allocate(AVNVTegraMap *map, AVNVTegraChannel *owner, uint32_t size,
|
|
uint32_t align, int heap_mask, int flags);
|
|
int av_nvtegra_map_free(AVNVTegraMap *map);
|
|
int av_nvtegra_map_from_va(AVNVTegraMap *map, AVNVTegraChannel *owner, void *mem,
|
|
uint32_t size, uint32_t align, uint32_t flags);
|
|
int av_nvtegra_map_close(AVNVTegraMap *map);
|
|
int av_nvtegra_map_map(AVNVTegraMap *map);
|
|
int av_nvtegra_map_unmap(AVNVTegraMap *map);
|
|
int av_nvtegra_map_cache_op(AVNVTegraMap *map, int op, void *addr, size_t len);
|
|
int av_nvtegra_map_realloc(AVNVTegraMap *map, uint32_t size, uint32_t align, int heap_mask, int flags);
|
|
|
|
static inline int av_nvtegra_map_create(AVNVTegraMap *map, AVNVTegraChannel *owner, uint32_t size, uint32_t align,
|
|
int heap_mask, int flags)
|
|
{
|
|
int err;
|
|
|
|
err = av_nvtegra_map_allocate(map, owner, size, align, heap_mask, flags);
|
|
if (err < 0)
|
|
return err;
|
|
|
|
return av_nvtegra_map_map(map);
|
|
}
|
|
|
|
static inline int av_nvtegra_map_destroy(AVNVTegraMap *map) {
|
|
int err;
|
|
|
|
err = av_nvtegra_map_unmap(map);
|
|
if (err < 0)
|
|
return err;
|
|
|
|
return av_nvtegra_map_free(map);
|
|
}
|
|
|
|
int av_nvtegra_cmdbuf_init(AVNVTegraCmdbuf *cmdbuf);
|
|
int av_nvtegra_cmdbuf_deinit(AVNVTegraCmdbuf *cmdbuf);
|
|
int av_nvtegra_cmdbuf_add_memory(AVNVTegraCmdbuf *cmdbuf, AVNVTegraMap *map, uint32_t offset, uint32_t size);
|
|
int av_nvtegra_cmdbuf_clear(AVNVTegraCmdbuf *cmdbuf);
|
|
int av_nvtegra_cmdbuf_begin(AVNVTegraCmdbuf *cmdbuf, uint32_t class_id);
|
|
int av_nvtegra_cmdbuf_end(AVNVTegraCmdbuf *cmdbuf);
|
|
int av_nvtegra_cmdbuf_push_word(AVNVTegraCmdbuf *cmdbuf, uint32_t word);
|
|
int av_nvtegra_cmdbuf_push_value(AVNVTegraCmdbuf *cmdbuf, uint32_t offset, uint32_t word);
|
|
int av_nvtegra_cmdbuf_push_reloc(AVNVTegraCmdbuf *cmdbuf, uint32_t offset, AVNVTegraMap *target, uint32_t target_offset,
|
|
int reloc_type, int shift);
|
|
int av_nvtegra_cmdbuf_push_syncpt_incr(AVNVTegraCmdbuf *cmdbuf, uint32_t syncpt);
|
|
int av_nvtegra_cmdbuf_push_wait(AVNVTegraCmdbuf *cmdbuf, uint32_t syncpt, uint32_t fence);
|
|
int av_nvtegra_cmdbuf_add_syncpt_incr(AVNVTegraCmdbuf *cmdbuf, uint32_t syncpt, uint32_t fence);
|
|
int av_nvtegra_cmdbuf_add_waitchk(AVNVTegraCmdbuf *cmdbuf, uint32_t syncpt, uint32_t fence);
|
|
|
|
/*
|
|
* Job allocation and submission routines
|
|
*/
|
|
int av_nvtegra_job_pool_init(AVNVTegraJobPool *pool, AVNVTegraChannel *channel,
|
|
size_t input_map_size, off_t cmdbuf_off, size_t max_cmdbuf_size);
|
|
int av_nvtegra_job_pool_uninit(AVNVTegraJobPool *pool);
|
|
AVBufferRef *av_nvtegra_job_pool_get(AVNVTegraJobPool *pool);
|
|
|
|
int av_nvtegra_job_submit(AVNVTegraJobPool *pool, AVNVTegraJob *job);
|
|
int av_nvtegra_job_wait(AVNVTegraJobPool *pool, AVNVTegraJob *job, int timeout);
|
|
|
|
static inline uint32_t av_nvtegra_map_get_handle(AVNVTegraMap *map) {
|
|
#ifndef __SWITCH__
|
|
return map->handle;
|
|
#else
|
|
return map->map.handle;
|
|
#endif
|
|
}
|
|
|
|
static inline void *av_nvtegra_map_get_addr(AVNVTegraMap *map) {
|
|
#ifndef __SWITCH__
|
|
return map->cpu_addr;
|
|
#else
|
|
return map->map.cpu_addr;
|
|
#endif
|
|
}
|
|
|
|
static inline uint32_t av_nvtegra_map_get_size(AVNVTegraMap *map) {
|
|
#ifndef __SWITCH__
|
|
return map->size;
|
|
#else
|
|
return map->map.size;
|
|
#endif
|
|
}
|
|
|
|
/* Addresses are shifted by 8 bits in the command buffer, requiring an alignment to 256 */
|
|
#define AV_NVTEGRA_MAP_ALIGN (1 << 8)
|
|
|
|
#define AV_NVTEGRA_VALUE(offset, field, value) \
|
|
((value & \
|
|
((uint32_t)((UINT64_C(1) << ((1?offset ## _ ## field) - (0?offset ## _ ## field) + 1)) - 1))) \
|
|
<< (0?offset ## _ ## field))
|
|
|
|
#define AV_NVTEGRA_ENUM(offset, field, value) \
|
|
((offset ## _ ## field ## _ ## value & \
|
|
((uint32_t)((UINT64_C(1) << ((1?offset ## _ ## field) - (0?offset ## _ ## field) + 1)) - 1))) \
|
|
<< (0?offset ## _ ## field))
|
|
|
|
#define AV_NVTEGRA_PUSH_VALUE(cmdbuf, offset, value) ({ \
|
|
int _err = av_nvtegra_cmdbuf_push_value(cmdbuf, (offset) / sizeof(uint32_t), value); \
|
|
if (_err < 0) \
|
|
return _err; \
|
|
})
|
|
|
|
#define AV_NVTEGRA_PUSH_RELOC(cmdbuf, offset, target, target_offset, type) ({ \
|
|
int _err = av_nvtegra_cmdbuf_push_reloc(cmdbuf, (offset) / sizeof(uint32_t), \
|
|
target, target_offset, type, 8); \
|
|
if (_err < 0) \
|
|
return _err; \
|
|
})
|
|
|
|
#endif /* AVUTIL_NVTEGRA_H */
|