diff --git a/Makefile.vita.vita2d.dolce b/Makefile.vita.vita2d.dolce deleted file mode 100644 index 4325b4aba..000000000 --- a/Makefile.vita.vita2d.dolce +++ /dev/null @@ -1,58 +0,0 @@ -# Based on port by xerpi -# Makefile to build the SDL library - -TARGET_LIB = libSDL2.a - -SOURCES = \ - src/*.c \ - src/atomic/*.c \ - src/audio/*.c \ - src/audio/vita/*.c \ - src/cpuinfo/*.c \ - src/events/*.c \ - src/file/*.c \ - src/haptic/*.c \ - src/haptic/dummy/*.c \ - src/joystick/*.c \ - src/joystick/vita/*.c \ - src/loadso/dummy/*.c \ - src/power/*.c \ - src/power/vita/*.c \ - src/filesystem/vita/*.c \ - src/render/*.c \ - src/render/software/*.c \ - src/render/vita2d/*.c \ - src/sensor/*.c \ - src/sensor/dummy/*.c \ - src/stdlib/*.c \ - src/thread/*.c \ - src/thread/generic/SDL_systls.c \ - src/thread/vita/*.c \ - src/timer/*.c \ - src/timer/vita/*.c \ - src/video/*.c \ - src/video/vita/*.c \ - src/video/yuv2rgb/*.c \ - -OBJS = $(shell echo $(SOURCES) | sed -e 's,\.c,\.o,g') - -PREFIX = arm-dolce-eabi -CC = $(PREFIX)-gcc -AR = $(PREFIX)-ar -CFLAGS = -g -Wl,-q -Wall -O3 -Iinclude \ - -D__VITA__ -D__ARM_ARCH=7 -D__ARM_ARCH_7A__ \ - -mfpu=neon -mcpu=cortex-a9 -mfloat-abi=hard -ASFLAGS = $(CFLAGS) - -$(TARGET_LIB): $(OBJS) - $(AR) rcs $@ $^ - -clean: - @rm -f $(TARGET_LIB) $(OBJS) - -install: $(TARGET_LIB) - @mkdir -p "$(DOLCESDK)/arm-dolce-eabi/lib" - @cp $(TARGET_LIB) $(DOLCESDK)/arm-dolce-eabi/lib - @mkdir -p "$(DOLCESDK)/arm-dolce-eabi/include/SDL2" - @cp include/*.h "$(DOLCESDK)/arm-dolce-eabi/include/SDL2" - @echo "Installed!" diff --git a/include/SDL_config_vita.h b/include/SDL_config_vita.h index 5c14b50fd..6b12108b1 100644 --- a/include/SDL_config_vita.h +++ b/include/SDL_config_vita.h @@ -140,8 +140,7 @@ //#define SDL_VIDEO_RENDER_VITA_GLES2 1 -//#define SDL_VIDEO_RENDER_VITA_GXM 1 -#define SDL_VIDEO_RENDER_VITA_VITA2D 1 +#define SDL_VIDEO_RENDER_VITA_GXM 1 #if defined(SDL_VIDEO_RENDER_VITA_GLES2) || defined(SDL_VIDEO_RENDER_VITA_GXM) #define SDL_VIDEO_OPENGL_ES2 1 diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c index 40f7f5a76..b5cf9c56e 100644 --- a/src/render/SDL_render.c +++ b/src/render/SDL_render.c @@ -110,9 +110,6 @@ static const SDL_RenderDriver *render_drivers[] = { #if SDL_VIDEO_RENDER_VITA_GXM &VITA_GXM_RenderDriver, #endif -#if SDL_VIDEO_RENDER_VITA_VITA2D - &VITA_VITA2D_RenderDriver, -#endif #if SDL_VIDEO_RENDER_SW &SW_RenderDriver #endif diff --git a/src/render/SDL_sysrender.h b/src/render/SDL_sysrender.h index 31bdb8eac..84411082b 100644 --- a/src/render/SDL_sysrender.h +++ b/src/render/SDL_sysrender.h @@ -252,7 +252,6 @@ extern SDL_RenderDriver PSP_RenderDriver; extern SDL_RenderDriver SW_RenderDriver; extern SDL_RenderDriver VITA_GLES2_RenderDriver; extern SDL_RenderDriver VITA_GXM_RenderDriver; -extern SDL_RenderDriver VITA_VITA2D_RenderDriver; /* Blend mode functions */ extern SDL_BlendFactor SDL_GetBlendModeSrcColorFactor(SDL_BlendMode blendMode); diff --git a/src/render/vita2d/SDL_render_vita_vita2d.c b/src/render/vita2d/SDL_render_vita_vita2d.c deleted file mode 100644 index 8e49f941a..000000000 --- a/src/render/vita2d/SDL_render_vita_vita2d.c +++ /dev/null @@ -1,713 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2015 Sam Lantinga - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. -*/ -#include "../../SDL_internal.h" - -#if SDL_VIDEO_RENDER_VITA_VITA2D - -#include "SDL_hints.h" -#include "../SDL_sysrender.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#define sceKernelDcacheWritebackAll() (void)0 - -/* VITA renderer implementation, based on the vita2d lib */ - -extern int SDL_RecreateWindow(SDL_Window *window, Uint32 flags); - -static SDL_Renderer *VITA_VITA2D_CreateRenderer(SDL_Window *window, Uint32 flags); -static void VITA_VITA2D_WindowEvent(SDL_Renderer *renderer, const SDL_WindowEvent *event); -static SDL_bool VITA_VITA2D_SupportsBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode); -static int VITA_VITA2D_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture); -static int VITA_VITA2D_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, - const SDL_Rect *rect, const void *pixels, int pitch); -static int VITA_VITA2D_UpdateTextureYUV(SDL_Renderer * renderer, SDL_Texture * texture, - const SDL_Rect * rect, - const Uint8 *Yplane, int Ypitch, - const Uint8 *Uplane, int Upitch, - const Uint8 *Vplane, int Vpitch); - -static int VITA_VITA2D_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture, - const SDL_Rect *rect, void **pixels, int *pitch); - -static void VITA_VITA2D_UnlockTexture(SDL_Renderer *renderer, - SDL_Texture *texture); - -static void VITA_VITA2D_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture, SDL_ScaleMode scaleMode); - -static int VITA_VITA2D_SetRenderTarget(SDL_Renderer *renderer, - SDL_Texture *texture); - -static int VITA_VITA2D_QueueSetViewport(SDL_Renderer * renderer, SDL_RenderCommand *cmd); - -static int VITA_VITA2D_QueueSetDrawColor(SDL_Renderer * renderer, SDL_RenderCommand *cmd); - -static int VITA_VITA2D_RenderClear(SDL_Renderer *renderer); - -static int VITA_VITA2D_QueueDrawPoints(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FPoint * points, int count); - -static int VITA_VITA2D_RenderDrawPoints(SDL_Renderer *renderer, - const SDL_FPoint *points, int count); - -static int VITA_VITA2D_RenderDrawLines(SDL_Renderer *renderer, - const SDL_FPoint *points, int count); - -static int VITA_VITA2D_QueueFillRects(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FRect * rects, int count); - -static int VITA_VITA2D_RenderFillRects(SDL_Renderer *renderer, - const SDL_FRect *rects, int count); - -static int VITA_VITA2D_QueueCopy(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture, - const SDL_Rect * srcrect, const SDL_FRect * dstrect); - -static int VITA_VITA2D_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize); - -static int VITA_VITA2D_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect, - Uint32 pixel_format, void *pixels, int pitch); - -static int VITA_VITA2D_QueueCopyEx(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture, - const SDL_Rect * srcquad, const SDL_FRect * dstrect, - const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip); - -static void VITA_VITA2D_RenderPresent(SDL_Renderer *renderer); -static void VITA_VITA2D_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture); -static void VITA_VITA2D_DestroyRenderer(SDL_Renderer *renderer); - - -SDL_RenderDriver VITA_VITA2D_RenderDriver = { - .CreateRenderer = VITA_VITA2D_CreateRenderer, - .info = { - .name = "VITA", - .flags = SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC, - .num_texture_formats = 1, - .texture_formats = { - [0] = SDL_PIXELFORMAT_ABGR8888, - }, - .max_texture_width = 1024, - .max_texture_height = 1024, - } -}; - -#define VITA_VITA2D_SCREEN_WIDTH 960 -#define VITA_VITA2D_SCREEN_HEIGHT 544 - -#define VITA_VITA2D_FRAME_BUFFER_WIDTH 1024 -#define VITA_VITA2D_FRAME_BUFFER_SIZE (VITA_VITA2D_FRAME_BUFFER_WIDTH*VITA_VITA2D_SCREEN_HEIGHT) - -#define COL5650(r,g,b,a) ((r>>3) | ((g>>2)<<5) | ((b>>3)<<11)) -#define COL5551(r,g,b,a) ((r>>3) | ((g>>3)<<5) | ((b>>3)<<10) | (a>0?0x7000:0)) -#define COL4444(r,g,b,a) ((r>>4) | ((g>>4)<<4) | ((b>>4)<<8) | ((a>>4)<<12)) -#define COL8888(r,g,b,a) ((r) | ((g)<<8) | ((b)<<16) | ((a)<<24)) - -typedef struct -{ - void *frontbuffer; - void *backbuffer; - SDL_bool initialized; - SDL_bool displayListAvail; - unsigned int psm; - unsigned int bpp; - SDL_bool vsync; - unsigned int currentColor; - int currentBlendMode; - -} VITA_VITA2D_RenderData; - - -typedef struct -{ - vita2d_texture *tex; - unsigned int pitch; - unsigned int w; - unsigned int h; -} VITA_VITA2D_TextureData; - -typedef struct -{ - SDL_Rect srcRect; - SDL_FRect dstRect; -} VITA_VITA2D_CopyData; - -void -StartDrawing(SDL_Renderer *renderer) -{ - VITA_VITA2D_RenderData *data = (VITA_VITA2D_RenderData *) renderer->driverdata; - if(data->displayListAvail) - return; - - vita2d_start_drawing(); - - data->displayListAvail = SDL_TRUE; -} - -SDL_Renderer * -VITA_VITA2D_CreateRenderer(SDL_Window *window, Uint32 flags) -{ - - SDL_Renderer *renderer; - VITA_VITA2D_RenderData *data; - - renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer)); - if (!renderer) { - SDL_OutOfMemory(); - return NULL; - } - - data = (VITA_VITA2D_RenderData *) SDL_calloc(1, sizeof(*data)); - if (!data) { - VITA_VITA2D_DestroyRenderer(renderer); - SDL_OutOfMemory(); - return NULL; - } - - renderer->WindowEvent = VITA_VITA2D_WindowEvent; - renderer->SupportsBlendMode = VITA_VITA2D_SupportsBlendMode; - renderer->CreateTexture = VITA_VITA2D_CreateTexture; - renderer->UpdateTexture = VITA_VITA2D_UpdateTexture; - renderer->UpdateTextureYUV = VITA_VITA2D_UpdateTextureYUV; - renderer->LockTexture = VITA_VITA2D_LockTexture; - renderer->UnlockTexture = VITA_VITA2D_UnlockTexture; - renderer->SetTextureScaleMode = VITA_VITA2D_SetTextureScaleMode; - renderer->SetRenderTarget = VITA_VITA2D_SetRenderTarget; - renderer->QueueSetViewport = VITA_VITA2D_QueueSetViewport; - renderer->QueueSetDrawColor = VITA_VITA2D_QueueSetDrawColor; - renderer->QueueDrawPoints = VITA_VITA2D_QueueDrawPoints; - renderer->QueueDrawLines = VITA_VITA2D_QueueDrawPoints; // lines and points queue the same way. - renderer->QueueFillRects = VITA_VITA2D_QueueFillRects; - renderer->QueueCopy = VITA_VITA2D_QueueCopy; - renderer->QueueCopyEx = VITA_VITA2D_QueueCopyEx; - renderer->RunCommandQueue = VITA_VITA2D_RunCommandQueue; - renderer->RenderReadPixels = VITA_VITA2D_RenderReadPixels; - renderer->RenderPresent = VITA_VITA2D_RenderPresent; - renderer->DestroyTexture = VITA_VITA2D_DestroyTexture; - renderer->DestroyRenderer = VITA_VITA2D_DestroyRenderer; - renderer->info = VITA_VITA2D_RenderDriver.info; - renderer->info.flags = (SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE); - renderer->driverdata = data; - renderer->window = window; - - if (data->initialized != SDL_FALSE) - return 0; - data->initialized = SDL_TRUE; - - if (flags & SDL_RENDERER_PRESENTVSYNC) { - data->vsync = SDL_TRUE; - } else { - data->vsync = SDL_FALSE; - } - - vita2d_init(); - vita2d_set_vblank_wait(data->vsync); - - return renderer; -} - -static void -VITA_VITA2D_WindowEvent(SDL_Renderer *renderer, const SDL_WindowEvent *event) -{ - -} - -static SDL_bool -VITA_VITA2D_SupportsBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode) -{ - return SDL_FALSE; -} - -static int -VITA_VITA2D_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) -{ - VITA_VITA2D_TextureData* vita_texture = (VITA_VITA2D_TextureData*) SDL_calloc(1, sizeof(*vita_texture)); - - if(!vita_texture) - return -1; - - vita_texture->tex = vita2d_create_empty_texture(texture->w, texture->h); - - if(!vita_texture->tex) - { - SDL_free(vita_texture); - return SDL_OutOfMemory(); - } - - texture->driverdata = vita_texture; - - VITA_VITA2D_SetTextureScaleMode(renderer, texture, texture->scaleMode); - - vita_texture->w = vita2d_texture_get_width(vita_texture->tex); - vita_texture->h = vita2d_texture_get_height(vita_texture->tex); - vita_texture->pitch = vita2d_texture_get_stride(vita_texture->tex); - - return 0; -} - - -static int -VITA_VITA2D_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, - const SDL_Rect *rect, const void *pixels, int pitch) -{ - const Uint8 *src; - Uint8 *dst; - int row, length,dpitch; - src = pixels; - - VITA_VITA2D_LockTexture(renderer, texture, rect, (void **)&dst, &dpitch); - length = rect->w * SDL_BYTESPERPIXEL(texture->format); - if (length == pitch && length == dpitch) { - SDL_memcpy(dst, src, length*rect->h); - } else { - for (row = 0; row < rect->h; ++row) { - SDL_memcpy(dst, src, length); - src += pitch; - dst += dpitch; - } - } - - sceKernelDcacheWritebackAll(); - return 0; -} - -static int -VITA_VITA2D_UpdateTextureYUV(SDL_Renderer * renderer, SDL_Texture * texture, - const SDL_Rect * rect, - const Uint8 *Yplane, int Ypitch, - const Uint8 *Uplane, int Upitch, - const Uint8 *Vplane, int Vpitch) -{ - return 0; -} - -static int -VITA_VITA2D_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture, - const SDL_Rect *rect, void **pixels, int *pitch) -{ - VITA_VITA2D_TextureData *vita_texture = (VITA_VITA2D_TextureData *) texture->driverdata; - - *pixels = - (void *) ((Uint8 *) vita2d_texture_get_datap(vita_texture->tex) - + (rect->y * vita_texture->pitch) + rect->x * SDL_BYTESPERPIXEL(texture->format)); - *pitch = vita_texture->pitch; - return 0; -} - -static void -VITA_VITA2D_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture) -{ - // no needs to update texture data on ps vita. VITA_VITA2D_LockTexture - // already return a pointer to the vita2d texture pixels buffer. - // This really improve framerate when using lock/unlock. - - /* - VITA_VITA2D_TextureData *vita_texture = (VITA_VITA2D_TextureData *) texture->driverdata; - SDL_Rect rect; - - // We do whole texture updates, at least for now - rect.x = 0; - rect.y = 0; - rect.w = texture->w; - rect.h = texture->h; - VITA_VITA2D_UpdateTexture(renderer, texture, &rect, vita_texture->data, vita_texture->pitch); - */ -} - -static void -VITA_VITA2D_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture, SDL_ScaleMode scaleMode) -{ - VITA_VITA2D_TextureData *vita_texture = (VITA_VITA2D_TextureData *) texture->driverdata; - - /* - set texture filtering according to scaleMode - suported hint values are nearest (0, default) or linear (1) - vitaScaleMode is either SCE_GXM_TEXTURE_FILTER_POINT (good for tile-map) - or SCE_GXM_TEXTURE_FILTER_LINEAR (good for scaling) - */ - - int vitaScaleMode = (scaleMode == SDL_ScaleModeNearest - ? SCE_GXM_TEXTURE_FILTER_POINT - : SCE_GXM_TEXTURE_FILTER_LINEAR); - vita2d_texture_set_filters(vita_texture->tex, vitaScaleMode, vitaScaleMode); - - return; -} - -static int -VITA_VITA2D_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture) -{ - return 0; -} - -static int -VITA_VITA2D_QueueSetViewport(SDL_Renderer * renderer, SDL_RenderCommand *cmd) -{ - return 0; -} - -static int -VITA_VITA2D_QueueSetDrawColor(SDL_Renderer * renderer, SDL_RenderCommand *cmd) -{ - return 0; -} - - -static void -VITA_VITA2D_SetBlendMode(SDL_Renderer *renderer, int blendMode) -{ - /*VITA_VITA2D_RenderData *data = (VITA_VITA2D_RenderData *) renderer->driverdata; - if (blendMode != data-> currentBlendMode) { - switch (blendMode) { - case SDL_BLENDMODE_NONE: - sceGuTexFunc(GU_TFX_REPLACE, GU_TCC_RGBA); - sceGuDisable(GU_BLEND); - break; - case SDL_BLENDMODE_BLEND: - sceGuTexFunc(GU_TFX_MODULATE , GU_TCC_RGBA); - sceGuEnable(GU_BLEND); - sceGuBlendFunc(GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0 ); - break; - case SDL_BLENDMODE_ADD: - sceGuTexFunc(GU_TFX_MODULATE , GU_TCC_RGBA); - sceGuEnable(GU_BLEND); - sceGuBlendFunc(GU_ADD, GU_SRC_ALPHA, GU_FIX, 0, 0x00FFFFFF ); - break; - case SDL_BLENDMODE_MOD: - sceGuTexFunc(GU_TFX_MODULATE , GU_TCC_RGBA); - sceGuEnable(GU_BLEND); - sceGuBlendFunc( GU_ADD, GU_FIX, GU_SRC_COLOR, 0, 0); - break; - } - data->currentBlendMode = blendMode; - }*/ -} - - - -static int -VITA_VITA2D_RenderClear(SDL_Renderer *renderer) -{ - int color = renderer->a << 24 | renderer->b << 16 | renderer->g << 8 | renderer->r; - vita2d_set_clear_color(color); - - vita2d_clear_screen(); - - return 0; -} - -static int -VITA_VITA2D_QueueDrawPoints(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FPoint * points, int count) -{ - const size_t vertlen = (sizeof (float) * 2) * count; - float *verts = (float *) SDL_AllocateRenderVertices(renderer, vertlen, 0, &cmd->data.draw.first); - if (!verts) { - return -1; - } - cmd->data.draw.count = count; - SDL_memcpy(verts, points, vertlen); - return 0; -} - -static int -VITA_VITA2D_RenderDrawPoints(SDL_Renderer *renderer, const SDL_FPoint *points, - int count) -{ - int color = renderer->a << 24 | renderer->b << 16 | renderer->g << 8 | renderer->r; - int i; - - for (i = 0; i < count; ++i) { - vita2d_draw_pixel(points[i].x, points[i].y, color); - } - - return 0; -} - -static int -VITA_VITA2D_RenderDrawLines(SDL_Renderer *renderer, const SDL_FPoint *points, - int count) -{ - int color = renderer->a << 24 | renderer->b << 16 | renderer->g << 8 | renderer->r; - int i; - - for (i = 0; i < count; ++i) { - if (i < count -1) { - vita2d_draw_line(points[i].x, points[i].y, points[i+1].x, points[i+1].y, color); - } - } - - return 0; -} - -static int -VITA_VITA2D_QueueFillRects(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FRect * rects, int count) -{ - const size_t outLen = count * sizeof (SDL_FRect); - SDL_FRect *outRects = (SDL_FRect *) SDL_AllocateRenderVertices(renderer, outLen, 0, &cmd->data.draw.first); - - if (!outRects) { - return -1; - } - cmd->data.draw.count = count; - SDL_memcpy(outRects, rects, outLen); - - return 0; -} - -static int -VITA_VITA2D_RenderFillRects(SDL_Renderer *renderer, const SDL_FRect *rects, - int count) -{ - int color = renderer->a << 24 | renderer->b << 16 | renderer->g << 8 | renderer->r; - int i; - - for (i = 0; i < count; ++i) { - const SDL_FRect *rect = &rects[i]; - - vita2d_draw_rectangle(rect->x, rect->y, rect->w, rect->h, color); - } - - return 0; -} - - -#define PI 3.14159265358979f - -#define radToDeg(x) ((x)*180.f/PI) -#define degToRad(x) ((x)*PI/180.f) - -float MathAbs(float x) -{ - return (x < 0) ? -x : x; -} - -void MathSincos(float r, float *s, float *c) -{ - *s = sinf(r); - *c = cosf(r); -} - -void Swap(float *a, float *b) -{ - float n=*a; - *a = *b; - *b = n; -} - -static int -VITA_VITA2D_QueueCopy(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture, - const SDL_Rect * srcrect, const SDL_FRect * dstrect) -{ - const size_t outLen = sizeof (VITA_VITA2D_CopyData); - VITA_VITA2D_CopyData *outData = (VITA_VITA2D_CopyData *) SDL_AllocateRenderVertices(renderer, outLen, 0, &cmd->data.draw.first); - - if (!outData) { - return -1; - } - cmd->data.draw.count = 1; - - SDL_memcpy(&outData->srcRect, srcrect, sizeof(SDL_Rect)); - SDL_memcpy(&outData->dstRect, dstrect, sizeof(SDL_FRect)); - - Uint8 r, g, b, a; - SDL_GetTextureColorMod(texture, &r, &g, &b); - SDL_GetTextureAlphaMod(texture, &a); - - cmd->data.draw.r = r; - cmd->data.draw.g = g; - cmd->data.draw.b = b; - cmd->data.draw.a = a; - cmd->data.draw.blend = renderer->blendMode; - - return 0; -} - - -static int -VITA_VITA2D_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize) -{ - StartDrawing(renderer); - - while (cmd) { - switch (cmd->command) { - case SDL_RENDERCMD_SETDRAWCOLOR: { - break; - } - - case SDL_RENDERCMD_SETVIEWPORT: { - break; - } - - case SDL_RENDERCMD_SETCLIPRECT: { - break; - } - - case SDL_RENDERCMD_CLEAR: { - VITA_VITA2D_RenderClear(renderer); - break; - } - - case SDL_RENDERCMD_DRAW_POINTS: { - const size_t count = cmd->data.draw.count; - const size_t first = cmd->data.draw.first; - const SDL_FPoint *points = (SDL_FPoint *) (((Uint8 *) vertices) + first); - VITA_VITA2D_RenderDrawPoints(renderer, points, count); - break; - } - - case SDL_RENDERCMD_DRAW_LINES: { - const size_t count = cmd->data.draw.count; - const size_t first = cmd->data.draw.first; - const SDL_FPoint *points = (SDL_FPoint *) (((Uint8 *) vertices) + first); - - VITA_VITA2D_RenderDrawLines(renderer, points, count); - break; - } - - case SDL_RENDERCMD_FILL_RECTS: { - const size_t count = cmd->data.draw.count; - const size_t first = cmd->data.draw.first; - const SDL_FRect *rects = (SDL_FRect *) (((Uint8 *) vertices) + first); - - VITA_VITA2D_RenderFillRects(renderer, rects, count); - break; - } - - case SDL_RENDERCMD_COPY: { - const size_t first = cmd->data.draw.first; - const VITA_VITA2D_CopyData *copyData = (VITA_VITA2D_CopyData *) (((Uint8 *) vertices) + first); - - VITA_VITA2D_TextureData *vita_texture = (VITA_VITA2D_TextureData *) cmd->data.draw.texture->driverdata; - - const SDL_Rect *srcrect = ©Data->srcRect; - const SDL_FRect *dstrect = ©Data->dstRect; - - float scaleX = dstrect->w == srcrect->w ? 1 : (float)(dstrect->w/srcrect->w); - float scaleY = dstrect->h == srcrect->h ? 1 : (float)(dstrect->h/srcrect->h); - - Uint8 r, g, b, a; - r = cmd->data.draw.r; - g = cmd->data.draw.g; - b = cmd->data.draw.b; - a = cmd->data.draw.a; - - VITA_VITA2D_SetBlendMode(renderer, cmd->data.draw.blend); - - if(r == 255 && g == 255 && b == 255 && a == 255) - { - vita2d_draw_texture_part_scale(vita_texture->tex, dstrect->x, dstrect->y, - srcrect->x, srcrect->y, srcrect->w, srcrect->h, scaleX, scaleY); - } else { - vita2d_draw_texture_tint_part_scale(vita_texture->tex, dstrect->x, dstrect->y, - srcrect->x, srcrect->y, srcrect->w, srcrect->h, scaleX, scaleY, (a << 24) + (b << 16) + (g << 8) + r); - } - - break; - } - - case SDL_RENDERCMD_COPY_EX: { - break; - } - - case SDL_RENDERCMD_NO_OP: - break; - } - - cmd = cmd->next; - } - - return 0; -} - -static int -VITA_VITA2D_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect, - Uint32 pixel_format, void *pixels, int pitch) -{ - return 0; -} - -static int -VITA_VITA2D_QueueCopyEx(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture, - const SDL_Rect * srcquad, const SDL_FRect * dstrect, - const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip) -{ - return 0; -} - -static void -VITA_VITA2D_RenderPresent(SDL_Renderer *renderer) -{ - VITA_VITA2D_RenderData *data = (VITA_VITA2D_RenderData *) renderer->driverdata; - if(!data->displayListAvail) - return; - - vita2d_end_drawing(); - vita2d_wait_rendering_done(); - vita2d_swap_buffers(); - - data->displayListAvail = SDL_FALSE; -} - -static void -VITA_VITA2D_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture) -{ - VITA_VITA2D_RenderData *renderdata = (VITA_VITA2D_RenderData *) renderer->driverdata; - VITA_VITA2D_TextureData *vita_texture = (VITA_VITA2D_TextureData *) texture->driverdata; - - if (renderdata == 0) - return; - - if(vita_texture == 0) - return; - - vita2d_wait_rendering_done(); - vita2d_free_texture(vita_texture->tex); - SDL_free(vita_texture); - texture->driverdata = NULL; -} - -static void -VITA_VITA2D_DestroyRenderer(SDL_Renderer *renderer) -{ - VITA_VITA2D_RenderData *data = (VITA_VITA2D_RenderData *) renderer->driverdata; - if (data) { - if (!data->initialized) - return; - - vita2d_fini(); - - data->initialized = SDL_FALSE; - data->displayListAvail = SDL_FALSE; - SDL_free(data); - } - SDL_free(renderer); -} - -#endif /* SDL_VIDEO_RENDER_VITA_VITA2D */ - -/* vi: set ts=4 sw=4 expandtab: */ - diff --git a/src/render/vitagxm/SDL_render_vita_gxm.c b/src/render/vitagxm/SDL_render_vita_gxm.c new file mode 100644 index 000000000..ae0f6ac9c --- /dev/null +++ b/src/render/vitagxm/SDL_render_vita_gxm.c @@ -0,0 +1,958 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2020 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#if SDL_VIDEO_RENDER_VITA_GXM + +#include "SDL_hints.h" +#include "../SDL_sysrender.h" +#include "SDL_log.h" + +#include +#include +#include +#include +#include + +#include "SDL_render_vita_gxm_types.h" +#include "SDL_render_vita_gxm_tools.h" +#include "SDL_render_vita_gxm_memory.h" + +static SDL_Renderer *VITA_GXM_CreateRenderer(SDL_Window *window, Uint32 flags); + +static void VITA_GXM_WindowEvent(SDL_Renderer *renderer, const SDL_WindowEvent *event); + +static SDL_bool VITA_GXM_SupportsBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode); + +static int VITA_GXM_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture); + +static int VITA_GXM_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, + const SDL_Rect *rect, const void *pixels, int pitch); + +static int VITA_GXM_UpdateTextureYUV(SDL_Renderer * renderer, SDL_Texture * texture, + const SDL_Rect * rect, + const Uint8 *Yplane, int Ypitch, + const Uint8 *Uplane, int Upitch, + const Uint8 *Vplane, int Vpitch); + +static int VITA_GXM_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture, + const SDL_Rect *rect, void **pixels, int *pitch); + +static void VITA_GXM_UnlockTexture(SDL_Renderer *renderer, + SDL_Texture *texture); + +static void VITA_GXM_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture, SDL_ScaleMode scaleMode); + +static int VITA_GXM_SetRenderTarget(SDL_Renderer *renderer, + SDL_Texture *texture); + + +static int VITA_GXM_QueueSetViewport(SDL_Renderer * renderer, SDL_RenderCommand *cmd); + +static int VITA_GXM_QueueSetDrawColor(SDL_Renderer * renderer, SDL_RenderCommand *cmd); + + +static int VITA_GXM_QueueDrawPoints(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FPoint * points, int count); +static int VITA_GXM_QueueDrawLines(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FPoint * points, int count); + +static int VITA_GXM_QueueCopy(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture, + const SDL_Rect * srcrect, const SDL_FRect * dstrect); + +static int VITA_GXM_QueueCopyEx(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture, + const SDL_Rect * srcrect, const SDL_FRect * dstrect, + const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip); + +static int VITA_GXM_RenderClear(SDL_Renderer *renderer, SDL_RenderCommand *cmd); + +static int VITA_GXM_RenderDrawPoints(SDL_Renderer *renderer, const SDL_RenderCommand *cmd); + +static int VITA_GXM_RenderDrawLines(SDL_Renderer *renderer, const SDL_RenderCommand *cmd); + +static int VITA_GXM_QueueFillRects(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FRect * rects, int count); + +static int VITA_GXM_RenderFillRects(SDL_Renderer *renderer, const SDL_RenderCommand *cmd); + + +static int VITA_GXM_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize); + +static int VITA_GXM_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect, + Uint32 pixel_format, void *pixels, int pitch); + + +static void VITA_GXM_RenderPresent(SDL_Renderer *renderer); +static void VITA_GXM_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture); +static void VITA_GXM_DestroyRenderer(SDL_Renderer *renderer); + + +SDL_RenderDriver VITA_GXM_RenderDriver = { + .CreateRenderer = VITA_GXM_CreateRenderer, + .info = { + .name = "VITA gxm", + .flags = SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC, + .num_texture_formats = 1, + .texture_formats = { + [0] = SDL_PIXELFORMAT_ABGR8888, // TODO: support more formats? ARGB8888 should be enough? + }, + .max_texture_width = 1024, + .max_texture_height = 1024, + } +}; + +void +StartDrawing(SDL_Renderer *renderer) +{ + VITA_GXM_RenderData *data = (VITA_GXM_RenderData *) renderer->driverdata; + if(data->drawing) + return; + + // reset blend mode + data->currentBlendMode = SDL_BLENDMODE_BLEND; + fragment_programs *in = &data->blendFragmentPrograms.blend_mode_blend; + data->colorFragmentProgram = in->color; + data->textureFragmentProgram = in->texture; + data->textureTintFragmentProgram = in->textureTint; + + sceGxmBeginScene( + data->gxm_context, + 0, + data->renderTarget, + NULL, + NULL, + data->displayBufferSync[data->backBufferIndex], + &data->displaySurface[data->backBufferIndex], + &data->depthSurface + ); + + unset_clip_rectangle(data); + + data->drawing = SDL_TRUE; +} + +SDL_Renderer * +VITA_GXM_CreateRenderer(SDL_Window *window, Uint32 flags) +{ + SDL_Renderer *renderer; + VITA_GXM_RenderData *data; + + renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer)); + if (!renderer) { + SDL_OutOfMemory(); + return NULL; + } + + data = (VITA_GXM_RenderData *) SDL_calloc(1, sizeof(VITA_GXM_RenderData)); + if (!data) { + VITA_GXM_DestroyRenderer(renderer); + SDL_OutOfMemory(); + return NULL; + } + + renderer->WindowEvent = VITA_GXM_WindowEvent; + renderer->SupportsBlendMode = VITA_GXM_SupportsBlendMode; + renderer->CreateTexture = VITA_GXM_CreateTexture; + renderer->UpdateTexture = VITA_GXM_UpdateTexture; + renderer->UpdateTextureYUV = VITA_GXM_UpdateTextureYUV; + renderer->LockTexture = VITA_GXM_LockTexture; + renderer->UnlockTexture = VITA_GXM_UnlockTexture; + renderer->SetTextureScaleMode = VITA_GXM_SetTextureScaleMode; + renderer->SetRenderTarget = VITA_GXM_SetRenderTarget; + renderer->QueueSetViewport = VITA_GXM_QueueSetViewport; + renderer->QueueSetDrawColor = VITA_GXM_QueueSetDrawColor; + renderer->QueueDrawPoints = VITA_GXM_QueueDrawPoints; + renderer->QueueDrawLines = VITA_GXM_QueueDrawLines; + renderer->QueueFillRects = VITA_GXM_QueueFillRects; + renderer->QueueCopy = VITA_GXM_QueueCopy; + renderer->QueueCopyEx = VITA_GXM_QueueCopyEx; + renderer->RunCommandQueue = VITA_GXM_RunCommandQueue; + renderer->RenderReadPixels = VITA_GXM_RenderReadPixels; + renderer->RenderPresent = VITA_GXM_RenderPresent; + renderer->DestroyTexture = VITA_GXM_DestroyTexture; + renderer->DestroyRenderer = VITA_GXM_DestroyRenderer; + + renderer->info = VITA_GXM_RenderDriver.info; + renderer->info.flags = (SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE); + renderer->driverdata = data; + renderer->window = window; + + if (data->initialized != SDL_FALSE) + return 0; + data->initialized = SDL_TRUE; + + if (flags & SDL_RENDERER_PRESENTVSYNC) { + data->displayData.wait_vblank = SDL_TRUE; + } else { + data->displayData.wait_vblank = SDL_FALSE; + } + + if (gxm_init(renderer) != 0) + { + return NULL; + } + + return renderer; +} + +static void +VITA_GXM_WindowEvent(SDL_Renderer *renderer, const SDL_WindowEvent *event) +{ +} + +static SDL_bool +VITA_GXM_SupportsBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode) +{ + // only for custom modes. we build all modes on init, so no custom modes, sorry + return SDL_FALSE; +} + +static int +VITA_GXM_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) +{ + VITA_GXM_RenderData *data = (VITA_GXM_RenderData *) renderer->driverdata; + VITA_GXM_TextureData* vita_texture = (VITA_GXM_TextureData*) SDL_calloc(1, sizeof(VITA_GXM_TextureData)); + + if (!vita_texture) { + return SDL_OutOfMemory(); + } + + vita_texture->tex = create_gxm_texture(data, texture->w, texture->h, SCE_GXM_TEXTURE_FORMAT_A8B8G8R8, 0); // TODO: rendertarget support, other formats + + if (!vita_texture->tex) { + SDL_free(vita_texture); + return SDL_OutOfMemory(); + } + + texture->driverdata = vita_texture; + + VITA_GXM_SetTextureScaleMode(renderer, texture, texture->scaleMode); + + vita_texture->w = gxm_texture_get_width(vita_texture->tex); + vita_texture->h = gxm_texture_get_height(vita_texture->tex); + vita_texture->pitch = gxm_texture_get_stride(vita_texture->tex); + + return 0; +} + + +static int +VITA_GXM_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, + const SDL_Rect *rect, const void *pixels, int pitch) +{ + const Uint8 *src; + Uint8 *dst; + int row, length,dpitch; + src = pixels; + + VITA_GXM_LockTexture(renderer, texture, rect, (void **)&dst, &dpitch); + length = rect->w * SDL_BYTESPERPIXEL(texture->format); + if (length == pitch && length == dpitch) { + SDL_memcpy(dst, src, length*rect->h); + } else { + for (row = 0; row < rect->h; ++row) { + SDL_memcpy(dst, src, length); + src += pitch; + dst += dpitch; + } + } + + return 0; +} + +static int +VITA_GXM_UpdateTextureYUV(SDL_Renderer * renderer, SDL_Texture * texture, + const SDL_Rect * rect, + const Uint8 *Yplane, int Ypitch, + const Uint8 *Uplane, int Upitch, + const Uint8 *Vplane, int Vpitch) +{ + return 0; +} + +static int +VITA_GXM_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture, + const SDL_Rect *rect, void **pixels, int *pitch) +{ + VITA_GXM_TextureData *vita_texture = (VITA_GXM_TextureData *) texture->driverdata; + + *pixels = + (void *) ((Uint8 *) gxm_texture_get_datap(vita_texture->tex) + + (rect->y * vita_texture->pitch) + rect->x * SDL_BYTESPERPIXEL(texture->format)); + *pitch = vita_texture->pitch; + return 0; +} + +static void +VITA_GXM_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture) +{ + // No need to update texture data on ps vita. + // VITA_GXM_LockTexture already returns a pointer to the texture pixels buffer. + // This really improves framerate when using lock/unlock. +} + +static void +VITA_GXM_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture, SDL_ScaleMode scaleMode) +{ + VITA_GXM_TextureData *vita_texture = (VITA_GXM_TextureData *) texture->driverdata; + + /* + set texture filtering according to scaleMode + suported hint values are nearest (0, default) or linear (1) + vitaScaleMode is either SCE_GXM_TEXTURE_FILTER_POINT (good for tile-map) + or SCE_GXM_TEXTURE_FILTER_LINEAR (good for scaling) + */ + + int vitaScaleMode = (scaleMode == SDL_ScaleModeNearest + ? SCE_GXM_TEXTURE_FILTER_POINT + : SCE_GXM_TEXTURE_FILTER_LINEAR); + gxm_texture_set_filters(vita_texture->tex, vitaScaleMode, vitaScaleMode); + + return; +} + +static int +VITA_GXM_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture) +{ + return 0; // TODO +} + +static void +VITA_GXM_SetBlendMode(SDL_Renderer *renderer, int blendMode) +{ + VITA_GXM_RenderData *data = (VITA_GXM_RenderData *) renderer->driverdata; + if (blendMode != data->currentBlendMode) + { + fragment_programs *in = &data->blendFragmentPrograms.blend_mode_blend; + + switch (blendMode) + { + case SDL_BLENDMODE_NONE: + in = &data->blendFragmentPrograms.blend_mode_none; + break; + case SDL_BLENDMODE_BLEND: + in = &data->blendFragmentPrograms.blend_mode_blend; + break; + case SDL_BLENDMODE_ADD: + in = &data->blendFragmentPrograms.blend_mode_add; + break; + case SDL_BLENDMODE_MOD: + in = &data->blendFragmentPrograms.blend_mode_mod; + break; + case SDL_BLENDMODE_MUL: + in = &data->blendFragmentPrograms.blend_mode_mul; + break; + } + data->colorFragmentProgram = in->color; + data->textureFragmentProgram = in->texture; + data->textureTintFragmentProgram = in->textureTint; + data->currentBlendMode = blendMode; + } +} + +static int +VITA_GXM_QueueSetViewport(SDL_Renderer * renderer, SDL_RenderCommand *cmd) +{ + return 0; // TODO +} + +static int +VITA_GXM_QueueSetDrawColor(SDL_Renderer * renderer, SDL_RenderCommand *cmd) +{ + VITA_GXM_RenderData *data = (VITA_GXM_RenderData *) renderer->driverdata; + + const Uint8 r = cmd->data.color.r; + const Uint8 g = cmd->data.color.g; + const Uint8 b = cmd->data.color.b; + const Uint8 a = cmd->data.color.a; + data->drawstate.color = ((a << 24) | (b << 16) | (g << 8) | r); + + return 0; +} + +static int +VITA_GXM_QueueDrawPoints(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FPoint * points, int count) +{ + VITA_GXM_RenderData *data = (VITA_GXM_RenderData *) renderer->driverdata; + + int color = data->drawstate.color; + + color_vertex *vertex = (color_vertex *)pool_memalign( + data, + count * sizeof(color_vertex), + sizeof(color_vertex) + ); + + cmd->data.draw.first = (size_t)vertex; + cmd->data.draw.count = count; + + for (int i = 0; i < count; i++) + { + vertex[i].x = points[i].x; + vertex[i].y = points[i].y; + vertex[i].z = +0.5f; + vertex[i].color = color; + } + return 0; +} + +static int +VITA_GXM_QueueDrawLines(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FPoint * points, int count) +{ + VITA_GXM_RenderData *data = (VITA_GXM_RenderData *) renderer->driverdata; + int color = data->drawstate.color; + + color_vertex *vertex = (color_vertex *)pool_memalign( + data, + (count-1) * 2 * sizeof(color_vertex), + sizeof(color_vertex) + ); + + cmd->data.draw.first = (size_t)vertex; + cmd->data.draw.count = (count-1) * 2; + + for (int i = 0; i < count - 1; i++) + { + vertex[i*2].x = points[i].x; + vertex[i*2].y = points[i].y; + vertex[i*2].z = +0.5f; + vertex[i*2].color = color; + + vertex[i*2+1].x = points[i+1].x; + vertex[i*2+1].y = points[i+1].y; + vertex[i*2+1].z = +0.5f; + vertex[i*2+1].color = color; + } + + return 0; +} + +static int +VITA_GXM_QueueFillRects(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FRect * rects, int count) +{ + VITA_GXM_RenderData *data = (VITA_GXM_RenderData *) renderer->driverdata; + + cmd->data.draw.count = count; + int color = data->drawstate.color; + + color_vertex *vertices = (color_vertex *)pool_memalign( + data, + 4 * count * sizeof(color_vertex), // 4 vertices * count + sizeof(color_vertex)); + + for (int i =0; i < count; i++) + { + const SDL_FRect *rect = &rects[i]; + + vertices[4*i+0].x = rect->x; + vertices[4*i+0].y = rect->y; + vertices[4*i+0].z = +0.5f; + vertices[4*i+0].color = color; + + vertices[4*i+1].x = rect->x + rect->w; + vertices[4*i+1].y = rect->y; + vertices[4*i+1].z = +0.5f; + vertices[4*i+1].color = color; + + vertices[4*i+2].x = rect->x; + vertices[4*i+2].y = rect->y + rect->h; + vertices[4*i+2].z = +0.5f; + vertices[4*i+2].color = color; + + vertices[4*i+3].x = rect->x + rect->w; + vertices[4*i+3].y = rect->y + rect->h; + vertices[4*i+3].z = +0.5f; + vertices[4*i+3].color = color; + } + + cmd->data.draw.first = (size_t)vertices; + + return 0; +} + + +#define PI 3.14159265358979f + +#define degToRad(x) ((x)*PI/180.f) + +void MathSincos(float r, float *s, float *c) +{ + *s = sinf(r); + *c = cosf(r); +} + +void Swap(float *a, float *b) +{ + float n=*a; + *a = *b; + *b = n; +} + +static int +VITA_GXM_QueueCopy(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture, + const SDL_Rect * srcrect, const SDL_FRect * dstrect) +{ + + VITA_GXM_RenderData *data = (VITA_GXM_RenderData *) renderer->driverdata; + + Uint8 r, g, b, a; + SDL_GetTextureColorMod(texture, &r, &g, &b); + SDL_GetTextureAlphaMod(texture, &a); + + cmd->data.draw.r = r; + cmd->data.draw.g = g; + cmd->data.draw.b = b; + cmd->data.draw.a = a; + cmd->data.draw.blend = renderer->blendMode; + + cmd->data.draw.count = 1; + + texture_vertex *vertices = (texture_vertex *)pool_memalign( + data, + 4 * sizeof(texture_vertex), // 4 vertices + sizeof(texture_vertex)); + + cmd->data.draw.first = (size_t)vertices; + cmd->data.draw.texture = texture; + + const float u0 = (float)srcrect->x / (float)texture->w; + const float v0 = (float)srcrect->y / (float)texture->h; + const float u1 = (float)(srcrect->x + srcrect->w) / (float)texture->w; + const float v1 = (float)(srcrect->y + srcrect->h) / (float)texture->h; + + vertices[0].x = dstrect->x; + vertices[0].y = dstrect->y; + vertices[0].z = +0.5f; + vertices[0].u = u0; + vertices[0].v = v0; + + vertices[1].x = dstrect->x + dstrect->w; + vertices[1].y = dstrect->y; + vertices[1].z = +0.5f; + vertices[1].u = u1; + vertices[1].v = v0; + + vertices[2].x = dstrect->x; + vertices[2].y = dstrect->y + dstrect->h; + vertices[2].z = +0.5f; + vertices[2].u = u0; + vertices[2].v = v1; + + vertices[3].x = dstrect->x + dstrect->w; + vertices[3].y = dstrect->y + dstrect->h; + vertices[3].z = +0.5f; + vertices[3].u = u1; + vertices[3].v = v1; + + return 0; +} + +static int +VITA_GXM_QueueCopyEx(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture, + const SDL_Rect * srcrect, const SDL_FRect * dstrect, + const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip) +{ + VITA_GXM_RenderData *data = (VITA_GXM_RenderData *) renderer->driverdata; + + Uint8 r, g, b, a; + SDL_GetTextureColorMod(texture, &r, &g, &b); + SDL_GetTextureAlphaMod(texture, &a); + + cmd->data.draw.r = r; + cmd->data.draw.g = g; + cmd->data.draw.b = b; + cmd->data.draw.a = a; + cmd->data.draw.blend = renderer->blendMode; + + cmd->data.draw.count = 1; + + texture_vertex *vertices = (texture_vertex *)pool_memalign( + data, + 4 * sizeof(texture_vertex), // 4 vertices + sizeof(texture_vertex)); + + cmd->data.draw.first = (size_t)vertices; + cmd->data.draw.texture = texture; + + float u0 = (float)srcrect->x / (float)texture->w; + float v0 = (float)srcrect->y / (float)texture->h; + float u1 = (float)(srcrect->x + srcrect->w) / (float)texture->w; + float v1 = (float)(srcrect->y + srcrect->h) / (float)texture->h; + + if (flip & SDL_FLIP_VERTICAL) { + Swap(&v0, &v1); + } + + if (flip & SDL_FLIP_HORIZONTAL) { + Swap(&u0, &u1); + } + + const float centerx = center->x; + const float centery = center->y; + const float x = dstrect->x + centerx; + const float y = dstrect->y + centery; + const float width = dstrect->w - centerx; + const float height = dstrect->h - centery; + float s, c; + + MathSincos(degToRad(angle), &s, &c); + + const float cw = c * width; + const float sw = s * width; + const float ch = c * height; + const float sh = s * height; + + vertices[0].x = x - cw + sh; + vertices[0].y = y - sw - ch; + vertices[0].z = +0.5f; + vertices[0].u = u0; + vertices[0].v = v0; + + vertices[1].x = x + cw + sh; + vertices[1].y = y + sw - ch; + vertices[1].z = +0.5f; + vertices[1].u = u1; + vertices[1].v = v0; + + + vertices[2].x = x - cw - sh; + vertices[2].y = y - sw + ch; + vertices[2].z = +0.5f; + vertices[2].u = u0; + vertices[2].v = v1; + + vertices[3].x = x + cw - sh; + vertices[3].y = y + sw + ch; + vertices[3].z = +0.5f; + vertices[3].u = u1; + vertices[3].v = v1; + + return 0; +} + + +static int +VITA_GXM_RenderClear(SDL_Renderer *renderer, SDL_RenderCommand *cmd) +{ + VITA_GXM_RenderData *data = (VITA_GXM_RenderData *) renderer->driverdata; + + float clear_color[4]; + clear_color[0] = (cmd->data.color.r)/255.0f; + clear_color[1] = (cmd->data.color.g)/255.0f; + clear_color[2] = (cmd->data.color.b)/255.0f; + clear_color[3] = (cmd->data.color.a)/255.0f; + + // set clear shaders + sceGxmSetVertexProgram(data->gxm_context, data->clearVertexProgram); + sceGxmSetFragmentProgram(data->gxm_context, data->clearFragmentProgram); + + // set the clear color + void *color_buffer; + sceGxmReserveFragmentDefaultUniformBuffer(data->gxm_context, &color_buffer); + sceGxmSetUniformDataF(color_buffer, data->clearClearColorParam, 0, 4, clear_color); + + // draw the clear triangle + sceGxmSetVertexStream(data->gxm_context, 0, data->clearVertices); + sceGxmDraw(data->gxm_context, SCE_GXM_PRIMITIVE_TRIANGLES, SCE_GXM_INDEX_FORMAT_U16, data->linearIndices, 3); + + return 0; +} + + +static int +VITA_GXM_RenderDrawPoints(SDL_Renderer *renderer, const SDL_RenderCommand *cmd) +{ + VITA_GXM_RenderData *data = (VITA_GXM_RenderData *) renderer->driverdata; + + sceGxmSetVertexProgram(data->gxm_context, data->colorVertexProgram); + sceGxmSetFragmentProgram(data->gxm_context, data->colorFragmentProgram); + + void *vertexDefaultBuffer; + sceGxmReserveVertexDefaultUniformBuffer(data->gxm_context, &vertexDefaultBuffer); + sceGxmSetUniformDataF(vertexDefaultBuffer, data->colorWvpParam, 0, 16, data->ortho_matrix); + + sceGxmSetVertexStream(data->gxm_context, 0, (const void*)cmd->data.draw.first); + + sceGxmSetFrontPolygonMode(data->gxm_context, SCE_GXM_POLYGON_MODE_POINT); + sceGxmDraw(data->gxm_context, SCE_GXM_PRIMITIVE_POINTS, SCE_GXM_INDEX_FORMAT_U16, data->linearIndices, cmd->data.draw.count); + sceGxmSetFrontPolygonMode(data->gxm_context, SCE_GXM_POLYGON_MODE_TRIANGLE_FILL); + + return 0; +} + +static int +VITA_GXM_RenderDrawLines(SDL_Renderer *renderer, const SDL_RenderCommand *cmd) +{ + VITA_GXM_RenderData *data = (VITA_GXM_RenderData *) renderer->driverdata; + + sceGxmSetVertexProgram(data->gxm_context, data->colorVertexProgram); + sceGxmSetFragmentProgram(data->gxm_context, data->colorFragmentProgram); + + void *vertexDefaultBuffer; + + sceGxmReserveVertexDefaultUniformBuffer(data->gxm_context, &vertexDefaultBuffer); + + sceGxmSetUniformDataF(vertexDefaultBuffer, data->colorWvpParam, 0, 16, data->ortho_matrix); + + sceGxmSetVertexStream(data->gxm_context, 0, (const void*)cmd->data.draw.first); + + sceGxmSetFrontPolygonMode(data->gxm_context, SCE_GXM_POLYGON_MODE_LINE); + sceGxmDraw(data->gxm_context, SCE_GXM_PRIMITIVE_LINES, SCE_GXM_INDEX_FORMAT_U16, data->linearIndices, cmd->data.draw.count); + sceGxmSetFrontPolygonMode(data->gxm_context, SCE_GXM_POLYGON_MODE_TRIANGLE_FILL); + return 0; +} + + +static int +VITA_GXM_RenderFillRects(SDL_Renderer *renderer, const SDL_RenderCommand *cmd) +{ + VITA_GXM_RenderData *data = (VITA_GXM_RenderData *) renderer->driverdata; + + sceGxmSetVertexProgram(data->gxm_context, data->colorVertexProgram); + sceGxmSetFragmentProgram(data->gxm_context, data->colorFragmentProgram); + + void *vertexDefaultBuffer; + sceGxmReserveVertexDefaultUniformBuffer(data->gxm_context, &vertexDefaultBuffer); + sceGxmSetUniformDataF(vertexDefaultBuffer, data->colorWvpParam, 0, 16, data->ortho_matrix); + + sceGxmSetVertexStream(data->gxm_context, 0, (const void*)cmd->data.draw.first); + sceGxmDraw(data->gxm_context, SCE_GXM_PRIMITIVE_TRIANGLE_STRIP, SCE_GXM_INDEX_FORMAT_U16, data->linearIndices, 4 * cmd->data.draw.count); + + return 0; +} + + + +static int +VITA_GXM_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize) +{ + StartDrawing(renderer); + VITA_GXM_RenderData *data = (VITA_GXM_RenderData *) renderer->driverdata; + + while (cmd) { + switch (cmd->command) { + case SDL_RENDERCMD_SETDRAWCOLOR: { + break; + } + + case SDL_RENDERCMD_SETVIEWPORT: { +/* SDL_Rect *viewport = &data->drawstate.viewport; + if (SDL_memcmp(viewport, &cmd->data.viewport.rect, sizeof (SDL_Rect)) != 0) { + SDL_memcpy(viewport, &cmd->data.viewport.rect, sizeof (SDL_Rect)); + data->drawstate.viewport_dirty = SDL_TRUE; + }*/ + break; + } + + case SDL_RENDERCMD_SETCLIPRECT: { + const SDL_Rect *rect = &cmd->data.cliprect.rect; + if (cmd->data.cliprect.enabled) + { + set_clip_rectangle(data, rect->x, rect->y, rect->w, rect->h); + } + else + { + unset_clip_rectangle(data); + } + break; + } + + case SDL_RENDERCMD_CLEAR: { + VITA_GXM_RenderClear(renderer, cmd); + break; + } + + case SDL_RENDERCMD_DRAW_POINTS: { + VITA_GXM_SetBlendMode(renderer, cmd->data.draw.blend); + VITA_GXM_RenderDrawPoints(renderer, cmd); + break; + } + + case SDL_RENDERCMD_DRAW_LINES: { + VITA_GXM_SetBlendMode(renderer, cmd->data.draw.blend); + VITA_GXM_RenderDrawLines(renderer, cmd); + break; + } + + case SDL_RENDERCMD_FILL_RECTS: { + VITA_GXM_SetBlendMode(renderer, cmd->data.draw.blend); + VITA_GXM_RenderFillRects(renderer, cmd); + break; + } + + case SDL_RENDERCMD_COPY: + case SDL_RENDERCMD_COPY_EX: { + SDL_BlendMode blend; + SDL_GetTextureBlendMode(cmd->data.draw.texture, &blend); + VITA_GXM_SetBlendMode(renderer, blend); + + Uint8 r, g, b, a; + r = cmd->data.draw.r; + g = cmd->data.draw.g; + b = cmd->data.draw.b; + a = cmd->data.draw.a; + + sceGxmSetVertexProgram(data->gxm_context, data->textureVertexProgram); + + if(r == 255 && g == 255 && b == 255 && a == 255) + { + sceGxmSetFragmentProgram(data->gxm_context, data->textureFragmentProgram); + } + else + { + sceGxmSetFragmentProgram(data->gxm_context, data->textureTintFragmentProgram); + void *texture_tint_color_buffer; + sceGxmReserveFragmentDefaultUniformBuffer(data->gxm_context, &texture_tint_color_buffer); + + float *tint_color = pool_memalign( + data, + 4 * sizeof(float), // RGBA + sizeof(float) + ); + + tint_color[0] = r / 255.0f; + tint_color[1] = g / 255.0f; + tint_color[2] = b / 255.0f; + tint_color[3] = a / 255.0f; + + sceGxmSetUniformDataF(texture_tint_color_buffer, data->textureTintColorParam, 0, 4, tint_color); + + } + + void *vertex_wvp_buffer; + sceGxmReserveVertexDefaultUniformBuffer(data->gxm_context, &vertex_wvp_buffer); + sceGxmSetUniformDataF(vertex_wvp_buffer, data->textureWvpParam, 0, 16, data->ortho_matrix); + + VITA_GXM_TextureData *vita_texture = (VITA_GXM_TextureData *) cmd->data.draw.texture->driverdata; + + sceGxmSetFragmentTexture(data->gxm_context, 0, &vita_texture->tex->gxm_tex); + + sceGxmSetVertexStream(data->gxm_context, 0, (const void*)cmd->data.draw.first); + sceGxmDraw(data->gxm_context, SCE_GXM_PRIMITIVE_TRIANGLE_STRIP, SCE_GXM_INDEX_FORMAT_U16, data->linearIndices, 4 * cmd->data.draw.count); + + break; + } + + case SDL_RENDERCMD_NO_OP: + break; + } + + cmd = cmd->next; + } + + return 0; +} + +static int +VITA_GXM_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect, + Uint32 pixel_format, void *pixels, int pitch) +{ + SceDisplayFrameBuf framebuf; + SDL_memset(&framebuf, 0x00, sizeof(SceDisplayFrameBuf)); + sceDisplayGetFrameBuf(&framebuf, SCE_DISPLAY_SETBUF_IMMEDIATE); + + // TODO + //pixels = framebuf.base; + + return 0; + +} + + +static void +VITA_GXM_RenderPresent(SDL_Renderer *renderer) +{ + VITA_GXM_RenderData *data = (VITA_GXM_RenderData *) renderer->driverdata; + + if(!data->drawing) + return; + + sceGxmEndScene(data->gxm_context, NULL, NULL); + sceGxmFinish(data->gxm_context); + + data->displayData.address = data->displayBufferData[data->backBufferIndex]; + + sceGxmDisplayQueueAddEntry( + data->displayBufferSync[data->frontBufferIndex], // OLD fb + data->displayBufferSync[data->backBufferIndex], // NEW fb + &data->displayData + ); + + // update buffer indices + data->frontBufferIndex = data->backBufferIndex; + data->backBufferIndex = (data->backBufferIndex + 1) % VITA_GXM_BUFFERS; + data->pool_index = 0; + data->drawing = SDL_FALSE; +} + +static void +VITA_GXM_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture) +{ + VITA_GXM_RenderData *data = (VITA_GXM_RenderData *) renderer->driverdata; + VITA_GXM_TextureData *vita_texture = (VITA_GXM_TextureData *) texture->driverdata; + + if (data == 0) + return; + + if(vita_texture == 0) + return; + + if(vita_texture->tex == 0) + return; + + sceGxmFinish(data->gxm_context); + + if (vita_texture->tex->gxm_rendertarget) { + sceGxmDestroyRenderTarget(vita_texture->tex->gxm_rendertarget); + } + + if (vita_texture->tex->depth_UID) { + gpu_free(vita_texture->tex->depth_UID); + } + + if (vita_texture->tex->palette_UID) { + gpu_free(vita_texture->tex->palette_UID); + } + + gpu_free(vita_texture->tex->data_UID); + SDL_free(vita_texture->tex); + SDL_free(vita_texture); + + texture->driverdata = NULL; +} + +static void +VITA_GXM_DestroyRenderer(SDL_Renderer *renderer) +{ + VITA_GXM_RenderData *data = (VITA_GXM_RenderData *) renderer->driverdata; + if (data) { + if (!data->initialized) + return; + + gxm_finish(renderer); + + data->initialized = SDL_FALSE; + data->drawing = SDL_FALSE; + SDL_free(data); + } + SDL_free(renderer); +} + +#endif /* SDL_VIDEO_RENDER_VITA_GXM */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/render/vitagxm/SDL_render_vita_gxm_memory.c b/src/render/vitagxm/SDL_render_vita_gxm_memory.c new file mode 100644 index 000000000..edb3e50c6 --- /dev/null +++ b/src/render/vitagxm/SDL_render_vita_gxm_memory.c @@ -0,0 +1,117 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2020 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#include "../../SDL_internal.h" + +#if SDL_VIDEO_RENDER_VITA_GXM + +#include "SDL_render_vita_gxm_memory.h" + +void * +gpu_alloc(SceKernelMemBlockType type, unsigned int size, unsigned int alignment, unsigned int attribs, SceUID *uid) +{ + void *mem; + + if (type == SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW) { + size = ALIGN(size, 256*1024); + } else { + size = ALIGN(size, 4*1024); + } + + *uid = sceKernelAllocMemBlock("gpu_mem", type, size, NULL); + + if (*uid < 0) + return NULL; + + if (sceKernelGetMemBlockBase(*uid, &mem) < 0) + return NULL; + + if (sceGxmMapMemory(mem, size, attribs) < 0) + return NULL; + + return mem; +} + +void +gpu_free(SceUID uid) +{ + void *mem = NULL; + if (sceKernelGetMemBlockBase(uid, &mem) < 0) + return; + sceGxmUnmapMemory(mem); + sceKernelFreeMemBlock(uid); +} + +void * +vertex_usse_alloc(unsigned int size, SceUID *uid, unsigned int *usse_offset) +{ + void *mem = NULL; + + size = ALIGN(size, 4096); + *uid = sceKernelAllocMemBlock("vertex_usse", SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE, size, NULL); + + if (sceKernelGetMemBlockBase(*uid, &mem) < 0) + return NULL; + if (sceGxmMapVertexUsseMemory(mem, size, usse_offset) < 0) + return NULL; + + return mem; +} + +void +vertex_usse_free(SceUID uid) +{ + void *mem = NULL; + if (sceKernelGetMemBlockBase(uid, &mem) < 0) + return; + sceGxmUnmapVertexUsseMemory(mem); + sceKernelFreeMemBlock(uid); +} + +void * +fragment_usse_alloc(unsigned int size, SceUID *uid, unsigned int *usse_offset) +{ + void *mem = NULL; + + size = ALIGN(size, 4096); + *uid = sceKernelAllocMemBlock("fragment_usse", SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE, size, NULL); + + if (sceKernelGetMemBlockBase(*uid, &mem) < 0) + return NULL; + if (sceGxmMapFragmentUsseMemory(mem, size, usse_offset) < 0) + return NULL; + + return mem; +} + +void +fragment_usse_free(SceUID uid) +{ + void *mem = NULL; + if (sceKernelGetMemBlockBase(uid, &mem) < 0) + return; + sceGxmUnmapFragmentUsseMemory(mem); + sceKernelFreeMemBlock(uid); +} + +#endif /* SDL_VIDEO_RENDER_VITA_GXM */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/render/vitagxm/SDL_render_vita_gxm_memory.h b/src/render/vitagxm/SDL_render_vita_gxm_memory.h new file mode 100644 index 000000000..d1989ff29 --- /dev/null +++ b/src/render/vitagxm/SDL_render_vita_gxm_memory.h @@ -0,0 +1,40 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2020 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef SDL_RENDER_VITA_GXM_MEMORY_H +#define SDL_RENDER_VITA_GXM_MEMORY_H + +#include +#include +#include + +#define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1)) + +void *gpu_alloc(SceKernelMemBlockType type, unsigned int size, unsigned int alignment, unsigned int attribs, SceUID *uid); +void gpu_free(SceUID uid); +void *vertex_usse_alloc(unsigned int size, SceUID *uid, unsigned int *usse_offset); +void vertex_usse_free(SceUID uid); +void *fragment_usse_alloc(unsigned int size, SceUID *uid, unsigned int *usse_offset); +void fragment_usse_free(SceUID uid); + +#endif /* SDL_RENDER_VITA_GXM_MEMORY_H */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/render/vitagxm/SDL_render_vita_gxm_shaders.h b/src/render/vitagxm/SDL_render_vita_gxm_shaders.h new file mode 100644 index 000000000..9d13e42cd --- /dev/null +++ b/src/render/vitagxm/SDL_render_vita_gxm_shaders.h @@ -0,0 +1,313 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2020 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef SDL_RENDER_VITA_GXM_SHADERS_H +#define SDL_RENDER_VITA_GXM_SHADERS_H + +#include + +#define gxm_shader_clear_f_size 232 +static const unsigned char gxm_shader_clear_f[gxm_shader_clear_f_size] = { + 0x47, 0x58, 0x50, 0x00, 0x01, 0x05, 0x50, 0x03, + 0xe8, 0x00, 0x00, 0x00, 0xa2, 0x55, 0x22, 0x3e, + 0xc6, 0x7e, 0x77, 0xf1, 0x01, 0x00, 0x18, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0xa4, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x68, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x5c, 0x00, 0x00, 0x00, 0xc0, 0x3d, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x07, 0x44, 0xfa, 0x02, 0x80, 0x19, 0xf0, + 0x7e, 0x0d, 0x80, 0x40, 0x0e, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x01, 0xe4, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x75, 0x43, 0x6c, 0x65, + 0x61, 0x72, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x00, +}; + +#define gxm_shader_clear_v_size 252 +static const unsigned char gxm_shader_clear_v[gxm_shader_clear_v_size] = { + 0x47, 0x58, 0x50, 0x00, 0x01, 0x05, 0x50, 0x03, + 0xfa, 0x00, 0x00, 0x00, 0xdc, 0x25, 0x34, 0x74, + 0x53, 0x4a, 0x7a, 0x5b, 0x04, 0x00, 0x19, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0xb8, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x74, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x78, 0x00, 0x00, 0x00, 0xc0, 0x3d, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x44, 0xfa, + 0x01, 0x00, 0x04, 0x90, 0x85, 0x11, 0xa5, 0x08, + 0x01, 0x80, 0x56, 0x90, 0x81, 0x11, 0x83, 0x08, + 0x00, 0x00, 0x20, 0xa0, 0x00, 0x50, 0x27, 0xfb, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x61, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, + 0x6e, 0x00, 0x00, 0x00, +}; + +#define gxm_shader_color_f_size 212 +static const unsigned char gxm_shader_color_f[gxm_shader_color_f_size] = { + 0x47, 0x58, 0x50, 0x00, 0x01, 0x05, 0x50, 0x03, + 0xd4, 0x00, 0x00, 0x00, 0x9c, 0xd6, 0x9b, 0xf7, + 0x78, 0x00, 0x5d, 0x31, 0x01, 0x10, 0x18, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xac, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x78, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x6c, 0x00, 0x00, 0x00, 0xc0, 0x3d, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x0f, 0xa0, 0xd0, 0x0e, 0x00, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x07, 0x44, 0xfa, 0x02, 0x80, 0x19, 0xa0, + 0x7e, 0x0d, 0x80, 0x40, +}; + +#define gxm_shader_color_v_size 344 +static const unsigned char gxm_shader_color_v[gxm_shader_color_v_size] = { + 0x47, 0x58, 0x50, 0x00, 0x01, 0x05, 0x50, 0x03, + 0x55, 0x01, 0x00, 0x00, 0x2e, 0x35, 0x0f, 0x26, + 0x23, 0x46, 0x37, 0xbb, 0x00, 0x00, 0x19, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0xe8, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x74, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0xa0, 0x00, 0x00, 0x00, 0xc0, 0x3d, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x44, 0xfa, + 0x80, 0x00, 0x08, 0x83, 0x21, 0x1d, 0x80, 0x38, + 0x02, 0x80, 0x81, 0xaf, 0x9c, 0x0d, 0xc0, 0x40, + 0x0e, 0x86, 0xb9, 0xff, 0xbc, 0x0d, 0xc0, 0x40, + 0x04, 0x11, 0x49, 0xcf, 0x80, 0x8f, 0xb1, 0x18, + 0x02, 0x11, 0x45, 0xcf, 0x80, 0x8f, 0xb1, 0x18, + 0x00, 0x11, 0x01, 0xc0, 0x81, 0x81, 0xb1, 0x18, + 0x01, 0xd1, 0x42, 0xc0, 0x81, 0x81, 0xb1, 0x18, + 0x00, 0x00, 0x20, 0xa0, 0x00, 0x50, 0x27, 0xfb, + 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2a, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x21, 0x00, 0x00, 0x00, 0x01, 0xe4, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x61, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, + 0x6e, 0x00, 0x61, 0x43, 0x6f, 0x6c, 0x6f, 0x72, + 0x00, 0x77, 0x76, 0x70, 0x00, 0x00, 0x00, 0x00, +}; + +#define gxm_shader_texture_f_size 256 +static const unsigned char gxm_shader_texture_f[gxm_shader_texture_f_size] = { + 0x47, 0x58, 0x50, 0x00, 0x01, 0x05, 0x50, 0x03, + 0x00, 0x01, 0x00, 0x00, 0x2f, 0x18, 0xe0, 0x2b, + 0x1f, 0x21, 0x47, 0x49, 0x01, 0x08, 0x18, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0xa4, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x78, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x64, 0x00, 0x00, 0x00, 0xc0, 0x3d, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, + 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, + 0x01, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x07, 0x44, 0xfa, 0x30, 0x00, 0x00, 0x00, + 0x02, 0x04, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x74, 0x65, 0x78, 0x00, +}; + +#define gxm_shader_texture_tint_f_size 324 +static const unsigned char gxm_shader_texture_tint_f[gxm_shader_texture_tint_f_size] = { + 0x47, 0x58, 0x50, 0x00, 0x01, 0x05, 0x50, 0x03, + 0x43, 0x01, 0x00, 0x00, 0x44, 0x2f, 0x5d, 0xfe, + 0x9e, 0xda, 0xf8, 0x6f, 0x05, 0x08, 0x18, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0xcc, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x78, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x84, 0x00, 0x00, 0x00, 0xc0, 0x3d, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, + 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, + 0x01, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x07, 0x44, 0xfa, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x09, 0x00, 0xf8, 0x02, 0x80, 0x99, 0xff, + 0xbc, 0x0d, 0xc0, 0x40, 0x02, 0x80, 0xb9, 0xaf, + 0xbc, 0x0d, 0x80, 0x40, 0x7c, 0x0f, 0x04, 0x00, + 0x86, 0x47, 0xa4, 0x10, 0x0e, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x04, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x01, 0xe4, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, + 0x02, 0x04, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x75, 0x54, 0x69, 0x6e, + 0x74, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x00, 0x74, + 0x65, 0x78, 0x00, 0x00, +}; + +#define gxm_shader_texture_v_size 344 +static const unsigned char gxm_shader_texture_v[gxm_shader_texture_v_size] = { + 0x47, 0x58, 0x50, 0x00, 0x01, 0x05, 0x50, 0x03, + 0x58, 0x01, 0x00, 0x00, 0xa3, 0x36, 0x7b, 0x62, + 0x1b, 0x80, 0x1c, 0xb0, 0x00, 0x00, 0x19, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0xe8, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x74, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0xa0, 0x00, 0x00, 0x00, 0xc0, 0x3d, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x06, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x44, 0xfa, + 0x80, 0x00, 0x08, 0x83, 0x21, 0x0d, 0x80, 0x38, + 0x02, 0x80, 0x81, 0xaf, 0x9c, 0x0d, 0xc0, 0x40, + 0x0e, 0x86, 0xb9, 0xff, 0xbc, 0x0d, 0xc0, 0x40, + 0x04, 0x11, 0x49, 0xcf, 0x80, 0x8f, 0xb1, 0x18, + 0x02, 0x11, 0x45, 0xcf, 0x80, 0x8f, 0xb1, 0x18, + 0x00, 0x11, 0x01, 0xc0, 0x81, 0x81, 0xb1, 0x18, + 0x01, 0xd1, 0x42, 0xc0, 0x81, 0x81, 0xb1, 0x18, + 0x00, 0x00, 0x20, 0xa0, 0x00, 0x50, 0x27, 0xfb, + 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2a, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x24, 0x00, 0x00, 0x00, 0x01, 0xe4, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x61, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, + 0x6e, 0x00, 0x61, 0x54, 0x65, 0x78, 0x63, 0x6f, + 0x6f, 0x72, 0x64, 0x00, 0x77, 0x76, 0x70, 0x00, +}; + + +static const SceGxmProgram *const clearVertexProgramGxp = (const SceGxmProgram*)gxm_shader_clear_v; +static const SceGxmProgram *const clearFragmentProgramGxp = (const SceGxmProgram *)gxm_shader_clear_f; +static const SceGxmProgram *const colorVertexProgramGxp = (const SceGxmProgram *)gxm_shader_color_v; +static const SceGxmProgram *const colorFragmentProgramGxp = (const SceGxmProgram *)gxm_shader_color_f; +static const SceGxmProgram *const textureVertexProgramGxp = (const SceGxmProgram *)gxm_shader_texture_v; +static const SceGxmProgram *const textureFragmentProgramGxp = (const SceGxmProgram *)gxm_shader_texture_f; +static const SceGxmProgram *const textureTintFragmentProgramGxp = (const SceGxmProgram *)gxm_shader_texture_tint_f; + +#endif // SDL_RENDER_VITA_GXM_SHADERS_H + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/render/vitagxm/SDL_render_vita_gxm_tools.c b/src/render/vitagxm/SDL_render_vita_gxm_tools.c new file mode 100644 index 000000000..7b0185af4 --- /dev/null +++ b/src/render/vitagxm/SDL_render_vita_gxm_tools.c @@ -0,0 +1,1147 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2020 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#if SDL_VIDEO_RENDER_VITA_GXM + +#include "SDL_hints.h" +#include "../SDL_sysrender.h" +#include "SDL_log.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "SDL_render_vita_gxm_tools.h" +#include "SDL_render_vita_gxm_types.h" +#include "SDL_render_vita_gxm_memory.h" +#include "SDL_render_vita_gxm_shaders.h" + +static void +init_orthographic_matrix(float *m, float left, float right, float bottom, float top, float near, float far) +{ + m[0x0] = 2.0f/(right-left); + m[0x4] = 0.0f; + m[0x8] = 0.0f; + m[0xC] = -(right+left)/(right-left); + + m[0x1] = 0.0f; + m[0x5] = 2.0f/(top-bottom); + m[0x9] = 0.0f; + m[0xD] = -(top+bottom)/(top-bottom); + + m[0x2] = 0.0f; + m[0x6] = 0.0f; + m[0xA] = -2.0f/(far-near); + m[0xE] = (far+near)/(far-near); + + m[0x3] = 0.0f; + m[0x7] = 0.0f; + m[0xB] = 0.0f; + m[0xF] = 1.0f; +} + + +static void * +patcher_host_alloc(void *user_data, unsigned int size) +{ + (void)user_data; + void *mem = SDL_malloc(size); + return mem; +} + +static void +patcher_host_free(void *user_data, void *mem) +{ + (void)user_data; + SDL_free(mem); +} + +void * +pool_malloc(VITA_GXM_RenderData *data, unsigned int size) +{ + + if ((data->pool_index + size) < VITA_GXM_POOL_SIZE) { + void *addr = (void *)((unsigned int)data->pool_addr + data->pool_index); + data->pool_index += size; + return addr; + } + SDL_LogError(SDL_LOG_CATEGORY_RENDER, "POOL OVERFLOW\n"); + return NULL; +} + +void * +pool_memalign(VITA_GXM_RenderData *data, unsigned int size, unsigned int alignment) +{ + unsigned int new_index = (data->pool_index + alignment - 1) & ~(alignment - 1); + if ((new_index + size) < VITA_GXM_POOL_SIZE) { + void *addr = (void *)((unsigned int)data->pool_addr + new_index); + data->pool_index = new_index + size; + return addr; + } + SDL_LogError(SDL_LOG_CATEGORY_RENDER, "POOL OVERFLOW\n"); + return NULL; +} + +static int +tex_format_to_bytespp(SceGxmTextureFormat format) +{ + switch (format & 0x9f000000U) { + case SCE_GXM_TEXTURE_BASE_FORMAT_U8: + case SCE_GXM_TEXTURE_BASE_FORMAT_S8: + case SCE_GXM_TEXTURE_BASE_FORMAT_P8: + return 1; + case SCE_GXM_TEXTURE_BASE_FORMAT_U4U4U4U4: + case SCE_GXM_TEXTURE_BASE_FORMAT_U8U3U3U2: + case SCE_GXM_TEXTURE_BASE_FORMAT_U1U5U5U5: + case SCE_GXM_TEXTURE_BASE_FORMAT_U5U6U5: + case SCE_GXM_TEXTURE_BASE_FORMAT_S5S5U6: + case SCE_GXM_TEXTURE_BASE_FORMAT_U8U8: + case SCE_GXM_TEXTURE_BASE_FORMAT_S8S8: + return 2; + case SCE_GXM_TEXTURE_BASE_FORMAT_U8U8U8: + case SCE_GXM_TEXTURE_BASE_FORMAT_S8S8S8: + return 3; + case SCE_GXM_TEXTURE_BASE_FORMAT_U8U8U8U8: + case SCE_GXM_TEXTURE_BASE_FORMAT_S8S8S8S8: + case SCE_GXM_TEXTURE_BASE_FORMAT_F32: + case SCE_GXM_TEXTURE_BASE_FORMAT_U32: + case SCE_GXM_TEXTURE_BASE_FORMAT_S32: + default: + return 4; + } +} + +static void +display_callback(const void *callback_data) +{ + SceDisplayFrameBuf framebuf; + const VITA_GXM_DisplayData *display_data = (const VITA_GXM_DisplayData *)callback_data; + + SDL_memset(&framebuf, 0x00, sizeof(SceDisplayFrameBuf)); + framebuf.size = sizeof(SceDisplayFrameBuf); + framebuf.base = display_data->address; + framebuf.pitch = VITA_GXM_SCREEN_STRIDE; + framebuf.pixelformat = VITA_GXM_PIXEL_FORMAT; + framebuf.width = VITA_GXM_SCREEN_WIDTH; + framebuf.height = VITA_GXM_SCREEN_HEIGHT; + sceDisplaySetFrameBuf(&framebuf, SCE_DISPLAY_SETBUF_NEXTFRAME); + + if (display_data->wait_vblank) { + sceDisplayWaitVblankStart(); + } +} + +static void +free_fragment_programs(VITA_GXM_RenderData *data, fragment_programs *out) +{ + sceGxmShaderPatcherReleaseFragmentProgram(data->shaderPatcher, out->color); + sceGxmShaderPatcherReleaseFragmentProgram(data->shaderPatcher, out->texture); + sceGxmShaderPatcherReleaseFragmentProgram(data->shaderPatcher, out->textureTint); +} + +static void +make_fragment_programs(VITA_GXM_RenderData *data, fragment_programs *out, + const SceGxmBlendInfo *blend_info) +{ + int err; + + err = sceGxmShaderPatcherCreateFragmentProgram( + data->shaderPatcher, + data->colorFragmentProgramId, + SCE_GXM_OUTPUT_REGISTER_FORMAT_UCHAR4, + 0, + blend_info, + colorVertexProgramGxp, + &out->color + ); + + if (err != SCE_OK) { + SDL_LogError(SDL_LOG_CATEGORY_RENDER, "Patcher create fragment failed: %d\n", err); + return; + } + + err = sceGxmShaderPatcherCreateFragmentProgram( + data->shaderPatcher, + data->textureFragmentProgramId, + SCE_GXM_OUTPUT_REGISTER_FORMAT_UCHAR4, + 0, + blend_info, + textureVertexProgramGxp, + &out->texture + ); + + if (err != SCE_OK) { + SDL_LogError(SDL_LOG_CATEGORY_RENDER, "Patcher create fragment failed: %d\n", err); + return; + } + + err = sceGxmShaderPatcherCreateFragmentProgram( + data->shaderPatcher, + data->textureTintFragmentProgramId, + SCE_GXM_OUTPUT_REGISTER_FORMAT_UCHAR4, + 0, + blend_info, + textureVertexProgramGxp, + &out->textureTint + ); + + if (err != SCE_OK) { + SDL_LogError(SDL_LOG_CATEGORY_RENDER, "Patcher create fragment failed: %d\n", err); + return; + } +} + + +static void +set_stencil_mask(VITA_GXM_RenderData *data, float x, float y, float w, float h) +{ + color_vertex *vertices = (color_vertex *)pool_memalign( + data, + 4 * sizeof(color_vertex), // 4 vertices + sizeof(color_vertex) + ); + + vertices[0].x = x; + vertices[0].y = y; + vertices[0].z = +0.5f; + vertices[0].color = 0; + + vertices[1].x = x + w; + vertices[1].y = y; + vertices[1].z = +0.5f; + vertices[1].color = 0; + + vertices[2].x = x; + vertices[2].y = y + h; + vertices[2].z = +0.5f; + vertices[2].color = 0; + + vertices[3].x = x + w; + vertices[3].y = y + h; + vertices[3].z = +0.5f; + vertices[3].color = 0; + + sceGxmSetVertexProgram(data->gxm_context, data->colorVertexProgram); + sceGxmSetFragmentProgram(data->gxm_context, data->colorFragmentProgram); + + void *vertexDefaultBuffer; + sceGxmReserveVertexDefaultUniformBuffer(data->gxm_context, &vertexDefaultBuffer); + sceGxmSetUniformDataF(vertexDefaultBuffer, data->colorWvpParam, 0, 16, data->ortho_matrix); + + sceGxmSetVertexStream(data->gxm_context, 0, vertices); + sceGxmDraw(data->gxm_context, SCE_GXM_PRIMITIVE_TRIANGLE_STRIP, SCE_GXM_INDEX_FORMAT_U16, data->linearIndices, 4); +} + + +void +set_clip_rectangle(VITA_GXM_RenderData *data, int x_min, int y_min, int x_max, int y_max) +{ + if(data->drawing) { + // clear the stencil buffer to 0 + sceGxmSetFrontStencilFunc( + data->gxm_context, + SCE_GXM_STENCIL_FUNC_NEVER, + SCE_GXM_STENCIL_OP_ZERO, + SCE_GXM_STENCIL_OP_ZERO, + SCE_GXM_STENCIL_OP_ZERO, + 0xFF, + 0xFF + ); + + set_stencil_mask(data, 0, 0, VITA_GXM_SCREEN_WIDTH, VITA_GXM_SCREEN_HEIGHT); + + // set the stencil to 1 in the desired region + sceGxmSetFrontStencilFunc( + data->gxm_context, + SCE_GXM_STENCIL_FUNC_NEVER, + SCE_GXM_STENCIL_OP_REPLACE, + SCE_GXM_STENCIL_OP_REPLACE, + SCE_GXM_STENCIL_OP_REPLACE, + 0xFF, + 0xFF + ); + + set_stencil_mask(data, x_min, y_min, x_max - x_min, y_max - y_min); + + // set the stencil function to only accept pixels where the stencil is 1 + sceGxmSetFrontStencilFunc( + data->gxm_context, + SCE_GXM_STENCIL_FUNC_EQUAL, + SCE_GXM_STENCIL_OP_KEEP, + SCE_GXM_STENCIL_OP_KEEP, + SCE_GXM_STENCIL_OP_KEEP, + 0xFF, + 0xFF + ); + } +} + +void +unset_clip_rectangle(VITA_GXM_RenderData *data) +{ + sceGxmSetFrontStencilFunc( + data->gxm_context, + SCE_GXM_STENCIL_FUNC_ALWAYS, + SCE_GXM_STENCIL_OP_KEEP, + SCE_GXM_STENCIL_OP_KEEP, + SCE_GXM_STENCIL_OP_KEEP, + 0xFF, + 0xFF + ); +} + +int +gxm_init(SDL_Renderer *renderer) +{ + unsigned int i, x, y; + int err; + + VITA_GXM_RenderData *data = (VITA_GXM_RenderData *) renderer->driverdata; + + SceGxmInitializeParams initializeParams; + SDL_memset(&initializeParams, 0, sizeof(SceGxmInitializeParams)); + initializeParams.flags = 0; + initializeParams.displayQueueMaxPendingCount = VITA_GXM_PENDING_SWAPS; + initializeParams.displayQueueCallback = display_callback; + initializeParams.displayQueueCallbackDataSize = sizeof(VITA_GXM_DisplayData); + initializeParams.parameterBufferSize = SCE_GXM_DEFAULT_PARAMETER_BUFFER_SIZE; + + err = sceGxmInitialize(&initializeParams); + + if (err != SCE_OK) { + SDL_LogError(SDL_LOG_CATEGORY_RENDER, "gxm init failed: %d\n", err); + return err; + } + + // allocate ring buffer memory using default sizes + void *vdmRingBuffer = gpu_alloc( + SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE, + SCE_GXM_DEFAULT_VDM_RING_BUFFER_SIZE, + 4, + SCE_GXM_MEMORY_ATTRIB_READ, + &data->vdmRingBufferUid); + + void *vertexRingBuffer = gpu_alloc( + SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE, + SCE_GXM_DEFAULT_VERTEX_RING_BUFFER_SIZE, + 4, + SCE_GXM_MEMORY_ATTRIB_READ, + &data->vertexRingBufferUid); + + void *fragmentRingBuffer = gpu_alloc( + SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE, + SCE_GXM_DEFAULT_FRAGMENT_RING_BUFFER_SIZE, + 4, + SCE_GXM_MEMORY_ATTRIB_READ, + &data->fragmentRingBufferUid); + + unsigned int fragmentUsseRingBufferOffset; + void *fragmentUsseRingBuffer = fragment_usse_alloc( + SCE_GXM_DEFAULT_FRAGMENT_USSE_RING_BUFFER_SIZE, + &data->fragmentUsseRingBufferUid, + &fragmentUsseRingBufferOffset); + + SDL_memset(&data->contextParams, 0, sizeof(SceGxmContextParams)); + data->contextParams.hostMem = SDL_malloc(SCE_GXM_MINIMUM_CONTEXT_HOST_MEM_SIZE); + data->contextParams.hostMemSize = SCE_GXM_MINIMUM_CONTEXT_HOST_MEM_SIZE; + data->contextParams.vdmRingBufferMem = vdmRingBuffer; + data->contextParams.vdmRingBufferMemSize = SCE_GXM_DEFAULT_VDM_RING_BUFFER_SIZE; + data->contextParams.vertexRingBufferMem = vertexRingBuffer; + data->contextParams.vertexRingBufferMemSize = SCE_GXM_DEFAULT_VERTEX_RING_BUFFER_SIZE; + data->contextParams.fragmentRingBufferMem = fragmentRingBuffer; + data->contextParams.fragmentRingBufferMemSize = SCE_GXM_DEFAULT_FRAGMENT_RING_BUFFER_SIZE; + data->contextParams.fragmentUsseRingBufferMem = fragmentUsseRingBuffer; + data->contextParams.fragmentUsseRingBufferMemSize = SCE_GXM_DEFAULT_FRAGMENT_USSE_RING_BUFFER_SIZE; + data->contextParams.fragmentUsseRingBufferOffset = fragmentUsseRingBufferOffset; + + err = sceGxmCreateContext(&data->contextParams, &data->gxm_context); + if (err != SCE_OK) { + SDL_LogError(SDL_LOG_CATEGORY_RENDER, "create context failed: %d\n", err); + return err; + } + + // set up parameters + SceGxmRenderTargetParams renderTargetParams; + SDL_memset(&renderTargetParams, 0, sizeof(SceGxmRenderTargetParams)); + renderTargetParams.flags = 0; + renderTargetParams.width = VITA_GXM_SCREEN_WIDTH; + renderTargetParams.height = VITA_GXM_SCREEN_HEIGHT; + renderTargetParams.scenesPerFrame = 1; + renderTargetParams.multisampleMode = 0; + renderTargetParams.multisampleLocations = 0; + renderTargetParams.driverMemBlock = -1; // Invalid UID + + // create the render target + err = sceGxmCreateRenderTarget(&renderTargetParams, &data->renderTarget); + if (err != SCE_OK) { + SDL_LogError(SDL_LOG_CATEGORY_RENDER, "render target creation failed: %d\n", err); + return err; + } + + // allocate memory and sync objects for display buffers + for (i = 0; i < VITA_GXM_BUFFERS; i++) { + + // allocate memory for display + data->displayBufferData[i] = gpu_alloc( + SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW, + 4 * VITA_GXM_SCREEN_STRIDE * VITA_GXM_SCREEN_HEIGHT, + SCE_GXM_COLOR_SURFACE_ALIGNMENT, + SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_WRITE, + &data->displayBufferUid[i]); + + // memset the buffer to black + for (y = 0; y < VITA_GXM_SCREEN_HEIGHT; y++) { + unsigned int *row = (unsigned int *)data->displayBufferData[i] + y * VITA_GXM_SCREEN_STRIDE; + for (x = 0; x < VITA_GXM_SCREEN_WIDTH; x++) { + row[x] = 0xff000000; + } + } + + // initialize a color surface for this display buffer + err = sceGxmColorSurfaceInit( + &data->displaySurface[i], + VITA_GXM_COLOR_FORMAT, + SCE_GXM_COLOR_SURFACE_LINEAR, + SCE_GXM_COLOR_SURFACE_SCALE_NONE, + SCE_GXM_OUTPUT_REGISTER_SIZE_32BIT, + VITA_GXM_SCREEN_WIDTH, + VITA_GXM_SCREEN_HEIGHT, + VITA_GXM_SCREEN_STRIDE, + data->displayBufferData[i] + ); + + if (err != SCE_OK) { + SDL_LogError(SDL_LOG_CATEGORY_RENDER, "color surface init failed: %d\n", err); + return err; + } + + + // create a sync object that we will associate with this buffer + err = sceGxmSyncObjectCreate(&data->displayBufferSync[i]); + if (err != SCE_OK) { + SDL_LogError(SDL_LOG_CATEGORY_RENDER, "sync object creation failed: %d\n", err); + return err; + } + + } + + // compute the memory footprint of the depth buffer + const unsigned int alignedWidth = ALIGN(VITA_GXM_SCREEN_WIDTH, SCE_GXM_TILE_SIZEX); + const unsigned int alignedHeight = ALIGN(VITA_GXM_SCREEN_HEIGHT, SCE_GXM_TILE_SIZEY); + + unsigned int sampleCount = alignedWidth * alignedHeight; + unsigned int depthStrideInSamples = alignedWidth; + + // allocate the depth buffer + data->depthBufferData = gpu_alloc( + SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE, + 4 * sampleCount, + SCE_GXM_DEPTHSTENCIL_SURFACE_ALIGNMENT, + SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_WRITE, + &data->depthBufferUid); + + // allocate the stencil buffer + data->stencilBufferData = gpu_alloc( + SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE, + 4 * sampleCount, + SCE_GXM_DEPTHSTENCIL_SURFACE_ALIGNMENT, + SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_WRITE, + &data->stencilBufferUid); + + // create the SceGxmDepthStencilSurface structure + err = sceGxmDepthStencilSurfaceInit( + &data->depthSurface, + SCE_GXM_DEPTH_STENCIL_FORMAT_S8D24, + SCE_GXM_DEPTH_STENCIL_SURFACE_TILED, + depthStrideInSamples, + data->depthBufferData, + data->stencilBufferData); + + // set the stencil test reference (this is currently assumed to always remain 1 after here for region clipping) + sceGxmSetFrontStencilRef(data->gxm_context, 1); + + + // set the stencil function (this wouldn't actually be needed, as the set clip rectangle function has to call this at the begginning of every scene) + sceGxmSetFrontStencilFunc( + data->gxm_context, + SCE_GXM_STENCIL_FUNC_ALWAYS, + SCE_GXM_STENCIL_OP_KEEP, + SCE_GXM_STENCIL_OP_KEEP, + SCE_GXM_STENCIL_OP_KEEP, + 0xFF, + 0xFF); + + // set buffer sizes for this sample + const unsigned int patcherBufferSize = 64*1024; + const unsigned int patcherVertexUsseSize = 64*1024; + const unsigned int patcherFragmentUsseSize = 64*1024; + + // allocate memory for buffers and USSE code + void *patcherBuffer = gpu_alloc( + SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE, + patcherBufferSize, + 4, + SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_WRITE, + &data->patcherBufferUid); + + unsigned int patcherVertexUsseOffset; + void *patcherVertexUsse = vertex_usse_alloc( + patcherVertexUsseSize, + &data->patcherVertexUsseUid, + &patcherVertexUsseOffset); + + unsigned int patcherFragmentUsseOffset; + void *patcherFragmentUsse = fragment_usse_alloc( + patcherFragmentUsseSize, + &data->patcherFragmentUsseUid, + &patcherFragmentUsseOffset); + + // create a shader patcher + SceGxmShaderPatcherParams patcherParams; + SDL_memset(&patcherParams, 0, sizeof(SceGxmShaderPatcherParams)); + patcherParams.userData = NULL; + patcherParams.hostAllocCallback = &patcher_host_alloc; + patcherParams.hostFreeCallback = &patcher_host_free; + patcherParams.bufferAllocCallback = NULL; + patcherParams.bufferFreeCallback = NULL; + patcherParams.bufferMem = patcherBuffer; + patcherParams.bufferMemSize = patcherBufferSize; + patcherParams.vertexUsseAllocCallback = NULL; + patcherParams.vertexUsseFreeCallback = NULL; + patcherParams.vertexUsseMem = patcherVertexUsse; + patcherParams.vertexUsseMemSize = patcherVertexUsseSize; + patcherParams.vertexUsseOffset = patcherVertexUsseOffset; + patcherParams.fragmentUsseAllocCallback = NULL; + patcherParams.fragmentUsseFreeCallback = NULL; + patcherParams.fragmentUsseMem = patcherFragmentUsse; + patcherParams.fragmentUsseMemSize = patcherFragmentUsseSize; + patcherParams.fragmentUsseOffset = patcherFragmentUsseOffset; + + err = sceGxmShaderPatcherCreate(&patcherParams, &data->shaderPatcher); + if (err != SCE_OK) { + SDL_LogError(SDL_LOG_CATEGORY_RENDER, "shader patcher creation failed: %d\n", err); + return err; + } + + + // check the shaders + err = sceGxmProgramCheck(clearVertexProgramGxp); + if (err != SCE_OK) { + SDL_LogError(SDL_LOG_CATEGORY_RENDER, "check program (clear vertex) failed: %d\n", err); + return err; + } + + err = sceGxmProgramCheck(clearFragmentProgramGxp); + if (err != SCE_OK) { + SDL_LogError(SDL_LOG_CATEGORY_RENDER, "check program (clear fragment) failed: %d\n", err); + return err; + } + + err = sceGxmProgramCheck(colorVertexProgramGxp); + if (err != SCE_OK) { + SDL_LogError(SDL_LOG_CATEGORY_RENDER, "check program (color vertex) failed: %d\n", err); + return err; + } + + err = sceGxmProgramCheck(colorFragmentProgramGxp); + if (err != SCE_OK) { + SDL_LogError(SDL_LOG_CATEGORY_RENDER, "check program (color fragment) failed: %d\n", err); + return err; + } + + err = sceGxmProgramCheck(textureVertexProgramGxp); + if (err != SCE_OK) { + SDL_LogError(SDL_LOG_CATEGORY_RENDER, "check program (texture vertex) failed: %d\n", err); + return err; + } + + err = sceGxmProgramCheck(textureFragmentProgramGxp); + if (err != SCE_OK) { + SDL_LogError(SDL_LOG_CATEGORY_RENDER, "check program (texture fragment) failed: %d\n", err); + return err; + } + + err = sceGxmProgramCheck(textureTintFragmentProgramGxp); + if (err != SCE_OK) { + SDL_LogError(SDL_LOG_CATEGORY_RENDER, "check program (texture tint fragment) failed: %d\n", err); + return err; + } + + // register programs with the patcher + err = sceGxmShaderPatcherRegisterProgram(data->shaderPatcher, clearVertexProgramGxp, &data->clearVertexProgramId); + if (err != SCE_OK) { + SDL_LogError(SDL_LOG_CATEGORY_RENDER, "register program (clear vertex) failed: %d\n", err); + return err; + } + + err = sceGxmShaderPatcherRegisterProgram(data->shaderPatcher, clearFragmentProgramGxp, &data->clearFragmentProgramId); + if (err != SCE_OK) { + SDL_LogError(SDL_LOG_CATEGORY_RENDER, "register program (clear fragment) failed: %d\n", err); + return err; + } + + err = sceGxmShaderPatcherRegisterProgram(data->shaderPatcher, colorVertexProgramGxp, &data->colorVertexProgramId); + if (err != SCE_OK) { + SDL_LogError(SDL_LOG_CATEGORY_RENDER, "register program (color vertex) failed: %d\n", err); + return err; + } + + err = sceGxmShaderPatcherRegisterProgram(data->shaderPatcher, colorFragmentProgramGxp, &data->colorFragmentProgramId); + if (err != SCE_OK) { + SDL_LogError(SDL_LOG_CATEGORY_RENDER, "register program (color fragment) failed: %d\n", err); + return err; + } + + err = sceGxmShaderPatcherRegisterProgram(data->shaderPatcher, textureVertexProgramGxp, &data->textureVertexProgramId); + if (err != SCE_OK) { + SDL_LogError(SDL_LOG_CATEGORY_RENDER, "register program (texture vertex) failed: %d\n", err); + return err; + } + + err = sceGxmShaderPatcherRegisterProgram(data->shaderPatcher, textureFragmentProgramGxp, &data->textureFragmentProgramId); + if (err != SCE_OK) { + SDL_LogError(SDL_LOG_CATEGORY_RENDER, "register program (texture fragment) failed: %d\n", err); + return err; + } + + err = sceGxmShaderPatcherRegisterProgram(data->shaderPatcher, textureTintFragmentProgramGxp, &data->textureTintFragmentProgramId); + if (err != SCE_OK) { + SDL_LogError(SDL_LOG_CATEGORY_RENDER, "register program (texture tint fragment) failed: %d\n", err); + return err; + } + + // Fill SceGxmBlendInfo + static const SceGxmBlendInfo blend_info_none = { + .colorFunc = SCE_GXM_BLEND_FUNC_NONE, + .alphaFunc = SCE_GXM_BLEND_FUNC_NONE, + .colorSrc = SCE_GXM_BLEND_FACTOR_ZERO, + .colorDst = SCE_GXM_BLEND_FACTOR_ZERO, + .alphaSrc = SCE_GXM_BLEND_FACTOR_ZERO, + .alphaDst = SCE_GXM_BLEND_FACTOR_ZERO, + .colorMask = SCE_GXM_COLOR_MASK_ALL + }; + + static const SceGxmBlendInfo blend_info_blend = { + .colorFunc = SCE_GXM_BLEND_FUNC_ADD, + .alphaFunc = SCE_GXM_BLEND_FUNC_ADD, + .colorSrc = SCE_GXM_BLEND_FACTOR_SRC_ALPHA, + .colorDst = SCE_GXM_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, + .alphaSrc = SCE_GXM_BLEND_FACTOR_ONE, + .alphaDst = SCE_GXM_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, + .colorMask = SCE_GXM_COLOR_MASK_ALL + }; + + static const SceGxmBlendInfo blend_info_add = { + .colorFunc = SCE_GXM_BLEND_FUNC_ADD, + .alphaFunc = SCE_GXM_BLEND_FUNC_ADD, + .colorSrc = SCE_GXM_BLEND_FACTOR_SRC_ALPHA, + .colorDst = SCE_GXM_BLEND_FACTOR_ONE, + .alphaSrc = SCE_GXM_BLEND_FACTOR_ZERO, + .alphaDst = SCE_GXM_BLEND_FACTOR_ONE, + .colorMask = SCE_GXM_COLOR_MASK_ALL + }; + + static const SceGxmBlendInfo blend_info_mod = { + .colorFunc = SCE_GXM_BLEND_FUNC_ADD, + .alphaFunc = SCE_GXM_BLEND_FUNC_ADD, + + .colorSrc = SCE_GXM_BLEND_FACTOR_ZERO, + .colorDst = SCE_GXM_BLEND_FACTOR_SRC_COLOR, + + .alphaSrc = SCE_GXM_BLEND_FACTOR_ZERO, + .alphaDst = SCE_GXM_BLEND_FACTOR_ONE, + .colorMask = SCE_GXM_COLOR_MASK_ALL + }; + + static const SceGxmBlendInfo blend_info_mul = { + .colorFunc = SCE_GXM_BLEND_FUNC_ADD, + .alphaFunc = SCE_GXM_BLEND_FUNC_ADD, + .colorSrc = SCE_GXM_BLEND_FACTOR_DST_COLOR, + .colorDst = SCE_GXM_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, + .alphaSrc = SCE_GXM_BLEND_FACTOR_DST_ALPHA, + .alphaDst = SCE_GXM_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, + .colorMask = SCE_GXM_COLOR_MASK_ALL + }; + + // get attributes by name to create vertex format bindings + const SceGxmProgramParameter *paramClearPositionAttribute = sceGxmProgramFindParameterByName(clearVertexProgramGxp, "aPosition"); + + // create clear vertex format + SceGxmVertexAttribute clearVertexAttributes[1]; + SceGxmVertexStream clearVertexStreams[1]; + clearVertexAttributes[0].streamIndex = 0; + clearVertexAttributes[0].offset = 0; + clearVertexAttributes[0].format = SCE_GXM_ATTRIBUTE_FORMAT_F32; + clearVertexAttributes[0].componentCount = 2; + clearVertexAttributes[0].regIndex = sceGxmProgramParameterGetResourceIndex(paramClearPositionAttribute); + clearVertexStreams[0].stride = sizeof(clear_vertex); + clearVertexStreams[0].indexSource = SCE_GXM_INDEX_SOURCE_INDEX_16BIT; + + // create clear programs + err = sceGxmShaderPatcherCreateVertexProgram( + data->shaderPatcher, + data->clearVertexProgramId, + clearVertexAttributes, + 1, + clearVertexStreams, + 1, + &data->clearVertexProgram + ); + if (err != SCE_OK) { + SDL_LogError(SDL_LOG_CATEGORY_RENDER, "create program (clear vertex) failed: %d\n", err); + return err; + } + + err = sceGxmShaderPatcherCreateFragmentProgram( + data->shaderPatcher, + data->clearFragmentProgramId, + SCE_GXM_OUTPUT_REGISTER_FORMAT_UCHAR4, + 0, + NULL, + clearVertexProgramGxp, + &data->clearFragmentProgram + ); + if (err != SCE_OK) { + SDL_LogError(SDL_LOG_CATEGORY_RENDER, "create program (clear fragment) failed: %d\n", err); + return err; + } + + // create the clear triangle vertex/index data + data->clearVertices = (clear_vertex *)gpu_alloc( + SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE, + 3*sizeof(clear_vertex), + 4, + SCE_GXM_MEMORY_ATTRIB_READ, + &data->clearVerticesUid + ); + + // Allocate a 64k * 2 bytes = 128 KiB buffer and store all possible + // 16-bit indices in linear ascending order, so we can use this for + // all drawing operations where we don't want to use indexing. + data->linearIndices = (uint16_t *)gpu_alloc( + SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE, + UINT16_MAX*sizeof(uint16_t), + sizeof(uint16_t), + SCE_GXM_MEMORY_ATTRIB_READ, + &data->linearIndicesUid + ); + + for (uint32_t i=0; i<=UINT16_MAX; ++i) + { + data->linearIndices[i] = i; + } + + data->clearVertices[0].x = -1.0f; + data->clearVertices[0].y = -1.0f; + data->clearVertices[1].x = 3.0f; + data->clearVertices[1].y = -1.0f; + data->clearVertices[2].x = -1.0f; + data->clearVertices[2].y = 3.0f; + + const SceGxmProgramParameter *paramColorPositionAttribute = sceGxmProgramFindParameterByName(colorVertexProgramGxp, "aPosition"); + + const SceGxmProgramParameter *paramColorColorAttribute = sceGxmProgramFindParameterByName(colorVertexProgramGxp, "aColor"); + + // create color vertex format + SceGxmVertexAttribute colorVertexAttributes[2]; + SceGxmVertexStream colorVertexStreams[1]; + /* x,y,z: 3 float 32 bits */ + colorVertexAttributes[0].streamIndex = 0; + colorVertexAttributes[0].offset = 0; + colorVertexAttributes[0].format = SCE_GXM_ATTRIBUTE_FORMAT_F32; + colorVertexAttributes[0].componentCount = 3; // (x, y, z) + colorVertexAttributes[0].regIndex = sceGxmProgramParameterGetResourceIndex(paramColorPositionAttribute); + /* color: 4 unsigned char = 32 bits */ + colorVertexAttributes[1].streamIndex = 0; + colorVertexAttributes[1].offset = 12; // (x, y, z) * 4 = 12 bytes + colorVertexAttributes[1].format = SCE_GXM_ATTRIBUTE_FORMAT_U8N; + colorVertexAttributes[1].componentCount = 4; // (color) + colorVertexAttributes[1].regIndex = sceGxmProgramParameterGetResourceIndex(paramColorColorAttribute); + // 16 bit (short) indices + colorVertexStreams[0].stride = sizeof(color_vertex); + colorVertexStreams[0].indexSource = SCE_GXM_INDEX_SOURCE_INDEX_16BIT; + + // create color shaders + err = sceGxmShaderPatcherCreateVertexProgram( + data->shaderPatcher, + data->colorVertexProgramId, + colorVertexAttributes, + 2, + colorVertexStreams, + 1, + &data->colorVertexProgram + ); + if (err != SCE_OK) { + SDL_LogError(SDL_LOG_CATEGORY_RENDER, "create program (color vertex) failed: %d\n", err); + return err; + } + + const SceGxmProgramParameter *paramTexturePositionAttribute = sceGxmProgramFindParameterByName(textureVertexProgramGxp, "aPosition"); + const SceGxmProgramParameter *paramTextureTexcoordAttribute = sceGxmProgramFindParameterByName(textureVertexProgramGxp, "aTexcoord"); + + // create texture vertex format + SceGxmVertexAttribute textureVertexAttributes[2]; + SceGxmVertexStream textureVertexStreams[1]; + /* x,y,z: 3 float 32 bits */ + textureVertexAttributes[0].streamIndex = 0; + textureVertexAttributes[0].offset = 0; + textureVertexAttributes[0].format = SCE_GXM_ATTRIBUTE_FORMAT_F32; + textureVertexAttributes[0].componentCount = 3; // (x, y, z) + textureVertexAttributes[0].regIndex = sceGxmProgramParameterGetResourceIndex(paramTexturePositionAttribute); + /* u,v: 2 floats 32 bits */ + textureVertexAttributes[1].streamIndex = 0; + textureVertexAttributes[1].offset = 12; // (x, y, z) * 4 = 12 bytes + textureVertexAttributes[1].format = SCE_GXM_ATTRIBUTE_FORMAT_F32; + textureVertexAttributes[1].componentCount = 2; // (u, v) + textureVertexAttributes[1].regIndex = sceGxmProgramParameterGetResourceIndex(paramTextureTexcoordAttribute); + // 16 bit (short) indices + textureVertexStreams[0].stride = sizeof(texture_vertex); + textureVertexStreams[0].indexSource = SCE_GXM_INDEX_SOURCE_INDEX_16BIT; + + // create texture shaders + err = sceGxmShaderPatcherCreateVertexProgram( + data->shaderPatcher, + data->textureVertexProgramId, + textureVertexAttributes, + 2, + textureVertexStreams, + 1, + &data->textureVertexProgram + ); + if (err != SCE_OK) { + SDL_LogError(SDL_LOG_CATEGORY_RENDER, "create program (texture vertex) failed: %d\n", err); + return err; + } + + // Create variations of the fragment program based on blending mode + make_fragment_programs(data, &data->blendFragmentPrograms.blend_mode_none, &blend_info_none); + make_fragment_programs(data, &data->blendFragmentPrograms.blend_mode_blend, &blend_info_blend); + make_fragment_programs(data, &data->blendFragmentPrograms.blend_mode_add, &blend_info_add); + make_fragment_programs(data, &data->blendFragmentPrograms.blend_mode_mod, &blend_info_mod); + make_fragment_programs(data, &data->blendFragmentPrograms.blend_mode_mul, &blend_info_mul); + + // Default to blend blending mode + fragment_programs *in = &data->blendFragmentPrograms.blend_mode_blend; + + data->colorFragmentProgram = in->color; + data->textureFragmentProgram = in->texture; + data->textureTintFragmentProgram = in->textureTint; + + // find vertex uniforms by name and cache parameter information + data->clearClearColorParam = (SceGxmProgramParameter *)sceGxmProgramFindParameterByName(clearFragmentProgramGxp, "uClearColor"); + data->colorWvpParam = (SceGxmProgramParameter *)sceGxmProgramFindParameterByName(colorVertexProgramGxp, "wvp"); + data->textureWvpParam = (SceGxmProgramParameter *)sceGxmProgramFindParameterByName(textureVertexProgramGxp, "wvp"); + data->textureTintColorParam = (SceGxmProgramParameter *)sceGxmProgramFindParameterByName(textureTintFragmentProgramGxp, "uTintColor"); + + // Allocate memory for the memory pool + data->pool_addr = gpu_alloc( + SCE_KERNEL_MEMBLOCK_TYPE_USER_RW, + VITA_GXM_POOL_SIZE, + sizeof(void *), + SCE_GXM_MEMORY_ATTRIB_READ, + &data->poolUid + ); + + init_orthographic_matrix(data->ortho_matrix, 0.0f, VITA_GXM_SCREEN_WIDTH, VITA_GXM_SCREEN_HEIGHT, 0.0f, 0.0f, 1.0f); + + data->backBufferIndex = 0; + data->frontBufferIndex = 0; + data->pool_index = 0; + + return 0; +} + +void gxm_finish(SDL_Renderer *renderer) +{ + VITA_GXM_RenderData *data = (VITA_GXM_RenderData *) renderer->driverdata; + + // wait until rendering is done + sceGxmFinish(data->gxm_context); + + // clean up allocations + sceGxmShaderPatcherReleaseFragmentProgram(data->shaderPatcher, data->clearFragmentProgram); + sceGxmShaderPatcherReleaseVertexProgram(data->shaderPatcher, data->clearVertexProgram); + sceGxmShaderPatcherReleaseVertexProgram(data->shaderPatcher, data->colorVertexProgram); + sceGxmShaderPatcherReleaseVertexProgram(data->shaderPatcher, data->textureVertexProgram); + + + free_fragment_programs(data, &data->blendFragmentPrograms.blend_mode_none); + free_fragment_programs(data, &data->blendFragmentPrograms.blend_mode_blend); + free_fragment_programs(data, &data->blendFragmentPrograms.blend_mode_add); + free_fragment_programs(data, &data->blendFragmentPrograms.blend_mode_mod); + free_fragment_programs(data, &data->blendFragmentPrograms.blend_mode_mul); + + gpu_free(data->linearIndicesUid); + gpu_free(data->clearVerticesUid); + + // wait until display queue is finished before deallocating display buffers + sceGxmDisplayQueueFinish(); + + // clean up display queue + gpu_free(data->depthBufferUid); + + for (size_t i = 0; i < VITA_GXM_BUFFERS; i++) + { + // clear the buffer then deallocate + SDL_memset(data->displayBufferData[i], 0, VITA_GXM_SCREEN_HEIGHT * VITA_GXM_SCREEN_STRIDE * 4); + gpu_free(data->displayBufferUid[i]); + + // destroy the sync object + sceGxmSyncObjectDestroy(data->displayBufferSync[i]); + } + + // free the depth and stencil buffer + gpu_free(data->depthBufferUid); + gpu_free(data->stencilBufferUid); + + // unregister programs and destroy shader patcher + sceGxmShaderPatcherUnregisterProgram(data->shaderPatcher, data->clearFragmentProgramId); + sceGxmShaderPatcherUnregisterProgram(data->shaderPatcher, data->clearVertexProgramId); + sceGxmShaderPatcherUnregisterProgram(data->shaderPatcher, data->colorFragmentProgramId); + sceGxmShaderPatcherUnregisterProgram(data->shaderPatcher, data->colorVertexProgramId); + sceGxmShaderPatcherUnregisterProgram(data->shaderPatcher, data->textureFragmentProgramId); + sceGxmShaderPatcherUnregisterProgram(data->shaderPatcher, data->textureTintFragmentProgramId); + sceGxmShaderPatcherUnregisterProgram(data->shaderPatcher, data->textureVertexProgramId); + + sceGxmShaderPatcherDestroy(data->shaderPatcher); + fragment_usse_free(data->patcherFragmentUsseUid); + vertex_usse_free(data->patcherVertexUsseUid); + gpu_free(data->patcherBufferUid); + + // destroy the render target + sceGxmDestroyRenderTarget(data->renderTarget); + + // destroy the gxm context + sceGxmDestroyContext(data->gxm_context); + fragment_usse_free(data->fragmentUsseRingBufferUid); + gpu_free(data->fragmentRingBufferUid); + gpu_free(data->vertexRingBufferUid); + gpu_free(data->vdmRingBufferUid); + SDL_free(data->contextParams.hostMem); + + gpu_free(data->poolUid); + + // terminate libgxm + sceGxmTerminate(); +} + +// textures + +void +free_gxm_texture(gxm_texture *texture) +{ + if (texture) { + if (texture->gxm_rendertarget) { + sceGxmDestroyRenderTarget(texture->gxm_rendertarget); + } + if (texture->depth_UID) { + gpu_free(texture->depth_UID); + } + if (texture->palette_UID) { + gpu_free(texture->palette_UID); + } + gpu_free(texture->data_UID); + SDL_free(texture); + } +} + +SceGxmTextureFormat +gxm_texture_get_format(const gxm_texture *texture) +{ + return sceGxmTextureGetFormat(&texture->gxm_tex); +} + +unsigned int +gxm_texture_get_width(const gxm_texture *texture) +{ + return sceGxmTextureGetWidth(&texture->gxm_tex); +} + +unsigned int +gxm_texture_get_height(const gxm_texture *texture) +{ + return sceGxmTextureGetHeight(&texture->gxm_tex); +} + +unsigned int +gxm_texture_get_stride(const gxm_texture *texture) +{ + return ((gxm_texture_get_width(texture) + 7) & ~7) + * tex_format_to_bytespp(gxm_texture_get_format(texture)); +} + +void * +gxm_texture_get_datap(const gxm_texture *texture) +{ + return sceGxmTextureGetData(&texture->gxm_tex); +} + +gxm_texture * +create_gxm_texture(VITA_GXM_RenderData *data, unsigned int w, unsigned int h, SceGxmTextureFormat format, unsigned int isRenderTarget) +{ + format = SCE_GXM_TEXTURE_FORMAT_A8B8G8R8; + gxm_texture *texture = SDL_malloc(sizeof(gxm_texture)); + if (!texture) + return NULL; + + const int tex_size = ((w + 7) & ~ 7) * h * tex_format_to_bytespp(format); + + /* Allocate a GPU buffer for the texture */ + void *texture_data = gpu_alloc( + SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW, + tex_size, + SCE_GXM_TEXTURE_ALIGNMENT, + SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_WRITE, + &texture->data_UID + ); + + if (!texture_data) { + free(texture); + return NULL; + } + + /* Clear the texture */ + SDL_memset(texture_data, 0, tex_size); + + /* Create the gxm texture */ + sceGxmTextureInitLinear( &texture->gxm_tex, texture_data, format, w, h, 0); + + if ((format & 0x9f000000U) == SCE_GXM_TEXTURE_BASE_FORMAT_P8) { + const int pal_size = 256 * sizeof(uint32_t); + + void *texture_palette = gpu_alloc( + SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW, + pal_size, + SCE_GXM_PALETTE_ALIGNMENT, + SCE_GXM_MEMORY_ATTRIB_READ, + &texture->palette_UID); + + if (!texture_palette) { + texture->palette_UID = 0; + free_gxm_texture(texture); + return NULL; + } + + SDL_memset(texture_palette, 0, pal_size); + + sceGxmTextureSetPalette(&texture->gxm_tex, texture_palette); + } else { + texture->palette_UID = 0; + } + + if (isRenderTarget) { + + int err = sceGxmColorSurfaceInit( + &texture->gxm_colorsurface, + SCE_GXM_COLOR_FORMAT_A8B8G8R8, + SCE_GXM_COLOR_SURFACE_LINEAR, + SCE_GXM_COLOR_SURFACE_SCALE_NONE, + SCE_GXM_OUTPUT_REGISTER_SIZE_32BIT, + w, + h, + w, + texture_data + ); + + if (err < 0) { + free_gxm_texture(texture); + SDL_LogError(SDL_LOG_CATEGORY_RENDER, "color surface init failed: %d\n", err); + return NULL; + } + + // create the depth/stencil surface + const uint32_t alignedWidth = ALIGN(w, SCE_GXM_TILE_SIZEX); + const uint32_t alignedHeight = ALIGN(h, SCE_GXM_TILE_SIZEY); + uint32_t sampleCount = alignedWidth*alignedHeight; + uint32_t depthStrideInSamples = alignedWidth; + + // allocate it + void *depthBufferData = gpu_alloc( + SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE, + 4*sampleCount, + SCE_GXM_DEPTHSTENCIL_SURFACE_ALIGNMENT, + SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_WRITE, + &texture->depth_UID); + + // create the SceGxmDepthStencilSurface structure + err = sceGxmDepthStencilSurfaceInit( + &texture->gxm_depthstencil, + SCE_GXM_DEPTH_STENCIL_FORMAT_S8D24, + SCE_GXM_DEPTH_STENCIL_SURFACE_TILED, + depthStrideInSamples, + depthBufferData, + NULL); + + if (err < 0) { + free_gxm_texture(texture); + SDL_LogError(SDL_LOG_CATEGORY_RENDER, "depth stencil init failed: %d\n", err); + return NULL; + } + + SceGxmRenderTarget *tgt = NULL; + + // set up parameters + SceGxmRenderTargetParams renderTargetParams; + memset(&renderTargetParams, 0, sizeof(SceGxmRenderTargetParams)); + renderTargetParams.flags = 0; + renderTargetParams.width = w; + renderTargetParams.height = h; + renderTargetParams.scenesPerFrame = 1; + renderTargetParams.multisampleMode = SCE_GXM_MULTISAMPLE_NONE; + renderTargetParams.multisampleLocations = 0; + renderTargetParams.driverMemBlock = -1; + + // create the render target + err = sceGxmCreateRenderTarget(&renderTargetParams, &tgt); + + texture->gxm_rendertarget = tgt; + + if (err < 0) { + free_gxm_texture(texture); + SDL_LogError(SDL_LOG_CATEGORY_RENDER, "create render target failed: %d\n", err); + return NULL; + } + + } + + return texture; +} + +void +gxm_texture_set_filters(gxm_texture *texture, SceGxmTextureFilter min_filter, SceGxmTextureFilter mag_filter) +{ + sceGxmTextureSetMinFilter(&texture->gxm_tex, min_filter); + sceGxmTextureSetMagFilter(&texture->gxm_tex, mag_filter); +} + +#endif /* SDL_VIDEO_RENDER_VITA_GXM */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/render/vitagxm/SDL_render_vita_gxm_tools.h b/src/render/vitagxm/SDL_render_vita_gxm_tools.h new file mode 100644 index 000000000..5787e4d3a --- /dev/null +++ b/src/render/vitagxm/SDL_render_vita_gxm_tools.h @@ -0,0 +1,61 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2020 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef SDL_RENDER_VITA_GXM_TOOLS_H +#define SDL_RENDER_VITA_GXM_TOOLS_H + +#include "../../SDL_internal.h" + +#include "SDL_hints.h" +#include "../SDL_sysrender.h" + +#include +#include +#include +#include +#include +#include + +#include "SDL_render_vita_gxm_types.h" + +void *pool_malloc(VITA_GXM_RenderData *data, unsigned int size); +void *pool_memalign(VITA_GXM_RenderData *data, unsigned int size, unsigned int alignment); + +void set_clip_rectangle(VITA_GXM_RenderData *data, int x_min, int y_min, int x_max, int y_max); +void unset_clip_rectangle(VITA_GXM_RenderData *data); + +int gxm_init(SDL_Renderer *renderer); +void gxm_finish(SDL_Renderer *renderer); + +gxm_texture *create_gxm_texture(VITA_GXM_RenderData *data, unsigned int w, unsigned int h, SceGxmTextureFormat format, unsigned int isRenderTarget); +void free_gxm_texture(gxm_texture *texture); + +void gxm_texture_set_filters(gxm_texture *texture, SceGxmTextureFilter min_filter, SceGxmTextureFilter mag_filter); +SceGxmTextureFormat gxm_texture_get_format(const gxm_texture *texture); + +unsigned int gxm_texture_get_width(const gxm_texture *texture); +unsigned int gxm_texture_get_height(const gxm_texture *texture); +unsigned int gxm_texture_get_stride(const gxm_texture *texture); +void *gxm_texture_get_datap(const gxm_texture *texture); + +#endif /* SDL_RENDER_VITA_GXM_TOOLS_H */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/render/vitagxm/SDL_render_vita_gxm_types.h b/src/render/vitagxm/SDL_render_vita_gxm_types.h new file mode 100644 index 000000000..cc4e5f22a --- /dev/null +++ b/src/render/vitagxm/SDL_render_vita_gxm_types.h @@ -0,0 +1,194 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2020 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef SDL_RENDER_VITA_GXM_TYPES_H +#define SDL_RENDER_VITA_GXM_TYPES_H + +#include "../../SDL_internal.h" + +#include "SDL_hints.h" +#include "../SDL_sysrender.h" + +#include +#include +#include +#include +#include +#include + +#include + +#define VITA_GXM_SCREEN_WIDTH 960 +#define VITA_GXM_SCREEN_HEIGHT 544 +#define VITA_GXM_SCREEN_STRIDE 960 + +#define VITA_GXM_COLOR_FORMAT SCE_GXM_COLOR_FORMAT_A8B8G8R8 +#define VITA_GXM_PIXEL_FORMAT SCE_DISPLAY_PIXELFORMAT_A8B8G8R8 + +#define VITA_GXM_BUFFERS 3 +#define VITA_GXM_PENDING_SWAPS 2 +#define VITA_GXM_POOL_SIZE 2 * 1024 * 1024 + +typedef struct +{ + void *address; + Uint8 wait_vblank; +} VITA_GXM_DisplayData; + +typedef struct clear_vertex { + float x; + float y; +} clear_vertex; + +typedef struct color_vertex { + float x; + float y; + float z; + unsigned int color; +} color_vertex; + +typedef struct texture_vertex { + float x; + float y; + float z; + float u; + float v; +} texture_vertex; + +typedef struct gxm_texture { + SceGxmTexture gxm_tex; + SceUID data_UID; + SceUID palette_UID; + SceGxmRenderTarget *gxm_rendertarget; + SceGxmColorSurface gxm_colorsurface; + SceGxmDepthStencilSurface gxm_depthstencil; + SceUID depth_UID; +} gxm_texture; + +typedef struct fragment_programs { + SceGxmFragmentProgram *color; + SceGxmFragmentProgram *texture; + SceGxmFragmentProgram *textureTint; +} fragment_programs; + +typedef struct blend_fragment_programs { + fragment_programs blend_mode_none; + fragment_programs blend_mode_blend; + fragment_programs blend_mode_add; + fragment_programs blend_mode_mod; + fragment_programs blend_mode_mul; +} blend_fragment_programs; + +typedef struct +{ + SDL_Rect viewport; + SDL_bool viewport_dirty; + SDL_Texture *texture; + SDL_Texture *target; + Uint32 color; +} gxm_drawstate_cache; + +typedef struct +{ + SDL_bool initialized; + SDL_bool drawing; + + unsigned int psm; + unsigned int bpp; + + int currentBlendMode; + + VITA_GXM_DisplayData displayData; + + SceUID vdmRingBufferUid; + SceUID vertexRingBufferUid; + SceUID fragmentRingBufferUid; + SceUID fragmentUsseRingBufferUid; + SceGxmContextParams contextParams; + SceGxmContext *gxm_context; + SceGxmRenderTarget *renderTarget; + SceUID displayBufferUid[VITA_GXM_BUFFERS]; + void *displayBufferData[VITA_GXM_BUFFERS]; + SceGxmColorSurface displaySurface[VITA_GXM_BUFFERS]; + SceGxmSyncObject *displayBufferSync[VITA_GXM_BUFFERS]; + + SceUID depthBufferUid; + SceUID stencilBufferUid; + SceGxmDepthStencilSurface depthSurface; + void *depthBufferData; + void *stencilBufferData; + + unsigned int backBufferIndex; + unsigned int frontBufferIndex; + + void* pool_addr; + SceUID poolUid; + unsigned int pool_index; + + float ortho_matrix[4*4]; + + SceGxmVertexProgram *colorVertexProgram; + SceGxmFragmentProgram *colorFragmentProgram; + SceGxmVertexProgram *textureVertexProgram; + SceGxmFragmentProgram *textureFragmentProgram; + SceGxmFragmentProgram *textureTintFragmentProgram; + SceGxmProgramParameter *clearClearColorParam; + SceGxmProgramParameter *colorWvpParam; + SceGxmProgramParameter *textureWvpParam; + SceGxmProgramParameter *textureTintColorParam; + + SceGxmShaderPatcher *shaderPatcher; + SceGxmVertexProgram *clearVertexProgram; + SceGxmFragmentProgram *clearFragmentProgram; + + SceGxmShaderPatcherId clearVertexProgramId; + SceGxmShaderPatcherId clearFragmentProgramId; + SceGxmShaderPatcherId colorVertexProgramId; + SceGxmShaderPatcherId colorFragmentProgramId; + SceGxmShaderPatcherId textureVertexProgramId; + SceGxmShaderPatcherId textureFragmentProgramId; + SceGxmShaderPatcherId textureTintFragmentProgramId; + + SceUID patcherBufferUid; + SceUID patcherVertexUsseUid; + SceUID patcherFragmentUsseUid; + + SceUID clearVerticesUid; + SceUID linearIndicesUid; + clear_vertex *clearVertices; + uint16_t *linearIndices; + + blend_fragment_programs blendFragmentPrograms; + + gxm_drawstate_cache drawstate; +} VITA_GXM_RenderData; + +typedef struct +{ + gxm_texture *tex; + unsigned int pitch; + unsigned int w; + unsigned int h; +} VITA_GXM_TextureData; + +#endif /* SDL_RENDER_VITA_GXM_TYPES_H */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/render/vitagxm/shader_src/clear_f.cg b/src/render/vitagxm/shader_src/clear_f.cg new file mode 100644 index 000000000..6d8fb3b72 --- /dev/null +++ b/src/render/vitagxm/shader_src/clear_f.cg @@ -0,0 +1,4 @@ +float4 main( uniform float4 uClearColor) : COLOR +{ + return uClearColor; +} diff --git a/src/render/vitagxm/shader_src/clear_v.cg b/src/render/vitagxm/shader_src/clear_v.cg new file mode 100644 index 000000000..ee5aa9fce --- /dev/null +++ b/src/render/vitagxm/shader_src/clear_v.cg @@ -0,0 +1,4 @@ +float4 main(float2 aPosition) : POSITION +{ + return float4(aPosition, 1.f, 1.f); +} diff --git a/src/render/vitagxm/shader_src/color_f.cg b/src/render/vitagxm/shader_src/color_f.cg new file mode 100644 index 000000000..dc87c2a11 --- /dev/null +++ b/src/render/vitagxm/shader_src/color_f.cg @@ -0,0 +1,4 @@ +float4 main(float4 vColor : COLOR) +{ + return vColor; +} diff --git a/src/render/vitagxm/shader_src/color_v.cg b/src/render/vitagxm/shader_src/color_v.cg new file mode 100644 index 000000000..f60879783 --- /dev/null +++ b/src/render/vitagxm/shader_src/color_v.cg @@ -0,0 +1,11 @@ +void main( + float3 aPosition, + float4 aColor, + uniform float4x4 wvp, + float4 out vPosition : POSITION, + float4 out vColor : COLOR +) +{ + vPosition = mul(float4(aPosition, 1.f), wvp); + vColor = aColor; +} diff --git a/src/render/vitagxm/shader_src/texture_f.cg b/src/render/vitagxm/shader_src/texture_f.cg new file mode 100644 index 000000000..232ee8585 --- /dev/null +++ b/src/render/vitagxm/shader_src/texture_f.cg @@ -0,0 +1,4 @@ +float4 main(float2 vTexcoord : TEXCOORD0, uniform sampler2D tex) +{ + return tex2D(tex, vTexcoord); +} diff --git a/src/render/vitagxm/shader_src/texture_tint_f.cg b/src/render/vitagxm/shader_src/texture_tint_f.cg new file mode 100644 index 000000000..8b12a8067 --- /dev/null +++ b/src/render/vitagxm/shader_src/texture_tint_f.cg @@ -0,0 +1,4 @@ +float4 main( float2 vTexcoord : TEXCOORD0, uniform sampler2D tex, uniform float4 uTintColor) +{ + return tex2D(tex, vTexcoord) * uTintColor; +} diff --git a/src/render/vitagxm/shader_src/texture_v.cg b/src/render/vitagxm/shader_src/texture_v.cg new file mode 100644 index 000000000..42e7df9ca --- /dev/null +++ b/src/render/vitagxm/shader_src/texture_v.cg @@ -0,0 +1,11 @@ +void main( + float3 aPosition, + float2 aTexcoord, + uniform float4x4 wvp, + float4 out vPosition : POSITION, + float2 out vTexcoord : TEXCOORD0 +) +{ + vPosition = mul(float4(aPosition, 1.f), wvp); + vTexcoord = aTexcoord; +}