mirror of
https://github.com/switchbrew/libnx.git
synced 2025-06-21 04:22:50 +02:00
Added display+layer support. Started 'gfx'.
This commit is contained in:
parent
d62b909757
commit
ec1faa34ef
@ -24,7 +24,7 @@ VERSION := $(LIBNX_MAJOR).$(LIBNX_MINOR).$(LIBNX_PATCH)
|
|||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
TARGET := nx
|
TARGET := nx
|
||||||
#BUILD := build
|
#BUILD := build
|
||||||
SOURCES := source/system source/kernel source/services source/devices
|
SOURCES := source/system source/kernel source/services source/devices source/gfx
|
||||||
|
|
||||||
DATA := data
|
DATA := data
|
||||||
INCLUDES := include
|
INCLUDES := include
|
||||||
|
@ -31,6 +31,8 @@ extern "C" {
|
|||||||
|
|
||||||
#include <switch/devices/usb_dev.h>
|
#include <switch/devices/usb_dev.h>
|
||||||
|
|
||||||
|
#include <switch/gfx/gfx.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
3
nx/include/switch/gfx/gfx.h
Normal file
3
nx/include/switch/gfx/gfx.h
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
/// Do not use viInitialize/viExit when using these.
|
||||||
|
void gfxInitDefault(void);
|
||||||
|
void gfxExit(void);
|
@ -12,3 +12,5 @@ typedef enum
|
|||||||
Result appletInitialize(void);
|
Result appletInitialize(void);
|
||||||
void appletExit(void);
|
void appletExit(void);
|
||||||
Result appletGetAppletResourceUserId(u64 *out);
|
Result appletGetAppletResourceUserId(u64 *out);
|
||||||
|
|
||||||
|
Result appletCreateManagedDisplayLayer(u64 *out);
|
||||||
|
@ -1,11 +1,27 @@
|
|||||||
typedef enum
|
typedef struct {
|
||||||
{
|
u64 DisplayId;
|
||||||
|
char DisplayName[0x40];
|
||||||
|
bool initialized;
|
||||||
|
} viDisplay;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u64 LayerId;
|
||||||
|
bool StrayLayer;
|
||||||
|
bool initialized;
|
||||||
|
} viLayer;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
VISERVTYPE_Default = -1,
|
VISERVTYPE_Default = -1,
|
||||||
VISERVTYPE_Application = 0,
|
VISERVTYPE_Application = 0,
|
||||||
VISERVTYPE_System = 1,
|
VISERVTYPE_System = 1,
|
||||||
VISERVTYPE_Manager = 2,
|
VISERVTYPE_Manager = 2,
|
||||||
} viServiceType;
|
} viServiceType;
|
||||||
|
|
||||||
|
/// Used by viOpenLayer when CreateStrayLayer is used internally.
|
||||||
|
typedef enum {
|
||||||
|
VILAYERFLAGS_Default = 0x1,
|
||||||
|
} viLayerFlags;
|
||||||
|
|
||||||
Result viInitialize(viServiceType servicetype);
|
Result viInitialize(viServiceType servicetype);
|
||||||
void viExit(void);
|
void viExit(void);
|
||||||
Handle viGetSessionService(void);
|
Handle viGetSessionService(void);
|
||||||
@ -14,3 +30,8 @@ Handle viGetSession_IHOSBinderDriverRelay(void);
|
|||||||
Handle viGetSession_ISystemDisplayService(void);
|
Handle viGetSession_ISystemDisplayService(void);
|
||||||
Handle viGetSession_IManagerDisplayService(void);
|
Handle viGetSession_IManagerDisplayService(void);
|
||||||
Handle viGetSession_IHOSBinderDriverIndirect(void);
|
Handle viGetSession_IHOSBinderDriverIndirect(void);
|
||||||
|
|
||||||
|
Result viOpenDisplay(const char *DisplayName, viDisplay *display);
|
||||||
|
Result viCloseDisplay(viDisplay *display);
|
||||||
|
Result viOpenLayer(u8 NativeWindow[0x100], u64 *NativeWindow_Size, const viDisplay *display, viLayer *layer, u32 LayerFlags, u64 LayerId);
|
||||||
|
Result viCloseLayer(viLayer *layer);
|
||||||
|
47
nx/source/gfx/gfx.c
Normal file
47
nx/source/gfx/gfx.c
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
#include <string.h>
|
||||||
|
#include <switch.h>
|
||||||
|
|
||||||
|
static bool g_gfxInitialized = 0;
|
||||||
|
static viDisplay g_gfxDisplay;
|
||||||
|
static viLayer g_gfxLayer;
|
||||||
|
static u8 g_gfxNativeWindow[0x100];
|
||||||
|
static u64 g_gfxNativeWindow_Size;
|
||||||
|
|
||||||
|
static Result _gfxInit(viServiceType servicetype, const char *DisplayName, u32 LayerFlags, u64 LayerId) {
|
||||||
|
Result rc=0;
|
||||||
|
|
||||||
|
if(g_gfxInitialized)return 0;
|
||||||
|
|
||||||
|
rc = viInitialize(servicetype);
|
||||||
|
if (R_FAILED(rc)) return rc;
|
||||||
|
|
||||||
|
rc = viOpenDisplay(DisplayName, &g_gfxDisplay);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) rc = viOpenLayer(g_gfxNativeWindow, &g_gfxNativeWindow_Size, &g_gfxDisplay, &g_gfxLayer, LayerFlags, LayerId);
|
||||||
|
|
||||||
|
if (R_FAILED(rc)) {
|
||||||
|
viCloseDisplay(&g_gfxDisplay);
|
||||||
|
viExit();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) g_gfxInitialized = 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gfxInitDefault(void) {
|
||||||
|
Result rc = _gfxInit(VILAYERFLAGS_Default, "Default", VILAYERFLAGS_Default, 0);
|
||||||
|
if (R_FAILED(rc)) fatalSimple(rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gfxExit(void) {
|
||||||
|
if(!g_gfxInitialized)return;
|
||||||
|
|
||||||
|
viCloseLayer(&g_gfxLayer);
|
||||||
|
viCloseDisplay(&g_gfxDisplay);
|
||||||
|
|
||||||
|
viExit();
|
||||||
|
|
||||||
|
g_gfxInitialized = 0;
|
||||||
|
}
|
||||||
|
|
@ -309,3 +309,39 @@ static Result _appletNotifyRunning(u8 *out) {
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result appletCreateManagedDisplayLayer(u64 *out) {
|
||||||
|
IpcCommand c;
|
||||||
|
ipcInitialize(&c);
|
||||||
|
|
||||||
|
struct {
|
||||||
|
u64 magic;
|
||||||
|
u64 cmd_id;
|
||||||
|
} *raw;
|
||||||
|
|
||||||
|
raw = ipcPrepareHeader(&c, sizeof(*raw));
|
||||||
|
|
||||||
|
raw->magic = SFCI_MAGIC;
|
||||||
|
raw->cmd_id = 40;
|
||||||
|
|
||||||
|
Result rc = ipcDispatch(g_appletISelfController);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
IpcCommandResponse r;
|
||||||
|
ipcParseResponse(&r);
|
||||||
|
|
||||||
|
struct {
|
||||||
|
u64 magic;
|
||||||
|
u64 result;
|
||||||
|
u64 out;
|
||||||
|
} *resp = r.Raw;
|
||||||
|
|
||||||
|
rc = resp->result;
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
*out = resp->out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -163,3 +163,233 @@ static Result _viGetSessionNoParams(Handle sessionhandle, Handle* handle_out, u6
|
|||||||
return _viGetSession(sessionhandle, handle_out, &raw, sizeof(raw));
|
return _viGetSession(sessionhandle, handle_out, &raw, sizeof(raw));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result viOpenDisplay(const char *DisplayName, viDisplay *display) {
|
||||||
|
IpcCommand c;
|
||||||
|
ipcInitialize(&c);
|
||||||
|
|
||||||
|
struct {
|
||||||
|
u64 magic;
|
||||||
|
u64 cmd_id;
|
||||||
|
char DisplayName[0x40];
|
||||||
|
} *raw;
|
||||||
|
|
||||||
|
memset(display, 0, sizeof(viDisplay));
|
||||||
|
|
||||||
|
raw = ipcPrepareHeader(&c, sizeof(raw));
|
||||||
|
raw->magic = SFCI_MAGIC;
|
||||||
|
raw->cmd_id = 1010;
|
||||||
|
|
||||||
|
strncpy(display->DisplayName, DisplayName, sizeof(display->DisplayName)-1);
|
||||||
|
memcpy(raw->DisplayName, display->DisplayName, sizeof(display->DisplayName));
|
||||||
|
|
||||||
|
Result rc = ipcDispatch(g_viIApplicationDisplayService);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
IpcCommandResponse r;
|
||||||
|
ipcParseResponse(&r);
|
||||||
|
|
||||||
|
struct {
|
||||||
|
u64 magic;
|
||||||
|
u64 result;
|
||||||
|
u64 DisplayId;
|
||||||
|
} *resp = r.Raw;
|
||||||
|
|
||||||
|
rc = resp->result;
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
display->DisplayId = resp->DisplayId;
|
||||||
|
display->initialized = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result viCloseDisplay(viDisplay *display) {
|
||||||
|
IpcCommand c;
|
||||||
|
ipcInitialize(&c);
|
||||||
|
|
||||||
|
if(!display->initialized)return 0;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
u64 magic;
|
||||||
|
u64 cmd_id;
|
||||||
|
u64 DisplayId;
|
||||||
|
} *raw;
|
||||||
|
|
||||||
|
raw = ipcPrepareHeader(&c, sizeof(raw));
|
||||||
|
raw->magic = SFCI_MAGIC;
|
||||||
|
raw->cmd_id = 1020;
|
||||||
|
raw->DisplayId = display->DisplayId;
|
||||||
|
|
||||||
|
Result rc = ipcDispatch(g_viIApplicationDisplayService);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
IpcCommandResponse r;
|
||||||
|
ipcParseResponse(&r);
|
||||||
|
|
||||||
|
struct {
|
||||||
|
u64 magic;
|
||||||
|
u64 result;
|
||||||
|
} *resp = r.Raw;
|
||||||
|
|
||||||
|
rc = resp->result;
|
||||||
|
|
||||||
|
display->initialized = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Result _viOpenLayer(u8 NativeWindow[0x100], u64 *NativeWindow_Size, const viDisplay *display, u64 LayerId, u64 AppletResourceUserId) {
|
||||||
|
IpcCommand c;
|
||||||
|
ipcInitialize(&c);
|
||||||
|
|
||||||
|
struct {
|
||||||
|
u64 magic;
|
||||||
|
u64 cmd_id;
|
||||||
|
char DisplayName[0x40];
|
||||||
|
u64 LayerId;
|
||||||
|
u64 AppletResourceUserId;
|
||||||
|
} *raw;
|
||||||
|
|
||||||
|
ipcSendPid(&c);
|
||||||
|
ipcAddRecvBuffer(&c, NativeWindow, 0x100, 0);
|
||||||
|
|
||||||
|
raw = ipcPrepareHeader(&c, sizeof(raw));
|
||||||
|
raw->magic = SFCI_MAGIC;
|
||||||
|
raw->cmd_id = 2020;
|
||||||
|
|
||||||
|
memcpy(raw->DisplayName, display->DisplayName, sizeof(display->DisplayName));
|
||||||
|
|
||||||
|
raw->LayerId = LayerId;
|
||||||
|
raw->AppletResourceUserId = AppletResourceUserId;
|
||||||
|
|
||||||
|
Result rc = ipcDispatch(g_viIApplicationDisplayService);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
IpcCommandResponse r;
|
||||||
|
ipcParseResponse(&r);
|
||||||
|
|
||||||
|
struct {
|
||||||
|
u64 magic;
|
||||||
|
u64 result;
|
||||||
|
u64 NativeWindow_Size;
|
||||||
|
} *resp = r.Raw;
|
||||||
|
|
||||||
|
rc = resp->result;
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
*NativeWindow_Size = resp->NativeWindow_Size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Result _viCreateStrayLayer(u8 NativeWindow[0x100], u64 *NativeWindow_Size, const viDisplay *display, u32 LayerFlags, u64 *LayerId) {
|
||||||
|
IpcCommand c;
|
||||||
|
ipcInitialize(&c);
|
||||||
|
|
||||||
|
struct {
|
||||||
|
u64 magic;
|
||||||
|
u64 cmd_id;
|
||||||
|
u32 LayerFlags;
|
||||||
|
u32 pad;
|
||||||
|
u64 DisplayId;
|
||||||
|
} *raw;
|
||||||
|
|
||||||
|
ipcAddRecvBuffer(&c, NativeWindow, 0x100, 0);
|
||||||
|
|
||||||
|
raw = ipcPrepareHeader(&c, sizeof(raw));
|
||||||
|
raw->magic = SFCI_MAGIC;
|
||||||
|
raw->cmd_id = 2030;
|
||||||
|
raw->LayerFlags = LayerFlags;
|
||||||
|
raw->DisplayId = display->DisplayId;
|
||||||
|
|
||||||
|
Result rc = ipcDispatch(g_viIApplicationDisplayService);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
IpcCommandResponse r;
|
||||||
|
ipcParseResponse(&r);
|
||||||
|
|
||||||
|
struct {
|
||||||
|
u64 magic;
|
||||||
|
u64 result;
|
||||||
|
u64 LayerId;
|
||||||
|
u64 NativeWindow_Size;
|
||||||
|
} *resp = r.Raw;
|
||||||
|
|
||||||
|
rc = resp->result;
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
*LayerId = resp->LayerId;
|
||||||
|
*NativeWindow_Size = resp->NativeWindow_Size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result viOpenLayer(u8 NativeWindow[0x100], u64 *NativeWindow_Size, const viDisplay *display, viLayer *layer, u32 LayerFlags, u64 LayerId) {
|
||||||
|
Result rc = 0;
|
||||||
|
u64 AppletResourceUserId = 0;
|
||||||
|
|
||||||
|
memset(layer, 0, sizeof(viLayer));
|
||||||
|
|
||||||
|
if (LayerId==0) rc = appletGetAppletResourceUserId(&AppletResourceUserId);
|
||||||
|
if (LayerId==0 && (R_FAILED(rc) || AppletResourceUserId == 0)) {
|
||||||
|
rc = _viCreateStrayLayer(NativeWindow, NativeWindow_Size, display, LayerFlags, &layer->LayerId);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (LayerId==0) {
|
||||||
|
rc = appletCreateManagedDisplayLayer(&LayerId);
|
||||||
|
if (R_FAILED(rc)) return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = _viOpenLayer(NativeWindow, NativeWindow_Size, display, LayerId, AppletResourceUserId);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) layer->LayerId = LayerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) layer->initialized = 1;
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result viCloseLayer(viLayer *layer) {
|
||||||
|
IpcCommand c;
|
||||||
|
ipcInitialize(&c);
|
||||||
|
|
||||||
|
if(!layer->initialized)return 0;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
u64 magic;
|
||||||
|
u64 cmd_id;
|
||||||
|
u64 LayerId;
|
||||||
|
} *raw;
|
||||||
|
|
||||||
|
raw = ipcPrepareHeader(&c, sizeof(raw));
|
||||||
|
raw->magic = SFCI_MAGIC;
|
||||||
|
raw->cmd_id = layer->StrayLayer==0 ? 2021 : 2031;
|
||||||
|
raw->LayerId = layer->LayerId;
|
||||||
|
|
||||||
|
Result rc = ipcDispatch(g_viIApplicationDisplayService);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
IpcCommandResponse r;
|
||||||
|
ipcParseResponse(&r);
|
||||||
|
|
||||||
|
struct {
|
||||||
|
u64 magic;
|
||||||
|
u64 result;
|
||||||
|
} *resp = r.Raw;
|
||||||
|
|
||||||
|
rc = resp->result;
|
||||||
|
|
||||||
|
memset(layer, 0, sizeof(viLayer));
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user