From 3884ce985c0ce825672a9e9c8352d8429abfedf5 Mon Sep 17 00:00:00 2001 From: smea Date: Sun, 24 Aug 2014 21:37:49 -0700 Subject: [PATCH] added gfx for simplified framebuffer access --- libctru/include/3ds/gfx.h | 36 ++++++++++ libctru/source/gfx.c | 145 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 181 insertions(+) create mode 100644 libctru/include/3ds/gfx.h create mode 100644 libctru/source/gfx.c diff --git a/libctru/include/3ds/gfx.h b/libctru/include/3ds/gfx.h new file mode 100644 index 0000000..27f941b --- /dev/null +++ b/libctru/include/3ds/gfx.h @@ -0,0 +1,36 @@ +#ifndef GFX_H +#define GFX_H + +#include <3ds/types.h> + +typedef enum +{ + GFX_TOP = 0, + GFX_BOTTOM = 1 +}gfxScreen_t; + +typedef enum +{ + GFX_LEFT = 0, + GFX_RIGHT = 1, + // GFX_BOTTOM = 0 +}gfx3dSide_t; + +//system stuff +void gfxInit(); +void gfxExit(); + +//control stuff +void gfxSet3D(bool enable); +void gfxFlushBuffers(); +void gfxSwapBuffers(); + +//helper stuff +u8* gfxGetFramebuffer(gfxScreen_t screen, gfx3dSide_t side, u16* width, u16* height); + +//global variables +extern u8* gfxTopLeftFramebuffers[2]; +extern u8* gfxSubFramebuffers[2]; +extern u8* gfxBottomFramebuffers[2]; + +#endif diff --git a/libctru/source/gfx.c b/libctru/source/gfx.c new file mode 100644 index 0000000..a55b4f4 --- /dev/null +++ b/libctru/source/gfx.c @@ -0,0 +1,145 @@ +#include +#include +#include + +#include <3ds/types.h> +#include <3ds/GSP.h> +#include <3ds/GX.h> +#include <3ds/svc.h> +#include <3ds/gfx.h> + +GSP_FramebufferInfo topFramebufferInfo, bottomFramebufferInfo; + +u8* gfxTopLeftFramebuffers[2]; +u8* gfxTopRightFramebuffers[2]; +u8* gfxBottomFramebuffers[2]; + +u8 currentBuffer; +bool enable3d; + +Handle gspEvent, gspSharedMemHandle; + +u8* gspHeap; +u32* gxCmdBuf; + +void gfxSet3D(bool enable) +{ + enable3d=enable; +} + +void gfxSetFramebufferInfo(gfxScreen_t screen, u8 id) +{ + if(screen==GFX_TOP) + { + topFramebufferInfo.active_framebuf=id; + topFramebufferInfo.framebuf0_vaddr=(u32*)gfxTopLeftFramebuffers[id]; + if(enable3d)topFramebufferInfo.framebuf1_vaddr=(u32*)gfxTopRightFramebuffers[id]; + else topFramebufferInfo.framebuf1_vaddr=topFramebufferInfo.framebuf0_vaddr; + topFramebufferInfo.framebuf_widthbytesize=240*3; + topFramebufferInfo.format=((1)<<8)|((1)<<6)|((enable3d&1)<<5)|GSP_BGR8_OES; + topFramebufferInfo.framebuf_dispselect=id; + topFramebufferInfo.unk=0x00000000; + }else{ + bottomFramebufferInfo.active_framebuf=id; + bottomFramebufferInfo.framebuf0_vaddr=(u32*)gfxBottomFramebuffers[id]; + bottomFramebufferInfo.framebuf1_vaddr=0x00000000; + bottomFramebufferInfo.framebuf_widthbytesize=240*3; + bottomFramebufferInfo.format=GSP_BGR8_OES; + bottomFramebufferInfo.framebuf_dispselect=id; + bottomFramebufferInfo.unk=0x00000000; + } +} + +void gfxInit() +{ + gspInit(); + + GSPGPU_AcquireRight(NULL, 0x0); + GSPGPU_SetLcdForceBlack(NULL, 0x0); + + //setup our gsp shared mem section + u8 threadID; + svcCreateEvent(&gspEvent, 0x0); + GSPGPU_RegisterInterruptRelayQueue(NULL, gspEvent, 0x1, &gspSharedMemHandle, &threadID); + svcMapMemoryBlock(gspSharedMemHandle, 0x10002000, 0x3, 0x10000000); + + //map GSP heap + svcControlMemory((u32*)&gspHeap, 0x0, 0x0, 0x02000000, 0x10003, 0x3); + + // default gspHeap configuration : + // topleft1 0x00000000-0x00046500 + // topleft2 0x00046500-0x0008CA00 + // bottom1 0x0008CA00-0x000C4E00 + // bottom2 0x000C4E00-0x000FD200 + // if 3d enabled : + // topright1 0x000FD200-0x00143700 + // topright2 0x00143700-0x00189C00 + + gfxTopLeftFramebuffers[0]=(u8*)gspHeap; + gfxTopLeftFramebuffers[1]=gfxTopLeftFramebuffers[0]+0x46500; + gfxBottomFramebuffers[0]=gfxTopLeftFramebuffers[1]+0x46500; + gfxBottomFramebuffers[1]=gfxBottomFramebuffers[0]+0x38400; + gfxTopRightFramebuffers[0]=gfxBottomFramebuffers[1]+0x38400; + gfxTopRightFramebuffers[1]=gfxTopRightFramebuffers[0]+0x46500; + enable3d=false; + + //initialize framebuffer info structures + gfxSetFramebufferInfo(GFX_TOP, 0); + gfxSetFramebufferInfo(GFX_BOTTOM, 0); + + //wait until we can write stuff to it + svcWaitSynchronization(gspEvent, 0x55bcb0); + + //GSP shared mem : 0x2779F000 + gxCmdBuf=(u32*)(0x10002000+0x800+threadID*0x200); + + currentBuffer=0; +} + +void gfxExit() +{ + //free GSP heap + svcControlMemory((u32*)&gspHeap, (u32)gspHeap, 0x0, 0x02000000, MEMOP_FREE, 0x0); + + //unmap GSP shared mem + svcUnmapMemoryBlock(gspSharedMemHandle, 0x10002000); + + GSPGPU_UnregisterInterruptRelayQueue(NULL); + + svcCloseHandle(gspSharedMemHandle); + svcCloseHandle(gspEvent); + + GSPGPU_ReleaseRight(NULL); + + gspExit(); +} + +u8* gfxGetFramebuffer(gfxScreen_t screen, gfx3dSide_t side, u16* width, u16* height) +{ + if(width)*width=240; + + if(screen==GFX_TOP) + { + if(height)*height=400; + return (side==GFX_LEFT || !enable3d)?(gfxTopLeftFramebuffers[currentBuffer^1]):(gfxTopRightFramebuffers[currentBuffer^1]); + }else{ + if(height)*height=320; + return gfxBottomFramebuffers[currentBuffer^1]; + } +} + +void gfxFlushBuffers() +{ + GSPGPU_FlushDataCache(NULL, gfxGetFramebuffer(GFX_TOP, GFX_LEFT, NULL, NULL), 0x46500); + if(enable3d)GSPGPU_FlushDataCache(NULL, gfxGetFramebuffer(GFX_TOP, GFX_RIGHT, NULL, NULL), 0x46500); + GSPGPU_FlushDataCache(NULL, gfxGetFramebuffer(GFX_BOTTOM, GFX_LEFT, NULL, NULL), 0x38400); +} + +void gfxSwapBuffers() +{ + currentBuffer^=1; + gfxSetFramebufferInfo(GFX_TOP, currentBuffer); + gfxSetFramebufferInfo(GFX_BOTTOM, currentBuffer); + GSPGPU_SetBufferSwap(NULL, GFX_TOP, &topFramebufferInfo); + GSPGPU_SetBufferSwap(NULL, GFX_BOTTOM, &bottomFramebufferInfo); +}