#include #include #include "types.h" #include "result.h" #include "arm/cache.h" #include "kernel/svc.h" #include "services/nv.h" #include "display/binder.h" #include "display/buffer_producer.h" #include "display/nvgfx.h" #include "nvidia/ioctl.h" typedef struct { bool initialized; u32 handle; u8 *mem; size_t mem_size; } nvmapobj; static bool g_nvgfxInitialized; static u32 g_nvgfx_fd_nvmap; u32 g_nvgfx_totalframebufs = 2; static nvmapobj nvmap_fb_obj; extern size_t g_gfx_singleframebuf_size; Result _gfxGraphicBufferInit(s32 buf, u32 nvmap_id, u32 nvmap_handle); static Result nvmapobjInitialize(nvmapobj *obj, size_t size) { Result rc=0; if(obj->initialized)return 0; memset(obj, 0, sizeof(nvmapobj)); obj->mem_size = size; obj->mem = memalign(0x1000, size); if (obj->mem==NULL) rc = MAKERESULT(Module_Libnx, LibnxError_OutOfMemory); if (R_SUCCEEDED(rc)) memset(obj->mem, 0, size); if (R_SUCCEEDED(rc)) armDCacheFlush(obj->mem, size); if (R_SUCCEEDED(rc)) obj->initialized = 1; return rc; } static void nvmapobjClose(nvmapobj *obj) { if(!obj->initialized)return; if (obj->mem) { free(obj->mem); obj->mem = NULL; } memset(obj, 0, sizeof(nvmapobj)); } static Result nvmapobjSetup(nvmapobj *obj, u32 heapmask, u32 flags, u32 align, u8 kind) { Result rc=0; rc = nvioctlNvmap_Create(g_nvgfx_fd_nvmap, obj->mem_size, &obj->handle); if (R_SUCCEEDED(rc)) rc = nvioctlNvmap_Alloc(g_nvgfx_fd_nvmap, obj->handle, heapmask, flags, align, kind, obj->mem); return rc; } Result nvgfxInitialize(void) { Result rc=0; if (g_nvgfxInitialized) return 0; if (R_SUCCEEDED(rc)) rc = nvOpen(&g_nvgfx_fd_nvmap, "/dev/nvmap"); if (R_SUCCEEDED(rc)) rc = nvmapobjInitialize(&nvmap_fb_obj, g_nvgfx_totalframebufs*g_gfx_singleframebuf_size); if (R_SUCCEEDED(rc)) rc = nvmapobjSetup(&nvmap_fb_obj, 0, 0x1, 0x20000, 0); if (R_SUCCEEDED(rc)) { u32 id = 0; rc = nvioctlNvmap_GetId(g_nvgfx_fd_nvmap, nvmap_fb_obj.handle, &id); if (R_SUCCEEDED(rc)) { for (int i = 0; i < g_nvgfx_totalframebufs; i ++) { rc = _gfxGraphicBufferInit(i, id, nvmap_fb_obj.handle); if (R_FAILED(rc)) break; } } } if (R_FAILED(rc)) { nvmapobjClose(&nvmap_fb_obj); if (g_nvgfx_fd_nvmap != -1) { nvClose(g_nvgfx_fd_nvmap); g_nvgfx_fd_nvmap = -1; } } if (R_SUCCEEDED(rc)) g_nvgfxInitialized = true; return rc; } void nvgfxExit(void) { if (!g_nvgfxInitialized) return; nvmapobjClose(&nvmap_fb_obj); if (g_nvgfx_fd_nvmap != -1) { nvClose(g_nvgfx_fd_nvmap); g_nvgfx_fd_nvmap = -1; } g_nvgfxInitialized = false; } Result nvgfxGetFramebuffer(u8 **buffer, size_t *size, u32 *handle) { if (!g_nvgfxInitialized) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); if (buffer != NULL) *buffer = nvmap_fb_obj.mem; if (size != NULL) *size = nvmap_fb_obj.mem_size; if (handle != NULL) *handle = nvmap_fb_obj.handle; return 0; }