
- GSPGPU changes: - gspInit now properly initializes the event queue, GSP shared memory and first-time initialization - previously this was done in gfxInit. - Removed gspInitEventHandler/gspExitEventHandler in line with above. - Added gspPresentBuffer for pushing a framebuffer to the internal GSP swap queue (previously this was an internal function in gfx.c). - Added defines for screen IDs and screen dimensions. - Removed sharedGspCmdBuf param from gspSubmitGxCommand (now uses the correct GSP shared memory address automatically). - Removed gxCmdBuf global variable (no longer needed as per above). - Removed GSPGPU_REBASE_REG (leftover from early 3DS homebrew). - GFX changes: - Documentation overhaul and code cleanup. - Simplified implementation using the enhanced GSPGPU service wrapper. - Top left/right framebuffers now form a single allocation instead of being split into two separate allocations. - Fixed LCD configuration mode when framebuffers are on VRAM. - Removed the ability to forcefully swap the screens: gspPresentBuffer is now always used (i.e. GSP shared mem). The 'immediate' parameter of gfxConfigScreen now does nothing, and gfxSwapBuffers/Gpu now do the same thing. - Removed gfx{TopLeft,TopRight,Bottom}Framebuffers global variables (please use gfxGetFramebuffer instead as originally intended...)
120 lines
2.6 KiB
C
120 lines
2.6 KiB
C
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <3ds/types.h>
|
|
#include <3ds/svc.h>
|
|
#include <3ds/synchronization.h>
|
|
#include <3ds/gpu/gx.h>
|
|
#include <3ds/services/gspgpu.h>
|
|
|
|
#define MAX_PARALLEL_CMDS 3
|
|
|
|
static gxCmdQueue_s* curQueue;
|
|
static bool isActive, isRunning, shouldStop;
|
|
static LightLock queueLock = 1;
|
|
|
|
static void gxCmdQueueDoCommands(void)
|
|
{
|
|
if (shouldStop)
|
|
return;
|
|
int batchSize = curQueue->lastEntry+MAX_PARALLEL_CMDS-curQueue->curEntry;
|
|
while (curQueue->curEntry < curQueue->numEntries && batchSize--)
|
|
{
|
|
gxCmdEntry_s* entry = &curQueue->entries[curQueue->curEntry++];
|
|
gspSubmitGxCommand(entry->data);
|
|
}
|
|
}
|
|
|
|
void gxCmdQueueInterrupt(GSPGPU_Event irq)
|
|
{
|
|
if (!isRunning || irq==GSPGPU_EVENT_PSC1 || irq==GSPGPU_EVENT_VBlank0 || irq==GSPGPU_EVENT_VBlank1)
|
|
return;
|
|
gxCmdQueue_s* runCb = NULL;
|
|
LightLock_Lock(&queueLock);
|
|
curQueue->lastEntry++;
|
|
if (shouldStop)
|
|
{
|
|
curQueue = NULL;
|
|
isActive = false;
|
|
isRunning = false;
|
|
shouldStop = false;
|
|
}
|
|
else if (curQueue->lastEntry < curQueue->numEntries)
|
|
gxCmdQueueDoCommands();
|
|
else
|
|
{
|
|
runCb = curQueue;
|
|
isRunning = false;
|
|
}
|
|
LightLock_Unlock(&queueLock);
|
|
if (runCb && runCb->callback)
|
|
runCb->callback(runCb);
|
|
}
|
|
|
|
void gxCmdQueueClear(gxCmdQueue_s* queue)
|
|
{
|
|
if (queue==curQueue && isRunning)
|
|
svcBreak(USERBREAK_PANIC); // Shouldn't happen.
|
|
queue->numEntries = 0;
|
|
queue->curEntry = 0;
|
|
queue->lastEntry = 0;
|
|
}
|
|
|
|
void gxCmdQueueAdd(gxCmdQueue_s* queue, const gxCmdEntry_s* entry)
|
|
{
|
|
if (queue->numEntries == queue->maxEntries)
|
|
svcBreak(USERBREAK_PANIC); // Shouldn't happen.
|
|
memcpy(&queue->entries[queue->numEntries], entry, sizeof(gxCmdEntry_s));
|
|
LightLock_Lock(&queueLock);
|
|
queue->numEntries++;
|
|
if (queue==curQueue && isActive && !isRunning)
|
|
{
|
|
isRunning = true;
|
|
gxCmdQueueDoCommands();
|
|
}
|
|
LightLock_Unlock(&queueLock);
|
|
}
|
|
|
|
void gxCmdQueueRun(gxCmdQueue_s* queue)
|
|
{
|
|
if (isRunning)
|
|
return;
|
|
curQueue = queue;
|
|
isActive = true;
|
|
if (queue->lastEntry < queue->numEntries)
|
|
{
|
|
isRunning = true;
|
|
LightLock_Lock(&queueLock);
|
|
gxCmdQueueDoCommands();
|
|
LightLock_Unlock(&queueLock);
|
|
} else
|
|
isRunning = false;
|
|
}
|
|
|
|
void gxCmdQueueStop(gxCmdQueue_s* queue)
|
|
{
|
|
if (!curQueue)
|
|
return;
|
|
LightLock_Lock(&queueLock);
|
|
if (!isRunning)
|
|
{
|
|
curQueue = NULL;
|
|
isActive = false;
|
|
} else
|
|
shouldStop = true;
|
|
LightLock_Unlock(&queueLock);
|
|
}
|
|
|
|
bool gxCmdQueueWait(gxCmdQueue_s* queue, s64 timeout)
|
|
{
|
|
u64 deadline = U64_MAX;
|
|
if (timeout >= 0)
|
|
deadline = svcGetSystemTick() + timeout;
|
|
while (isRunning)
|
|
{
|
|
if (timeout >= 0 && (s64)(u64)(svcGetSystemTick()-deadline) >= 0)
|
|
return false;
|
|
gspWaitForAnyEvent();
|
|
}
|
|
return true;
|
|
}
|