From 3d94c159391ae378e9ef1b865b87ab5807c91c77 Mon Sep 17 00:00:00 2001 From: Francisco Javier Trujillo Mata Date: Sat, 21 Dec 2024 19:24:14 +0100 Subject: [PATCH] Render to texture --- CMakeLists.txt | 3 + ee/gs/include/gsCore.h | 3 + ee/gs/include/gsTexture.h | 1 + ee/gs/src/gsCore.c | 21 ++++++ ee/gs/src/gsTexture.c | 21 ++++++ examples/rendertexture/rendertexture.c | 97 ++++++++++++++++++++++++++ 6 files changed, 146 insertions(+) create mode 100644 examples/rendertexture/rendertexture.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 3592c88..008d4cf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -111,6 +111,7 @@ add_object_library_macros(GS_CORE_OBJS ee/gs/src/gsCore.c gsKit_vram_clear gsKit_sync_flip gsKit_setactive + gsKit_renderToScreen gsKit_finish gsKit_lock_buffer gsKit_unlock_buffer @@ -216,6 +217,7 @@ add_object_library_macros(GS_TEXTURE_OBJS ee/gs/src/gsTexture.c gsKit_texture_send gsKit_texture_send_inline gsKit_texture_upload + gsKit_renderToTexture gsKit_prim_sprite_texture_3d gsKit_prim_sprite_striped_texture_3d gsKit_prim_triangle_texture_3d @@ -361,6 +363,7 @@ if(NOT SKIP_BUILD_EXAMPLES) modetest modetesthires pixelperfect + rendertexture texstream textures vsync diff --git a/ee/gs/include/gsCore.h b/ee/gs/include/gsCore.h index 972d600..eada6c4 100644 --- a/ee/gs/include/gsCore.h +++ b/ee/gs/include/gsCore.h @@ -128,6 +128,9 @@ void gsKit_switch_context(GSGLOBAL *gsGlobal); /// Sets Your Active Framebuffer void gsKit_setactive(GSGLOBAL *gsGlobal); +/// Set the render target to the current screen buffer +void gsKit_renderToScreen(GSGLOBAL *gsGlobal); + /// Blocks until FINISH is triggered void gsKit_finish(void); diff --git a/ee/gs/include/gsTexture.h b/ee/gs/include/gsTexture.h index b5f236a..762b858 100644 --- a/ee/gs/include/gsTexture.h +++ b/ee/gs/include/gsTexture.h @@ -117,6 +117,7 @@ void gsKit_texture_to_psm16(GSTEXTURE *Texture); void gsKit_texture_send(u32 *mem, int width, int height, u32 tbp, u32 psm, u32 tbw, u8 clut); void gsKit_texture_send_inline(GSGLOBAL *gsGlobal, u32 *mem, int width, int height, u32 tbp, u32 psm, u32 tbw, u8 clut); void gsKit_texture_upload(GSGLOBAL *gsGlobal, GSTEXTURE *Texture); +void gsKit_renderToTexture(GSGLOBAL *gsGlobal, GSTEXTURE *texture); void gsKit_prim_sprite_texture_3d(GSGLOBAL *gsGlobal, const GSTEXTURE *Texture, float x1, float y1, int iz1, float u1, float v1, float x2, float y2, int iz2, float u2, float v2, diff --git a/ee/gs/src/gsCore.c b/ee/gs/src/gsCore.c index 095eea4..13efbfd 100644 --- a/ee/gs/src/gsCore.c +++ b/ee/gs/src/gsCore.c @@ -120,6 +120,27 @@ void gsKit_setactive(GSGLOBAL *gsGlobal) } #endif +#if F_gsKit_renderToScreen +void gsKit_renderToScreen(GSGLOBAL *gsGlobal) +{ + u64 *p_data; + u64 *p_store; + int qsize = 1; + + p_store = p_data = gsKit_heap_alloc(gsGlobal, qsize, (qsize*16), GIF_AD); + + if(p_store == gsGlobal->CurQueue->last_tag) + { + *p_data++ = GIF_TAG_AD(qsize); + *p_data++ = GIF_AD; + } + + *p_data++ = GS_SETREG_FRAME_1( gsGlobal->ScreenBuffer[gsGlobal->ActiveBuffer & 1] / 8192, + gsGlobal->Width / 64, gsGlobal->PSM, 0 ); + *p_data++ = GS_FRAME_1; +} +#endif + #if F_gsKit_finish void gsKit_finish(void) { diff --git a/ee/gs/src/gsTexture.c b/ee/gs/src/gsTexture.c index 73ef218..e4ee73c 100644 --- a/ee/gs/src/gsTexture.c +++ b/ee/gs/src/gsTexture.c @@ -522,6 +522,27 @@ void gsKit_prim_sprite_texture_3d(GSGLOBAL *gsGlobal, const GSTEXTURE *Texture, } #endif +#if F_gsKit_renderToTexture +void gsKit_renderToTexture(GSGLOBAL *gsGlobal, GSTEXTURE *texture) +{ + u64 *p_data; + u64 *p_store; + int qsize = 1; + + p_store = p_data = gsKit_heap_alloc(gsGlobal, qsize, (qsize*16), GIF_AD); + + if(p_store == gsGlobal->CurQueue->last_tag) + { + *p_data++ = GIF_TAG_AD(qsize); + *p_data++ = GIF_AD; + } + + *p_data++ = GS_SETREG_FRAME_1(texture->Vram / 8192, + texture->Width / 64, texture->PSM, 0 ); + *p_data++ = GS_FRAME_1; +} +#endif + #if F_gsKit_prim_sprite_striped_texture_3d void gsKit_prim_sprite_striped_texture_3d(GSGLOBAL *gsGlobal, const GSTEXTURE *Texture, float x1, float y1, int iz1, float u1, float v1, diff --git a/examples/rendertexture/rendertexture.c b/examples/rendertexture/rendertexture.c new file mode 100644 index 0000000..8654d9d --- /dev/null +++ b/examples/rendertexture/rendertexture.c @@ -0,0 +1,97 @@ +// ____ ___ | / _____ _____ +// | __ | |___/ | | +// |___| ___| | \ __|__ | gsKit Open Source Project. +// ---------------------------------------------------------------------- +// Copyright 2004 - Chris "Neovanglist" Gilbert +// Licenced under Academic Free License version 2.0 +// Review gsKit README & LICENSE files for further details. +// +// renderTexture.c - Example demonstrating render to texture operation. +// First we are rendering a triangle to a texture, +// then we are rendering the texture to the screen. +// + +#include +#include + +#include +#include +#include +#include +#include + +#define TEXTURE_WIDTH 256 +#define TEXTURE_HEIGHT 256 + +int main(int argc, char *argv[]) +{ + GSGLOBAL *gsGlobal; + GSTEXTURE renderTexture; + uint32_t i, j, offset; + uint32_t totalVertices = 3; + uint32_t textureTotalVertices = 2; + uint64_t White = GS_SETREG_RGBAQ(0xFF, 0xFF, 0xFF, 0x00, 0x00); + gs_rgbaq color = color_to_RGBAQ(0x80, 0x80, 0x80, 0x80, 0); + u32 render_target_ptr; + + gsGlobal = gsKit_init_global(); + + gsGlobal->PSM = GS_PSM_CT24; + gsGlobal->PSMZ = GS_PSMZ_16S; + + dmaKit_init(D_CTRL_RELE_OFF, D_CTRL_MFD_OFF, D_CTRL_STS_UNSPEC, + D_CTRL_STD_OFF, D_CTRL_RCYC_8, 1 << DMA_CHANNEL_GIF); + + // Initialize the DMAC + dmaKit_chan_init(DMA_CHANNEL_GIF); + + gsKit_init_screen(gsGlobal); + gsKit_mode_switch(gsGlobal, GS_ONESHOT); + + renderTexture.Width = TEXTURE_WIDTH; + renderTexture.Height = TEXTURE_HEIGHT; + renderTexture.PSM = GS_PSM_CT16; + renderTexture.Mem = 0; // NOT NEEDED + renderTexture.Vram = gsKit_vram_alloc(gsGlobal, gsKit_texture_size(renderTexture.Width, renderTexture.Height, renderTexture.PSM), GSKIT_ALLOC_USERBUFFER); + + gsKit_set_clamp(gsGlobal, GS_CMODE_CLAMP); + + GSPRIMPOINT *verts = (GSPRIMPOINT *)malloc(sizeof(GSPRIMPOINT) * totalVertices); + verts[0].xyz2 = vertex_to_XYZ2(gsGlobal, 0, 0, 0); + verts[0].rgbaq = color_to_RGBAQ(0xFF, 0x00, 0x00, 0xFF, 0); + + verts[1].xyz2 = vertex_to_XYZ2(gsGlobal, renderTexture.Width, 0, 0); + verts[1].rgbaq = color_to_RGBAQ(0x00, 0xFF, 0x00, 0xFF, 0); + + verts[2].xyz2 = vertex_to_XYZ2(gsGlobal, renderTexture.Width / 2, renderTexture.Height, 0); + verts[2].rgbaq = color_to_RGBAQ(0x00, 0x00, 0xFF, 0xFF, 0); + + GSPRIMUVPOINTFLAT *textureVertex = (GSPRIMUVPOINTFLAT *)malloc(sizeof(GSPRIMUVPOINTFLAT) * textureTotalVertices); + textureVertex[0].xyz2 = vertex_to_XYZ2(gsGlobal, 0, 0, 0); + textureVertex[0].uv = vertex_to_UV(&renderTexture, 0, 0); + + textureVertex[1].xyz2 = vertex_to_XYZ2(gsGlobal, gsGlobal->Width, gsGlobal->Height, 0); + textureVertex[1].uv = vertex_to_UV(&renderTexture, renderTexture.Width, renderTexture.Height); + + while (1) + { + gsKit_clear(gsGlobal, White); + + // set render target to the texture + gsKit_renderToTexture(gsGlobal, &renderTexture); + + gsKit_prim_list_triangle_gouraud_3d(gsGlobal, totalVertices, verts); + + // set render target back to the screen + gsKit_renderToScreen(gsGlobal); + + gskit_prim_list_sprite_texture_uv_flat_color(gsGlobal, &renderTexture, color, textureTotalVertices, textureVertex); + + gsKit_queue_exec(gsGlobal); + gsKit_sync_flip(gsGlobal); + } + + free(verts); + + return 0; +}