mirror of
https://github.com/libretro/RetroArch
synced 2025-03-31 10:20:41 +00:00
2934af8af0 Added Patreon sponsor link. c8f18b6f0f Getting current program only when required for vglDrawObjects. 4c5d136b0d Added directive to enable vitaShaRK usage from cmd. 4a10df3be5 Minor adjustments and bugfixes. 14a0124acf Added GL_TEXTURE_LOD_BIAS support. 40c8c6205e Added GL_NONE def and fixed glUniform4f impl. 868079c51e Added glUniform4f implementation. 0a682cbad2 Typo fix. be3ce61ae7 Added GL_DEPTH_BITS and GL_STENCIL_BITS support. 21e6d1d330 Added runtime shader compiler support. 696e40bc62 Beautify error handler code. 537b37b110 Added glUniform3fv implementation. 7dd1403015 Fixed GLenum size and added missing types defines. 0c75f27ff1 Moved to NEON optimized memcpy usage. 98951895de Added gluPerspective implementation. 23e0b0b309 Fix for vglInitExtended not working on sys app mode. 4989c33ef5 Run clang-format. 429f1c1d8a Added system mode support. 9231680d02 Initializing sceGxm before free mem checking on vglInitExtended. 091e5e7882 Added vglInitWithCustomSizes. f4c646ea78 Added vglSetParamBufferSize. 1b9a063c41 Beautify some code. 089e81efc5 Fix for duplicated symbols 789dcbf812 Typo fix in readRGBA4444. 1514a4b2cb Disabling lto due to it being broken on vitasdk with gcc 9.1. fca18d9ab7 Added support for RGBA4444 texture format. d449f12808 Added support for RGB565 texture format. git-subtree-dir: deps/vitaGL git-subtree-split: 2934af8af083a9acf598ab75233c518a251c6f0d
593 lines
18 KiB
C
593 lines
18 KiB
C
/*
|
|
* This file is part of vitaGL
|
|
* Copyright 2017, 2018, 2019, 2020 Rinnegatamante
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Lesser General Public License as published
|
|
* by the Free Software Foundation, version 3 of the License, or (at your
|
|
* option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
/*
|
|
* legacy.c:
|
|
* Implementation for legacy openGL 1.0 rendering method
|
|
*/
|
|
|
|
#include "shared.h"
|
|
|
|
// Vertex list struct
|
|
typedef struct vertexList {
|
|
vector3f v;
|
|
void *next;
|
|
} vertexList;
|
|
|
|
// Color vertex list struct
|
|
typedef struct rgbaList {
|
|
vector4f v;
|
|
void *next;
|
|
} rgbaList;
|
|
|
|
// Texture coord list struct
|
|
typedef struct uvList {
|
|
vector2f v;
|
|
void *next;
|
|
} uvList;
|
|
|
|
static vertexList *model_vertices = NULL; // Pointer to vertex list
|
|
static vertexList *last_vert = NULL; // Pointer to last element in vertex list
|
|
static rgbaList *model_color = NULL; // Pointer to color vertex list
|
|
static rgbaList *last_clr = NULL; // Pointer to last element in color vertex list
|
|
static uvList *model_uv = NULL; // Pointer to texcoord list
|
|
static uvList *last_uv = NULL; // Pointer to last element in texcoord list
|
|
static uint64_t vertex_count = 0; // Vertex counter for vertex list
|
|
static SceGxmPrimitiveType prim; // Current in use primitive for rendering
|
|
static SceGxmPrimitiveTypeExtra prim_extra = SCE_GXM_PRIMITIVE_NONE; // Current in use non native primitive for rendering
|
|
static uint8_t np = 0xFF; // Number of expected vertices per element for current in use primitive
|
|
|
|
vector4f current_color = { 1.0f, 1.0f, 1.0f, 1.0f }; // Current in use color
|
|
|
|
static void purge_vertex_list() {
|
|
vertexList *old;
|
|
rgbaList *old2;
|
|
uvList *old3;
|
|
|
|
// Purging color and vertex lists
|
|
while (model_vertices != NULL) {
|
|
old = model_vertices;
|
|
old2 = model_color;
|
|
model_vertices = model_vertices->next;
|
|
model_color = model_color->next;
|
|
free(old);
|
|
free(old2);
|
|
}
|
|
|
|
// Purging texcoord list
|
|
while (model_uv != NULL) {
|
|
old3 = model_uv;
|
|
model_uv = model_uv->next;
|
|
free(old3);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* ------------------------------
|
|
* - IMPLEMENTATION STARTS HERE -
|
|
* ------------------------------
|
|
*/
|
|
|
|
void glVertex3f(GLfloat x, GLfloat y, GLfloat z) {
|
|
#ifndef SKIP_ERROR_HANDLING
|
|
// Error handling
|
|
if (phase != MODEL_CREATION) {
|
|
SET_GL_ERROR(GL_INVALID_OPERATION)
|
|
}
|
|
#endif
|
|
|
|
// Adding a new element to color and vertex lists
|
|
if (model_vertices == NULL) {
|
|
model_vertices = last_vert = (vertexList *)malloc(sizeof(vertexList));
|
|
model_color = last_clr = (rgbaList *)malloc(sizeof(rgbaList));
|
|
} else {
|
|
last_vert->next = (vertexList *)malloc(sizeof(vertexList));
|
|
last_clr->next = (rgbaList *)malloc(sizeof(rgbaList));
|
|
last_vert = last_vert->next;
|
|
last_clr = last_clr->next;
|
|
}
|
|
|
|
// Properly populating the new element
|
|
last_vert->v.x = x;
|
|
last_vert->v.y = y;
|
|
last_vert->v.z = z;
|
|
memcpy_neon(&last_clr->v, ¤t_color.r, sizeof(vector4f));
|
|
last_clr->next = last_vert->next = NULL;
|
|
|
|
// Increasing vertex counter
|
|
vertex_count++;
|
|
}
|
|
|
|
void glVertex3fv(const GLfloat *v) {
|
|
#ifndef SKIP_ERROR_HANDLING
|
|
// Error handling
|
|
if (phase != MODEL_CREATION) {
|
|
SET_GL_ERROR(GL_INVALID_OPERATION)
|
|
}
|
|
#endif
|
|
|
|
// Adding a new element to color and vertex lists
|
|
if (model_vertices == NULL) {
|
|
model_vertices = last_vert = (vertexList *)malloc(sizeof(vertexList));
|
|
model_color = last_clr = (rgbaList *)malloc(sizeof(rgbaList));
|
|
} else {
|
|
last_vert->next = (vertexList *)malloc(sizeof(vertexList));
|
|
last_clr->next = (rgbaList *)malloc(sizeof(rgbaList));
|
|
last_vert = last_vert->next;
|
|
last_clr = last_clr->next;
|
|
}
|
|
|
|
// Properly populating the new element
|
|
memcpy_neon(&last_vert->v, v, sizeof(vector3f));
|
|
memcpy_neon(&last_clr->v, ¤t_color.r, sizeof(vector4f));
|
|
last_clr->next = last_vert->next = NULL;
|
|
|
|
// Increasing vertex counter
|
|
vertex_count++;
|
|
}
|
|
|
|
void glVertex2f(GLfloat x, GLfloat y) {
|
|
glVertex3f(x, y, 0.0f);
|
|
}
|
|
|
|
void glColor3f(GLfloat red, GLfloat green, GLfloat blue) {
|
|
// Setting current color value
|
|
current_color.r = red;
|
|
current_color.g = green;
|
|
current_color.b = blue;
|
|
current_color.a = 1.0f;
|
|
}
|
|
|
|
void glColor3fv(const GLfloat *v) {
|
|
// Setting current color value
|
|
memcpy_neon(¤t_color.r, v, sizeof(vector3f));
|
|
current_color.a = 1.0f;
|
|
}
|
|
|
|
void glColor3ub(GLubyte red, GLubyte green, GLubyte blue) {
|
|
// Setting current color value
|
|
current_color.r = (1.0f * red) / 255.0f;
|
|
current_color.g = (1.0f * green) / 255.0f;
|
|
current_color.b = (1.0f * blue) / 255.0f;
|
|
current_color.a = 1.0f;
|
|
}
|
|
|
|
void glColor3ubv(const GLubyte *c) {
|
|
// Setting current color value
|
|
current_color.r = (1.0f * c[0]) / 255.0f;
|
|
current_color.g = (1.0f * c[1]) / 255.0f;
|
|
current_color.b = (1.0f * c[2]) / 255.0f;
|
|
current_color.a = 1.0f;
|
|
}
|
|
|
|
void glColor4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) {
|
|
// Setting current color value
|
|
current_color.r = red;
|
|
current_color.g = green;
|
|
current_color.b = blue;
|
|
current_color.a = alpha;
|
|
}
|
|
|
|
void glColor4fv(const GLfloat *v) {
|
|
// Setting current color value
|
|
memcpy_neon(¤t_color.r, v, sizeof(vector4f));
|
|
}
|
|
|
|
void glColor4ub(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha) {
|
|
current_color.r = (1.0f * red) / 255.0f;
|
|
current_color.g = (1.0f * green) / 255.0f;
|
|
current_color.b = (1.0f * blue) / 255.0f;
|
|
current_color.a = (1.0f * alpha) / 255.0f;
|
|
}
|
|
|
|
void glColor4ubv(const GLubyte *c) {
|
|
// Setting current color value
|
|
current_color.r = (1.0f * c[0]) / 255.0f;
|
|
current_color.g = (1.0f * c[1]) / 255.0f;
|
|
current_color.b = (1.0f * c[2]) / 255.0f;
|
|
current_color.a = (1.0f * c[3]) / 255.0f;
|
|
}
|
|
|
|
void glTexCoord2fv(GLfloat *f) {
|
|
#ifndef SKIP_ERROR_HANDLING
|
|
// Error handling
|
|
if (phase != MODEL_CREATION) {
|
|
SET_GL_ERROR(GL_INVALID_OPERATION)
|
|
}
|
|
#endif
|
|
|
|
// Adding a new element to texcoord list
|
|
if (model_uv == NULL) {
|
|
model_uv = last_uv = (uvList *)malloc(sizeof(uvList));
|
|
} else {
|
|
last_uv->next = (uvList *)malloc(sizeof(uvList));
|
|
last_uv = last_uv->next;
|
|
}
|
|
|
|
// Properly populating the new element
|
|
last_uv->v.x = f[0];
|
|
last_uv->v.y = f[1];
|
|
last_uv->next = NULL;
|
|
}
|
|
|
|
void glTexCoord2f(GLfloat s, GLfloat t) {
|
|
#ifndef SKIP_ERROR_HANDLING
|
|
// Error handling
|
|
if (phase != MODEL_CREATION) {
|
|
SET_GL_ERROR(GL_INVALID_OPERATION)
|
|
}
|
|
#endif
|
|
|
|
// Adding a new element to texcoord list
|
|
if (model_uv == NULL) {
|
|
model_uv = last_uv = (uvList *)malloc(sizeof(uvList));
|
|
} else {
|
|
last_uv->next = (uvList *)malloc(sizeof(uvList));
|
|
last_uv = last_uv->next;
|
|
}
|
|
|
|
// Properly populating the new element
|
|
last_uv->v.x = s;
|
|
last_uv->v.y = t;
|
|
last_uv->next = NULL;
|
|
}
|
|
|
|
void glTexCoord2i(GLint s, GLint t) {
|
|
#ifndef SKIP_ERROR_HANDLING
|
|
// Error handling
|
|
if (phase != MODEL_CREATION) {
|
|
SET_GL_ERROR(GL_INVALID_OPERATION)
|
|
}
|
|
#endif
|
|
|
|
// Adding a new element to texcoord list
|
|
if (model_uv == NULL) {
|
|
model_uv = last_uv = (uvList *)malloc(sizeof(uvList));
|
|
} else {
|
|
last_uv->next = (uvList *)malloc(sizeof(uvList));
|
|
last_uv = last_uv->next;
|
|
}
|
|
|
|
// Properly populating the new element
|
|
last_uv->v.x = s;
|
|
last_uv->v.y = t;
|
|
last_uv->next = NULL;
|
|
}
|
|
|
|
void glArrayElement(GLint i) {
|
|
#ifndef SKIP_ERROR_HANDLING
|
|
// Error handling
|
|
if (i < 0) {
|
|
SET_GL_ERROR(GL_INVALID_VALUE)
|
|
}
|
|
#endif
|
|
|
|
// Aliasing client texture unit for better code readability
|
|
texture_unit *tex_unit = &texture_units[client_texture_unit];
|
|
|
|
// Checking if current texture unit has GL_VERTEX_ARRAY enabled
|
|
if (tex_unit->vertex_array_state) {
|
|
// Calculating offset of requested element
|
|
uint8_t *ptr;
|
|
if (tex_unit->vertex_array.stride == 0)
|
|
ptr = ((uint8_t *)tex_unit->vertex_array.pointer) + (i * (tex_unit->vertex_array.num * tex_unit->vertex_array.size));
|
|
else
|
|
ptr = ((uint8_t *)tex_unit->vertex_array.pointer) + (i * tex_unit->vertex_array.stride);
|
|
|
|
// Adding a new element to vertex and color lists
|
|
if (model_vertices == NULL) {
|
|
model_vertices = last_vert = (vertexList *)malloc(sizeof(vertexList));
|
|
model_color = last_clr = (rgbaList *)malloc(sizeof(rgbaList));
|
|
} else {
|
|
last_vert->next = (vertexList *)malloc(sizeof(vertexList));
|
|
last_clr->next = (rgbaList *)malloc(sizeof(rgbaList));
|
|
last_vert = last_vert->next;
|
|
last_clr = last_clr->next;
|
|
}
|
|
last_vert->next = NULL;
|
|
last_clr->next = NULL;
|
|
|
|
// Populating new vertex element
|
|
memcpy_neon(&last_vert->v, ptr, tex_unit->vertex_array.size * tex_unit->vertex_array.num);
|
|
|
|
// Checking if current texture unit has GL_COLOR_ARRAY enabled
|
|
if (tex_unit->color_array_state) {
|
|
// Calculating offset of requested element
|
|
uint8_t *ptr_clr;
|
|
if (tex_unit->color_array.stride == 0)
|
|
ptr_clr = ((uint8_t *)tex_unit->color_array.pointer) + (i * (tex_unit->color_array.num * tex_unit->color_array.size));
|
|
else
|
|
ptr_clr = ((uint8_t *)tex_unit->color_array.pointer) + (i * tex_unit->color_array.stride);
|
|
|
|
// Populating new color element
|
|
last_clr->v.a = 1.0f;
|
|
memcpy_neon(&last_clr->v, ptr_clr, tex_unit->color_array.size * tex_unit->color_array.num);
|
|
|
|
} else {
|
|
// Populating new color element with current color
|
|
memcpy_neon(&last_clr->v, ¤t_color.r, sizeof(vector4f));
|
|
}
|
|
|
|
// Checking if current texture unit has GL_TEXTURE_COORD_ARRAY enabled
|
|
if (tex_unit->texture_array_state) {
|
|
// Calculating offset of requested element
|
|
uint8_t *ptr_tex;
|
|
if (tex_unit->texture_array.stride == 0)
|
|
ptr_tex = ((uint8_t *)tex_unit->texture_array.pointer) + (i * (tex_unit->texture_array.num * tex_unit->texture_array.size));
|
|
else
|
|
ptr_tex = ((uint8_t *)tex_unit->texture_array.pointer) + (i * tex_unit->texture_array.stride);
|
|
|
|
// Adding a new element to texcoord list
|
|
if (model_uv == NULL) {
|
|
model_uv = last_uv = (uvList *)malloc(sizeof(uvList));
|
|
} else {
|
|
last_uv->next = (uvList *)malloc(sizeof(uvList));
|
|
last_uv = last_uv->next;
|
|
}
|
|
|
|
// Populating new texcoord element
|
|
memcpy_neon(&last_uv->v, ptr_tex, tex_unit->vertex_array.size * 2);
|
|
last_uv->next = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
void glBegin(GLenum mode) {
|
|
#ifndef SKIP_ERROR_HANDLING
|
|
// Error handling
|
|
if (phase == MODEL_CREATION) {
|
|
SET_GL_ERROR(GL_INVALID_OPERATION)
|
|
}
|
|
#endif
|
|
|
|
// Changing current openGL machine state
|
|
phase = MODEL_CREATION;
|
|
|
|
// Translating primitive to sceGxm one
|
|
prim_extra = SCE_GXM_PRIMITIVE_NONE;
|
|
switch (mode) {
|
|
case GL_POINTS:
|
|
prim = SCE_GXM_PRIMITIVE_POINTS;
|
|
np = 1;
|
|
break;
|
|
case GL_LINES:
|
|
prim = SCE_GXM_PRIMITIVE_LINES;
|
|
np = 2;
|
|
break;
|
|
case GL_TRIANGLES:
|
|
prim = SCE_GXM_PRIMITIVE_TRIANGLES;
|
|
np = 3;
|
|
break;
|
|
case GL_TRIANGLE_STRIP:
|
|
prim = SCE_GXM_PRIMITIVE_TRIANGLE_STRIP;
|
|
np = 1;
|
|
break;
|
|
case GL_TRIANGLE_FAN:
|
|
prim = SCE_GXM_PRIMITIVE_TRIANGLE_FAN;
|
|
np = 1;
|
|
break;
|
|
case GL_QUADS:
|
|
prim = SCE_GXM_PRIMITIVE_TRIANGLES;
|
|
prim_extra = SCE_GXM_PRIMITIVE_QUADS;
|
|
np = 4;
|
|
break;
|
|
default:
|
|
SET_GL_ERROR(GL_INVALID_ENUM)
|
|
break;
|
|
}
|
|
|
|
// Resetting vertex count
|
|
vertex_count = 0;
|
|
}
|
|
|
|
void glEnd(void) {
|
|
#ifndef SKIP_ERROR_HANDLING
|
|
// Integrity checks
|
|
if (vertex_count == 0 || ((vertex_count % np) != 0))
|
|
return;
|
|
|
|
// Error handling
|
|
if (phase != MODEL_CREATION) {
|
|
SET_GL_ERROR(GL_INVALID_OPERATION)
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
// Changing current openGL machine state
|
|
phase = NONE;
|
|
|
|
// Checking if we can totally skip drawing cause of culling mode
|
|
if (no_polygons_mode && ((prim == SCE_GXM_PRIMITIVE_TRIANGLES) || (prim >= SCE_GXM_PRIMITIVE_TRIANGLE_STRIP))) {
|
|
purge_vertex_list();
|
|
vertex_count = 0;
|
|
return;
|
|
}
|
|
|
|
// Aliasing server texture unit and texture id for better code readability
|
|
texture_unit *tex_unit = &texture_units[server_texture_unit];
|
|
int texture2d_idx = tex_unit->tex_id;
|
|
|
|
// Calculating mvp matrix
|
|
if (mvp_modified) {
|
|
matrix4x4_multiply(mvp_matrix, projection_matrix, modelview_matrix);
|
|
mvp_modified = GL_FALSE;
|
|
}
|
|
|
|
// Checking if we have to write a texture
|
|
if ((server_texture_unit >= 0) && (tex_unit->enabled) && (model_uv != NULL) && (tex_unit->textures[texture2d_idx].valid)) {
|
|
// Setting proper vertex and fragment programs
|
|
sceGxmSetVertexProgram(gxm_context, texture2d_vertex_program_patched);
|
|
sceGxmSetFragmentProgram(gxm_context, texture2d_fragment_program_patched);
|
|
|
|
// Setting fragment uniforms for alpha test and texture environment
|
|
void *alpha_buffer;
|
|
sceGxmReserveFragmentDefaultUniformBuffer(gxm_context, &alpha_buffer);
|
|
sceGxmSetUniformDataF(alpha_buffer, texture2d_alpha_cut, 0, 1, &alpha_ref);
|
|
float alpha_operation = (float)alpha_op;
|
|
sceGxmSetUniformDataF(alpha_buffer, texture2d_alpha_op, 0, 1, &alpha_operation);
|
|
sceGxmSetUniformDataF(alpha_buffer, texture2d_tint_color, 0, 4, ¤t_color.r);
|
|
float tex_env = (float)tex_unit->env_mode;
|
|
sceGxmSetUniformDataF(alpha_buffer, texture2d_tex_env, 0, 1, &tex_env);
|
|
float fogmode = (float)internal_fog_mode;
|
|
sceGxmSetUniformDataF(alpha_buffer, texture2d_fog_mode, 0, 1, &fogmode);
|
|
sceGxmSetUniformDataF(alpha_buffer, texture2d_fog_color, 0, 4, &fog_color.r);
|
|
sceGxmSetUniformDataF(alpha_buffer, texture2d_tex_env_color, 0, 4, &texenv_color.r);
|
|
sceGxmSetUniformDataF(alpha_buffer, texture2d_fog_near, 0, 1, (const float *)&fog_near);
|
|
sceGxmSetUniformDataF(alpha_buffer, texture2d_fog_far, 0, 1, (const float *)&fog_far);
|
|
sceGxmSetUniformDataF(alpha_buffer, texture2d_fog_density, 0, 1, (const float *)&fog_density);
|
|
|
|
} else {
|
|
// Setting proper vertex and fragment programs
|
|
sceGxmSetVertexProgram(gxm_context, rgba_vertex_program_patched);
|
|
sceGxmSetFragmentProgram(gxm_context, rgba_fragment_program_patched);
|
|
}
|
|
|
|
// Reserving default uniform buffer for wvp
|
|
int i, j;
|
|
void *vertex_wvp_buffer;
|
|
sceGxmReserveVertexDefaultUniformBuffer(gxm_context, &vertex_wvp_buffer);
|
|
|
|
// Checking if we have to write a texture
|
|
if (model_uv != NULL) {
|
|
// Setting wvp matrix
|
|
sceGxmSetUniformDataF(vertex_wvp_buffer, texture2d_wvp, 0, 16, (const float *)mvp_matrix);
|
|
|
|
// Setting fogging uniforms
|
|
float clipplane0 = (float)clip_plane0;
|
|
sceGxmSetUniformDataF(vertex_wvp_buffer, texture2d_clip_plane0, 0, 1, &clipplane0);
|
|
sceGxmSetUniformDataF(vertex_wvp_buffer, texture2d_clip_plane0_eq, 0, 4, &clip_plane0_eq.x);
|
|
sceGxmSetUniformDataF(vertex_wvp_buffer, texture2d_mv, 0, 16, (const float *)modelview_matrix);
|
|
|
|
// Setting in use texture
|
|
sceGxmSetFragmentTexture(gxm_context, 0, &tex_unit->textures[texture2d_idx].gxm_tex);
|
|
|
|
// Properly generating vertices, uv map and indices buffers
|
|
vector3f *vertices;
|
|
vector2f *uv_map;
|
|
uint16_t *indices;
|
|
int n = 0, quad_n = 0;
|
|
vertexList *object = model_vertices;
|
|
uvList *object_uv = model_uv;
|
|
uint64_t idx_count = vertex_count;
|
|
switch (prim_extra) {
|
|
case SCE_GXM_PRIMITIVE_NONE:
|
|
vertices = (vector3f *)gpu_pool_memalign(vertex_count * sizeof(vector3f), sizeof(vector3f));
|
|
uv_map = (vector2f *)gpu_pool_memalign(vertex_count * sizeof(vector2f), sizeof(vector2f));
|
|
memset(vertices, 0, (vertex_count * sizeof(vector3f)));
|
|
indices = (uint16_t *)gpu_pool_memalign(idx_count * sizeof(uint16_t), sizeof(uint16_t));
|
|
for (i = 0; i < vertex_count; i++) {
|
|
memcpy_neon(&vertices[n], &object->v, sizeof(vector3f));
|
|
memcpy_neon(&uv_map[n], &object_uv->v, sizeof(vector2f));
|
|
indices[n] = n;
|
|
object = object->next;
|
|
object_uv = object_uv->next;
|
|
n++;
|
|
}
|
|
break;
|
|
case SCE_GXM_PRIMITIVE_QUADS:
|
|
quad_n = vertex_count >> 2;
|
|
idx_count = quad_n * 6;
|
|
vertices = (vector3f *)gpu_pool_memalign(vertex_count * sizeof(vector3f), sizeof(vector3f));
|
|
uv_map = (vector2f *)gpu_pool_memalign(vertex_count * sizeof(vector2f), sizeof(vector2f));
|
|
memset(vertices, 0, (vertex_count * sizeof(vector3f)));
|
|
indices = (uint16_t *)gpu_pool_memalign(idx_count * sizeof(uint16_t), sizeof(uint16_t));
|
|
for (i = 0; i < quad_n; i++) {
|
|
indices[i * 6] = i * 4;
|
|
indices[i * 6 + 1] = i * 4 + 1;
|
|
indices[i * 6 + 2] = i * 4 + 3;
|
|
indices[i * 6 + 3] = i * 4 + 1;
|
|
indices[i * 6 + 4] = i * 4 + 2;
|
|
indices[i * 6 + 5] = i * 4 + 3;
|
|
}
|
|
for (j = 0; j < vertex_count; j++) {
|
|
memcpy_neon(&vertices[j], &object->v, sizeof(vector3f));
|
|
memcpy_neon(&uv_map[j], &object_uv->v, sizeof(vector2f));
|
|
object = object->next;
|
|
object_uv = object_uv->next;
|
|
}
|
|
break;
|
|
}
|
|
|
|
// Performing the requested draw call
|
|
sceGxmSetVertexStream(gxm_context, 0, vertices);
|
|
sceGxmSetVertexStream(gxm_context, 1, uv_map);
|
|
sceGxmDraw(gxm_context, prim, SCE_GXM_INDEX_FORMAT_U16, indices, idx_count);
|
|
|
|
} else {
|
|
// Setting wvp matrix
|
|
sceGxmSetUniformDataF(vertex_wvp_buffer, rgba_wvp, 0, 16, (const float *)mvp_matrix);
|
|
|
|
// Properly generating vertices, colors and indices buffers
|
|
vector3f *vertices;
|
|
vector4f *colors;
|
|
uint16_t *indices;
|
|
int n = 0, quad_n = 0;
|
|
vertexList *object = model_vertices;
|
|
rgbaList *object_clr = model_color;
|
|
uint64_t idx_count = vertex_count;
|
|
switch (prim_extra) {
|
|
case SCE_GXM_PRIMITIVE_NONE:
|
|
vertices = (vector3f *)gpu_pool_memalign(vertex_count * sizeof(vector3f), sizeof(vector3f));
|
|
colors = (vector4f *)gpu_pool_memalign(vertex_count * sizeof(vector4f), sizeof(vector4f));
|
|
memset(vertices, 0, (vertex_count * sizeof(vector3f)));
|
|
indices = (uint16_t *)gpu_pool_memalign(idx_count * sizeof(uint16_t), sizeof(uint16_t));
|
|
for (i = 0; i < vertex_count; i++) {
|
|
memcpy_neon(&vertices[n], &object->v, sizeof(vector3f));
|
|
memcpy_neon(&colors[n], &object_clr->v, sizeof(vector4f));
|
|
indices[n] = n;
|
|
object = object->next;
|
|
object_clr = object_clr->next;
|
|
n++;
|
|
}
|
|
break;
|
|
case SCE_GXM_PRIMITIVE_QUADS:
|
|
quad_n = vertex_count >> 2;
|
|
idx_count = quad_n * 6;
|
|
vertices = (vector3f *)gpu_pool_memalign(vertex_count * sizeof(vector3f), sizeof(vector3f));
|
|
colors = (vector4f *)gpu_pool_memalign(vertex_count * sizeof(vector4f), sizeof(vector4f));
|
|
memset(vertices, 0, (vertex_count * sizeof(vector3f)));
|
|
indices = (uint16_t *)gpu_pool_memalign(idx_count * sizeof(uint16_t), sizeof(uint16_t));
|
|
int i, j;
|
|
for (i = 0; i < quad_n; i++) {
|
|
indices[i * 6] = i * 4;
|
|
indices[i * 6 + 1] = i * 4 + 1;
|
|
indices[i * 6 + 2] = i * 4 + 3;
|
|
indices[i * 6 + 3] = i * 4 + 1;
|
|
indices[i * 6 + 4] = i * 4 + 2;
|
|
indices[i * 6 + 5] = i * 4 + 3;
|
|
}
|
|
for (j = 0; j < vertex_count; j++) {
|
|
memcpy_neon(&vertices[j], &object->v, sizeof(vector3f));
|
|
memcpy_neon(&colors[j], &object_clr->v, sizeof(vector4f));
|
|
object = object->next;
|
|
object_clr = object_clr->next;
|
|
}
|
|
break;
|
|
}
|
|
|
|
// Performing the requested draw call
|
|
sceGxmSetVertexStream(gxm_context, 0, vertices);
|
|
sceGxmSetVertexStream(gxm_context, 1, colors);
|
|
sceGxmDraw(gxm_context, prim, SCE_GXM_INDEX_FORMAT_U16, indices, idx_count);
|
|
}
|
|
|
|
// Purging vertex, colors and texcoord lists
|
|
purge_vertex_list();
|
|
vertex_count = 0;
|
|
}
|