]> Chaos Git - corbenik/ctrulib.git/commitdiff
GSP: add basic event handling system
authorfincs <fincs.alt1@gmail.com>
Wed, 20 Aug 2014 22:09:39 +0000 (00:09 +0200)
committerfincs <fincs.alt1@gmail.com>
Wed, 20 Aug 2014 22:09:39 +0000 (00:09 +0200)
libctru/include/3ds/GSP.h
libctru/source/services/gsp.c

index 5ac95ea77fd9c4575e37ad98d9bda1ba9dc99eba..c592731cb3f81ff6d87b4c0015733a868573e6f3 100644 (file)
@@ -27,9 +27,33 @@ typedef struct
        GSP_CaptureInfoEntry screencapture[2];
 } GSP_CaptureInfo;
 
+typedef enum
+{
+       GSPEVENT_PSC0 = 0,
+       GSPEVENT_PSC1,
+       GSPEVENT_VBlank0,
+       GSPEVENT_VBlank1,
+       GSPEVENT_PPF,
+       GSPEVENT_P3D,
+       GSPEVENT_DMA,
+       GSPEVENT_count, // used to know how many events there are
+} GSP_Event;
+
 Result gspInit();
 void gspExit();
 
+Result gspInitEventHandler(Handle gspEvent, vu8* gspSharedMem, u8 gspThreadId);
+void gspExitEventHandler();
+void gspWaitForEvent(GSP_Event id);
+#define gspWaitForPSC0() gspWaitForEvent(GSPEVENT_PSC0)
+#define gspWaitForPSC1() gspWaitForEvent(GSPEVENT_PSC1)
+#define gspWaitForVBlank() gspWaitForVBlank0()
+#define gspWaitForVBlank0() gspWaitForEvent(GSPEVENT_VBlank0)
+#define gspWaitForVBlank1() gspWaitForEvent(GSPEVENT_VBlank1)
+#define gspWaitForPPF() gspWaitForEvent(GSPEVENT_PPF)
+#define gspWaitForP3D() gspWaitForEvent(GSPEVENT_P3D)
+#define gspWaitForDMA() gspWaitForEvent(GSPEVENT_DMA)
+
 Result GSPGPU_AcquireRight(Handle *handle, u8 flags);
 Result GSPGPU_ReleaseRight(Handle *handle);
 Result GSPGPU_ImportDisplayCaptureInfo(Handle* handle, GSP_CaptureInfo *captureinfo);
index 95e724d9f86d98d96885ea529f56d13fb51a935c..a8e115acde9b9e9b5b4b5afbaa59a80284aef5eb 100644 (file)
@@ -5,7 +5,18 @@
 #include <3ds/svc.h>
 #include <3ds/srv.h>
 
+#define GSP_EVENT_STACK_SIZE 0x1000
+
 Handle gspGpuHandle=0;
+Handle gspEvents[GSPEVENT_count];
+u64 gspEventStack[GSP_EVENT_STACK_SIZE/sizeof(u64)]; //u64 so that it's 8-byte aligned
+volatile bool gspRunEvents;
+Handle gspEventThread;
+
+static Handle gspEvent;
+static vu8* gspEventData;
+
+static void gspEventThreadMain(u32 arg);
 
 Result gspInit()
 {
@@ -17,6 +28,76 @@ void gspExit()
        if(gspGpuHandle)svcCloseHandle(gspGpuHandle);
 }
 
+Result gspInitEventHandler(Handle _gspEvent, vu8* _gspSharedMem, u8 gspThreadId)
+{
+       // Create events
+       int i;
+       for (i = 0; i < GSPEVENT_count; i ++)
+       {
+               Result rc = svcCreateEvent(&gspEvents[i], 0);
+               if (rc != 0)
+               {
+                       // Destroy already created events due to failure
+                       int j;
+                       for (j = 0; j < i; j ++)
+                               svcCloseHandle(gspEvents[j]);
+                       return rc;
+               }
+       }
+
+       // Start event thread
+       gspEvent = _gspEvent;
+       gspEventData = _gspSharedMem + gspThreadId*0x40;
+       gspRunEvents = true;
+       return svcCreateThread(&gspEventThread, gspEventThreadMain, 0x0, (u32*)((char*)gspEventStack + sizeof(gspEventStack)), 0x31, 0xfffffffe);
+}
+
+void gspExitEventHandler()
+{
+       // Stop event thread
+       gspRunEvents = false;
+       svcWaitSynchronization(gspEventThread, 1000000000);
+
+       // Free events
+       int i;
+       for (i = 0; i < GSPEVENT_count; i ++)
+               svcCloseHandle(gspEvents[i]);
+}
+
+void gspWaitForEvent(GSP_Event id)
+{
+       svcClearEvent(gspEvents[id]);
+       svcWaitSynchronization(gspEvents[id], U64_MAX);
+}
+
+void gspEventThreadMain(u32 arg)
+{
+       while (gspRunEvents)
+       {
+               svcWaitSynchronization(gspEvent, U64_MAX);
+               svcClearEvent(gspEvent);
+
+               int count = gspEventData[1];
+               int last = gspEventData[0] + count;
+               while (last >= 0x34) last -= 0x34;
+               int cur = last;
+               int i;
+               for (i = 0; i < count; i ++)
+               {
+                       int curEvt = gspEventData[0xC + cur];
+                       cur --;
+                       if (cur < 0) cur += 0x34;
+                       if (curEvt >= GSPEVENT_count) continue;
+                       svcSignalEvent(gspEvents[curEvt]);
+               }
+
+               gspEventData[0] = last;
+               gspEventData[1] -= count;
+               gspEventData[2] = 0;
+       }
+       svcExitThread();
+}
+
 Result GSPGPU_AcquireRight(Handle* handle, u8 flags)
 {
        if(!handle)handle=&gspGpuHandle;