mirror of
https://github.com/wiiu-env/wut.git
synced 2025-01-08 11:40:42 +01:00
Add libwhb - WUT HomeBrew library.
A library with utility functions for helping create simple homebrew applications. Mainly based off shinyquagsire23's gx2 sample. https://github.com/shinyquagsire23/gx2texture2D
This commit is contained in:
parent
f177555ca3
commit
2cb787fabf
@ -48,6 +48,16 @@ externalproject_add(libgfd
|
|||||||
-DCMAKE_INSTALL_PREFIX:string=<INSTALL_DIR>
|
-DCMAKE_INSTALL_PREFIX:string=<INSTALL_DIR>
|
||||||
-DCMAKE_TOOLCHAIN_FILE:string=${CMAKE_SOURCE_DIR}/cmake/wut-toolchain.cmake)
|
-DCMAKE_TOOLCHAIN_FILE:string=${CMAKE_SOURCE_DIR}/cmake/wut-toolchain.cmake)
|
||||||
|
|
||||||
|
externalproject_add(libwhb
|
||||||
|
SOURCE_DIR "${CMAKE_SOURCE_DIR}/src/libwhb"
|
||||||
|
CMAKE_GENERATOR "Unix Makefiles"
|
||||||
|
INSTALL_DIR "${CMAKE_BINARY_DIR}/staging"
|
||||||
|
CMAKE_CACHE_ARGS
|
||||||
|
-DDEVKITPPC:string=${DEVKITPPC}
|
||||||
|
-DWUT_ROOT:string=${CMAKE_SOURCE_DIR}
|
||||||
|
-DCMAKE_INSTALL_PREFIX:string=<INSTALL_DIR>
|
||||||
|
-DCMAKE_TOOLCHAIN_FILE:string=${CMAKE_SOURCE_DIR}/cmake/wut-toolchain.cmake)
|
||||||
|
|
||||||
# We must force build because changes are not detected with ExternalProject...
|
# We must force build because changes are not detected with ExternalProject...
|
||||||
externalproject_add_step(crt forcebuild
|
externalproject_add_step(crt forcebuild
|
||||||
COMMAND ${CMAKE_COMMAND} -E echo "Force build of crt"
|
COMMAND ${CMAKE_COMMAND} -E echo "Force build of crt"
|
||||||
@ -78,3 +88,9 @@ externalproject_add_step(libgfd forcebuild
|
|||||||
DEPENDEES "configure"
|
DEPENDEES "configure"
|
||||||
DEPENDERS "build"
|
DEPENDERS "build"
|
||||||
ALWAYS 1)
|
ALWAYS 1)
|
||||||
|
|
||||||
|
externalproject_add_step(libwhb forcebuild
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E echo "Force build of libwhb"
|
||||||
|
DEPENDEES "configure"
|
||||||
|
DEPENDERS "build"
|
||||||
|
ALWAYS 1)
|
||||||
|
19
src/libwhb/CMakeLists.txt
Normal file
19
src/libwhb/CMakeLists.txt
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.2)
|
||||||
|
project(libwhb)
|
||||||
|
|
||||||
|
file(GLOB_RECURSE SOURCE_FILES *.c)
|
||||||
|
file(GLOB_RECURSE HEADER_FILES *.h)
|
||||||
|
|
||||||
|
add_library(whb STATIC ${SOURCE_FILES} ${HEADER_FILES})
|
||||||
|
|
||||||
|
target_include_directories(whb PRIVATE "../../include")
|
||||||
|
target_include_directories(whb PRIVATE "../libdefaultheap/include")
|
||||||
|
target_include_directories(whb PRIVATE "../libgfd/include")
|
||||||
|
target_include_directories(whb PUBLIC "include")
|
||||||
|
|
||||||
|
install(TARGETS whb
|
||||||
|
ARCHIVE DESTINATION "${CMAKE_INSTALL_PREFIX}/lib")
|
||||||
|
install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/
|
||||||
|
DESTINATION "${CMAKE_INSTALL_PREFIX}/include"
|
||||||
|
FILES_MATCHING PATTERN "*.h*")
|
||||||
|
|
20
src/libwhb/include/whb/align.h
Normal file
20
src/libwhb/include/whb/align.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <wut.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \defgroup whb_align Align
|
||||||
|
* \ingroup whb
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define WHBAlignUp(val, align) ((val + align - 1) & ~(align - 1))
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** @} */
|
47
src/libwhb/include/whb/file.h
Normal file
47
src/libwhb/include/whb/file.h
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <wut.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \defgroup whb_file Filesystem
|
||||||
|
* \ingroup whb
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef enum WHBFileError
|
||||||
|
{
|
||||||
|
WHB_FILE_OK = 0,
|
||||||
|
WHB_FILE_FATAL_ERROR = -1,
|
||||||
|
} WHBFileError;
|
||||||
|
|
||||||
|
int32_t
|
||||||
|
WHBOpenFile(const char *path,
|
||||||
|
const char *mode);
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
WHBGetFileSize(int32_t handle);
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
WHBReadFile(int32_t handle,
|
||||||
|
void *buf,
|
||||||
|
uint32_t size,
|
||||||
|
uint32_t count);
|
||||||
|
|
||||||
|
int32_t
|
||||||
|
WHBCloseFile(int32_t handle);
|
||||||
|
|
||||||
|
char *
|
||||||
|
WHBReadWholeFile(const char *path,
|
||||||
|
uint32_t *outSize);
|
||||||
|
|
||||||
|
void
|
||||||
|
WHBFreeWholeFile(char *file);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** @} */
|
87
src/libwhb/include/whb/gfx.h
Normal file
87
src/libwhb/include/whb/gfx.h
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <wut.h>
|
||||||
|
#include <gx2/shaders.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \defgroup whb_gfx Graphics
|
||||||
|
* \ingroup whb
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct WHBGfxShaderGroup WHBGfxShaderGroup;
|
||||||
|
|
||||||
|
struct WHBGfxShaderGroup
|
||||||
|
{
|
||||||
|
GX2FetchShader fetchShader;
|
||||||
|
void *fetchShaderProgram;
|
||||||
|
GX2PixelShader *pixelShader;
|
||||||
|
GX2VertexShader *vertexShader;
|
||||||
|
uint32_t numAttributes;
|
||||||
|
GX2AttribStream attributes[16];
|
||||||
|
};
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
WHBGfxInit();
|
||||||
|
|
||||||
|
void
|
||||||
|
WHBGfxShutdown();
|
||||||
|
|
||||||
|
void
|
||||||
|
WHBGfxBeginRender();
|
||||||
|
|
||||||
|
void
|
||||||
|
WHBGfxFinishRender();
|
||||||
|
|
||||||
|
void
|
||||||
|
WHBGfxBeginRenderDRC();
|
||||||
|
|
||||||
|
void
|
||||||
|
WHBGfxFinishRenderDRC();
|
||||||
|
|
||||||
|
void
|
||||||
|
WHBGfxBeginRenderTV();
|
||||||
|
|
||||||
|
void
|
||||||
|
WHBGfxFinishRenderTV();
|
||||||
|
|
||||||
|
GX2PixelShader *
|
||||||
|
WHBGfxLoadGFDPixelShader(uint32_t index,
|
||||||
|
const void *file);
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
WHBGfxFreePixelShader(GX2PixelShader *shader);
|
||||||
|
|
||||||
|
GX2VertexShader *
|
||||||
|
WHBGfxLoadGFDVertexShader(uint32_t index,
|
||||||
|
const void *file);
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
WHBGfxFreeVertexShader(GX2VertexShader *shader);
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
WHBGfxLoadGFDShaderGroup(WHBGfxShaderGroup *group,
|
||||||
|
uint32_t index,
|
||||||
|
const void *file);
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
WHBGfxInitShaderAttribute(WHBGfxShaderGroup *group,
|
||||||
|
const char *name,
|
||||||
|
uint32_t buffer,
|
||||||
|
uint32_t offset,
|
||||||
|
GX2AttribFormat format);
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
WHBGfxInitFetchShader(WHBGfxShaderGroup *group);
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
WHBGfxFreeShaderGroup(WHBGfxShaderGroup *group);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** @} */
|
14
src/libwhb/include/whb/proc.h
Normal file
14
src/libwhb/include/whb/proc.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <wut.h>
|
||||||
|
|
||||||
|
void
|
||||||
|
WHBProcInit();
|
||||||
|
|
||||||
|
void
|
||||||
|
WHBProcShutdown();
|
||||||
|
|
||||||
|
void
|
||||||
|
WHBProcStopRunning();
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
WHBProcIsRunning();
|
150
src/libwhb/src/file.c
Normal file
150
src/libwhb/src/file.c
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
#include <coreinit/filesystem.h>
|
||||||
|
#include <defaultheap.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <whb/file.h>
|
||||||
|
|
||||||
|
static BOOL
|
||||||
|
sInitialised = FALSE;
|
||||||
|
|
||||||
|
static FSClient
|
||||||
|
sClient;
|
||||||
|
|
||||||
|
static BOOL
|
||||||
|
InitFileSystem()
|
||||||
|
{
|
||||||
|
if (!sInitialised) {
|
||||||
|
FSInit();
|
||||||
|
|
||||||
|
if (FSAddClient(&sClient, -1) != FS_STATUS_OK) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
sInitialised = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t
|
||||||
|
WHBOpenFile(const char *path,
|
||||||
|
const char *mode)
|
||||||
|
{
|
||||||
|
FSCmdBlock cmd;
|
||||||
|
FSStatus result;
|
||||||
|
FSFileHandle handle;
|
||||||
|
char tmp[256];
|
||||||
|
tmp[0] = 0;
|
||||||
|
|
||||||
|
if (!InitFileSystem()) {
|
||||||
|
return WHB_FILE_FATAL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (path[0] != '/') {
|
||||||
|
strcat(tmp, "/vol/content/");
|
||||||
|
strcat(tmp, path);
|
||||||
|
} else {
|
||||||
|
strcat(tmp, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
FSInitCmdBlock(&cmd);
|
||||||
|
result = FSOpenFile(&sClient, &cmd, tmp, mode, &handle, -1);
|
||||||
|
if (result < 0) {
|
||||||
|
return WHB_FILE_FATAL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (int32_t)handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
WHBGetFileSize(int32_t handle)
|
||||||
|
{
|
||||||
|
FSCmdBlock cmd;
|
||||||
|
FSStatus result;
|
||||||
|
FSStat stat;
|
||||||
|
FSInitCmdBlock(&cmd);
|
||||||
|
result = FSGetStatFile(&sClient, &cmd, (FSFileHandle)handle, &stat, -1);
|
||||||
|
if (result < 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return stat.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
WHBReadFile(int32_t handle,
|
||||||
|
void *buf,
|
||||||
|
uint32_t size,
|
||||||
|
uint32_t count)
|
||||||
|
{
|
||||||
|
FSCmdBlock cmd;
|
||||||
|
FSStatus result;
|
||||||
|
FSInitCmdBlock(&cmd);
|
||||||
|
result = FSReadFile(&sClient, &cmd, buf, size, count, (FSFileHandle)handle, 0, -1);
|
||||||
|
if (result < 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (uint32_t)result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t
|
||||||
|
WHBCloseFile(int32_t handle)
|
||||||
|
{
|
||||||
|
FSCmdBlock cmd;
|
||||||
|
FSStatus result;
|
||||||
|
FSInitCmdBlock(&cmd);
|
||||||
|
result = FSCloseFile(&sClient, &cmd, (FSFileHandle)handle, -1);
|
||||||
|
if (result != FS_STATUS_OK) {
|
||||||
|
return WHB_FILE_FATAL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return WHB_FILE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
WHBReadWholeFile(const char *path,
|
||||||
|
uint32_t *outSize)
|
||||||
|
{
|
||||||
|
int32_t handle;
|
||||||
|
uint32_t size;
|
||||||
|
char *buf = NULL;
|
||||||
|
handle = WHBOpenFile(path, "r");
|
||||||
|
if (handle == WHB_FILE_FATAL_ERROR) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
size = WHBGetFileSize(handle);
|
||||||
|
if (size == 0) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf = MEMAllocFromDefaultHeapEx(size, 64);
|
||||||
|
if (!buf) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (WHBReadFile(handle, buf, 1, size) != size) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (outSize) {
|
||||||
|
*outSize = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
WHBCloseFile(handle);
|
||||||
|
return buf;
|
||||||
|
|
||||||
|
error:
|
||||||
|
if (buf) {
|
||||||
|
MEMFreeToDefaultHeap(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
WHBCloseFile(handle);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
WHBFreeWholeFile(char *file)
|
||||||
|
{
|
||||||
|
MEMFreeToDefaultHeap(file);
|
||||||
|
}
|
465
src/libwhb/src/gfx.c
Normal file
465
src/libwhb/src/gfx.c
Normal file
@ -0,0 +1,465 @@
|
|||||||
|
#include "gfx_heap.h"
|
||||||
|
|
||||||
|
#include <gx2/context.h>
|
||||||
|
#include <gx2/display.h>
|
||||||
|
#include <gx2/event.h>
|
||||||
|
#include <gx2/registers.h>
|
||||||
|
#include <gx2/shaders.h>
|
||||||
|
#include <gx2/surface.h>
|
||||||
|
#include <gx2/swap.h>
|
||||||
|
#include <gx2r/mem.h>
|
||||||
|
#include <proc_ui/procui.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <whb/gfx.h>
|
||||||
|
|
||||||
|
#define WHB_GFX_COMMAND_BUFFER_POOL_SIZE (0x400000)
|
||||||
|
|
||||||
|
static void *
|
||||||
|
sCommandBufferPool = NULL;
|
||||||
|
|
||||||
|
static GX2DrcRenderMode
|
||||||
|
sDrcRenderMode;
|
||||||
|
|
||||||
|
static void *
|
||||||
|
sDrcScanBuffer = NULL;
|
||||||
|
|
||||||
|
static uint32_t
|
||||||
|
sDrcScanBufferSize = 0;
|
||||||
|
|
||||||
|
static GX2SurfaceFormat
|
||||||
|
sDrcSurfaceFormat;
|
||||||
|
|
||||||
|
static GX2TVRenderMode
|
||||||
|
sTvRenderMode;
|
||||||
|
|
||||||
|
static void *
|
||||||
|
sTvScanBuffer = NULL;
|
||||||
|
|
||||||
|
static uint32_t
|
||||||
|
sTvScanBufferSize = 0;
|
||||||
|
|
||||||
|
static GX2SurfaceFormat
|
||||||
|
sTvSurfaceFormat;
|
||||||
|
|
||||||
|
static GX2ColorBuffer
|
||||||
|
sTvColourBuffer = { 0 };
|
||||||
|
|
||||||
|
static GX2DepthBuffer
|
||||||
|
sTvDepthBuffer = { 0 };
|
||||||
|
|
||||||
|
static GX2ColorBuffer
|
||||||
|
sDrcColourBuffer = { 0 };
|
||||||
|
|
||||||
|
static GX2DepthBuffer
|
||||||
|
sDrcDepthBuffer = { 0 };
|
||||||
|
|
||||||
|
static GX2ContextState *
|
||||||
|
sTvContextState = NULL;
|
||||||
|
|
||||||
|
static GX2ContextState *
|
||||||
|
sDrcContextState = NULL;
|
||||||
|
|
||||||
|
static void *
|
||||||
|
GfxGX2RAlloc(GX2RResourceFlags flags,
|
||||||
|
uint32_t size,
|
||||||
|
uint32_t alignment)
|
||||||
|
{
|
||||||
|
// Color, depth, scan buffers all belong in MEM1
|
||||||
|
if ((flags & (GX2R_RESOURCE_BIND_COLOR_BUFFER
|
||||||
|
| GX2R_RESOURCE_BIND_DEPTH_BUFFER
|
||||||
|
| GX2R_RESOURCE_BIND_SCAN_BUFFER
|
||||||
|
| GX2R_RESOURCE_USAGE_FORCE_MEM1))
|
||||||
|
&& !(flags & GX2R_RESOURCE_USAGE_FORCE_MEM2)) {
|
||||||
|
return GfxHeapAllocMEM1(size, alignment);
|
||||||
|
} else {
|
||||||
|
return GfxHeapAllocMEM2(size, alignment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
GfxGX2RFree(GX2RResourceFlags flags, void *block)
|
||||||
|
{
|
||||||
|
if ((flags & (GX2R_RESOURCE_BIND_COLOR_BUFFER
|
||||||
|
| GX2R_RESOURCE_BIND_DEPTH_BUFFER
|
||||||
|
| GX2R_RESOURCE_BIND_SCAN_BUFFER
|
||||||
|
| GX2R_RESOURCE_USAGE_FORCE_MEM1))
|
||||||
|
&& !(flags & GX2R_RESOURCE_USAGE_FORCE_MEM2)) {
|
||||||
|
return GfxHeapFreeMEM1(block);
|
||||||
|
} else {
|
||||||
|
return GfxHeapFreeMEM2(block);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
GfxInitTvColourBuffer(GX2ColorBuffer *cb,
|
||||||
|
uint32_t width,
|
||||||
|
uint32_t height,
|
||||||
|
GX2SurfaceFormat format,
|
||||||
|
GX2AAMode aa)
|
||||||
|
{
|
||||||
|
memset(cb, 0, sizeof(GX2ColorBuffer));
|
||||||
|
cb->surface.use = GX2_SURFACE_USE_TEXTURE_COLOR_BUFFER_TV;
|
||||||
|
cb->surface.dim = GX2_SURFACE_DIM_TEXTURE_2D;
|
||||||
|
cb->surface.width = width;
|
||||||
|
cb->surface.height = height;
|
||||||
|
cb->surface.depth = 1;
|
||||||
|
cb->surface.mipLevels = 1;
|
||||||
|
cb->surface.format = format;
|
||||||
|
cb->surface.aa = aa;
|
||||||
|
cb->surface.tileMode = GX2_TILE_MODE_DEFAULT;
|
||||||
|
cb->viewNumSlices = 1;
|
||||||
|
GX2CalcSurfaceSizeAndAlignment(&cb->surface);
|
||||||
|
GX2InitColorBufferRegs(cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
GfxInitDepthBuffer(GX2DepthBuffer *db,
|
||||||
|
uint32_t width,
|
||||||
|
uint32_t height,
|
||||||
|
GX2SurfaceFormat format,
|
||||||
|
GX2AAMode aa)
|
||||||
|
{
|
||||||
|
memset(db, 0, sizeof(GX2DepthBuffer));
|
||||||
|
|
||||||
|
if (format == GX2_SURFACE_FORMAT_UNORM_R24_X8 || format == GX2_SURFACE_FORMAT_FLOAT_D24_S8) {
|
||||||
|
db->surface.use = GX2_SURFACE_USE_DEPTH_BUFFER;
|
||||||
|
} else {
|
||||||
|
db->surface.use = GX2_SURFACE_USE_DEPTH_BUFFER | GX2_SURFACE_USE_TEXTURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
db->surface.dim = GX2_SURFACE_DIM_TEXTURE_2D;
|
||||||
|
db->surface.width = width;
|
||||||
|
db->surface.height = height;
|
||||||
|
db->surface.depth = 1;
|
||||||
|
db->surface.mipLevels = 1;
|
||||||
|
db->surface.format = format;
|
||||||
|
db->surface.aa = aa;
|
||||||
|
db->surface.tileMode = GX2_TILE_MODE_DEFAULT;
|
||||||
|
db->viewNumSlices = 1;
|
||||||
|
db->depthClear = 1.0f;
|
||||||
|
GX2CalcSurfaceSizeAndAlignment(&db->surface);
|
||||||
|
GX2InitDepthBufferRegs(db);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t
|
||||||
|
GfxProcCallbackAcquired(void *context)
|
||||||
|
{
|
||||||
|
GfxHeapInitMEM1();
|
||||||
|
GfxHeapInitForeground();
|
||||||
|
|
||||||
|
// Allocate TV scan buffer.
|
||||||
|
sTvScanBuffer = GfxHeapAllocForeground(sTvScanBufferSize, GX2_SCAN_BUFFER_ALIGNMENT);
|
||||||
|
if (!sTvScanBuffer) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
GX2Invalidate(GX2_INVALIDATE_MODE_CPU, sTvScanBuffer, sTvScanBufferSize);
|
||||||
|
GX2SetTVBuffer(sTvScanBuffer, sTvScanBufferSize, sTvRenderMode, sTvSurfaceFormat, GX2_BUFFERING_MODE_DOUBLE);
|
||||||
|
|
||||||
|
// Allocate TV colour buffer.
|
||||||
|
sTvColourBuffer.surface.image = GfxHeapAllocMEM1(sTvColourBuffer.surface.imageSize, sTvColourBuffer.surface.alignment);
|
||||||
|
if (!sTvColourBuffer.surface.image) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
GX2Invalidate(GX2_INVALIDATE_MODE_CPU, sTvColourBuffer.surface.image, sTvColourBuffer.surface.imageSize);
|
||||||
|
|
||||||
|
// Allocate TV depth buffer.
|
||||||
|
sTvDepthBuffer.surface.image = GfxHeapAllocMEM1(sTvDepthBuffer.surface.imageSize, sTvDepthBuffer.surface.alignment);
|
||||||
|
if (!sTvDepthBuffer.surface.image) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
GX2Invalidate(GX2_INVALIDATE_MODE_CPU, sTvDepthBuffer.surface.image, sTvDepthBuffer.surface.imageSize);
|
||||||
|
|
||||||
|
// Allocate DRC scan buffer.
|
||||||
|
sDrcScanBuffer = GfxHeapAllocForeground(sDrcScanBufferSize, GX2_SCAN_BUFFER_ALIGNMENT);
|
||||||
|
if (!sDrcScanBuffer) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
GX2Invalidate(GX2_INVALIDATE_MODE_CPU, sDrcScanBuffer, sDrcScanBufferSize);
|
||||||
|
GX2SetDRCBuffer(sDrcScanBuffer, sDrcScanBufferSize, sDrcRenderMode, sDrcSurfaceFormat, GX2_BUFFERING_MODE_DOUBLE);
|
||||||
|
|
||||||
|
// Allocate DRC colour buffer.
|
||||||
|
sDrcColourBuffer.surface.image = GfxHeapAllocMEM1(sDrcColourBuffer.surface.imageSize, sDrcColourBuffer.surface.alignment);
|
||||||
|
if (!sDrcColourBuffer.surface.image) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
GX2Invalidate(GX2_INVALIDATE_MODE_CPU, sDrcColourBuffer.surface.image, sDrcColourBuffer.surface.imageSize);
|
||||||
|
|
||||||
|
// Allocate DRC depth buffer.
|
||||||
|
sDrcDepthBuffer.surface.image = GfxHeapAllocMEM1(sDrcDepthBuffer.surface.imageSize, sDrcDepthBuffer.surface.alignment);
|
||||||
|
if (!sDrcDepthBuffer.surface.image) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
GX2Invalidate(GX2_INVALIDATE_MODE_CPU, sDrcDepthBuffer.surface.image, sDrcDepthBuffer.surface.imageSize);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
error:
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t
|
||||||
|
GfxProcCallbackReleased(void *context)
|
||||||
|
{
|
||||||
|
GX2DrawDone();
|
||||||
|
|
||||||
|
if (sTvScanBuffer) {
|
||||||
|
GfxHeapFreeForeground(sTvScanBuffer);
|
||||||
|
sTvScanBuffer = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sTvColourBuffer.surface.image) {
|
||||||
|
GfxHeapFreeMEM1(sTvColourBuffer.surface.image);
|
||||||
|
sTvColourBuffer.surface.image = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sTvDepthBuffer.surface.image) {
|
||||||
|
GfxHeapFreeMEM1(sTvDepthBuffer.surface.image);
|
||||||
|
sTvDepthBuffer.surface.image = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sDrcScanBuffer) {
|
||||||
|
GfxHeapFreeForeground(sDrcScanBuffer);
|
||||||
|
sDrcScanBuffer = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sDrcColourBuffer.surface.image) {
|
||||||
|
GfxHeapFreeMEM1(sDrcColourBuffer.surface.image);
|
||||||
|
sDrcColourBuffer.surface.image = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sDrcDepthBuffer.surface.image) {
|
||||||
|
GfxHeapFreeMEM1(sDrcDepthBuffer.surface.image);
|
||||||
|
sDrcDepthBuffer.surface.image = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
GfxHeapDestroyMEM1();
|
||||||
|
GfxHeapDestroyForeground();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
WHBGfxInit()
|
||||||
|
{
|
||||||
|
uint32_t drcWidth, drcHeight;
|
||||||
|
uint32_t tvWidth, tvHeight;
|
||||||
|
uint32_t unk;
|
||||||
|
|
||||||
|
sCommandBufferPool = GfxHeapAllocMEM2(WHB_GFX_COMMAND_BUFFER_POOL_SIZE,
|
||||||
|
GX2_COMMAND_BUFFER_ALIGNMENT);
|
||||||
|
if (!sCommandBufferPool) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t initAttribs[] = {
|
||||||
|
GX2_INIT_CMD_BUF_BASE, (uintptr_t)sCommandBufferPool,
|
||||||
|
GX2_INIT_CMD_BUF_POOL_SIZE, WHB_GFX_COMMAND_BUFFER_POOL_SIZE,
|
||||||
|
GX2_INIT_ARGC, 0,
|
||||||
|
GX2_INIT_ARGV, 0,
|
||||||
|
GX2_INIT_END
|
||||||
|
};
|
||||||
|
GX2Init(initAttribs);
|
||||||
|
|
||||||
|
sDrcRenderMode = GX2GetSystemDRCScanMode();
|
||||||
|
sTvSurfaceFormat = GX2_SURFACE_FORMAT_UNORM_R8_G8_B8_A8;
|
||||||
|
sDrcSurfaceFormat = GX2_SURFACE_FORMAT_UNORM_R8_G8_B8_A8;
|
||||||
|
|
||||||
|
switch(GX2GetSystemTVScanMode())
|
||||||
|
{
|
||||||
|
case GX2_TV_SCAN_MODE_480I:
|
||||||
|
case GX2_TV_SCAN_MODE_480P:
|
||||||
|
sTvRenderMode = GX2_TV_RENDER_MODE_WIDE_480P;
|
||||||
|
tvWidth = 854;
|
||||||
|
tvHeight = 480;
|
||||||
|
break;
|
||||||
|
case GX2_TV_SCAN_MODE_1080I:
|
||||||
|
case GX2_TV_SCAN_MODE_1080P:
|
||||||
|
sTvRenderMode = GX2_TV_RENDER_MODE_WIDE_1080P;
|
||||||
|
tvWidth = 1920;
|
||||||
|
tvHeight = 1080;
|
||||||
|
break;
|
||||||
|
case GX2_TV_SCAN_MODE_720P:
|
||||||
|
default:
|
||||||
|
sTvRenderMode = GX2_TV_RENDER_MODE_WIDE_720P;
|
||||||
|
tvWidth = 1280;
|
||||||
|
tvHeight = 720;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
drcWidth = 854;
|
||||||
|
drcHeight = 480;
|
||||||
|
|
||||||
|
// Setup TV and DRC buffers - they will be allocated in GfxProcCallbackAcquired.
|
||||||
|
GX2CalcTVSize(sTvRenderMode, sTvSurfaceFormat, GX2_BUFFERING_MODE_DOUBLE, &sTvScanBufferSize, &unk);
|
||||||
|
GfxInitTvColourBuffer(&sTvColourBuffer, tvWidth, tvHeight, sTvSurfaceFormat, GX2_AA_MODE1X);
|
||||||
|
GfxInitDepthBuffer(&sTvDepthBuffer, sTvColourBuffer.surface.width, sTvColourBuffer.surface.height, GX2_SURFACE_FORMAT_FLOAT_R32, sTvColourBuffer.surface.aa);
|
||||||
|
|
||||||
|
GX2CalcDRCSize(sDrcRenderMode, sDrcSurfaceFormat, GX2_BUFFERING_MODE_DOUBLE, &sDrcScanBufferSize, &unk);
|
||||||
|
GfxInitTvColourBuffer(&sDrcColourBuffer, drcWidth, drcHeight, sDrcSurfaceFormat, GX2_AA_MODE1X);
|
||||||
|
GfxInitDepthBuffer(&sDrcDepthBuffer, sDrcColourBuffer.surface.width, sDrcColourBuffer.surface.height, GX2_SURFACE_FORMAT_FLOAT_R32, sDrcColourBuffer.surface.aa);
|
||||||
|
|
||||||
|
if (GfxProcCallbackAcquired(NULL) != 0) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
GX2RSetAllocator(&GfxGX2RAlloc, &GfxGX2RFree);
|
||||||
|
ProcUIRegisterCallback(PROCUI_CALLBACK_ACQUIRE, GfxProcCallbackAcquired, NULL, 100);
|
||||||
|
ProcUIRegisterCallback(PROCUI_CALLBACK_RELEASE, GfxProcCallbackReleased, NULL, 100);
|
||||||
|
|
||||||
|
// Initialise TV context state.
|
||||||
|
sTvContextState = GfxHeapAllocMEM2(sizeof(GX2ContextState), GX2_CONTEXT_STATE_ALIGNMENT);
|
||||||
|
if (!sTvContextState) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
GX2SetupContextStateEx(sTvContextState, TRUE);
|
||||||
|
GX2SetContextState(sTvContextState);
|
||||||
|
GX2SetColorBuffer(&sTvColourBuffer, GX2_RENDER_TARGET_0);
|
||||||
|
GX2SetDepthBuffer(&sTvDepthBuffer);
|
||||||
|
GX2SetViewport(0, 0, (float)sTvColourBuffer.surface.width, (float)sTvColourBuffer.surface.height, 0.0f, 1.0f);
|
||||||
|
GX2SetScissor(0, 0, (float)sTvColourBuffer.surface.width, (float)sTvColourBuffer.surface.height);
|
||||||
|
GX2SetTVScale((float)sTvColourBuffer.surface.width, (float)sTvColourBuffer.surface.height);
|
||||||
|
|
||||||
|
// Initialise DRC context state.
|
||||||
|
sDrcContextState = GfxHeapAllocMEM2(sizeof(GX2ContextState), GX2_CONTEXT_STATE_ALIGNMENT);
|
||||||
|
if (!sDrcContextState) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
GX2SetupContextStateEx(sDrcContextState, TRUE);
|
||||||
|
GX2SetContextState(sDrcContextState);
|
||||||
|
GX2SetColorBuffer(&sDrcColourBuffer, GX2_RENDER_TARGET_0);
|
||||||
|
GX2SetDepthBuffer(&sDrcDepthBuffer);
|
||||||
|
GX2SetViewport(0, 0, (float)sDrcColourBuffer.surface.width, (float)sDrcColourBuffer.surface.height, 0.0f, 1.0f);
|
||||||
|
GX2SetScissor(0, 0, (float)sDrcColourBuffer.surface.width, (float)sDrcColourBuffer.surface.height);
|
||||||
|
GX2SetDRCScale((float)sDrcColourBuffer.surface.width, (float)sDrcColourBuffer.surface.height);
|
||||||
|
|
||||||
|
// Set 60fps VSync
|
||||||
|
GX2SetSwapInterval(1);
|
||||||
|
GX2SetTVEnable(TRUE);
|
||||||
|
GX2SetDRCEnable(TRUE);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
error:
|
||||||
|
if (sCommandBufferPool) {
|
||||||
|
GfxHeapFreeMEM2(sCommandBufferPool);
|
||||||
|
sCommandBufferPool = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sTvScanBuffer) {
|
||||||
|
GfxHeapFreeForeground(sTvScanBuffer);
|
||||||
|
sTvScanBuffer = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sTvColourBuffer.surface.image) {
|
||||||
|
GfxHeapFreeMEM1(sTvColourBuffer.surface.image);
|
||||||
|
sTvColourBuffer.surface.image = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sTvDepthBuffer.surface.image) {
|
||||||
|
GfxHeapFreeMEM1(sTvDepthBuffer.surface.image);
|
||||||
|
sTvDepthBuffer.surface.image = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sTvContextState) {
|
||||||
|
GfxHeapFreeMEM2(sTvContextState);
|
||||||
|
sTvContextState = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sDrcScanBuffer) {
|
||||||
|
GfxHeapFreeForeground(sDrcScanBuffer);
|
||||||
|
sDrcScanBuffer = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sDrcColourBuffer.surface.image) {
|
||||||
|
GfxHeapFreeMEM1(sDrcColourBuffer.surface.image);
|
||||||
|
sDrcColourBuffer.surface.image = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sDrcDepthBuffer.surface.image) {
|
||||||
|
GfxHeapFreeMEM1(sDrcDepthBuffer.surface.image);
|
||||||
|
sDrcDepthBuffer.surface.image = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sDrcContextState) {
|
||||||
|
GfxHeapFreeMEM2(sDrcContextState);
|
||||||
|
sDrcContextState = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
WHBGfxShutdown()
|
||||||
|
{
|
||||||
|
GfxProcCallbackReleased(NULL);
|
||||||
|
GX2Shutdown();
|
||||||
|
|
||||||
|
if (sTvContextState) {
|
||||||
|
GfxHeapFreeMEM2(sTvContextState);
|
||||||
|
sTvContextState = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sDrcContextState) {
|
||||||
|
GfxHeapFreeMEM2(sDrcContextState);
|
||||||
|
sDrcContextState = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sCommandBufferPool) {
|
||||||
|
GfxHeapFreeMEM2(sCommandBufferPool);
|
||||||
|
sCommandBufferPool = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
GX2RSetAllocator(NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
WHBGfxBeginRender()
|
||||||
|
{
|
||||||
|
uint32_t swapCount, flipCount;
|
||||||
|
OSTime lastFlip, lastVsync;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
GX2WaitForVsync();
|
||||||
|
GX2GetSwapStatus(&swapCount, &flipCount, &lastFlip, &lastVsync);
|
||||||
|
|
||||||
|
if (flipCount >= swapCount) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
WHBGfxFinishRender()
|
||||||
|
{
|
||||||
|
GX2Flush();
|
||||||
|
GX2SwapScanBuffers();
|
||||||
|
GX2Flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
WHBGfxBeginRenderDRC()
|
||||||
|
{
|
||||||
|
GX2SetContextState(sDrcContextState);
|
||||||
|
GX2ClearColor(&sDrcColourBuffer, 0.0f, 1.0f, 0.0f, 1.0f);
|
||||||
|
GX2ClearDepthStencilEx(&sDrcDepthBuffer, sDrcDepthBuffer.depthClear, sDrcDepthBuffer.stencilClear, GX2_CLEAR_FLAGS_DEPTH | GX2_CLEAR_FLAGS_STENCIL);
|
||||||
|
GX2SetContextState(sDrcContextState);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
WHBGfxFinishRenderDRC()
|
||||||
|
{
|
||||||
|
GX2CopyColorBufferToScanBuffer(&sDrcColourBuffer, GX2_SCAN_TARGET_DRC);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
WHBGfxBeginRenderTV()
|
||||||
|
{
|
||||||
|
GX2SetContextState(sTvContextState);
|
||||||
|
GX2ClearColor(&sTvColourBuffer, 1.0f, 0.0f, 0.0f, 1.0f);
|
||||||
|
GX2ClearDepthStencilEx(&sTvDepthBuffer, sTvDepthBuffer.depthClear, sTvDepthBuffer.stencilClear, GX2_CLEAR_FLAGS_DEPTH | GX2_CLEAR_FLAGS_STENCIL);
|
||||||
|
GX2SetContextState(sTvContextState);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
WHBGfxFinishRenderTV()
|
||||||
|
{
|
||||||
|
GX2CopyColorBufferToScanBuffer(&sTvColourBuffer, GX2_SCAN_TARGET_TV);
|
||||||
|
}
|
156
src/libwhb/src/gfx_heap.c
Normal file
156
src/libwhb/src/gfx_heap.c
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
#include "gfx_heap.h"
|
||||||
|
#include <coreinit/baseheap.h>
|
||||||
|
#include <coreinit/expandedheap.h>
|
||||||
|
#include <coreinit/frameheap.h>
|
||||||
|
#include <defaultheap.h>
|
||||||
|
|
||||||
|
static void *
|
||||||
|
sGfxHeapMEM1 = NULL;
|
||||||
|
|
||||||
|
static void *
|
||||||
|
sGfxHeapForeground = NULL;
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
GfxHeapInitMEM1()
|
||||||
|
{
|
||||||
|
MEMHeapHandle mem1 = MEMGetBaseHeapHandle(MEM_BASE_HEAP_MEM1);
|
||||||
|
uint32_t size = MEMGetAllocatableSizeForFrmHeapEx(mem1, 4);
|
||||||
|
if (!size) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *base = MEMAllocFromFrmHeapEx(mem1, size, 4);
|
||||||
|
if (!base) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
sGfxHeapMEM1 = MEMCreateExpHeapEx(base, size, 0);
|
||||||
|
if (!sGfxHeapMEM1) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
GfxHeapDestroyMEM1()
|
||||||
|
{
|
||||||
|
MEMHeapHandle mem1 = MEMGetBaseHeapHandle(MEM_BASE_HEAP_MEM1);
|
||||||
|
|
||||||
|
if (sGfxHeapMEM1) {
|
||||||
|
MEMDestroyExpHeap(sGfxHeapMEM1);
|
||||||
|
sGfxHeapMEM1 = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
MEMFreeToFrmHeap(mem1, MEM_FRAME_HEAP_FREE_ALL);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
GfxHeapInitForeground()
|
||||||
|
{
|
||||||
|
MEMHeapHandle mem1 = MEMGetBaseHeapHandle(MEM_BASE_HEAP_FG);
|
||||||
|
uint32_t size = MEMGetAllocatableSizeForFrmHeapEx(mem1, 4);
|
||||||
|
if (!size) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *base = MEMAllocFromFrmHeapEx(mem1, size, 4);
|
||||||
|
if (!base) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
sGfxHeapForeground = MEMCreateExpHeapEx(base, size, 0);
|
||||||
|
if (!sGfxHeapForeground) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
GfxHeapDestroyForeground()
|
||||||
|
{
|
||||||
|
MEMHeapHandle foreground = MEMGetBaseHeapHandle(MEM_BASE_HEAP_FG);
|
||||||
|
|
||||||
|
if (sGfxHeapForeground) {
|
||||||
|
MEMDestroyExpHeap(sGfxHeapForeground);
|
||||||
|
sGfxHeapForeground = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
MEMFreeToFrmHeap(foreground, MEM_FRAME_HEAP_FREE_ALL);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *
|
||||||
|
GfxHeapAllocMEM1(uint32_t size,
|
||||||
|
uint32_t alignment)
|
||||||
|
{
|
||||||
|
void *block;
|
||||||
|
|
||||||
|
if (!sGfxHeapMEM1) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (alignment < 4) {
|
||||||
|
alignment = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
block = MEMAllocFromExpHeapEx(sGfxHeapMEM1, size, alignment);
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GfxHeapFreeMEM1(void *block)
|
||||||
|
{
|
||||||
|
if (!sGfxHeapMEM1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MEMFreeToExpHeap(sGfxHeapMEM1, block);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *
|
||||||
|
GfxHeapAllocForeground(uint32_t size,
|
||||||
|
uint32_t alignment)
|
||||||
|
{
|
||||||
|
void *block;
|
||||||
|
|
||||||
|
if (!sGfxHeapForeground) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (alignment < 4) {
|
||||||
|
alignment = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
block = MEMAllocFromExpHeapEx(sGfxHeapForeground, size, alignment);
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GfxHeapFreeForeground(void *block)
|
||||||
|
{
|
||||||
|
if (!sGfxHeapForeground) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MEMFreeToExpHeap(sGfxHeapForeground, block);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *
|
||||||
|
GfxHeapAllocMEM2(uint32_t size,
|
||||||
|
uint32_t alignment)
|
||||||
|
{
|
||||||
|
if (alignment < 4) {
|
||||||
|
alignment = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
return MEMAllocFromDefaultHeapEx(size, alignment);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GfxHeapFreeMEM2(void *block)
|
||||||
|
{
|
||||||
|
MEMFreeToDefaultHeap(block);
|
||||||
|
}
|
35
src/libwhb/src/gfx_heap.h
Normal file
35
src/libwhb/src/gfx_heap.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <wut.h>
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
GfxHeapInitMEM1();
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
GfxHeapDestroyMEM1();
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
GfxHeapInitForeground();
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
GfxHeapDestroyForeground();
|
||||||
|
|
||||||
|
void *
|
||||||
|
GfxHeapAllocMEM1(uint32_t size,
|
||||||
|
uint32_t alignment);
|
||||||
|
|
||||||
|
void
|
||||||
|
GfxHeapFreeMEM1(void *block);
|
||||||
|
|
||||||
|
void *
|
||||||
|
GfxHeapAllocForeground(uint32_t size,
|
||||||
|
uint32_t alignment);
|
||||||
|
|
||||||
|
void
|
||||||
|
GfxHeapFreeForeground(void *block);
|
||||||
|
|
||||||
|
void *
|
||||||
|
GfxHeapAllocMEM2(uint32_t size,
|
||||||
|
uint32_t alignment);
|
||||||
|
|
||||||
|
void
|
||||||
|
GfxHeapFreeMEM2(void *block);
|
265
src/libwhb/src/gfx_shader.c
Normal file
265
src/libwhb/src/gfx_shader.c
Normal file
@ -0,0 +1,265 @@
|
|||||||
|
#include "gfx_heap.h"
|
||||||
|
#include <gfd.h>
|
||||||
|
#include <gx2r/buffer.h>
|
||||||
|
#include <gx2/shaders.h>
|
||||||
|
#include <latte/latte_enum_sq.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <whb/gfx.h>
|
||||||
|
|
||||||
|
GX2PixelShader *
|
||||||
|
WHBGfxLoadGFDPixelShader(uint32_t index,
|
||||||
|
const void *file)
|
||||||
|
{
|
||||||
|
uint32_t headerSize, programSize;
|
||||||
|
GX2PixelShader *shader = NULL;
|
||||||
|
void *program = NULL;
|
||||||
|
|
||||||
|
if (index >= GFDGetPixelShaderCount(file)) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
headerSize = GFDGetPixelShaderHeaderSize(index, file);
|
||||||
|
programSize = GFDGetPixelShaderProgramSize(index, file);
|
||||||
|
|
||||||
|
if (!headerSize || !programSize) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
shader = (GX2PixelShader *)GfxHeapAllocMEM2(headerSize, 64);
|
||||||
|
if (!shader) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
shader->gx2rBuffer.flags = GX2R_RESOURCE_BIND_SHADER_PROGRAM | GX2R_RESOURCE_USAGE_CPU_WRITE | GX2R_RESOURCE_USAGE_GPU_READ;
|
||||||
|
shader->gx2rBuffer.elemSize = programSize;
|
||||||
|
shader->gx2rBuffer.elemCount = 1;
|
||||||
|
shader->gx2rBuffer.buffer = NULL;
|
||||||
|
if (!GX2RCreateBuffer(&shader->gx2rBuffer)) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
program = GX2RLockBufferEx(&shader->gx2rBuffer, 0);
|
||||||
|
if (!GFDGetPixelShader(shader, program, index, file)) {
|
||||||
|
GX2RUnlockBufferEx(&shader->gx2rBuffer, GX2R_RESOURCE_DISABLE_CPU_INVALIDATE | GX2R_RESOURCE_DISABLE_GPU_INVALIDATE);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
GX2RUnlockBufferEx(&shader->gx2rBuffer, 0);
|
||||||
|
return shader;
|
||||||
|
|
||||||
|
error:
|
||||||
|
if (shader) {
|
||||||
|
if (shader->gx2rBuffer.buffer) {
|
||||||
|
GX2RDestroyBufferEx(&shader->gx2rBuffer, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
GfxHeapFreeMEM2(shader);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
WHBGfxFreePixelShader(GX2PixelShader *shader)
|
||||||
|
{
|
||||||
|
if (shader->gx2rBuffer.buffer) {
|
||||||
|
GX2RDestroyBufferEx(&shader->gx2rBuffer, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
GfxHeapFreeMEM2(shader);
|
||||||
|
}
|
||||||
|
|
||||||
|
GX2VertexShader *
|
||||||
|
WHBGfxLoadGFDVertexShader(uint32_t index,
|
||||||
|
const void *file)
|
||||||
|
{
|
||||||
|
uint32_t headerSize, programSize;
|
||||||
|
GX2VertexShader *shader = NULL;
|
||||||
|
void *program = NULL;
|
||||||
|
|
||||||
|
if (index >= GFDGetVertexShaderCount(file)) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
headerSize = GFDGetVertexShaderHeaderSize(index, file);
|
||||||
|
programSize = GFDGetVertexShaderProgramSize(index, file);
|
||||||
|
|
||||||
|
if (!headerSize || !programSize) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
shader = (GX2VertexShader *)GfxHeapAllocMEM2(headerSize, 64);
|
||||||
|
if (!shader) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
shader->gx2rBuffer.flags = GX2R_RESOURCE_BIND_SHADER_PROGRAM | GX2R_RESOURCE_USAGE_CPU_WRITE | GX2R_RESOURCE_USAGE_GPU_READ;
|
||||||
|
shader->gx2rBuffer.elemSize = programSize;
|
||||||
|
shader->gx2rBuffer.elemCount = 1;
|
||||||
|
shader->gx2rBuffer.buffer = NULL;
|
||||||
|
if (!GX2RCreateBuffer(&shader->gx2rBuffer)) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
program = GX2RLockBufferEx(&shader->gx2rBuffer, 0);
|
||||||
|
if (!GFDGetVertexShader(shader, program, index, file)) {
|
||||||
|
GX2RUnlockBufferEx(&shader->gx2rBuffer, GX2R_RESOURCE_DISABLE_CPU_INVALIDATE | GX2R_RESOURCE_DISABLE_GPU_INVALIDATE);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
GX2RUnlockBufferEx(&shader->gx2rBuffer, 0);
|
||||||
|
return shader;
|
||||||
|
|
||||||
|
error:
|
||||||
|
if (shader) {
|
||||||
|
if (shader->gx2rBuffer.buffer) {
|
||||||
|
GX2RDestroyBufferEx(&shader->gx2rBuffer, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
GfxHeapFreeMEM2(shader);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
WHBGfxFreeVertexShader(GX2VertexShader *shader)
|
||||||
|
{
|
||||||
|
if (shader->gx2rBuffer.buffer) {
|
||||||
|
GX2RDestroyBufferEx(&shader->gx2rBuffer, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
GfxHeapFreeMEM2(shader);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
WHBGfxLoadGFDShaderGroup(WHBGfxShaderGroup *group,
|
||||||
|
uint32_t index,
|
||||||
|
const void *file)
|
||||||
|
{
|
||||||
|
memset(group, 0, sizeof(WHBGfxShaderGroup));
|
||||||
|
group->vertexShader = WHBGfxLoadGFDVertexShader(index, file);
|
||||||
|
group->pixelShader = WHBGfxLoadGFDPixelShader(index, file);
|
||||||
|
|
||||||
|
if (!group->vertexShader || !group->pixelShader) {
|
||||||
|
// A shader group requires at least a vertex shader and a pixel shader.
|
||||||
|
WHBGfxFreeShaderGroup(group);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SQ_SEL_MASK(x, y, z, w) (((x) << 24) | ((y) << 16) | ((z) << 8) | (w))
|
||||||
|
|
||||||
|
static uint32_t
|
||||||
|
GfxGetAttribFormatSel(GX2AttribFormat format)
|
||||||
|
{
|
||||||
|
switch (format) {
|
||||||
|
case GX2_ATTRIB_FORMAT_UNORM_8:
|
||||||
|
case GX2_ATTRIB_FORMAT_UINT_8:
|
||||||
|
case GX2_ATTRIB_FORMAT_SNORM_8:
|
||||||
|
case GX2_ATTRIB_FORMAT_SINT_8:
|
||||||
|
case GX2_ATTRIB_FORMAT_FLOAT_32:
|
||||||
|
return SQ_SEL_MASK(LATTE_SQ_SEL_X, LATTE_SQ_SEL_0, LATTE_SQ_SEL_0, LATTE_SQ_SEL_1);
|
||||||
|
case GX2_ATTRIB_FORMAT_UNORM_8_8:
|
||||||
|
case GX2_ATTRIB_FORMAT_UINT_8_8:
|
||||||
|
case GX2_ATTRIB_FORMAT_SNORM_8_8:
|
||||||
|
case GX2_ATTRIB_FORMAT_SINT_8_8:
|
||||||
|
case GX2_ATTRIB_FORMAT_FLOAT_32_32:
|
||||||
|
return SQ_SEL_MASK(LATTE_SQ_SEL_X, LATTE_SQ_SEL_Y, LATTE_SQ_SEL_0, LATTE_SQ_SEL_1);
|
||||||
|
case GX2_ATTRIB_FORMAT_FLOAT_32_32_32:
|
||||||
|
return SQ_SEL_MASK(LATTE_SQ_SEL_X, LATTE_SQ_SEL_Y, LATTE_SQ_SEL_Z, LATTE_SQ_SEL_1);
|
||||||
|
case GX2_ATTRIB_FORMAT_UNORM_8_8_8_8:
|
||||||
|
case GX2_ATTRIB_FORMAT_UINT_8_8_8_8:
|
||||||
|
case GX2_ATTRIB_FORMAT_SNORM_8_8_8_8:
|
||||||
|
case GX2_ATTRIB_FORMAT_SINT_8_8_8_8:
|
||||||
|
case GX2_ATTRIB_FORMAT_FLOAT_32_32_32_32:
|
||||||
|
return SQ_SEL_MASK(LATTE_SQ_SEL_X, LATTE_SQ_SEL_Y, LATTE_SQ_SEL_Z, LATTE_SQ_SEL_W);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return SQ_SEL_MASK(LATTE_SQ_SEL_0, LATTE_SQ_SEL_0, LATTE_SQ_SEL_0, LATTE_SQ_SEL_1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t
|
||||||
|
GfxGetVertexAttribVarLocation(const GX2VertexShader* shader,
|
||||||
|
const char *name)
|
||||||
|
{
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < shader->attribVarCount; ++i) {
|
||||||
|
if (strcmp(shader->attribVars[i].name, name) == 0) {
|
||||||
|
return shader->attribVars[i].location;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
WHBGfxInitShaderAttribute(WHBGfxShaderGroup *group,
|
||||||
|
const char *name,
|
||||||
|
uint32_t buffer,
|
||||||
|
uint32_t offset,
|
||||||
|
GX2AttribFormat format)
|
||||||
|
{
|
||||||
|
GX2AttribStream *attrib;
|
||||||
|
int32_t location;
|
||||||
|
|
||||||
|
location = GfxGetVertexAttribVarLocation(group->vertexShader, name);
|
||||||
|
if (location == -1) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
attrib = &group->attributes[group->numAttributes++];
|
||||||
|
attrib->location = location;
|
||||||
|
attrib->buffer = buffer;
|
||||||
|
attrib->offset = offset;
|
||||||
|
attrib->format = format;
|
||||||
|
attrib->type = GX2_ATTRIB_INDEX_PER_VERTEX;
|
||||||
|
attrib->aluDivisor = 0;
|
||||||
|
attrib->mask = GfxGetAttribFormatSel(format);
|
||||||
|
attrib->endianSwap = GX2_ENDIAN_SWAP_DEFAULT;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
WHBGfxInitFetchShader(WHBGfxShaderGroup *group)
|
||||||
|
{
|
||||||
|
uint32_t size = GX2CalcFetchShaderSizeEx(group->numAttributes,
|
||||||
|
GX2_FETCH_SHADER_TESSELLATION_NONE,
|
||||||
|
GX2_TESSELLATION_MODE_DISCRETE);
|
||||||
|
group->fetchShaderProgram = GfxHeapAllocMEM2(size, GX2_SHADER_PROGRAM_ALIGNMENT);
|
||||||
|
|
||||||
|
GX2InitFetchShaderEx(&group->fetchShader,
|
||||||
|
group->fetchShaderProgram,
|
||||||
|
group->numAttributes,
|
||||||
|
group->attributes,
|
||||||
|
GX2_FETCH_SHADER_TESSELLATION_NONE,
|
||||||
|
GX2_TESSELLATION_MODE_DISCRETE);
|
||||||
|
|
||||||
|
GX2Invalidate(GX2_INVALIDATE_MODE_CPU_SHADER, group->fetchShaderProgram, size);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
WHBGfxFreeShaderGroup(WHBGfxShaderGroup *group)
|
||||||
|
{
|
||||||
|
if (group->fetchShaderProgram) {
|
||||||
|
GfxHeapFreeMEM2(group->fetchShaderProgram);
|
||||||
|
group->fetchShaderProgram = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (group->pixelShader) {
|
||||||
|
WHBGfxFreePixelShader(group->pixelShader);
|
||||||
|
group->pixelShader = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (group->vertexShader) {
|
||||||
|
WHBGfxFreeVertexShader(group->vertexShader);
|
||||||
|
group->vertexShader = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
66
src/libwhb/src/proc.c
Normal file
66
src/libwhb/src/proc.c
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
#include <whb/proc.h>
|
||||||
|
#include <coreinit/core.h>
|
||||||
|
#include <coreinit/foreground.h>
|
||||||
|
#include <gx2/event.h>
|
||||||
|
#include <proc_ui/procui.h>
|
||||||
|
|
||||||
|
static uint32_t
|
||||||
|
sMainCore;
|
||||||
|
|
||||||
|
static BOOL
|
||||||
|
sRunning = FALSE;
|
||||||
|
|
||||||
|
static ProcUICallback
|
||||||
|
sAcquireCallback = NULL;
|
||||||
|
|
||||||
|
static uint32_t
|
||||||
|
ProcSaveCallback(void *context)
|
||||||
|
{
|
||||||
|
OSSavesDone_ReadyToRelease();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
WHBProcInit()
|
||||||
|
{
|
||||||
|
sMainCore = OSGetCoreId();
|
||||||
|
sRunning = TRUE;
|
||||||
|
ProcUIInitEx(&ProcSaveCallback, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
WHBProcShutdown()
|
||||||
|
{
|
||||||
|
sRunning = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
WHBProcStopRunning()
|
||||||
|
{
|
||||||
|
sRunning = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
WHBProcIsRunning()
|
||||||
|
{
|
||||||
|
ProcUIStatus status;
|
||||||
|
|
||||||
|
if (sMainCore != OSGetCoreId()) {
|
||||||
|
ProcUISubProcessMessages(TRUE);
|
||||||
|
return sRunning;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = ProcUIProcessMessages(TRUE);
|
||||||
|
if (status == PROCUI_STATUS_EXITING) {
|
||||||
|
WHBProcStopRunning();
|
||||||
|
} else if (status == PROCUI_STATUS_RELEASE_FOREGROUND) {
|
||||||
|
ProcUIDrawDoneRelease();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sRunning) {
|
||||||
|
GX2DrawDone();
|
||||||
|
ProcUIShutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
return sRunning;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user