diff --git a/src/render/wiiu/SDL_rdraw_wiiu.c b/src/render/wiiu/SDL_rdraw_wiiu.c index bab0e403c..310a0d6bc 100644 --- a/src/render/wiiu/SDL_rdraw_wiiu.c +++ b/src/render/wiiu/SDL_rdraw_wiiu.c @@ -62,6 +62,9 @@ int WIIU_SDL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, GX2RInvalidateSurface(&tdata->texture.surface, 0, 0); } + /* Update texture rendering state */ + WIIU_TextureStartRendering(data, tdata); + /* Allocate attribute buffers */ a_position = WIIU_AllocRenderData(data, (GX2RBuffer) { .flags = @@ -168,6 +171,9 @@ int WIIU_SDL_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture, GX2RInvalidateSurface(&tdata->texture.surface, 0, 0); } + /* Update texture rendering state */ + WIIU_TextureStartRendering(data, tdata); + /* Allocate attribute buffers */ a_position = WIIU_AllocRenderData(data, (GX2RBuffer) { .flags = diff --git a/src/render/wiiu/SDL_render_wiiu.c b/src/render/wiiu/SDL_render_wiiu.c index 139136c15..e83dcd362 100644 --- a/src/render/wiiu/SDL_render_wiiu.c +++ b/src/render/wiiu/SDL_render_wiiu.c @@ -139,6 +139,9 @@ int WIIU_SDL_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture) WIIU_TextureData *tdata = (WIIU_TextureData *)((texture) ? texture->driverdata : data->windowTex.driverdata); + /* Wait for the texture rendering to finish */ + WIIU_TextureCheckWaitRendering(data, tdata); + /* Update u_viewSize */ data->u_viewSize = (WIIUVec4) { .x = (float)tdata->cbuf.surface.width, diff --git a/src/render/wiiu/SDL_render_wiiu.h b/src/render/wiiu/SDL_render_wiiu.h index fcf5b3180..a3480bd36 100644 --- a/src/render/wiiu/SDL_render_wiiu.h +++ b/src/render/wiiu/SDL_render_wiiu.h @@ -26,62 +26,80 @@ #include "../SDL_sysrender.h" #include "SDL_pixels.h" +#include #include #include #include #include -#include +#include /* Driver internal data structures */ -typedef struct +typedef struct WIIUVec2 WIIUVec2; +typedef struct WIIUVec3 WIIUVec3; +typedef struct WIIUVec4 WIIUVec4; +typedef struct WIIUPixFmt WIIUPixFmt; +typedef struct WIIU_RenderAllocData WIIU_RenderAllocData; +typedef struct WIIU_TextureDrawData WIIU_TextureDrawData; +typedef struct WIIU_RenderData WIIU_RenderData; +typedef struct WIIU_TextureData WIIU_TextureData; + +struct WIIUVec2 { union { float x, r; }; union { float y, g; }; -} WIIUVec2; +}; -typedef struct +struct WIIUVec3 { union { float x, r; }; union { float y, g; }; union { float z, b; }; -} WIIUVec3; +}; -typedef struct +struct WIIUVec4 { union { float x, r; }; union { float y, g; }; union { float z, b; }; union { float w, a; }; -} WIIUVec4; +}; -typedef struct +struct WIIUPixFmt { GX2SurfaceFormat fmt; uint32_t compMap; -} WIIUPixFmt; +}; -typedef struct +struct WIIU_RenderAllocData { void *next; GX2RBuffer buffer; -} WIIU_RenderAllocData; +}; -typedef struct +struct WIIU_TextureDrawData +{ + void *next; + WIIU_TextureData *texdata; +}; + +struct WIIU_RenderData { GX2ContextState *ctx; WIIU_RenderAllocData *listfree; + WIIU_TextureDrawData *listdraw; WIIUVec4 u_viewSize; SDL_Texture windowTex; -} WIIU_RenderData; +}; -typedef struct +struct WIIU_TextureData { GX2Sampler sampler; GX2Texture texture; GX2ColorBuffer cbuf; WIIUVec4 u_texSize; WIIUVec4 u_mod; -} WIIU_TextureData; + int isRendering; +}; /* SDL_render API implementation */ SDL_Renderer *WIIU_SDL_CreateRenderer(SDL_Window * window, Uint32 flags); @@ -149,6 +167,38 @@ static inline void WIIU_FreeRenderData(WIIU_RenderData *r) } } +static inline void WIIU_TextureStartRendering(WIIU_RenderData *r, WIIU_TextureData *t) +{ + WIIU_TextureDrawData *d = SDL_malloc(sizeof(WIIU_TextureDrawData)); + t->isRendering = 1; + d->texdata = t; + d->next = r->listdraw; + r->listdraw = d; +} + +static inline void WIIU_TextureDoneRendering(WIIU_RenderData *r) +{ + while (r->listdraw) { + WIIU_TextureDrawData *d = r->listdraw; + r->listdraw = r->listdraw->next; + d->texdata->isRendering = 0; + SDL_free(d); + } +} + +/* If the texture is currently being rendered and we change the content + before the rendering is finished, the GPU will end up partially drawing + the new data, so we wait for the GPU to finish rendering before + updating the texture */ +static inline void WIIU_TextureCheckWaitRendering(WIIU_RenderData *r, WIIU_TextureData *t) +{ + if (t->isRendering) + { + GX2DrawDone(); + WIIU_TextureDoneRendering(r); + } +} + static inline SDL_Texture * WIIU_GetRenderTarget(SDL_Renderer* renderer) { WIIU_RenderData *data = (WIIU_RenderData *) renderer->driverdata; diff --git a/src/render/wiiu/SDL_rpresent_wiiu.c b/src/render/wiiu/SDL_rpresent_wiiu.c index 6b0274414..4e1649ea6 100644 --- a/src/render/wiiu/SDL_rpresent_wiiu.c +++ b/src/render/wiiu/SDL_rpresent_wiiu.c @@ -143,8 +143,9 @@ void WIIU_SDL_RenderPresent(SDL_Renderer * renderer) WHBGfxFinishRender(); - /* Free the list of render data */ + /* Free the list of render and draw data */ WIIU_FreeRenderData(data); + WIIU_TextureDoneRendering(data); /* Restore SDL context state */ GX2SetContextState(data->ctx); diff --git a/src/render/wiiu/SDL_rtexture_wiiu.c b/src/render/wiiu/SDL_rtexture_wiiu.c index 6e04e70cd..e57e5b10b 100644 --- a/src/render/wiiu/SDL_rtexture_wiiu.c +++ b/src/render/wiiu/SDL_rtexture_wiiu.c @@ -113,6 +113,7 @@ int WIIU_SDL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) .a = (float)texture->a / 255.0f, }; + /* Setup texture driver data */ texture->driverdata = tdata; return 0; @@ -124,9 +125,15 @@ int WIIU_SDL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) int WIIU_SDL_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture, const SDL_Rect * rect, void **pixels, int *pitch) { + WIIU_RenderData *data = (WIIU_RenderData *) renderer->driverdata; WIIU_TextureData *tdata = (WIIU_TextureData *) texture->driverdata; Uint32 BytesPerPixel = SDL_BYTESPERPIXEL(texture->format); - void* pixel_buffer = GX2RLockSurfaceEx(&tdata->texture.surface, 0, 0); + void* pixel_buffer; + + /* Wait for the texture rendering to finish */ + WIIU_TextureCheckWaitRendering(data, tdata); + + pixel_buffer = GX2RLockSurfaceEx(&tdata->texture.surface, 0, 0); /* Calculate pointer to first pixel in rect */ *pixels = (void *) ((Uint8 *) pixel_buffer + @@ -192,8 +199,12 @@ int WIIU_SDL_SetTextureAlphaMod(SDL_Renderer * renderer, SDL_Texture * texture) void WIIU_SDL_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture) { + WIIU_RenderData *data = (WIIU_RenderData *) renderer->driverdata; WIIU_TextureData *tdata = (WIIU_TextureData *) texture->driverdata; + /* Wait for the texture rendering to finish */ + WIIU_TextureCheckWaitRendering(data, tdata); + GX2RDestroySurfaceEx(&tdata->cbuf.surface, 0); GX2RDestroySurfaceEx(&tdata->texture.surface, 0);