Merge pull request #9184 from frangarcj/new_gxm

[WIP][VITA] Improving gfx driver
This commit is contained in:
Twinaphex 2019-07-24 19:27:52 +02:00 committed by GitHub
commit 3de2e9a4b4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 496 additions and 155 deletions

View File

@ -35,6 +35,10 @@ typedef struct vita2d_texture {
SceGxmTexture gxm_tex;
SceUID data_UID;
SceUID palette_UID;
SceGxmRenderTarget *gxm_rtgt;
SceGxmColorSurface gxm_sfc;
SceGxmDepthStencilSurface gxm_sfd;
SceUID depth_UID;
} vita2d_texture;
typedef struct vita2d_font vita2d_font;
@ -42,6 +46,7 @@ typedef struct vita2d_pgf vita2d_pgf;
int vita2d_init();
int vita2d_init_advanced(unsigned int temp_pool_size);
int vita2d_init_advanced_with_msaa(unsigned int temp_pool_size, SceGxmMultisampleMode msaa);
void vita2d_wait_rendering_done();
int vita2d_fini();
@ -49,6 +54,7 @@ void vita2d_clear_screen();
void vita2d_swap_buffers();
void vita2d_start_drawing();
void vita2d_start_drawing_advanced(vita2d_texture *target, unsigned int flags);
void vita2d_end_drawing();
int vita2d_common_dialog_update();
@ -56,10 +62,21 @@ int vita2d_common_dialog_update();
void vita2d_set_clear_color(unsigned int color);
unsigned int vita2d_get_clear_color();
void vita2d_set_clear_color(unsigned int color);
unsigned int vita2d_get_clear_color();
void vita2d_set_vblank_wait(int enable);
void *vita2d_get_current_fb();
SceGxmContext *vita2d_get_context();
SceGxmShaderPatcher *vita2d_get_shader_patcher();
const uint16_t *vita2d_get_linear_indices();
void vita2d_set_region_clip(SceGxmRegionClipMode mode, unsigned int x_min, unsigned int y_min, unsigned int x_max, unsigned int y_max);
void vita2d_enable_clipping();
void vita2d_disable_clipping();
int vita2d_get_clipping_enabled();
void vita2d_set_clip_rectangle(int x_min, int y_min, int x_max, int y_max);
void vita2d_get_clip_rectangle(int *x_min, int *y_min, int *x_max, int *y_max);
void vita2d_set_blend_mode_add(int enable);
void *vita2d_pool_malloc(unsigned int size);
void *vita2d_pool_memalign(unsigned int size, unsigned int alignment);
@ -70,9 +87,14 @@ void vita2d_draw_pixel(float x, float y, unsigned int color);
void vita2d_draw_line(float x0, float y0, float x1, float y1, unsigned int color);
void vita2d_draw_rectangle(float x, float y, float w, float h, unsigned int color);
void vita2d_draw_fill_circle(float x, float y, float radius, unsigned int color);
void vita2d_draw_array(SceGxmPrimitiveType mode, const vita2d_color_vertex *vertices, size_t count);
void vita2d_texture_set_alloc_memblock_type(SceKernelMemBlockType type);
SceKernelMemBlockType vita2d_texture_get_alloc_memblock_type();
vita2d_texture *vita2d_create_empty_texture(unsigned int w, unsigned int h);
vita2d_texture *vita2d_create_empty_texture_format(unsigned int w, unsigned int h, SceGxmTextureFormat format);
vita2d_texture *vita2d_create_empty_texture_rendertarget(unsigned int w, unsigned int h, SceGxmTextureFormat format);
void vita2d_free_texture(vita2d_texture *texture);
unsigned int vita2d_texture_get_width(const vita2d_texture *texture);
@ -93,6 +115,7 @@ void vita2d_draw_texture_part(const vita2d_texture *texture, float x, float y, f
void vita2d_draw_texture_part_scale(const vita2d_texture *texture, float x, float y, float tex_x, float tex_y, float tex_w, float tex_h, float x_scale, float y_scale);
void vita2d_draw_texture_scale_rotate_hotspot(const vita2d_texture *texture, float x, float y, float x_scale, float y_scale, float rad, float center_x, float center_y);
void vita2d_draw_texture_scale_rotate(const vita2d_texture *texture, float x, float y, float x_scale, float y_scale, float rad);
void vita2d_draw_texture_part_scale_rotate(const vita2d_texture *texture, float x, float y, float tex_x, float tex_y, float tex_w, float tex_h, float x_scale, float y_scale, float rad);
void vita2d_draw_texture_tint(const vita2d_texture *texture, float x, float y, unsigned int color);
void vita2d_draw_texture_tint_rotate(const vita2d_texture *texture, float x, float y, float rad, unsigned int color);
@ -102,6 +125,8 @@ void vita2d_draw_texture_tint_part(const vita2d_texture *texture, float x, float
void vita2d_draw_texture_tint_part_scale(const vita2d_texture *texture, float x, float y, float tex_x, float tex_y, float tex_w, float tex_h, float x_scale, float y_scale, unsigned int color);
void vita2d_draw_texture_tint_scale_rotate_hotspot(const vita2d_texture *texture, float x, float y, float x_scale, float y_scale, float rad, float center_x, float center_y, unsigned int color);
void vita2d_draw_texture_tint_scale_rotate(const vita2d_texture *texture, float x, float y, float x_scale, float y_scale, float rad, unsigned int color);
void vita2d_draw_texture_part_tint_scale_rotate(const vita2d_texture *texture, float x, float y, float tex_x, float tex_y, float tex_w, float tex_h, float x_scale, float y_scale, float rad, unsigned int color);
void vita2d_draw_array_textured(const vita2d_texture *texture, SceGxmPrimitiveType mode, const vita2d_texture_vertex *vertices, size_t count, unsigned int color);
/** ADVANCED **/
void vita2d_texture_set_wvp(float x, float y, float width, float height);

View File

@ -25,7 +25,6 @@
#define DISPLAY_PIXEL_FORMAT SCE_DISPLAY_PIXELFORMAT_A8B8G8R8
#define DISPLAY_BUFFER_COUNT 3
#define DISPLAY_MAX_PENDING_SWAPS 2
#define MSAA_MODE SCE_GXM_MULTISAMPLE_NONE
#define DEFAULT_TEMP_POOL_SIZE (1 * 1024 * 1024)
typedef struct vita2d_display_data {
@ -56,8 +55,14 @@ static const SceGxmProgram *const textureTintFragmentProgramGxp = &texture_tint_
static int vita2d_initialized = 0;
static float clear_color[4] = {0.0f, 0.0f, 0.0f, 1.0f};
static unsigned int clear_color_u = 0xff000000;
static unsigned int clear_color_u = 0xFF000000;
static int clip_rect_x_min = 0;
static int clip_rect_y_min = 0;
static int clip_rect_x_max = DISPLAY_WIDTH;
static int clip_rect_y_max = DISPLAY_HEIGHT;
static int vblank_wait = 1;
static int drawing = 0;
static int clipping_enabled = 0;
static SceUID vdmRingBufferUid;
static SceUID vertexRingBufferUid;
@ -72,8 +77,10 @@ static SceUID displayBufferUid[DISPLAY_BUFFER_COUNT];
static SceGxmColorSurface displaySurface[DISPLAY_BUFFER_COUNT];
static SceGxmSyncObject *displayBufferSync[DISPLAY_BUFFER_COUNT];
static SceUID depthBufferUid;
static SceUID stencilBufferUid;
static SceGxmDepthStencilSurface depthSurface;
static void *depthBufferData = NULL;
static void *stencilBufferData = NULL;
static unsigned int backBufferIndex = 0;
static unsigned int frontBufferIndex = 0;
@ -95,9 +102,9 @@ static SceUID patcherVertexUsseUid;
static SceUID patcherFragmentUsseUid;
static SceUID clearVerticesUid;
static SceUID clearIndicesUid;
static SceUID linearIndicesUid;
static vita2d_clear_vertex *clearVertices = NULL;
static uint16_t *clearIndices = NULL;
static uint16_t *linearIndices = NULL;
/* Shared with other .c */
float _vita2d_ortho_matrix[4*4];
@ -112,6 +119,17 @@ const SceGxmProgramParameter *_vita2d_colorWvpParam = NULL;
const SceGxmProgramParameter *_vita2d_textureWvpParam = NULL;
const SceGxmProgramParameter *_vita2d_textureTintColorParam = NULL;
typedef struct vita2d_fragment_programs {
SceGxmFragmentProgram *color;
SceGxmFragmentProgram *texture;
SceGxmFragmentProgram *textureTint;
} vita2d_fragment_programs;
struct {
vita2d_fragment_programs blend_mode_normal;
vita2d_fragment_programs blend_mode_add;
} _vita2d_fragmentPrograms;
// Temporary memory pool
static void *pool_addr = NULL;
static SceUID poolUid;
@ -149,12 +167,54 @@ static void display_callback(const void *callback_data)
}
}
int vita2d_init()
static void _vita2d_free_fragment_programs(vita2d_fragment_programs *out)
{
return vita2d_init_advanced(DEFAULT_TEMP_POOL_SIZE);
sceGxmShaderPatcherReleaseFragmentProgram(shaderPatcher, out->color);
sceGxmShaderPatcherReleaseFragmentProgram(shaderPatcher, out->texture);
sceGxmShaderPatcherReleaseFragmentProgram(shaderPatcher, out->textureTint);
}
int vita2d_init_advanced(unsigned int temp_pool_size)
static void _vita2d_make_fragment_programs(vita2d_fragment_programs *out,
const SceGxmBlendInfo *blend_info, SceGxmMultisampleMode msaa)
{
int err;
(void)err;
err = sceGxmShaderPatcherCreateFragmentProgram(
shaderPatcher,
colorFragmentProgramId,
SCE_GXM_OUTPUT_REGISTER_FORMAT_UCHAR4,
msaa,
blend_info,
colorVertexProgramGxp,
&out->color);
VITA2D_DEBUG("color sceGxmShaderPatcherCreateFragmentProgram(): 0x%08X\n", err);
err = sceGxmShaderPatcherCreateFragmentProgram(
shaderPatcher,
textureFragmentProgramId,
SCE_GXM_OUTPUT_REGISTER_FORMAT_UCHAR4,
msaa,
blend_info,
textureVertexProgramGxp,
&out->texture);
VITA2D_DEBUG("texture sceGxmShaderPatcherCreateFragmentProgram(): 0x%08X\n", err);
err = sceGxmShaderPatcherCreateFragmentProgram(
shaderPatcher,
textureTintFragmentProgramId,
SCE_GXM_OUTPUT_REGISTER_FORMAT_UCHAR4,
msaa,
blend_info,
textureVertexProgramGxp,
&out->textureTint);
VITA2D_DEBUG("texture_tint sceGxmShaderPatcherCreateFragmentProgram(): 0x%08X\n", err);
}
static int vita2d_init_internal(unsigned int temp_pool_size, SceGxmMultisampleMode msaa)
{
int err;
unsigned int i, x, y;
@ -227,7 +287,7 @@ int vita2d_init_advanced(unsigned int temp_pool_size)
renderTargetParams.width = DISPLAY_WIDTH;
renderTargetParams.height = DISPLAY_HEIGHT;
renderTargetParams.scenesPerFrame = 1;
renderTargetParams.multisampleMode = MSAA_MODE;
renderTargetParams.multisampleMode = msaa;
renderTargetParams.multisampleLocations = 0;
renderTargetParams.driverMemBlock = -1; // Invalid UID
@ -258,7 +318,7 @@ int vita2d_init_advanced(unsigned int temp_pool_size)
&displaySurface[i],
DISPLAY_COLOR_FORMAT,
SCE_GXM_COLOR_SURFACE_LINEAR,
(MSAA_MODE == SCE_GXM_MULTISAMPLE_NONE) ? SCE_GXM_COLOR_SURFACE_SCALE_NONE : SCE_GXM_COLOR_SURFACE_SCALE_MSAA_DOWNSCALE,
(msaa == SCE_GXM_MULTISAMPLE_NONE) ? SCE_GXM_COLOR_SURFACE_SCALE_NONE : SCE_GXM_COLOR_SURFACE_SCALE_MSAA_DOWNSCALE,
SCE_GXM_OUTPUT_REGISTER_SIZE_32BIT,
DISPLAY_WIDTH,
DISPLAY_HEIGHT,
@ -274,11 +334,11 @@ int vita2d_init_advanced(unsigned int temp_pool_size)
const unsigned int alignedHeight = ALIGN(DISPLAY_HEIGHT, SCE_GXM_TILE_SIZEY);
unsigned int sampleCount = alignedWidth*alignedHeight;
unsigned int depthStrideInSamples = alignedWidth;
if (MSAA_MODE == SCE_GXM_MULTISAMPLE_4X) {
if (msaa == SCE_GXM_MULTISAMPLE_4X) {
// samples increase in X and Y
sampleCount *= 4;
depthStrideInSamples *= 2;
} else if (MSAA_MODE == SCE_GXM_MULTISAMPLE_2X) {
} else if (msaa == SCE_GXM_MULTISAMPLE_2X) {
// samples increase in Y only
sampleCount *= 2;
}
@ -291,6 +351,14 @@ int vita2d_init_advanced(unsigned int temp_pool_size)
SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_WRITE,
&depthBufferUid);
// allocate the stencil buffer
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,
&stencilBufferUid);
// create the SceGxmDepthStencilSurface structure
err = sceGxmDepthStencilSurfaceInit(
&depthSurface,
@ -298,7 +366,19 @@ int vita2d_init_advanced(unsigned int temp_pool_size)
SCE_GXM_DEPTH_STENCIL_SURFACE_TILED,
depthStrideInSamples,
depthBufferData,
NULL);
stencilBufferData);
// set the stencil test reference (this is currently assumed to always remain 1 after here for region clipping)
sceGxmSetFrontStencilRef(_vita2d_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(
_vita2d_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;
@ -393,8 +473,18 @@ int vita2d_init_advanced(unsigned int temp_pool_size)
.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_SRC_ALPHA,
.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_ONE,
.colorDst = SCE_GXM_BLEND_FACTOR_ONE,
.alphaSrc = SCE_GXM_BLEND_FACTOR_ONE,
.alphaDst = SCE_GXM_BLEND_FACTOR_ZERO,
.alphaDst = SCE_GXM_BLEND_FACTOR_ONE,
.colorMask = SCE_GXM_COLOR_MASK_ALL
};
@ -428,7 +518,7 @@ int vita2d_init_advanced(unsigned int temp_pool_size)
shaderPatcher,
clearFragmentProgramId,
SCE_GXM_OUTPUT_REGISTER_FORMAT_UCHAR4,
MSAA_MODE,
msaa,
NULL,
clearVertexProgramGxp,
&clearFragmentProgram);
@ -443,12 +533,20 @@ int vita2d_init_advanced(unsigned int temp_pool_size)
SCE_GXM_MEMORY_ATTRIB_READ,
&clearVerticesUid);
clearIndices = (uint16_t *)gpu_alloc(
// 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.
linearIndices = (uint16_t *)gpu_alloc(
SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE,
3*sizeof(uint16_t),
2,
UINT16_MAX*sizeof(uint16_t),
sizeof(uint16_t),
SCE_GXM_MEMORY_ATTRIB_READ,
&clearIndicesUid);
&linearIndicesUid);
// Range of i must be greater than uint16_t, this doesn't endless-loop
for (uint32_t i=0; i<=UINT16_MAX; ++i) {
linearIndices[i] = i;
}
clearVertices[0].x = -1.0f;
clearVertices[0].y = -1.0f;
@ -457,10 +555,6 @@ int vita2d_init_advanced(unsigned int temp_pool_size)
clearVertices[2].x = -1.0f;
clearVertices[2].y = 3.0f;
clearIndices[0] = 0;
clearIndices[1] = 1;
clearIndices[2] = 2;
const SceGxmProgramParameter *paramColorPositionAttribute = sceGxmProgramFindParameterByName(colorVertexProgramGxp, "aPosition");
VITA2D_DEBUG("aPosition sceGxmProgramFindParameterByName(): %p\n", paramColorPositionAttribute);
@ -498,17 +592,6 @@ int vita2d_init_advanced(unsigned int temp_pool_size)
VITA2D_DEBUG("color sceGxmShaderPatcherCreateVertexProgram(): 0x%08X\n", err);
err = sceGxmShaderPatcherCreateFragmentProgram(
shaderPatcher,
colorFragmentProgramId,
SCE_GXM_OUTPUT_REGISTER_FORMAT_UCHAR4,
MSAA_MODE,
&blend_info,
colorVertexProgramGxp,
&_vita2d_colorFragmentProgram);
VITA2D_DEBUG("color sceGxmShaderPatcherCreateFragmentProgram(): 0x%08X\n", err);
const SceGxmProgramParameter *paramTexturePositionAttribute = sceGxmProgramFindParameterByName(textureVertexProgramGxp, "aPosition");
VITA2D_DEBUG("aPosition sceGxmProgramFindParameterByName(): %p\n", paramTexturePositionAttribute);
@ -547,27 +630,12 @@ int vita2d_init_advanced(unsigned int temp_pool_size)
VITA2D_DEBUG("texture sceGxmShaderPatcherCreateVertexProgram(): 0x%08X\n", err);
err = sceGxmShaderPatcherCreateFragmentProgram(
shaderPatcher,
textureFragmentProgramId,
SCE_GXM_OUTPUT_REGISTER_FORMAT_UCHAR4,
MSAA_MODE,
&blend_info,
textureVertexProgramGxp,
&_vita2d_textureFragmentProgram);
// Create variations of the fragment program based on blending mode
_vita2d_make_fragment_programs(&_vita2d_fragmentPrograms.blend_mode_normal, &blend_info, msaa);
_vita2d_make_fragment_programs(&_vita2d_fragmentPrograms.blend_mode_add, &blend_info_add, msaa);
VITA2D_DEBUG("texture sceGxmShaderPatcherCreateFragmentProgram(): 0x%08X\n", err);
err = sceGxmShaderPatcherCreateFragmentProgram(
shaderPatcher,
textureTintFragmentProgramId,
SCE_GXM_OUTPUT_REGISTER_FORMAT_UCHAR4,
MSAA_MODE,
&blend_info,
textureVertexProgramGxp,
&_vita2d_textureTintFragmentProgram);
VITA2D_DEBUG("texture_tint sceGxmShaderPatcherCreateFragmentProgram(): 0x%08X\n", err);
// Default to "normal" blending mode (non-additive)
vita2d_set_blend_mode_add(0);
// find vertex uniforms by name and cache parameter information
_vita2d_clearClearColorParam = sceGxmProgramFindParameterByName(clearFragmentProgramGxp, "uClearColor");
@ -590,6 +658,7 @@ int vita2d_init_advanced(unsigned int temp_pool_size)
sizeof(void *),
SCE_GXM_MEMORY_ATTRIB_READ,
&poolUid);
matrix_init_orthographic(_vita2d_ortho_matrix, 0.0f, DISPLAY_WIDTH, DISPLAY_HEIGHT, 0.0f, 0.0f, 1.0f);
@ -605,6 +674,21 @@ int vita2d_init_advanced(unsigned int temp_pool_size)
return 1;
}
int vita2d_init()
{
return vita2d_init_internal(DEFAULT_TEMP_POOL_SIZE, SCE_GXM_MULTISAMPLE_NONE);
}
int vita2d_init_advanced(unsigned int temp_pool_size)
{
return vita2d_init_internal(temp_pool_size, SCE_GXM_MULTISAMPLE_NONE);
}
int vita2d_init_advanced_with_msaa(unsigned int temp_pool_size, SceGxmMultisampleMode msaa)
{
return vita2d_init_internal(temp_pool_size, msaa);
}
void vita2d_wait_rendering_done()
{
sceGxmFinish(_vita2d_context);
@ -625,12 +709,13 @@ int vita2d_fini()
// clean up allocations
sceGxmShaderPatcherReleaseFragmentProgram(shaderPatcher, clearFragmentProgram);
sceGxmShaderPatcherReleaseVertexProgram(shaderPatcher, clearVertexProgram);
sceGxmShaderPatcherReleaseFragmentProgram(shaderPatcher, _vita2d_colorFragmentProgram);
sceGxmShaderPatcherReleaseVertexProgram(shaderPatcher, _vita2d_colorVertexProgram);
sceGxmShaderPatcherReleaseFragmentProgram(shaderPatcher, _vita2d_textureFragmentProgram);
sceGxmShaderPatcherReleaseFragmentProgram(shaderPatcher, _vita2d_textureTintFragmentProgram);
sceGxmShaderPatcherReleaseVertexProgram(shaderPatcher, _vita2d_textureVertexProgram);
gpu_free(clearIndicesUid);
_vita2d_free_fragment_programs(&_vita2d_fragmentPrograms.blend_mode_normal);
_vita2d_free_fragment_programs(&_vita2d_fragmentPrograms.blend_mode_add);
gpu_free(linearIndicesUid);
gpu_free(clearVerticesUid);
// wait until display queue is finished before deallocating display buffers
@ -647,8 +732,9 @@ int vita2d_fini()
sceGxmSyncObjectDestroy(displayBufferSync[i]);
}
// free the depth buffer
// free the depth and stencil buffer
gpu_free(depthBufferUid);
gpu_free(stencilBufferUid);
// unregister programs and destroy shader patcher
sceGxmShaderPatcherUnregisterProgram(shaderPatcher, clearFragmentProgramId);
@ -701,7 +787,7 @@ void vita2d_clear_screen()
// draw the clear triangle
sceGxmSetVertexStream(_vita2d_context, 0, clearVertices);
sceGxmDraw(_vita2d_context, SCE_GXM_PRIMITIVE_TRIANGLES, SCE_GXM_INDEX_FORMAT_U16, clearIndices, 3);
sceGxmDraw(_vita2d_context, SCE_GXM_PRIMITIVE_TRIANGLES, SCE_GXM_INDEX_FORMAT_U16, linearIndices, 3);
}
void vita2d_swap_buffers()
@ -723,23 +809,129 @@ void vita2d_swap_buffers()
void vita2d_start_drawing()
{
/* Reset the temporary memory pool */
vita2d_pool_reset();
vita2d_start_drawing_advanced(NULL, 0);
}
sceGxmBeginScene(
void vita2d_start_drawing_advanced(vita2d_texture *target, unsigned int flags)
{
if (target == NULL) {
sceGxmBeginScene(
_vita2d_context,
0,
flags,
renderTarget,
NULL,
NULL,
displayBufferSync[backBufferIndex],
&displaySurface[backBufferIndex],
&depthSurface);
} else {
sceGxmBeginScene(
_vita2d_context,
flags,
target->gxm_rtgt,
NULL,
NULL,
NULL,
&target->gxm_sfc,
&target->gxm_sfd);
}
drawing = 1;
// in the current way, the library keeps the region clip across scenes
if (clipping_enabled) {
vita2d_set_clip_rectangle(clip_rect_x_min, clip_rect_y_min, clip_rect_x_max, clip_rect_y_max);
}
}
void vita2d_end_drawing()
{
sceGxmEndScene(_vita2d_context, NULL, NULL);
drawing = 0;
}
void vita2d_enable_clipping()
{
clipping_enabled = 1;
vita2d_set_clip_rectangle(clip_rect_x_min, clip_rect_y_min, clip_rect_x_max, clip_rect_y_max);
}
void vita2d_disable_clipping()
{
clipping_enabled = 0;
sceGxmSetFrontStencilFunc(
_vita2d_context,
SCE_GXM_STENCIL_FUNC_ALWAYS,
SCE_GXM_STENCIL_OP_KEEP,
SCE_GXM_STENCIL_OP_KEEP,
SCE_GXM_STENCIL_OP_KEEP,
0xFF,
0xFF);
}
int vita2d_get_clipping_enabled()
{
return clipping_enabled;
}
void vita2d_set_clip_rectangle(int x_min, int y_min, int x_max, int y_max)
{
clip_rect_x_min = x_min;
clip_rect_y_min = y_min;
clip_rect_x_max = x_max;
clip_rect_y_max = y_max;
// we can only draw during a scene, but we can cache the values since they're not going to have any visible effect till the scene starts anyways
if(drawing) {
// clear the stencil buffer to 0
sceGxmSetFrontStencilFunc(
_vita2d_context,
SCE_GXM_STENCIL_FUNC_NEVER,
SCE_GXM_STENCIL_OP_ZERO,
SCE_GXM_STENCIL_OP_ZERO,
SCE_GXM_STENCIL_OP_ZERO,
0xFF,
0xFF);
vita2d_draw_rectangle(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, 0);
// set the stencil to 1 in the desired region
sceGxmSetFrontStencilFunc(
_vita2d_context,
SCE_GXM_STENCIL_FUNC_NEVER,
SCE_GXM_STENCIL_OP_REPLACE,
SCE_GXM_STENCIL_OP_REPLACE,
SCE_GXM_STENCIL_OP_REPLACE,
0xFF,
0xFF);
vita2d_draw_rectangle(x_min, y_min, x_max - x_min, y_max - y_min, 0);
if(clipping_enabled) {
// set the stencil function to only accept pixels where the stencil is 1
sceGxmSetFrontStencilFunc(
_vita2d_context,
SCE_GXM_STENCIL_FUNC_EQUAL,
SCE_GXM_STENCIL_OP_KEEP,
SCE_GXM_STENCIL_OP_KEEP,
SCE_GXM_STENCIL_OP_KEEP,
0xFF,
0xFF);
} else {
sceGxmSetFrontStencilFunc(
_vita2d_context,
SCE_GXM_STENCIL_FUNC_ALWAYS,
SCE_GXM_STENCIL_OP_KEEP,
SCE_GXM_STENCIL_OP_KEEP,
SCE_GXM_STENCIL_OP_KEEP,
0xFF,
0xFF);
}
}
}
void vita2d_get_clip_rectangle(int *x_min, int *y_min, int *x_max, int *y_max)
{
*x_min = clip_rect_x_min;
*y_min = clip_rect_y_min;
*x_max = clip_rect_x_max;
*y_max = clip_rect_y_max;
}
int vita2d_common_dialog_update()
@ -769,7 +961,8 @@ void vita2d_set_clear_color(unsigned int color)
clear_color_u = color;
}
unsigned int vita2d_get_clear_color(){
unsigned int vita2d_get_clear_color()
{
return clear_color_u;
}
@ -783,6 +976,21 @@ void *vita2d_get_current_fb()
return displayBufferData[frontBufferIndex];
}
SceGxmContext *vita2d_get_context()
{
return _vita2d_context;
}
SceGxmShaderPatcher *vita2d_get_shader_patcher()
{
return shaderPatcher;
}
const uint16_t *vita2d_get_linear_indices()
{
return linearIndices;
}
void vita2d_set_region_clip(SceGxmRegionClipMode mode, unsigned int x_min, unsigned int y_min, unsigned int x_max, unsigned int y_max)
{
sceGxmSetRegionClip(_vita2d_context, mode, x_min, y_min, x_max, y_max);
@ -818,3 +1026,13 @@ void vita2d_pool_reset()
{
pool_index = 0;
}
void vita2d_set_blend_mode_add(int enable)
{
vita2d_fragment_programs *in = enable ? &_vita2d_fragmentPrograms.blend_mode_add
: &_vita2d_fragmentPrograms.blend_mode_normal;
_vita2d_colorFragmentProgram = in->color;
_vita2d_textureFragmentProgram = in->texture;
_vita2d_textureTintFragmentProgram = in->textureTint;
}

View File

@ -7,6 +7,7 @@
#include "shared.h"
#define GXM_TEX_MAX_SIZE 4096
static SceKernelMemBlockType MemBlockType = SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW;
static int tex_format_to_bytespp(SceGxmTextureFormat format)
{
@ -36,12 +37,22 @@ static int tex_format_to_bytespp(SceGxmTextureFormat format)
}
}
void vita2d_texture_set_alloc_memblock_type(SceKernelMemBlockType type)
{
MemBlockType = (type == 0) ? SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW : type;
}
SceKernelMemBlockType vita2d_texture_get_alloc_memblock_type()
{
return MemBlockType;
}
vita2d_texture *vita2d_create_empty_texture(unsigned int w, unsigned int h)
{
return vita2d_create_empty_texture_format(w, h, SCE_GXM_TEXTURE_FORMAT_A8B8G8R8);
}
vita2d_texture *vita2d_create_empty_texture_format(unsigned int w, unsigned int h, SceGxmTextureFormat format)
static vita2d_texture *_vita2d_create_empty_texture_format_advanced(unsigned int w, unsigned int h, SceGxmTextureFormat format, unsigned int isRenderTarget)
{
if (w > GXM_TEX_MAX_SIZE || h > GXM_TEX_MAX_SIZE)
return NULL;
@ -50,14 +61,16 @@ vita2d_texture *vita2d_create_empty_texture_format(unsigned int w, unsigned int
if (!texture)
return NULL;
memset(texture, 0, sizeof(vita2d_texture));
const int tex_size = w * 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,
MemBlockType,
tex_size,
SCE_GXM_TEXTURE_ALIGNMENT,
SCE_GXM_MEMORY_ATTRIB_READ,
SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_WRITE,
&texture->data_UID);
if (!texture_data) {
@ -66,7 +79,7 @@ vita2d_texture *vita2d_create_empty_texture_format(unsigned int w, unsigned int
}
/* Clear the texture */
//memset(texture_data, 0, tex_size);
memset(texture_data, 0, tex_size);
/* Create the gxm texture */
sceGxmTextureInitLinear(
@ -82,7 +95,7 @@ vita2d_texture *vita2d_create_empty_texture_format(unsigned int w, unsigned int
const int pal_size = 256 * sizeof(uint32_t);
void *texture_palette = gpu_alloc(
SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW,
MemBlockType,
pal_size,
SCE_GXM_PALETTE_ALIGNMENT,
SCE_GXM_MEMORY_ATTRIB_READ,
@ -94,19 +107,107 @@ vita2d_texture *vita2d_create_empty_texture_format(unsigned int w, unsigned int
return NULL;
}
//memset(texture_palette, 0, pal_size);
memset(texture_palette, 0, pal_size);
sceGxmTextureSetPalette(&texture->gxm_tex, texture_palette);
} else {
texture->palette_UID = 0;
}
if (isRenderTarget) {
int err = sceGxmColorSurfaceInit(
&texture->gxm_sfc,
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) {
vita2d_free_texture(texture);
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_sfd,
SCE_GXM_DEPTH_STENCIL_FORMAT_S8D24,
SCE_GXM_DEPTH_STENCIL_SURFACE_TILED,
depthStrideInSamples,
depthBufferData,
NULL);
if (err < 0) {
vita2d_free_texture(texture);
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_rtgt = tgt;
if (err < 0) {
vita2d_free_texture(texture);
return NULL;
}
}
return texture;
}
vita2d_texture * vita2d_create_empty_texture_format(unsigned int w, unsigned int h, SceGxmTextureFormat format)
{
return _vita2d_create_empty_texture_format_advanced(w, h, format, 0);
}
vita2d_texture * vita2d_create_empty_texture_rendertarget(unsigned int w, unsigned int h, SceGxmTextureFormat format)
{
return _vita2d_create_empty_texture_format_advanced(w, h, format, 1);
}
void vita2d_free_texture(vita2d_texture *texture)
{
if (texture) {
if (texture->gxm_rtgt) {
sceGxmDestroyRenderTarget(texture->gxm_rtgt);
}
if (texture->depth_UID) {
gpu_free(texture->depth_UID);
}
if (texture->palette_UID) {
gpu_free(texture->palette_UID);
}
@ -178,7 +279,6 @@ static inline void set_texture_wvp_uniform()
{
void *vertex_wvp_buffer;
sceGxmReserveVertexDefaultUniformBuffer(_vita2d_context, &vertex_wvp_buffer);
//matrix_init_orthographic(_vita2d_ortho_matrix, 0.0f, DISPLAY_WIDTH, DISPLAY_HEIGHT, 0.0f, 0.0f, 1.0f);
sceGxmSetUniformDataF(vertex_wvp_buffer, _vita2d_textureWvpParam, 0, 16, _vita2d_ortho_matrix);
}
@ -205,10 +305,6 @@ static inline void draw_texture_generic(const vita2d_texture *texture, float x,
4 * sizeof(vita2d_texture_vertex), // 4 vertices
sizeof(vita2d_texture_vertex));
uint16_t *indices = (uint16_t *)vita2d_pool_memalign(
4 * sizeof(uint16_t), // 4 indices
sizeof(uint16_t));
const float w = vita2d_texture_get_width(texture);
const float h = vita2d_texture_get_height(texture);
@ -236,16 +332,11 @@ static inline void draw_texture_generic(const vita2d_texture *texture, float x,
vertices[3].u = 1.0f;
vertices[3].v = 1.0f;
indices[0] = 0;
indices[1] = 1;
indices[2] = 2;
indices[3] = 3;
// Set the texture to the TEXUNIT0
sceGxmSetFragmentTexture(_vita2d_context, 0, &texture->gxm_tex);
sceGxmSetVertexStream(_vita2d_context, 0, vertices);
sceGxmDraw(_vita2d_context, SCE_GXM_PRIMITIVE_TRIANGLE_STRIP, SCE_GXM_INDEX_FORMAT_U16, indices, 4);
sceGxmDraw(_vita2d_context, SCE_GXM_PRIMITIVE_TRIANGLE_STRIP, SCE_GXM_INDEX_FORMAT_U16, vita2d_get_linear_indices(), 4);
}
void vita2d_draw_texture(const vita2d_texture *texture, float x, float y)
@ -284,10 +375,6 @@ static inline void draw_texture_rotate_hotspot_generic(const vita2d_texture *tex
4 * sizeof(vita2d_texture_vertex), // 4 vertices
sizeof(vita2d_texture_vertex));
uint16_t *indices = (uint16_t *)vita2d_pool_memalign(
4 * sizeof(uint16_t), // 4 indices
sizeof(uint16_t));
const float w = vita2d_texture_get_width(texture);
const float h = vita2d_texture_get_height(texture);
@ -325,16 +412,11 @@ static inline void draw_texture_rotate_hotspot_generic(const vita2d_texture *tex
vertices[i].y = _x*s + _y*c + y;
}
indices[0] = 0;
indices[1] = 1;
indices[2] = 2;
indices[3] = 3;
// Set the texture to the TEXUNIT0
sceGxmSetFragmentTexture(_vita2d_context, 0, &texture->gxm_tex);
sceGxmSetVertexStream(_vita2d_context, 0, vertices);
sceGxmDraw(_vita2d_context, SCE_GXM_PRIMITIVE_TRIANGLE_STRIP, SCE_GXM_INDEX_FORMAT_U16, indices, 4);
sceGxmDraw(_vita2d_context, SCE_GXM_PRIMITIVE_TRIANGLE_STRIP, SCE_GXM_INDEX_FORMAT_U16, vita2d_get_linear_indices(), 4);
}
void vita2d_draw_texture_rotate_hotspot(const vita2d_texture *texture, float x, float y, float rad, float center_x, float center_y)
@ -358,10 +440,6 @@ static inline void draw_texture_scale_generic(const vita2d_texture *texture, flo
4 * sizeof(vita2d_texture_vertex), // 4 vertices
sizeof(vita2d_texture_vertex));
uint16_t *indices = (uint16_t *)vita2d_pool_memalign(
4 * sizeof(uint16_t), // 4 indices
sizeof(uint16_t));
const float w = x_scale * vita2d_texture_get_width(texture);
const float h = y_scale * vita2d_texture_get_height(texture);
@ -389,16 +467,11 @@ static inline void draw_texture_scale_generic(const vita2d_texture *texture, flo
vertices[3].u = 1.0f;
vertices[3].v = 1.0f;
indices[0] = 0;
indices[1] = 1;
indices[2] = 2;
indices[3] = 3;
// Set the texture to the TEXUNIT0
sceGxmSetFragmentTexture(_vita2d_context, 0, &texture->gxm_tex);
sceGxmSetVertexStream(_vita2d_context, 0, vertices);
sceGxmDraw(_vita2d_context, SCE_GXM_PRIMITIVE_TRIANGLE_STRIP, SCE_GXM_INDEX_FORMAT_U16, indices, 4);
sceGxmDraw(_vita2d_context, SCE_GXM_PRIMITIVE_TRIANGLE_STRIP, SCE_GXM_INDEX_FORMAT_U16, vita2d_get_linear_indices(), 4);
}
void vita2d_draw_texture_scale(const vita2d_texture *texture, float x, float y, float x_scale, float y_scale)
@ -423,10 +496,6 @@ static inline void draw_texture_part_generic(const vita2d_texture *texture, floa
4 * sizeof(vita2d_texture_vertex), // 4 vertices
sizeof(vita2d_texture_vertex));
uint16_t *indices = (uint16_t *)vita2d_pool_memalign(
4 * sizeof(uint16_t), // 4 indices
sizeof(uint16_t));
const float w = vita2d_texture_get_width(texture);
const float h = vita2d_texture_get_height(texture);
@ -459,16 +528,11 @@ static inline void draw_texture_part_generic(const vita2d_texture *texture, floa
vertices[3].u = u1;
vertices[3].v = v1;
indices[0] = 0;
indices[1] = 1;
indices[2] = 2;
indices[3] = 3;
// Set the texture to the TEXUNIT0
sceGxmSetFragmentTexture(_vita2d_context, 0, &texture->gxm_tex);
sceGxmSetVertexStream(_vita2d_context, 0, vertices);
sceGxmDraw(_vita2d_context, SCE_GXM_PRIMITIVE_TRIANGLE_STRIP, SCE_GXM_INDEX_FORMAT_U16, indices, 4);
sceGxmDraw(_vita2d_context, SCE_GXM_PRIMITIVE_TRIANGLE_STRIP, SCE_GXM_INDEX_FORMAT_U16, vita2d_get_linear_indices(), 4);
}
void vita2d_draw_texture_part(const vita2d_texture *texture, float x, float y, float tex_x, float tex_y, float tex_w, float tex_h)
@ -492,10 +556,6 @@ static inline void draw_texture_part_scale_generic(const vita2d_texture *texture
4 * sizeof(vita2d_texture_vertex), // 4 vertices
sizeof(vita2d_texture_vertex));
uint16_t *indices = (uint16_t *)vita2d_pool_memalign(
4 * sizeof(uint16_t), // 4 indices
sizeof(uint16_t));
const float w = vita2d_texture_get_width(texture);
const float h = vita2d_texture_get_height(texture);
@ -531,16 +591,11 @@ static inline void draw_texture_part_scale_generic(const vita2d_texture *texture
vertices[3].u = u1;
vertices[3].v = v1;
indices[0] = 0;
indices[1] = 1;
indices[2] = 2;
indices[3] = 3;
// Set the texture to the TEXUNIT0
sceGxmSetFragmentTexture(_vita2d_context, 0, &texture->gxm_tex);
sceGxmSetVertexStream(_vita2d_context, 0, vertices);
sceGxmDraw(_vita2d_context, SCE_GXM_PRIMITIVE_TRIANGLE_STRIP, SCE_GXM_INDEX_FORMAT_U16, indices, 4);
sceGxmDraw(_vita2d_context, SCE_GXM_PRIMITIVE_TRIANGLE_STRIP, SCE_GXM_INDEX_FORMAT_U16, vita2d_get_linear_indices(), 4);
}
void vita2d_draw_texture_part_scale(const vita2d_texture *texture, float x, float y, float tex_x, float tex_y, float tex_w, float tex_h, float x_scale, float y_scale)
@ -564,10 +619,6 @@ static inline void draw_texture_scale_rotate_hotspot_generic(const vita2d_textur
4 * sizeof(vita2d_texture_vertex), // 4 vertices
sizeof(vita2d_texture_vertex));
uint16_t *indices = (uint16_t *)vita2d_pool_memalign(
4 * sizeof(uint16_t), // 4 indices
sizeof(uint16_t));
const float w = x_scale * vita2d_texture_get_width(texture);
const float h = y_scale * vita2d_texture_get_height(texture);
const float center_x_scaled = x_scale * center_x;
@ -607,16 +658,11 @@ static inline void draw_texture_scale_rotate_hotspot_generic(const vita2d_textur
vertices[i].y = _x*s + _y*c + y + center_y_scaled;
}
indices[0] = 0;
indices[1] = 1;
indices[2] = 2;
indices[3] = 3;
// Set the texture to the TEXUNIT0
sceGxmSetFragmentTexture(_vita2d_context, 0, &texture->gxm_tex);
sceGxmSetVertexStream(_vita2d_context, 0, vertices);
sceGxmDraw(_vita2d_context, SCE_GXM_PRIMITIVE_TRIANGLE_STRIP, SCE_GXM_INDEX_FORMAT_U16, indices, 4);
sceGxmDraw(_vita2d_context, SCE_GXM_PRIMITIVE_TRIANGLE_STRIP, SCE_GXM_INDEX_FORMAT_U16, vita2d_get_linear_indices(), 4);
}
void vita2d_draw_texture_scale_rotate_hotspot(const vita2d_texture *texture, float x, float y, float x_scale, float y_scale, float rad, float center_x, float center_y)
@ -650,43 +696,95 @@ void vita2d_draw_texture_tint_scale_rotate(const vita2d_texture *texture, float
vita2d_texture_get_height(texture)/2.0f, color);
}
void vita2d_texture_set_wvp(float x, float y, float width, float height)
static inline void draw_texture_part_scale_rotate_generic(const vita2d_texture *texture, float x, float y,
float tex_x, float tex_y, float tex_w, float tex_h, float x_scale, float y_scale, float rad)
{
void *vertex_wvp_buffer;
matrix_init_orthographic(_vita2d_ortho_matrix, x, width, height, y, 0.0f, 1.0f);
sceGxmReserveVertexDefaultUniformBuffer(_vita2d_context, &vertex_wvp_buffer);
sceGxmSetUniformDataF(vertex_wvp_buffer, _vita2d_textureWvpParam, 0, 16, _vita2d_ortho_matrix);
}
vita2d_texture_vertex *vertices = (vita2d_texture_vertex *)vita2d_pool_memalign(
4 * sizeof(vita2d_texture_vertex), // 4 vertices
sizeof(vita2d_texture_vertex));
void vita2d_texture_set_program(){
set_texture_program();
}
const float w_full = vita2d_texture_get_width(texture);
const float h_full = vita2d_texture_get_height(texture);
void vita2d_texture_set_tint_program(){
set_texture_tint_program();
}
const float w_half = (tex_w * x_scale) / 2.0f;
const float h_half = (tex_h * y_scale) / 2.0f;
void vita2d_texture_set_tint_color_uniform(unsigned int color){
set_texture_tint_color_uniform(color);
}
const float u0 = tex_x / w_full;
const float v0 = tex_y / h_full;
const float u1 = (tex_x + tex_w) / w_full;
const float v1 = (tex_y + tex_h) / h_full;
vertices[0].x = -w_half;
vertices[0].y = -h_half;
vertices[0].z = +0.5f;
vertices[0].u = u0;
vertices[0].v = v0;
void vita2d_draw_texture_part_generic(const vita2d_texture *texture, SceGxmPrimitiveType type, vita2d_texture_vertex *vertices, unsigned int num_vertices)
{
vertices[1].x = w_half;
vertices[1].y = -h_half;
vertices[1].z = +0.5f;
vertices[1].u = u1;
vertices[1].v = v0;
uint16_t *indices = (uint16_t *)vita2d_pool_memalign(
num_vertices * sizeof(uint16_t), // 4 indices
sizeof(uint16_t));
vertices[2].x = -w_half;
vertices[2].y = h_half;
vertices[2].z = +0.5f;
vertices[2].u = u0;
vertices[2].v = v1;
for(int n = 0; n < num_vertices; n++){
indices[n] = n;
vertices[3].x = w_half;
vertices[3].y = h_half;
vertices[3].z = +0.5f;
vertices[3].u = u1;
vertices[3].v = v1;
const float c = cosf(rad);
const float s = sinf(rad);
int i;
for (i = 0; i < 4; ++i) { // Rotate and translate
float _x = vertices[i].x;
float _y = vertices[i].y;
vertices[i].x = _x*c - _y*s + x;
vertices[i].y = _x*s + _y*c + y;
}
// Set the texture to the TEXUNIT0
sceGxmSetFragmentTexture(_vita2d_context, 0, &texture->gxm_tex);
sceGxmSetVertexStream(_vita2d_context, 0, vertices);
sceGxmDraw(_vita2d_context, type, SCE_GXM_INDEX_FORMAT_U16, indices, 4);
sceGxmDraw(_vita2d_context, SCE_GXM_PRIMITIVE_TRIANGLE_STRIP, SCE_GXM_INDEX_FORMAT_U16, vita2d_get_linear_indices(), 4);
}
void vita2d_draw_texture_part_scale_rotate(const vita2d_texture *texture, float x, float y,
float tex_x, float tex_y, float tex_w, float tex_h, float x_scale, float y_scale, float rad)
{
set_texture_program();
set_texture_wvp_uniform();
draw_texture_part_scale_rotate_generic(texture, x, y,
tex_x, tex_y, tex_w, tex_h, x_scale, y_scale, rad);
}
void vita2d_draw_texture_part_tint_scale_rotate(const vita2d_texture *texture, float x, float y,
float tex_x, float tex_y, float tex_w, float tex_h, float x_scale, float y_scale, float rad, unsigned int color)
{
set_texture_tint_program();
set_texture_wvp_uniform();
set_texture_tint_color_uniform(color);
draw_texture_part_scale_rotate_generic(texture, x, y,
tex_x, tex_y, tex_w, tex_h, x_scale, y_scale, rad);
}
void vita2d_draw_array_textured(const vita2d_texture *texture, SceGxmPrimitiveType mode, const vita2d_texture_vertex *vertices, size_t count, unsigned int color)
{
set_texture_tint_program();
set_texture_wvp_uniform();
set_texture_tint_color_uniform(color);
sceGxmSetBackPolygonMode(_vita2d_context, SCE_GXM_POLYGON_MODE_TRIANGLE_FILL);
// Set the texture to the TEXUNIT0
sceGxmSetFragmentTexture(_vita2d_context, 0, &texture->gxm_tex);
sceGxmSetVertexStream(_vita2d_context, 0, vertices);
sceGxmDraw(_vita2d_context, mode, SCE_GXM_INDEX_FORMAT_U16, vita2d_get_linear_indices(), count);
}