RetroArch/source/vitaGL.c
Francisco José García García 8838992085 Squashed 'deps/vitaGL/' changes from 2934af8af0..81403e2751
81403e2751 Fix error requiring HAVE_SHARK to be enabled to build. (#45)
58551e1f52 Added possibility to change runtime shader compiler optimization flags.
77ab50a7b1 Added GL_BGR and GL_BGRA texture formats support.
0ac2793bcf Fix error in texture wrapping options. (#42)
0d2110ac7b Improvements to GL buffer support. (#41)
cf86149a85 Added proper compressed texture support. (#40)
8b0a0f735a Unbinded textures and texture units concepts.
1b04851efc Added glUniform2i and glUniform2f implementations.
9a65397ef6 Properly checking for uniform locations existence.
91c557f35d Added support for GL_SHORT attribute types for shaders.
3237fd3fe3 Added vglTexImageDepthBuffer function.
f58b3818f2 Typo fix on mag filter setting.
ee11f7e1d0 Added vglHasRuntimeShaderCompiler function.
3596242f73 Add PowerVR texture compression (PVRTC) support (#39)
2ae694df4b Added support for mipmaps filtering.
af7804b44c Added vglGetGxmTexture implementation.
54b1df4ca2 Removed unused arguments.
7c2ed742ee Allow to call vglBind*Location funcs with wrong param names.
8be84ff698 Fixed RGB565 color conversion.
234ff57f65 Properly setting a single stream with packed attributes.
d3b28a5e32 Fix for correct vglBindAttribLocation behaviour.
46e72d3564 Use a single stream for packed attributes.
72a39315e9 Properly dealing with missing attrs in glGetUniformLocation.
a6269ce574 Added TEXUNIT1 support for custom shaders.
824d43073e Resetting custom shaders uniforms only when invalidated.
d242570161 Minor fix in glShaderSource.
bc28bd946d Added glGetShaderInfoLog implementation.

git-subtree-dir: deps/vitaGL
git-subtree-split: 81403e2751c4dc28cf17cc89a5ab053eb2c5af67
2020-10-16 20:24:43 +02:00

2248 lines
85 KiB
C

/*
* This file is part of vitaGL
* Copyright 2017, 2018, 2019, 2020 Rinnegatamante
* Copyright 2020 Asakura Reiko
*
* 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/>.
*/
/*
*
*/
#include "vitaGL.h"
#include "shared.h"
#include "texture_callbacks.h"
// Shaders
#include "shaders/clear_f.h"
#include "shaders/clear_v.h"
#include "shaders/disable_color_buffer_f.h"
#include "shaders/rgb_v.h"
#include "shaders/rgba_f.h"
#include "shaders/rgba_v.h"
#include "shaders/texture2d_f.h"
#include "shaders/texture2d_rgba_f.h"
#include "shaders/texture2d_rgba_v.h"
#include "shaders/texture2d_v.h"
// Disable color buffer shader
SceGxmShaderPatcherId disable_color_buffer_fragment_id;
const SceGxmProgramParameter *disable_color_buffer_position;
SceGxmFragmentProgram *disable_color_buffer_fragment_program_patched;
const SceGxmProgramParameter *clear_depth;
// Clear shader
SceGxmShaderPatcherId clear_vertex_id;
SceGxmShaderPatcherId clear_fragment_id;
const SceGxmProgramParameter *clear_position;
const SceGxmProgramParameter *clear_color;
SceGxmVertexProgram *clear_vertex_program_patched;
SceGxmFragmentProgram *clear_fragment_program_patched;
// Color (RGBA/RGB) shader
SceGxmShaderPatcherId rgba_vertex_id;
SceGxmShaderPatcherId rgb_vertex_id;
SceGxmShaderPatcherId rgba_fragment_id;
const SceGxmProgramParameter *rgba_position;
const SceGxmProgramParameter *rgba_color;
const SceGxmProgramParameter *rgba_wvp;
const SceGxmProgramParameter *rgb_position;
const SceGxmProgramParameter *rgb_color;
const SceGxmProgramParameter *rgb_wvp;
SceGxmVertexProgram *rgba_vertex_program_patched;
SceGxmVertexProgram *rgba_u8n_vertex_program_patched;
SceGxmVertexProgram *rgb_vertex_program_patched;
SceGxmVertexProgram *rgb_u8n_vertex_program_patched;
SceGxmFragmentProgram *rgba_fragment_program_patched;
const SceGxmProgram *rgba_fragment_program;
// Texture2D shader
SceGxmShaderPatcherId texture2d_vertex_id;
SceGxmShaderPatcherId texture2d_fragment_id;
const SceGxmProgramParameter *texture2d_position;
const SceGxmProgramParameter *texture2d_texcoord;
const SceGxmProgramParameter *texture2d_wvp;
const SceGxmProgramParameter *texture2d_alpha_cut;
const SceGxmProgramParameter *texture2d_alpha_op;
const SceGxmProgramParameter *texture2d_tint_color;
const SceGxmProgramParameter *texture2d_tex_env;
const SceGxmProgramParameter *texture2d_clip_plane0;
const SceGxmProgramParameter *texture2d_clip_plane0_eq;
const SceGxmProgramParameter *texture2d_mv;
const SceGxmProgramParameter *texture2d_fog_mode;
const SceGxmProgramParameter *texture2d_fog_near;
const SceGxmProgramParameter *texture2d_fog_far;
const SceGxmProgramParameter *texture2d_fog_density;
const SceGxmProgramParameter *texture2d_fog_color;
const SceGxmProgramParameter *texture2d_tex_env_color;
SceGxmVertexProgram *texture2d_vertex_program_patched;
SceGxmFragmentProgram *texture2d_fragment_program_patched;
const SceGxmProgram *texture2d_fragment_program;
// Texture2D+RGBA shader
SceGxmShaderPatcherId texture2d_rgba_vertex_id;
SceGxmShaderPatcherId texture2d_rgba_fragment_id;
const SceGxmProgramParameter *texture2d_rgba_position;
const SceGxmProgramParameter *texture2d_rgba_texcoord;
const SceGxmProgramParameter *texture2d_rgba_wvp;
const SceGxmProgramParameter *texture2d_rgba_alpha_cut;
const SceGxmProgramParameter *texture2d_rgba_alpha_op;
const SceGxmProgramParameter *texture2d_rgba_color;
const SceGxmProgramParameter *texture2d_rgba_tex_env;
const SceGxmProgramParameter *texture2d_rgba_clip_plane0;
const SceGxmProgramParameter *texture2d_rgba_clip_plane0_eq;
const SceGxmProgramParameter *texture2d_rgba_mv;
const SceGxmProgramParameter *texture2d_rgba_fog_mode;
const SceGxmProgramParameter *texture2d_rgba_fog_near;
const SceGxmProgramParameter *texture2d_rgba_fog_far;
const SceGxmProgramParameter *texture2d_rgba_fog_density;
const SceGxmProgramParameter *texture2d_rgba_fog_color;
const SceGxmProgramParameter *texture2d_rgba_tex_env_color;
SceGxmVertexProgram *texture2d_rgba_vertex_program_patched;
SceGxmVertexProgram *texture2d_rgba_u8n_vertex_program_patched;
SceGxmFragmentProgram *texture2d_rgba_fragment_program_patched;
const SceGxmProgram *texture2d_rgba_fragment_program;
typedef struct gpubuffer {
void *ptr;
int32_t size;
} gpubuffer;
// sceGxm viewport setup (NOTE: origin is on center screen)
float x_port = 480.0f;
float y_port = 272.0f;
float z_port = 0.5f;
float x_scale = 480.0f;
float y_scale = -272.0f;
float z_scale = 0.5f;
// Fullscreen sceGxm viewport (NOTE: origin is on center screen)
float fullscreen_x_port = 480.0f;
float fullscreen_y_port = 272.0f;
float fullscreen_z_port = 0.5f;
float fullscreen_x_scale = 480.0f;
float fullscreen_y_scale = -272.0f;
float fullscreen_z_scale = 0.5f;
GLboolean vblank = GL_TRUE; // Current setting for VSync
extern int _newlib_heap_memblock; // Newlib Heap memblock
extern unsigned _newlib_heap_size; // Newlib Heap size
static const SceGxmProgram *const gxm_program_disable_color_buffer_f = (SceGxmProgram *)&disable_color_buffer_f;
static const SceGxmProgram *const gxm_program_clear_v = (SceGxmProgram *)&clear_v;
static const SceGxmProgram *const gxm_program_clear_f = (SceGxmProgram *)&clear_f;
static const SceGxmProgram *const gxm_program_rgba_v = (SceGxmProgram *)&rgba_v;
static const SceGxmProgram *const gxm_program_rgba_f = (SceGxmProgram *)&rgba_f;
static const SceGxmProgram *const gxm_program_rgb_v = (SceGxmProgram *)&rgb_v;
static const SceGxmProgram *const gxm_program_texture2d_v = (SceGxmProgram *)&texture2d_v;
static const SceGxmProgram *const gxm_program_texture2d_f = (SceGxmProgram *)&texture2d_f;
static const SceGxmProgram *const gxm_program_texture2d_rgba_v = (SceGxmProgram *)&texture2d_rgba_v;
static const SceGxmProgram *const gxm_program_texture2d_rgba_f = (SceGxmProgram *)&texture2d_rgba_f;
// Disable color buffer shader
uint16_t *depth_clear_indices = NULL; // Memblock starting address for clear screen indices
// Clear shaders
SceGxmVertexProgram *clear_vertex_program_patched; // Patched vertex program for clearing screen
vector4f *clear_vertices = NULL; // Memblock starting address for clear screen vertices
vector3f *depth_vertices = NULL; // Memblock starting address for depth clear screen vertices
// Internal stuffs
SceGxmMultisampleMode msaa_mode = SCE_GXM_MULTISAMPLE_NONE;
extern uint8_t use_vram;
extern uint8_t use_vram_for_usse;
static GLuint buffers[BUFFERS_NUM]; // Buffers array
static gpubuffer gpu_buffers[BUFFERS_NUM]; // Buffers array
static SceGxmColorMask blend_color_mask = SCE_GXM_COLOR_MASK_ALL; // Current in-use color mask (glColorMask)
static SceGxmBlendFunc blend_func_rgb = SCE_GXM_BLEND_FUNC_ADD; // Current in-use RGB blend func
static SceGxmBlendFunc blend_func_a = SCE_GXM_BLEND_FUNC_ADD; // Current in-use A blend func
static int vertex_array_unit = -1; // Current in-use vertex array unit
static int index_array_unit = -1; // Current in-use index array unit
vector4f texenv_color = { 0.0f, 0.0f, 0.0f, 0.0f }; // Current in use texture environment color
// Internal functions
#ifdef ENABLE_LOG
void LOG(const char *format, ...) {
__gnuc_va_list arg;
int done;
va_start(arg, format);
char msg[512];
done = vsprintf(msg, format, arg);
va_end(arg);
int i;
sprintf(msg, "%s\n", msg);
FILE *log = fopen("ux0:/data/vitaGL.log", "a+");
if (log != NULL) {
fwrite(msg, 1, strlen(msg), log);
fclose(log);
}
}
#endif
static void _change_blend_factor(SceGxmBlendInfo *blend_info) {
changeCustomShadersBlend(blend_info);
sceGxmShaderPatcherCreateFragmentProgram(gxm_shader_patcher,
rgba_fragment_id,
SCE_GXM_OUTPUT_REGISTER_FORMAT_UCHAR4,
msaa_mode,
blend_info,
NULL,
&rgba_fragment_program_patched);
sceGxmShaderPatcherCreateFragmentProgram(gxm_shader_patcher,
texture2d_fragment_id,
SCE_GXM_OUTPUT_REGISTER_FORMAT_UCHAR4,
msaa_mode,
blend_info,
NULL,
&texture2d_fragment_program_patched);
sceGxmShaderPatcherCreateFragmentProgram(gxm_shader_patcher,
texture2d_rgba_fragment_id,
SCE_GXM_OUTPUT_REGISTER_FORMAT_UCHAR4,
msaa_mode,
blend_info,
NULL,
&texture2d_rgba_fragment_program_patched);
}
void change_blend_factor() {
static SceGxmBlendInfo blend_info;
blend_info.colorMask = blend_color_mask;
blend_info.colorFunc = blend_func_rgb;
blend_info.alphaFunc = blend_func_a;
blend_info.colorSrc = blend_sfactor_rgb;
blend_info.colorDst = blend_dfactor_rgb;
blend_info.alphaSrc = blend_sfactor_a;
blend_info.alphaDst = blend_dfactor_a;
_change_blend_factor(&blend_info);
if (cur_program != 0) {
reloadCustomShader();
}
}
void change_blend_mask() {
static SceGxmBlendInfo blend_info;
blend_info.colorMask = blend_color_mask;
blend_info.colorFunc = SCE_GXM_BLEND_FUNC_NONE;
blend_info.alphaFunc = SCE_GXM_BLEND_FUNC_NONE;
blend_info.colorSrc = SCE_GXM_BLEND_FACTOR_SRC_ALPHA;
blend_info.colorDst = SCE_GXM_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
blend_info.alphaSrc = SCE_GXM_BLEND_FACTOR_ONE;
blend_info.alphaDst = SCE_GXM_BLEND_FACTOR_ZERO;
_change_blend_factor(&blend_info);
if (cur_program != 0) {
reloadCustomShader();
}
}
void disable_blend() {
if (blend_color_mask == SCE_GXM_COLOR_MASK_ALL) {
_change_blend_factor(NULL);
if (cur_program != 0) {
reloadCustomShader();
}
} else
change_blend_mask();
}
void vector4f_convert_to_local_space(vector4f *out, int x, int y, int width, int height) {
out[0].x = (float)(2 * x) / DISPLAY_WIDTH_FLOAT - 1.0f;
out[0].y = (float)(2 * (x + width)) / DISPLAY_WIDTH_FLOAT - 1.0f;
out[0].z = 1.0f - (float)(2 * y) / DISPLAY_HEIGHT_FLOAT;
out[0].w = 1.0f - (float)(2 * (y + height)) / DISPLAY_HEIGHT_FLOAT;
}
// vitaGL specific functions
void vglUseVram(GLboolean usage) {
use_vram = usage;
}
void vglUseVramForUSSE(GLboolean usage) {
use_vram_for_usse = usage;
}
void vglInitWithCustomSizes(uint32_t gpu_pool_size, int width, int height, int ram_pool_size, int cdram_pool_size, int phycont_pool_size, SceGxmMultisampleMode msaa) {
// Setting our display size
msaa_mode = msaa;
DISPLAY_WIDTH = width;
DISPLAY_HEIGHT = height;
DISPLAY_WIDTH_FLOAT = width * 1.0f;
DISPLAY_HEIGHT_FLOAT = height * 1.0f;
DISPLAY_STRIDE = ALIGN(DISPLAY_WIDTH, 64);
// Adjusting default values for internal viewport
x_port = DISPLAY_WIDTH_FLOAT / 2.0f;
x_scale = x_port;
y_scale = -(DISPLAY_HEIGHT_FLOAT / 2.0f);
y_port = -y_scale;
fullscreen_x_port = x_port;
fullscreen_x_scale = x_scale;
fullscreen_y_port = y_port;
fullscreen_y_scale = y_scale;
// Init viewport state
gl_viewport.x = 0;
gl_viewport.y = 0;
gl_viewport.w = DISPLAY_WIDTH;
gl_viewport.h = DISPLAY_HEIGHT;
// Initializing sceGxm
initGxm();
// Initializing memory heap for CDRAM and RAM memory
mem_init(ram_pool_size, cdram_pool_size, phycont_pool_size);
// Initializing sceGxm context
initGxmContext();
// Creating render target for the display
createDisplayRenderTarget();
// Creating color surfaces for the display
initDisplayColorSurfaces();
// Creating depth and stencil surfaces for the display
initDepthStencilSurfaces();
// Starting a sceGxmShaderPatcher instance
startShaderPatcher();
// Disable color buffer shader register
sceGxmShaderPatcherRegisterProgram(gxm_shader_patcher, gxm_program_disable_color_buffer_f,
&disable_color_buffer_fragment_id);
const SceGxmProgram *disable_color_buffer_fragment_program = sceGxmShaderPatcherGetProgramFromId(disable_color_buffer_fragment_id);
clear_depth = sceGxmProgramFindParameterByName(
disable_color_buffer_fragment_program, "depth_clear");
SceGxmBlendInfo disable_color_buffer_blend_info;
memset(&disable_color_buffer_blend_info, 0, sizeof(SceGxmBlendInfo));
disable_color_buffer_blend_info.colorMask = SCE_GXM_COLOR_MASK_NONE;
disable_color_buffer_blend_info.colorFunc = SCE_GXM_BLEND_FUNC_NONE;
disable_color_buffer_blend_info.alphaFunc = SCE_GXM_BLEND_FUNC_NONE;
disable_color_buffer_blend_info.colorSrc = SCE_GXM_BLEND_FACTOR_ZERO;
disable_color_buffer_blend_info.colorDst = SCE_GXM_BLEND_FACTOR_ZERO;
disable_color_buffer_blend_info.alphaSrc = SCE_GXM_BLEND_FACTOR_ZERO;
disable_color_buffer_blend_info.alphaDst = SCE_GXM_BLEND_FACTOR_ZERO;
sceGxmShaderPatcherCreateFragmentProgram(gxm_shader_patcher,
disable_color_buffer_fragment_id,
SCE_GXM_OUTPUT_REGISTER_FORMAT_UCHAR4,
msaa,
&disable_color_buffer_blend_info, NULL,
&disable_color_buffer_fragment_program_patched);
vglMemType type = VGL_MEM_RAM;
clear_vertices = gpu_alloc_mapped(1 * sizeof(vector4f), &type);
depth_clear_indices = gpu_alloc_mapped(4 * sizeof(unsigned short), &type);
vector4f_convert_to_local_space(clear_vertices, 0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT);
depth_clear_indices[0] = 0;
depth_clear_indices[1] = 1;
depth_clear_indices[2] = 2;
depth_clear_indices[3] = 3;
// Clear shader register
sceGxmShaderPatcherRegisterProgram(gxm_shader_patcher, gxm_program_clear_v,
&clear_vertex_id);
sceGxmShaderPatcherRegisterProgram(gxm_shader_patcher, gxm_program_clear_f,
&clear_fragment_id);
const SceGxmProgram *clear_vertex_program = sceGxmShaderPatcherGetProgramFromId(clear_vertex_id);
const SceGxmProgram *clear_fragment_program = sceGxmShaderPatcherGetProgramFromId(clear_fragment_id);
clear_position = sceGxmProgramFindParameterByName(
clear_vertex_program, "position");
clear_color = sceGxmProgramFindParameterByName(
clear_fragment_program, "u_clear_color");
sceGxmShaderPatcherCreateVertexProgram(gxm_shader_patcher,
clear_vertex_id, NULL, 0, NULL, 0, &clear_vertex_program_patched);
sceGxmShaderPatcherCreateFragmentProgram(gxm_shader_patcher,
clear_fragment_id, SCE_GXM_OUTPUT_REGISTER_FORMAT_UCHAR4,
msaa, NULL, NULL,
&clear_fragment_program_patched);
// Color shader register
sceGxmShaderPatcherRegisterProgram(gxm_shader_patcher, gxm_program_rgba_v,
&rgba_vertex_id);
sceGxmShaderPatcherRegisterProgram(gxm_shader_patcher, gxm_program_rgb_v,
&rgb_vertex_id);
sceGxmShaderPatcherRegisterProgram(gxm_shader_patcher, gxm_program_rgba_f,
&rgba_fragment_id);
const SceGxmProgram *rgba_vertex_program = sceGxmShaderPatcherGetProgramFromId(rgba_vertex_id);
const SceGxmProgram *rgb_vertex_program = sceGxmShaderPatcherGetProgramFromId(rgb_vertex_id);
rgba_fragment_program = sceGxmShaderPatcherGetProgramFromId(rgba_fragment_id);
rgba_position = sceGxmProgramFindParameterByName(
rgba_vertex_program, "aPosition");
rgba_color = sceGxmProgramFindParameterByName(
rgba_vertex_program, "aColor");
rgb_position = sceGxmProgramFindParameterByName(
rgba_vertex_program, "aPosition");
rgb_color = sceGxmProgramFindParameterByName(
rgba_vertex_program, "aColor");
SceGxmVertexAttribute rgba_vertex_attribute[2];
SceGxmVertexStream rgba_vertex_stream[2];
rgba_vertex_attribute[0].streamIndex = 0;
rgba_vertex_attribute[0].offset = 0;
rgba_vertex_attribute[0].format = SCE_GXM_ATTRIBUTE_FORMAT_F32;
rgba_vertex_attribute[0].componentCount = 3;
rgba_vertex_attribute[0].regIndex = sceGxmProgramParameterGetResourceIndex(
rgba_position);
rgba_vertex_attribute[1].streamIndex = 1;
rgba_vertex_attribute[1].offset = 0;
rgba_vertex_attribute[1].format = SCE_GXM_ATTRIBUTE_FORMAT_F32;
rgba_vertex_attribute[1].componentCount = 4;
rgba_vertex_attribute[1].regIndex = sceGxmProgramParameterGetResourceIndex(
rgba_color);
rgba_vertex_stream[0].stride = sizeof(vector3f);
rgba_vertex_stream[0].indexSource = SCE_GXM_INDEX_SOURCE_INDEX_16BIT;
rgba_vertex_stream[1].stride = sizeof(vector4f);
rgba_vertex_stream[1].indexSource = SCE_GXM_INDEX_SOURCE_INDEX_16BIT;
sceGxmShaderPatcherCreateVertexProgram(gxm_shader_patcher,
rgba_vertex_id, rgba_vertex_attribute,
2, rgba_vertex_stream, 2, &rgba_vertex_program_patched);
rgba_vertex_attribute[1].format = SCE_GXM_ATTRIBUTE_FORMAT_U8N;
rgba_vertex_stream[1].stride = sizeof(uint8_t) * 4;
sceGxmShaderPatcherCreateVertexProgram(gxm_shader_patcher,
rgba_vertex_id, rgba_vertex_attribute,
2, rgba_vertex_stream, 2, &rgba_u8n_vertex_program_patched);
SceGxmVertexAttribute rgb_vertex_attribute[2];
SceGxmVertexStream rgb_vertex_stream[2];
rgb_vertex_attribute[0].streamIndex = 0;
rgb_vertex_attribute[0].offset = 0;
rgb_vertex_attribute[0].format = SCE_GXM_ATTRIBUTE_FORMAT_F32;
rgb_vertex_attribute[0].componentCount = 3;
rgb_vertex_attribute[0].regIndex = sceGxmProgramParameterGetResourceIndex(
rgb_position);
rgb_vertex_attribute[1].streamIndex = 1;
rgb_vertex_attribute[1].offset = 0;
rgb_vertex_attribute[1].format = SCE_GXM_ATTRIBUTE_FORMAT_F32;
rgb_vertex_attribute[1].componentCount = 3;
rgb_vertex_attribute[1].regIndex = sceGxmProgramParameterGetResourceIndex(
rgb_color);
rgb_vertex_stream[0].stride = sizeof(vector3f);
rgb_vertex_stream[0].indexSource = SCE_GXM_INDEX_SOURCE_INDEX_16BIT;
rgb_vertex_stream[1].stride = sizeof(vector3f);
rgb_vertex_stream[1].indexSource = SCE_GXM_INDEX_SOURCE_INDEX_16BIT;
sceGxmShaderPatcherCreateVertexProgram(gxm_shader_patcher,
rgb_vertex_id, rgb_vertex_attribute,
2, rgb_vertex_stream, 2, &rgb_vertex_program_patched);
rgb_vertex_attribute[1].format = SCE_GXM_ATTRIBUTE_FORMAT_U8N;
rgb_vertex_stream[1].stride = sizeof(uint8_t) * 3;
sceGxmShaderPatcherCreateVertexProgram(gxm_shader_patcher,
rgb_vertex_id, rgb_vertex_attribute,
2, rgb_vertex_stream, 2, &rgb_u8n_vertex_program_patched);
sceGxmShaderPatcherCreateFragmentProgram(gxm_shader_patcher,
rgba_fragment_id, SCE_GXM_OUTPUT_REGISTER_FORMAT_UCHAR4,
msaa, NULL, NULL,
&rgba_fragment_program_patched);
rgba_wvp = sceGxmProgramFindParameterByName(rgba_vertex_program, "wvp");
rgb_wvp = sceGxmProgramFindParameterByName(rgb_vertex_program, "wvp");
// Texture2D shader register
sceGxmShaderPatcherRegisterProgram(gxm_shader_patcher, gxm_program_texture2d_v,
&texture2d_vertex_id);
sceGxmShaderPatcherRegisterProgram(gxm_shader_patcher, gxm_program_texture2d_f,
&texture2d_fragment_id);
const SceGxmProgram *texture2d_vertex_program = sceGxmShaderPatcherGetProgramFromId(texture2d_vertex_id);
texture2d_fragment_program = sceGxmShaderPatcherGetProgramFromId(texture2d_fragment_id);
texture2d_position = sceGxmProgramFindParameterByName(
texture2d_vertex_program, "position");
texture2d_texcoord = sceGxmProgramFindParameterByName(
texture2d_vertex_program, "texcoord");
texture2d_alpha_cut = sceGxmProgramFindParameterByName(
texture2d_fragment_program, "alphaCut");
texture2d_alpha_op = sceGxmProgramFindParameterByName(
texture2d_fragment_program, "alphaOp");
texture2d_tint_color = sceGxmProgramFindParameterByName(
texture2d_fragment_program, "tintColor");
texture2d_tex_env = sceGxmProgramFindParameterByName(
texture2d_fragment_program, "texEnv");
texture2d_fog_mode = sceGxmProgramFindParameterByName(
texture2d_fragment_program, "fog_mode");
texture2d_fog_color = sceGxmProgramFindParameterByName(
texture2d_fragment_program, "fogColor");
texture2d_clip_plane0 = sceGxmProgramFindParameterByName(
texture2d_vertex_program, "clip_plane0");
texture2d_clip_plane0_eq = sceGxmProgramFindParameterByName(
texture2d_vertex_program, "clip_plane0_eq");
texture2d_mv = sceGxmProgramFindParameterByName(
texture2d_vertex_program, "modelview");
texture2d_fog_near = sceGxmProgramFindParameterByName(
texture2d_fragment_program, "fog_near");
texture2d_fog_far = sceGxmProgramFindParameterByName(
texture2d_fragment_program, "fog_far");
texture2d_fog_density = sceGxmProgramFindParameterByName(
texture2d_fragment_program, "fog_density");
texture2d_tex_env_color = sceGxmProgramFindParameterByName(
texture2d_fragment_program, "texEnvColor");
SceGxmVertexAttribute texture2d_vertex_attribute[2];
SceGxmVertexStream texture2d_vertex_stream[2];
texture2d_vertex_attribute[0].streamIndex = 0;
texture2d_vertex_attribute[0].offset = 0;
texture2d_vertex_attribute[0].format = SCE_GXM_ATTRIBUTE_FORMAT_F32;
texture2d_vertex_attribute[0].componentCount = 3;
texture2d_vertex_attribute[0].regIndex = sceGxmProgramParameterGetResourceIndex(
texture2d_position);
texture2d_vertex_attribute[1].streamIndex = 1;
texture2d_vertex_attribute[1].offset = 0;
texture2d_vertex_attribute[1].format = SCE_GXM_ATTRIBUTE_FORMAT_F32;
texture2d_vertex_attribute[1].componentCount = 2;
texture2d_vertex_attribute[1].regIndex = sceGxmProgramParameterGetResourceIndex(
texture2d_texcoord);
texture2d_vertex_stream[0].stride = sizeof(vector3f);
texture2d_vertex_stream[0].indexSource = SCE_GXM_INDEX_SOURCE_INDEX_16BIT;
texture2d_vertex_stream[1].stride = sizeof(vector2f);
texture2d_vertex_stream[1].indexSource = SCE_GXM_INDEX_SOURCE_INDEX_16BIT;
sceGxmShaderPatcherCreateVertexProgram(gxm_shader_patcher,
texture2d_vertex_id, texture2d_vertex_attribute,
2, texture2d_vertex_stream, 2, &texture2d_vertex_program_patched);
sceGxmShaderPatcherCreateFragmentProgram(gxm_shader_patcher,
texture2d_fragment_id, SCE_GXM_OUTPUT_REGISTER_FORMAT_UCHAR4,
msaa, NULL, NULL,
&texture2d_fragment_program_patched);
texture2d_wvp = sceGxmProgramFindParameterByName(texture2d_vertex_program, "wvp");
// Texture2D+RGBA shader register
sceGxmShaderPatcherRegisterProgram(gxm_shader_patcher, gxm_program_texture2d_rgba_v,
&texture2d_rgba_vertex_id);
sceGxmShaderPatcherRegisterProgram(gxm_shader_patcher, gxm_program_texture2d_rgba_f,
&texture2d_rgba_fragment_id);
const SceGxmProgram *texture2d_rgba_vertex_program = sceGxmShaderPatcherGetProgramFromId(texture2d_rgba_vertex_id);
texture2d_rgba_fragment_program = sceGxmShaderPatcherGetProgramFromId(texture2d_rgba_fragment_id);
texture2d_rgba_position = sceGxmProgramFindParameterByName(
texture2d_rgba_vertex_program, "position");
texture2d_rgba_texcoord = sceGxmProgramFindParameterByName(
texture2d_rgba_vertex_program, "texcoord");
texture2d_rgba_alpha_cut = sceGxmProgramFindParameterByName(
texture2d_rgba_fragment_program, "alphaCut");
texture2d_rgba_alpha_op = sceGxmProgramFindParameterByName(
texture2d_rgba_fragment_program, "alphaOp");
texture2d_rgba_color = sceGxmProgramFindParameterByName(
texture2d_rgba_vertex_program, "color");
texture2d_rgba_tex_env = sceGxmProgramFindParameterByName(
texture2d_rgba_fragment_program, "texEnv");
texture2d_rgba_fog_mode = sceGxmProgramFindParameterByName(
texture2d_rgba_fragment_program, "fog_mode");
texture2d_rgba_clip_plane0 = sceGxmProgramFindParameterByName(
texture2d_rgba_vertex_program, "clip_plane0");
texture2d_rgba_clip_plane0_eq = sceGxmProgramFindParameterByName(
texture2d_rgba_vertex_program, "clip_plane0_eq");
texture2d_rgba_mv = sceGxmProgramFindParameterByName(
texture2d_rgba_vertex_program, "modelview");
texture2d_rgba_fog_near = sceGxmProgramFindParameterByName(
texture2d_rgba_fragment_program, "fog_near");
texture2d_rgba_fog_far = sceGxmProgramFindParameterByName(
texture2d_rgba_fragment_program, "fog_far");
texture2d_rgba_fog_density = sceGxmProgramFindParameterByName(
texture2d_rgba_fragment_program, "fog_density");
texture2d_rgba_fog_color = sceGxmProgramFindParameterByName(
texture2d_rgba_fragment_program, "fogColor");
texture2d_rgba_tex_env_color = sceGxmProgramFindParameterByName(
texture2d_rgba_fragment_program, "texEnvColor");
SceGxmVertexAttribute texture2d_rgba_vertex_attribute[3];
SceGxmVertexStream texture2d_rgba_vertex_stream[3];
texture2d_rgba_vertex_attribute[0].streamIndex = 0;
texture2d_rgba_vertex_attribute[0].offset = 0;
texture2d_rgba_vertex_attribute[0].format = SCE_GXM_ATTRIBUTE_FORMAT_F32;
texture2d_rgba_vertex_attribute[0].componentCount = 3;
texture2d_rgba_vertex_attribute[0].regIndex = sceGxmProgramParameterGetResourceIndex(
texture2d_rgba_position);
texture2d_rgba_vertex_attribute[1].streamIndex = 1;
texture2d_rgba_vertex_attribute[1].offset = 0;
texture2d_rgba_vertex_attribute[1].format = SCE_GXM_ATTRIBUTE_FORMAT_F32;
texture2d_rgba_vertex_attribute[1].componentCount = 2;
texture2d_rgba_vertex_attribute[1].regIndex = sceGxmProgramParameterGetResourceIndex(
texture2d_rgba_texcoord);
texture2d_rgba_vertex_attribute[2].streamIndex = 2;
texture2d_rgba_vertex_attribute[2].offset = 0;
texture2d_rgba_vertex_attribute[2].format = SCE_GXM_ATTRIBUTE_FORMAT_F32;
texture2d_rgba_vertex_attribute[2].componentCount = 4;
texture2d_rgba_vertex_attribute[2].regIndex = sceGxmProgramParameterGetResourceIndex(
texture2d_rgba_color);
texture2d_rgba_vertex_stream[0].stride = sizeof(vector3f);
texture2d_rgba_vertex_stream[0].indexSource = SCE_GXM_INDEX_SOURCE_INDEX_16BIT;
texture2d_rgba_vertex_stream[1].stride = sizeof(vector2f);
texture2d_rgba_vertex_stream[1].indexSource = SCE_GXM_INDEX_SOURCE_INDEX_16BIT;
texture2d_rgba_vertex_stream[2].stride = sizeof(vector4f);
texture2d_rgba_vertex_stream[2].indexSource = SCE_GXM_INDEX_SOURCE_INDEX_16BIT;
sceGxmShaderPatcherCreateVertexProgram(gxm_shader_patcher,
texture2d_rgba_vertex_id, texture2d_rgba_vertex_attribute,
3, texture2d_rgba_vertex_stream, 3, &texture2d_rgba_vertex_program_patched);
texture2d_rgba_vertex_attribute[2].format = SCE_GXM_ATTRIBUTE_FORMAT_U8N;
texture2d_rgba_vertex_stream[2].stride = sizeof(uint8_t) * 4;
sceGxmShaderPatcherCreateVertexProgram(gxm_shader_patcher,
texture2d_rgba_vertex_id, texture2d_rgba_vertex_attribute,
3, texture2d_rgba_vertex_stream, 3, &texture2d_rgba_u8n_vertex_program_patched);
sceGxmShaderPatcherCreateFragmentProgram(gxm_shader_patcher,
texture2d_rgba_fragment_id, SCE_GXM_OUTPUT_REGISTER_FORMAT_UCHAR4,
msaa, NULL, NULL,
&texture2d_rgba_fragment_program_patched);
texture2d_rgba_wvp = sceGxmProgramFindParameterByName(texture2d_rgba_vertex_program, "wvp");
sceGxmSetTwoSidedEnable(gxm_context, SCE_GXM_TWO_SIDED_ENABLED);
// Scissor Test shader register
sceGxmShaderPatcherCreateMaskUpdateFragmentProgram(gxm_shader_patcher, &scissor_test_fragment_program);
scissor_test_vertices = gpu_alloc_mapped(1 * sizeof(vector4f), &type);
// Allocate temp pool for non-VBO drawing
gpu_pool_init(gpu_pool_size);
// Init texture units
int i, j;
for (i = 0; i < GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS; i++) {
texture_units[i].env_mode = MODULATE;
texture_units[i].tex_id = 0;
texture_units[i].enabled = GL_FALSE;
texture_units[i].min_filter = SCE_GXM_TEXTURE_FILTER_LINEAR;
texture_units[i].mag_filter = SCE_GXM_TEXTURE_FILTER_LINEAR;
texture_units[i].mip_filter = SCE_GXM_TEXTURE_MIP_FILTER_DISABLED;
texture_units[i].u_mode = SCE_GXM_TEXTURE_ADDR_REPEAT;
texture_units[i].v_mode = SCE_GXM_TEXTURE_ADDR_REPEAT;
texture_units[i].lod_bias = GL_MAX_TEXTURE_LOD_BIAS; // sceGxm range is 0 - (GL_MAX_TEXTURE_LOD_BIAS*2 + 1)
}
// Init texture slots
for (j = 0; j < TEXTURES_NUM; j++) {
textures[j].used = 0;
textures[j].valid = 0;
}
// Init custom shaders
resetCustomShaders();
// Init buffers
for (i = 0; i < BUFFERS_NUM; i++) {
buffers[i] = BUFFERS_ADDR + i;
gpu_buffers[i].ptr = NULL;
}
// Init scissor test state
resetScissorTestRegion();
// Getting newlib heap memblock starting address
void *addr = NULL;
sceKernelGetMemBlockBase(_newlib_heap_memblock, &addr);
// Mapping newlib heap into sceGxm
sceGxmMapMemory(addr, _newlib_heap_size, SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_WRITE);
}
void vglInitExtended(uint32_t gpu_pool_size, int width, int height, int ram_threshold, SceGxmMultisampleMode msaa) {
// Initializing sceGxm
initGxm();
// Getting max allocatable CDRAM and RAM memory
if (system_app_mode) {
SceAppMgrBudgetInfo info;
info.size = sizeof(SceAppMgrBudgetInfo);
sceAppMgrGetBudgetInfo(&info);
vglInitWithCustomSizes(gpu_pool_size, width, height, info.free_user_rw > ram_threshold ? info.free_user_rw - ram_threshold : info.free_user_rw, 0, 0, msaa);
} else {
SceKernelFreeMemorySizeInfo info;
info.size = sizeof(SceKernelFreeMemorySizeInfo);
sceKernelGetFreeMemorySize(&info);
vglInitWithCustomSizes(gpu_pool_size, width, height, info.size_user > ram_threshold ? info.size_user - ram_threshold : info.size_user, info.size_cdram - 256 * 1024, info.size_phycont - 1 * 1024 * 1024, msaa);
}
}
void vglInit(uint32_t gpu_pool_size) {
vglInitExtended(gpu_pool_size, DISPLAY_WIDTH_DEF, DISPLAY_HEIGHT_DEF, 0x1000000, SCE_GXM_MULTISAMPLE_NONE);
}
void vglEnd(void) {
// Wait for rendering to be finished
waitRenderingDone();
// Deallocating default vertices buffers
mempool_free(clear_vertices, VGL_MEM_RAM);
mempool_free(depth_vertices, VGL_MEM_RAM);
mempool_free(depth_clear_indices, VGL_MEM_RAM);
mempool_free(scissor_test_vertices, VGL_MEM_RAM);
// Releasing shader programs from sceGxmShaderPatcher
sceGxmShaderPatcherReleaseFragmentProgram(gxm_shader_patcher, scissor_test_fragment_program);
sceGxmShaderPatcherReleaseFragmentProgram(gxm_shader_patcher, disable_color_buffer_fragment_program_patched);
sceGxmShaderPatcherReleaseVertexProgram(gxm_shader_patcher, clear_vertex_program_patched);
sceGxmShaderPatcherReleaseFragmentProgram(gxm_shader_patcher, clear_fragment_program_patched);
sceGxmShaderPatcherReleaseVertexProgram(gxm_shader_patcher, rgba_vertex_program_patched);
sceGxmShaderPatcherReleaseVertexProgram(gxm_shader_patcher, rgb_vertex_program_patched);
sceGxmShaderPatcherReleaseFragmentProgram(gxm_shader_patcher, rgba_fragment_program_patched);
sceGxmShaderPatcherReleaseVertexProgram(gxm_shader_patcher, texture2d_vertex_program_patched);
sceGxmShaderPatcherReleaseFragmentProgram(gxm_shader_patcher, texture2d_fragment_program_patched);
// Unregistering shader programs from sceGxmShaderPatcher
sceGxmShaderPatcherUnregisterProgram(gxm_shader_patcher, clear_vertex_id);
sceGxmShaderPatcherUnregisterProgram(gxm_shader_patcher, clear_fragment_id);
sceGxmShaderPatcherUnregisterProgram(gxm_shader_patcher, rgb_vertex_id);
sceGxmShaderPatcherUnregisterProgram(gxm_shader_patcher, rgba_vertex_id);
sceGxmShaderPatcherUnregisterProgram(gxm_shader_patcher, rgba_fragment_id);
sceGxmShaderPatcherUnregisterProgram(gxm_shader_patcher, texture2d_vertex_id);
sceGxmShaderPatcherUnregisterProgram(gxm_shader_patcher, texture2d_fragment_id);
sceGxmShaderPatcherUnregisterProgram(gxm_shader_patcher, disable_color_buffer_fragment_id);
// Terminating shader patcher
stopShaderPatcher();
// Deallocating depth and stencil surfaces for display
termDepthStencilSurfaces();
// Terminating display's color surfaces
termDisplayColorSurfaces();
// Destroing display's render target
destroyDisplayRenderTarget();
// Terminating sceGxm context
termGxmContext();
// Terminating sceGxm
sceGxmTerminate();
}
void vglWaitVblankStart(GLboolean enable) {
vblank = enable;
}
// openGL implementation
void glGenBuffers(GLsizei n, GLuint *res) {
int i = 0, j = 0;
#ifndef SKIP_ERROR_HANDLING
if (n < 0) {
SET_GL_ERROR(GL_INVALID_VALUE)
}
#endif
for (i = 0; i < BUFFERS_NUM; i++) {
if (buffers[i] != 0x0000) {
res[j++] = buffers[i];
buffers[i] = 0x0000;
}
if (j >= n)
break;
}
}
void glBindBuffer(GLenum target, GLuint buffer) {
#ifndef SKIP_ERROR_HANDLING
if ((buffer != 0x0000) && ((buffer >= BUFFERS_ADDR + BUFFERS_NUM) || (buffer < BUFFERS_ADDR))) {
SET_GL_ERROR(GL_INVALID_VALUE)
}
#endif
switch (target) {
case GL_ARRAY_BUFFER:
vertex_array_unit = buffer - BUFFERS_ADDR;
break;
case GL_ELEMENT_ARRAY_BUFFER:
index_array_unit = buffer - BUFFERS_ADDR;
break;
default:
SET_GL_ERROR(GL_INVALID_ENUM)
break;
}
}
void glDeleteBuffers(GLsizei n, const GLuint *gl_buffers) {
#ifndef SKIP_ERROR_HANDLING
if (n < 0) {
SET_GL_ERROR(GL_INVALID_VALUE)
return;
}
#endif
int i, j;
for (j = 0; j < n; j++) {
if (gl_buffers[j] >= BUFFERS_ADDR && gl_buffers[j] < (BUFFERS_ADDR + BUFFERS_NUM)) {
uint8_t idx = gl_buffers[j] - BUFFERS_ADDR;
buffers[idx] = gl_buffers[j];
if (gpu_buffers[idx].ptr != NULL) {
mempool_free(gpu_buffers[idx].ptr, VGL_MEM_VRAM);
gpu_buffers[idx].ptr = NULL;
gpu_buffers[idx].size = 0;
}
}
}
}
void glBufferData(GLenum target, GLsizei size, const GLvoid *data, GLenum usage) {
int idx = 0;
switch (target) {
case GL_ARRAY_BUFFER:
idx = vertex_array_unit;
break;
case GL_ELEMENT_ARRAY_BUFFER:
idx = index_array_unit;
break;
default:
SET_GL_ERROR(GL_INVALID_ENUM)
break;
}
#ifndef SKIP_ERROR_HANDLING
if (size < 0) {
SET_GL_ERROR(GL_INVALID_VALUE)
}
if (idx < 0) {
SET_GL_ERROR(GL_INVALID_OPERATION)
}
#endif
vglMemType type = use_vram ? VGL_MEM_VRAM : VGL_MEM_RAM;
// Free buffer if already existing.
if (gpu_buffers[idx].ptr != NULL)
mempool_free(gpu_buffers[idx].ptr, type);
gpu_buffers[idx].ptr = gpu_alloc_mapped(size, &type);
gpu_buffers[idx].size = size;
#ifndef SKIP_ERROR_HANDLING
if (gpu_buffers[idx].ptr == NULL) {
gpu_buffers[idx].size = 0;
SET_GL_ERROR(GL_OUT_OF_MEMORY)
}
#endif
memcpy_neon(gpu_buffers[idx].ptr, data, size);
}
void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const void *data) {
int idx = 0;
switch (target) {
case GL_ARRAY_BUFFER:
idx = vertex_array_unit;
break;
case GL_ELEMENT_ARRAY_BUFFER:
idx = index_array_unit;
break;
default:
SET_GL_ERROR(GL_INVALID_ENUM)
break;
}
#ifndef SKIP_ERROR_HANDLING
if ((size < 0) || (offset < 0) || ((offset + size) > gpu_buffers[idx].size)) {
SET_GL_ERROR(GL_INVALID_VALUE)
}
if (idx < 0) {
SET_GL_ERROR(GL_INVALID_OPERATION)
}
#endif
memcpy_neon(gpu_buffers[idx].ptr + offset, data, size);
}
void glBlendFunc(GLenum sfactor, GLenum dfactor) {
switch (sfactor) {
case GL_ZERO:
blend_sfactor_rgb = blend_sfactor_a = SCE_GXM_BLEND_FACTOR_ZERO;
break;
case GL_ONE:
blend_sfactor_rgb = blend_sfactor_a = SCE_GXM_BLEND_FACTOR_ONE;
break;
case GL_SRC_COLOR:
blend_sfactor_rgb = blend_sfactor_a = SCE_GXM_BLEND_FACTOR_SRC_COLOR;
break;
case GL_ONE_MINUS_SRC_COLOR:
blend_sfactor_rgb = blend_sfactor_a = SCE_GXM_BLEND_FACTOR_ONE_MINUS_SRC_COLOR;
break;
case GL_DST_COLOR:
blend_sfactor_rgb = blend_sfactor_a = SCE_GXM_BLEND_FACTOR_DST_COLOR;
break;
case GL_ONE_MINUS_DST_COLOR:
blend_sfactor_rgb = blend_sfactor_a = SCE_GXM_BLEND_FACTOR_ONE_MINUS_DST_COLOR;
break;
case GL_SRC_ALPHA:
blend_sfactor_rgb = blend_sfactor_a = SCE_GXM_BLEND_FACTOR_SRC_ALPHA;
break;
case GL_ONE_MINUS_SRC_ALPHA:
blend_sfactor_rgb = blend_sfactor_a = SCE_GXM_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
break;
case GL_DST_ALPHA:
blend_sfactor_rgb = blend_sfactor_a = SCE_GXM_BLEND_FACTOR_DST_ALPHA;
break;
case GL_ONE_MINUS_DST_ALPHA:
blend_sfactor_rgb = blend_sfactor_a = SCE_GXM_BLEND_FACTOR_ONE_MINUS_DST_ALPHA;
break;
case GL_SRC_ALPHA_SATURATE:
blend_sfactor_rgb = blend_sfactor_a = SCE_GXM_BLEND_FACTOR_SRC_ALPHA_SATURATE;
break;
default:
SET_GL_ERROR(GL_INVALID_ENUM)
break;
}
switch (dfactor) {
case GL_ZERO:
blend_dfactor_rgb = blend_dfactor_a = SCE_GXM_BLEND_FACTOR_ZERO;
break;
case GL_ONE:
blend_dfactor_rgb = blend_dfactor_a = SCE_GXM_BLEND_FACTOR_ONE;
break;
case GL_SRC_COLOR:
blend_dfactor_rgb = blend_dfactor_a = SCE_GXM_BLEND_FACTOR_SRC_COLOR;
break;
case GL_ONE_MINUS_SRC_COLOR:
blend_dfactor_rgb = blend_dfactor_a = SCE_GXM_BLEND_FACTOR_ONE_MINUS_SRC_COLOR;
break;
case GL_DST_COLOR:
blend_dfactor_rgb = blend_dfactor_a = SCE_GXM_BLEND_FACTOR_DST_COLOR;
break;
case GL_ONE_MINUS_DST_COLOR:
blend_dfactor_rgb = blend_dfactor_a = SCE_GXM_BLEND_FACTOR_ONE_MINUS_DST_COLOR;
break;
case GL_SRC_ALPHA:
blend_dfactor_rgb = blend_dfactor_a = SCE_GXM_BLEND_FACTOR_SRC_ALPHA;
break;
case GL_ONE_MINUS_SRC_ALPHA:
blend_dfactor_rgb = blend_dfactor_a = SCE_GXM_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
break;
case GL_DST_ALPHA:
blend_dfactor_rgb = blend_dfactor_a = SCE_GXM_BLEND_FACTOR_DST_ALPHA;
break;
case GL_ONE_MINUS_DST_ALPHA:
blend_dfactor_rgb = blend_dfactor_a = SCE_GXM_BLEND_FACTOR_ONE_MINUS_DST_ALPHA;
break;
case GL_SRC_ALPHA_SATURATE:
blend_dfactor_rgb = blend_dfactor_a = SCE_GXM_BLEND_FACTOR_SRC_ALPHA_SATURATE;
break;
default:
SET_GL_ERROR(GL_INVALID_ENUM)
break;
}
if (blend_state)
change_blend_factor();
}
void glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) {
switch (srcRGB) {
case GL_ZERO:
blend_sfactor_rgb = SCE_GXM_BLEND_FACTOR_ZERO;
break;
case GL_ONE:
blend_sfactor_rgb = SCE_GXM_BLEND_FACTOR_ONE;
break;
case GL_SRC_COLOR:
blend_sfactor_rgb = SCE_GXM_BLEND_FACTOR_SRC_COLOR;
break;
case GL_ONE_MINUS_SRC_COLOR:
blend_sfactor_rgb = SCE_GXM_BLEND_FACTOR_ONE_MINUS_SRC_COLOR;
break;
case GL_DST_COLOR:
blend_sfactor_rgb = SCE_GXM_BLEND_FACTOR_DST_COLOR;
break;
case GL_ONE_MINUS_DST_COLOR:
blend_sfactor_rgb = SCE_GXM_BLEND_FACTOR_ONE_MINUS_DST_COLOR;
break;
case GL_SRC_ALPHA:
blend_sfactor_rgb = SCE_GXM_BLEND_FACTOR_SRC_ALPHA;
break;
case GL_ONE_MINUS_SRC_ALPHA:
blend_sfactor_rgb = SCE_GXM_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
break;
case GL_DST_ALPHA:
blend_sfactor_rgb = SCE_GXM_BLEND_FACTOR_DST_ALPHA;
break;
case GL_ONE_MINUS_DST_ALPHA:
blend_sfactor_rgb = SCE_GXM_BLEND_FACTOR_ONE_MINUS_DST_ALPHA;
break;
case GL_SRC_ALPHA_SATURATE:
blend_sfactor_rgb = SCE_GXM_BLEND_FACTOR_SRC_ALPHA_SATURATE;
break;
default:
SET_GL_ERROR(GL_INVALID_ENUM)
break;
}
switch (dstRGB) {
case GL_ZERO:
blend_dfactor_rgb = SCE_GXM_BLEND_FACTOR_ZERO;
break;
case GL_ONE:
blend_dfactor_rgb = SCE_GXM_BLEND_FACTOR_ONE;
break;
case GL_SRC_COLOR:
blend_dfactor_rgb = SCE_GXM_BLEND_FACTOR_SRC_COLOR;
break;
case GL_ONE_MINUS_SRC_COLOR:
blend_dfactor_rgb = SCE_GXM_BLEND_FACTOR_ONE_MINUS_SRC_COLOR;
break;
case GL_DST_COLOR:
blend_dfactor_rgb = SCE_GXM_BLEND_FACTOR_DST_COLOR;
break;
case GL_ONE_MINUS_DST_COLOR:
blend_dfactor_rgb = SCE_GXM_BLEND_FACTOR_ONE_MINUS_DST_COLOR;
break;
case GL_SRC_ALPHA:
blend_dfactor_rgb = SCE_GXM_BLEND_FACTOR_SRC_ALPHA;
break;
case GL_ONE_MINUS_SRC_ALPHA:
blend_dfactor_rgb = SCE_GXM_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
break;
case GL_DST_ALPHA:
blend_dfactor_rgb = SCE_GXM_BLEND_FACTOR_DST_ALPHA;
break;
case GL_ONE_MINUS_DST_ALPHA:
blend_dfactor_rgb = SCE_GXM_BLEND_FACTOR_ONE_MINUS_DST_ALPHA;
break;
case GL_SRC_ALPHA_SATURATE:
blend_dfactor_rgb = SCE_GXM_BLEND_FACTOR_SRC_ALPHA_SATURATE;
break;
default:
SET_GL_ERROR(GL_INVALID_ENUM)
break;
}
switch (srcAlpha) {
case GL_ZERO:
blend_sfactor_a = SCE_GXM_BLEND_FACTOR_ZERO;
break;
case GL_ONE:
blend_sfactor_a = SCE_GXM_BLEND_FACTOR_ONE;
break;
case GL_SRC_COLOR:
blend_sfactor_a = SCE_GXM_BLEND_FACTOR_SRC_COLOR;
break;
case GL_ONE_MINUS_SRC_COLOR:
blend_sfactor_a = SCE_GXM_BLEND_FACTOR_ONE_MINUS_SRC_COLOR;
break;
case GL_DST_COLOR:
blend_sfactor_a = SCE_GXM_BLEND_FACTOR_DST_COLOR;
break;
case GL_ONE_MINUS_DST_COLOR:
blend_sfactor_a = SCE_GXM_BLEND_FACTOR_ONE_MINUS_DST_COLOR;
break;
case GL_SRC_ALPHA:
blend_sfactor_a = SCE_GXM_BLEND_FACTOR_SRC_ALPHA;
break;
case GL_ONE_MINUS_SRC_ALPHA:
blend_sfactor_a = SCE_GXM_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
break;
case GL_DST_ALPHA:
blend_sfactor_a = SCE_GXM_BLEND_FACTOR_DST_ALPHA;
break;
case GL_ONE_MINUS_DST_ALPHA:
blend_sfactor_a = SCE_GXM_BLEND_FACTOR_ONE_MINUS_DST_ALPHA;
break;
case GL_SRC_ALPHA_SATURATE:
blend_sfactor_a = SCE_GXM_BLEND_FACTOR_SRC_ALPHA_SATURATE;
break;
default:
SET_GL_ERROR(GL_INVALID_ENUM)
break;
}
switch (dstAlpha) {
case GL_ZERO:
blend_dfactor_a = SCE_GXM_BLEND_FACTOR_ZERO;
break;
case GL_ONE:
blend_dfactor_a = SCE_GXM_BLEND_FACTOR_ONE;
break;
case GL_SRC_COLOR:
blend_dfactor_a = SCE_GXM_BLEND_FACTOR_SRC_COLOR;
break;
case GL_ONE_MINUS_SRC_COLOR:
blend_dfactor_a = SCE_GXM_BLEND_FACTOR_ONE_MINUS_SRC_COLOR;
break;
case GL_DST_COLOR:
blend_dfactor_a = SCE_GXM_BLEND_FACTOR_DST_COLOR;
break;
case GL_ONE_MINUS_DST_COLOR:
blend_dfactor_a = SCE_GXM_BLEND_FACTOR_ONE_MINUS_DST_COLOR;
break;
case GL_SRC_ALPHA:
blend_dfactor_a = SCE_GXM_BLEND_FACTOR_SRC_ALPHA;
break;
case GL_ONE_MINUS_SRC_ALPHA:
blend_dfactor_a = SCE_GXM_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
break;
case GL_DST_ALPHA:
blend_dfactor_a = SCE_GXM_BLEND_FACTOR_DST_ALPHA;
break;
case GL_ONE_MINUS_DST_ALPHA:
blend_dfactor_a = SCE_GXM_BLEND_FACTOR_ONE_MINUS_DST_ALPHA;
break;
case GL_SRC_ALPHA_SATURATE:
blend_dfactor_a = SCE_GXM_BLEND_FACTOR_SRC_ALPHA_SATURATE;
break;
default:
SET_GL_ERROR(GL_INVALID_ENUM)
break;
}
if (blend_state)
change_blend_factor();
}
void glBlendEquation(GLenum mode) {
switch (mode) {
case GL_FUNC_ADD:
blend_func_rgb = blend_func_a = SCE_GXM_BLEND_FUNC_ADD;
break;
case GL_FUNC_SUBTRACT:
blend_func_rgb = blend_func_a = SCE_GXM_BLEND_FUNC_SUBTRACT;
break;
case GL_FUNC_REVERSE_SUBTRACT:
blend_func_rgb = blend_func_a = SCE_GXM_BLEND_FUNC_REVERSE_SUBTRACT;
break;
case GL_MIN:
blend_func_rgb = blend_func_a = SCE_GXM_BLEND_FUNC_MIN;
break;
case GL_MAX:
blend_func_rgb = blend_func_a = SCE_GXM_BLEND_FUNC_MAX;
break;
default:
SET_GL_ERROR(GL_INVALID_ENUM)
break;
}
if (blend_state)
change_blend_factor();
}
void glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha) {
switch (modeRGB) {
case GL_FUNC_ADD:
blend_func_rgb = SCE_GXM_BLEND_FUNC_ADD;
break;
case GL_FUNC_SUBTRACT:
blend_func_rgb = SCE_GXM_BLEND_FUNC_SUBTRACT;
break;
case GL_FUNC_REVERSE_SUBTRACT:
blend_func_rgb = SCE_GXM_BLEND_FUNC_REVERSE_SUBTRACT;
break;
case GL_MIN:
blend_func_rgb = SCE_GXM_BLEND_FUNC_MIN;
break;
case GL_MAX:
blend_func_rgb = SCE_GXM_BLEND_FUNC_MAX;
break;
default:
SET_GL_ERROR(GL_INVALID_ENUM)
break;
}
switch (modeAlpha) {
case GL_FUNC_ADD:
blend_func_a = SCE_GXM_BLEND_FUNC_ADD;
break;
case GL_FUNC_SUBTRACT:
blend_func_a = SCE_GXM_BLEND_FUNC_SUBTRACT;
break;
case GL_FUNC_REVERSE_SUBTRACT:
blend_func_a = SCE_GXM_BLEND_FUNC_REVERSE_SUBTRACT;
break;
case GL_MIN:
blend_func_a = SCE_GXM_BLEND_FUNC_MIN;
break;
case GL_MAX:
blend_func_a = SCE_GXM_BLEND_FUNC_MAX;
break;
default:
SET_GL_ERROR(GL_INVALID_ENUM)
break;
}
if (blend_state)
change_blend_factor();
}
void glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) {
blend_color_mask = SCE_GXM_COLOR_MASK_NONE;
if (red)
blend_color_mask += SCE_GXM_COLOR_MASK_R;
if (green)
blend_color_mask += SCE_GXM_COLOR_MASK_G;
if (blue)
blend_color_mask += SCE_GXM_COLOR_MASK_B;
if (alpha)
blend_color_mask += SCE_GXM_COLOR_MASK_A;
if (blend_state)
change_blend_factor();
else
change_blend_mask();
}
void glVertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) {
#ifndef SKIP_ERROR_HANDLING
if ((stride < 0) || (size < 2) || (size > 4)) {
SET_GL_ERROR(GL_INVALID_VALUE)
}
#endif
texture_unit *tex_unit = &texture_units[client_texture_unit];
switch (type) {
case GL_FLOAT:
tex_unit->vertex_array.size = sizeof(GLfloat);
break;
case GL_SHORT:
tex_unit->vertex_array.size = sizeof(GLshort);
break;
default:
SET_GL_ERROR(GL_INVALID_ENUM)
break;
}
tex_unit->vertex_array.num = size;
tex_unit->vertex_array.stride = stride;
tex_unit->vertex_array.pointer = pointer;
}
void glColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) {
#ifndef SKIP_ERROR_HANDLING
if ((stride < 0) || (size < 3) || (size > 4)) {
SET_GL_ERROR(GL_INVALID_VALUE)
}
#endif
texture_unit *tex_unit = &texture_units[client_texture_unit];
switch (type) {
case GL_FLOAT:
tex_unit->color_array.size = sizeof(GLfloat);
break;
case GL_SHORT:
tex_unit->color_array.size = sizeof(GLshort);
break;
default:
SET_GL_ERROR(GL_INVALID_ENUM)
break;
}
tex_unit->color_array.num = size;
tex_unit->color_array.stride = stride;
tex_unit->color_array.pointer = pointer;
}
void glTexCoordPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) {
#ifndef SKIP_ERROR_HANDLING
if ((stride < 0) || (size < 2) || (size > 4)) {
SET_GL_ERROR(GL_INVALID_VALUE)
}
#endif
texture_unit *tex_unit = &texture_units[client_texture_unit];
switch (type) {
case GL_FLOAT:
tex_unit->texture_array.size = sizeof(GLfloat);
break;
case GL_SHORT:
tex_unit->texture_array.size = sizeof(GLshort);
break;
default:
SET_GL_ERROR(GL_INVALID_ENUM)
break;
}
tex_unit->texture_array.num = size;
tex_unit->texture_array.stride = stride;
tex_unit->texture_array.pointer = pointer;
}
void glDrawArrays(GLenum mode, GLint first, GLsizei count) {
texture_unit *tex_unit = &texture_units[client_texture_unit];
int texture2d_idx = tex_unit->tex_id;
SceGxmPrimitiveType gxm_p;
if (tex_unit->vertex_array_state) {
GLboolean skip_draw = GL_FALSE;
switch (mode) {
case GL_POINTS:
gxm_p = SCE_GXM_PRIMITIVE_POINTS;
break;
case GL_LINES:
gxm_p = SCE_GXM_PRIMITIVE_LINES;
if ((count % 2) != 0)
skip_draw = GL_TRUE;
break;
case GL_TRIANGLES:
gxm_p = SCE_GXM_PRIMITIVE_TRIANGLES;
if (no_polygons_mode)
skip_draw = GL_TRUE;
else if ((count % 3) != 0)
skip_draw = GL_TRUE;
break;
case GL_TRIANGLE_STRIP:
gxm_p = SCE_GXM_PRIMITIVE_TRIANGLE_STRIP;
if (no_polygons_mode)
skip_draw = GL_TRUE;
break;
case GL_TRIANGLE_FAN:
gxm_p = SCE_GXM_PRIMITIVE_TRIANGLE_FAN;
if (no_polygons_mode)
skip_draw = GL_TRUE;
break;
default:
SET_GL_ERROR(GL_INVALID_ENUM)
break;
}
if (!skip_draw) {
if (mvp_modified) {
matrix4x4_multiply(mvp_matrix, projection_matrix, modelview_matrix);
mvp_modified = GL_FALSE;
}
if (tex_unit->texture_array_state) {
if (!(textures[texture2d_idx].valid))
return;
if (tex_unit->color_array_state) {
sceGxmSetVertexProgram(gxm_context, texture2d_rgba_vertex_program_patched);
sceGxmSetFragmentProgram(gxm_context, texture2d_rgba_fragment_program_patched);
void *alpha_buffer;
sceGxmReserveFragmentDefaultUniformBuffer(gxm_context, &alpha_buffer);
sceGxmSetUniformDataF(alpha_buffer, texture2d_rgba_alpha_cut, 0, 1, &alpha_ref);
float alpha_operation = (float)alpha_op;
sceGxmSetUniformDataF(alpha_buffer, texture2d_rgba_alpha_op, 0, 1, &alpha_operation);
float env_mode = (float)tex_unit->env_mode;
sceGxmSetUniformDataF(alpha_buffer, texture2d_rgba_tex_env, 0, 1, &env_mode);
float fogmode = (float)internal_fog_mode;
sceGxmSetUniformDataF(alpha_buffer, texture2d_rgba_fog_mode, 0, 1, &fogmode);
sceGxmSetUniformDataF(alpha_buffer, texture2d_rgba_fog_color, 0, 4, &fog_color.r);
sceGxmSetUniformDataF(alpha_buffer, texture2d_rgba_tex_env_color, 0, 4, &texenv_color.r);
sceGxmSetUniformDataF(alpha_buffer, texture2d_rgba_fog_near, 0, 1, (const float *)&fog_near);
sceGxmSetUniformDataF(alpha_buffer, texture2d_rgba_fog_far, 0, 1, (const float *)&fog_far);
sceGxmSetUniformDataF(alpha_buffer, texture2d_rgba_fog_density, 0, 1, (const float *)&fog_density);
} else {
sceGxmSetVertexProgram(gxm_context, texture2d_vertex_program_patched);
sceGxmSetFragmentProgram(gxm_context, texture2d_fragment_program_patched);
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, &current_color.r);
float env_mode = (float)tex_unit->env_mode;
sceGxmSetUniformDataF(alpha_buffer, texture2d_tex_env, 0, 1, &env_mode);
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_rgba_fog_near, 0, 1, (const float *)&fog_near);
sceGxmSetUniformDataF(alpha_buffer, texture2d_rgba_fog_far, 0, 1, (const float *)&fog_far);
sceGxmSetUniformDataF(alpha_buffer, texture2d_rgba_fog_density, 0, 1, (const float *)&fog_density);
}
} else if (tex_unit->color_array_state && (tex_unit->color_array.num == 3)) {
sceGxmSetVertexProgram(gxm_context, rgb_vertex_program_patched);
sceGxmSetFragmentProgram(gxm_context, rgba_fragment_program_patched);
} else {
sceGxmSetVertexProgram(gxm_context, rgba_vertex_program_patched);
sceGxmSetFragmentProgram(gxm_context, rgba_fragment_program_patched);
}
void *vertex_wvp_buffer;
sceGxmReserveVertexDefaultUniformBuffer(gxm_context, &vertex_wvp_buffer);
if (tex_unit->texture_array_state) {
if (tex_unit->color_array_state) {
sceGxmSetUniformDataF(vertex_wvp_buffer, texture2d_rgba_wvp, 0, 16, (const float *)mvp_matrix);
float clipplane0 = (float)clip_plane0;
sceGxmSetUniformDataF(vertex_wvp_buffer, texture2d_rgba_clip_plane0, 0, 1, &clipplane0);
sceGxmSetUniformDataF(vertex_wvp_buffer, texture2d_rgba_clip_plane0_eq, 0, 4, &clip_plane0_eq.x);
sceGxmSetUniformDataF(vertex_wvp_buffer, texture2d_rgba_mv, 0, 16, (const float *)modelview_matrix);
} else {
sceGxmSetUniformDataF(vertex_wvp_buffer, texture2d_wvp, 0, 16, (const float *)mvp_matrix);
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);
}
sceGxmSetFragmentTexture(gxm_context, 0, &textures[texture2d_idx].gxm_tex);
vector3f *vertices = NULL;
vector2f *uv_map = NULL;
vector4f *colors = NULL;
uint16_t *indices;
uint16_t n;
if (vertex_array_unit >= 0) {
if (tex_unit->vertex_array.stride == 0)
vertices = (vector3f *)(((uint32_t)gpu_buffers[vertex_array_unit].ptr + (uint32_t)tex_unit->vertex_array.pointer) + (first * (tex_unit->vertex_array.num * tex_unit->vertex_array.size)));
else
vertices = (vector3f *)(((uint32_t)gpu_buffers[vertex_array_unit].ptr + (uint32_t)tex_unit->vertex_array.pointer) + (first * tex_unit->vertex_array.stride));
if (tex_unit->texture_array.stride == 0)
uv_map = (vector2f *)(((uint32_t)gpu_buffers[vertex_array_unit].ptr + (uint32_t)tex_unit->texture_array.pointer) + (first * (tex_unit->texture_array.num * tex_unit->texture_array.size)));
else
uv_map = (vector2f *)(((uint32_t)gpu_buffers[vertex_array_unit].ptr + (uint32_t)tex_unit->texture_array.pointer) + (first * tex_unit->texture_array.stride));
if (tex_unit->color_array_state) {
if (tex_unit->color_array.stride == 0)
colors = (vector4f *)(((uint32_t)gpu_buffers[vertex_array_unit].ptr + (uint32_t)tex_unit->color_array.pointer) + (first * (tex_unit->color_array.num * tex_unit->color_array.size)));
else
colors = (vector4f *)(((uint32_t)gpu_buffers[vertex_array_unit].ptr + (uint32_t)tex_unit->color_array.pointer) + (first * tex_unit->color_array.stride));
}
indices = (uint16_t *)gpu_pool_memalign(count * sizeof(uint16_t), sizeof(uint16_t));
for (n = 0; n < count; n++) {
indices[n] = n;
}
} else {
uint8_t *ptr;
uint8_t *ptr_tex;
uint8_t *ptr_clr;
vertices = (vector3f *)gpu_pool_memalign(count * sizeof(vector3f), sizeof(vector3f));
uv_map = (vector2f *)gpu_pool_memalign(count * sizeof(vector2f), sizeof(vector2f));
if (tex_unit->color_array_state)
colors = (vector4f *)gpu_pool_memalign(count * sizeof(vector4f), sizeof(vector4f));
memset(vertices, 0, (count * sizeof(vector3f)));
uint8_t vec_set = 0, tex_set = 0, clr_set = 0;
if (tex_unit->vertex_array.stride == 0) {
ptr = ((uint8_t *)tex_unit->vertex_array.pointer) + (first * (tex_unit->vertex_array.num * tex_unit->vertex_array.size));
memcpy_neon(&vertices[0], ptr, count * sizeof(vector3f));
vec_set = 1;
} else
ptr = ((uint8_t *)tex_unit->vertex_array.pointer) + (first * tex_unit->vertex_array.stride);
if (tex_unit->texture_array.stride == 0) {
ptr_tex = ((uint8_t *)tex_unit->texture_array.pointer) + (first * (tex_unit->texture_array.num * tex_unit->texture_array.size));
memcpy_neon(&uv_map[0], ptr_tex, count * sizeof(vector2f));
tex_set = 1;
} else
ptr_tex = ((uint8_t *)tex_unit->texture_array.pointer) + (first * tex_unit->texture_array.stride);
if (tex_unit->color_array_state) {
if (tex_unit->color_array.stride == 0) {
ptr_clr = ((uint8_t *)tex_unit->color_array.pointer) + (first * sizeof(vector4f));
memcpy_neon(&colors[0], ptr_clr, count * sizeof(vector4f));
clr_set = 1;
} else
ptr_clr = ((uint8_t *)tex_unit->color_array.pointer) + (first * tex_unit->color_array.stride);
}
indices = (uint16_t *)gpu_pool_memalign(count * sizeof(uint16_t), sizeof(uint16_t));
for (n = 0; n < count; n++) {
if (!vec_set) {
memcpy_neon(&vertices[n], ptr, tex_unit->vertex_array.size * tex_unit->vertex_array.num);
ptr += tex_unit->vertex_array.stride;
}
if (!tex_set) {
memcpy_neon(&uv_map[n], ptr_tex, tex_unit->texture_array.size * tex_unit->texture_array.num);
ptr_tex += tex_unit->texture_array.stride;
}
if (tex_unit->color_array_state && (!clr_set)) {
memcpy_neon(&colors[n], ptr_clr, tex_unit->color_array.size * tex_unit->color_array.num);
ptr_clr += tex_unit->color_array.stride;
}
indices[n] = n;
}
}
sceGxmSetVertexStream(gxm_context, 0, vertices);
sceGxmSetVertexStream(gxm_context, 1, uv_map);
if (tex_unit->color_array_state)
sceGxmSetVertexStream(gxm_context, 2, colors);
sceGxmDraw(gxm_context, gxm_p, SCE_GXM_INDEX_FORMAT_U16, indices, count);
} else if (tex_unit->color_array_state) {
if (tex_unit->color_array.num == 3)
sceGxmSetUniformDataF(vertex_wvp_buffer, rgb_wvp, 0, 16, (const float *)mvp_matrix);
else
sceGxmSetUniformDataF(vertex_wvp_buffer, rgba_wvp, 0, 16, (const float *)mvp_matrix);
vector3f *vertices = NULL;
uint8_t *colors = NULL;
uint16_t *indices;
uint16_t n = 0;
if (vertex_array_unit >= 0) {
if (tex_unit->vertex_array.stride == 0)
vertices = (vector3f *)(((uint32_t)gpu_buffers[vertex_array_unit].ptr + (uint32_t)tex_unit->vertex_array.pointer) + (first * (tex_unit->vertex_array.num * tex_unit->vertex_array.size)));
else
vertices = (vector3f *)(((uint32_t)gpu_buffers[vertex_array_unit].ptr + (uint32_t)tex_unit->vertex_array.pointer) + (first * tex_unit->vertex_array.stride));
if (tex_unit->color_array.stride == 0)
colors = (uint8_t *)(((uint32_t)gpu_buffers[vertex_array_unit].ptr + (uint32_t)tex_unit->color_array.pointer) + (first * (tex_unit->color_array.num * tex_unit->color_array.size)));
else
colors = (uint8_t *)(((uint32_t)gpu_buffers[vertex_array_unit].ptr + (uint32_t)tex_unit->color_array.pointer) + (first * tex_unit->color_array.stride));
indices = (uint16_t *)gpu_pool_memalign(count * sizeof(uint16_t), sizeof(uint16_t));
for (n = 0; n < count; n++) {
indices[n] = n;
}
} else {
uint8_t *ptr;
uint8_t *ptr_clr;
vertices = (vector3f *)gpu_pool_memalign(count * sizeof(vector3f), sizeof(vector3f));
colors = (uint8_t *)gpu_pool_memalign(count * tex_unit->color_array.num * tex_unit->color_array.size, tex_unit->color_array.num * tex_unit->color_array.size);
memset(vertices, 0, (count * sizeof(vector3f)));
uint8_t vec_set = 0, clr_set = 0;
if (tex_unit->vertex_array.stride == 0) {
ptr = ((uint8_t *)tex_unit->vertex_array.pointer) + (first * ((tex_unit->vertex_array.num * tex_unit->vertex_array.size)));
memcpy_neon(&vertices[n], ptr, count * sizeof(vector3f));
vec_set = 1;
} else
ptr = ((uint8_t *)tex_unit->vertex_array.pointer) + (first * (tex_unit->vertex_array.stride));
if (tex_unit->color_array.stride == 0) {
ptr_clr = ((uint8_t *)tex_unit->color_array.pointer) + (first * ((tex_unit->color_array.num * tex_unit->color_array.size)));
memcpy_neon(&colors[n], ptr_clr, count * tex_unit->color_array.num * tex_unit->color_array.size);
clr_set = 1;
} else
ptr_clr = ((uint8_t *)tex_unit->color_array.pointer) + (first * tex_unit->color_array.size);
indices = (uint16_t *)gpu_pool_memalign(count * sizeof(uint16_t), sizeof(uint16_t));
for (n = 0; n < count; n++) {
if (!vec_set) {
memcpy_neon(&vertices[n], ptr, tex_unit->vertex_array.size * tex_unit->vertex_array.num);
ptr += tex_unit->vertex_array.stride;
}
if (!clr_set) {
memcpy_neon(&colors[n * tex_unit->color_array.num * tex_unit->color_array.size], ptr_clr, tex_unit->color_array.size * tex_unit->color_array.num);
ptr_clr += tex_unit->color_array.stride;
}
indices[n] = n;
}
}
sceGxmSetVertexStream(gxm_context, 0, vertices);
sceGxmSetVertexStream(gxm_context, 1, colors);
sceGxmDraw(gxm_context, gxm_p, SCE_GXM_INDEX_FORMAT_U16, indices, count);
} else {
sceGxmSetUniformDataF(vertex_wvp_buffer, rgba_wvp, 0, 16, (const float *)mvp_matrix);
vector3f *vertices = NULL;
vector4f *colors = NULL;
uint16_t *indices;
uint16_t n = 0;
if (vertex_array_unit >= 0) {
if (tex_unit->vertex_array.stride == 0)
vertices = (vector3f *)(((uint32_t)gpu_buffers[vertex_array_unit].ptr + (uint32_t)tex_unit->vertex_array.pointer) + (first * (tex_unit->vertex_array.num * tex_unit->vertex_array.size)));
else
vertices = (vector3f *)(((uint32_t)gpu_buffers[vertex_array_unit].ptr + (uint32_t)tex_unit->vertex_array.pointer) + (first * tex_unit->vertex_array.stride));
colors = (vector4f *)gpu_pool_memalign(count * sizeof(vector4f), sizeof(vector4f));
indices = (uint16_t *)gpu_pool_memalign(count * sizeof(uint16_t), sizeof(uint16_t));
for (n = 0; n < count; n++) {
memcpy_neon(&colors[n], &current_color.r, sizeof(vector4f));
indices[n] = n;
}
} else {
uint8_t *ptr;
vertices = (vector3f *)gpu_pool_memalign(count * sizeof(vector3f), sizeof(vector3f));
colors = (vector4f *)gpu_pool_memalign(count * sizeof(vector4f), sizeof(vector4f));
memset(vertices, 0, (count * sizeof(vector3f)));
uint8_t vec_set = 0;
if (tex_unit->vertex_array.stride == 0) {
ptr = ((uint8_t *)tex_unit->vertex_array.pointer) + (first * ((tex_unit->vertex_array.num * tex_unit->vertex_array.size)));
memcpy_neon(&vertices[n], ptr, count * sizeof(vector3f));
vec_set = 1;
} else
ptr = ((uint8_t *)tex_unit->vertex_array.pointer) + (first * (tex_unit->vertex_array.stride));
indices = (uint16_t *)gpu_pool_memalign(count * sizeof(uint16_t), sizeof(uint16_t));
for (n = 0; n < count; n++) {
if (!vec_set) {
memcpy_neon(&vertices[n], ptr, tex_unit->vertex_array.size * tex_unit->vertex_array.num);
ptr += tex_unit->vertex_array.stride;
}
memcpy_neon(&colors[n], &current_color.r, sizeof(vector4f));
indices[n] = n;
}
}
sceGxmSetVertexStream(gxm_context, 0, vertices);
sceGxmSetVertexStream(gxm_context, 1, colors);
sceGxmDraw(gxm_context, gxm_p, SCE_GXM_INDEX_FORMAT_U16, indices, count);
}
}
}
}
void glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *gl_indices) {
SceGxmPrimitiveType gxm_p;
texture_unit *tex_unit = &texture_units[client_texture_unit];
int texture2d_idx = tex_unit->tex_id;
if (tex_unit->vertex_array_state) {
GLboolean skip_draw = GL_FALSE;
#ifndef SKIP_ERROR_HANDLING
if (type != GL_UNSIGNED_SHORT) {
SET_GL_ERROR(GL_INVALID_ENUM)
} else if (phase == MODEL_CREATION) {
SET_GL_ERROR(GL_INVALID_OPERATION)
} else if (count < 0) {
SET_GL_ERROR(GL_INVALID_VALUE)
}
#endif
switch (mode) {
case GL_POINTS:
gxm_p = SCE_GXM_PRIMITIVE_POINTS;
break;
case GL_LINES:
gxm_p = SCE_GXM_PRIMITIVE_LINES;
break;
case GL_TRIANGLES:
gxm_p = SCE_GXM_PRIMITIVE_TRIANGLES;
if (no_polygons_mode)
skip_draw = GL_TRUE;
break;
case GL_TRIANGLE_STRIP:
gxm_p = SCE_GXM_PRIMITIVE_TRIANGLE_STRIP;
if (no_polygons_mode)
skip_draw = GL_TRUE;
break;
case GL_TRIANGLE_FAN:
gxm_p = SCE_GXM_PRIMITIVE_TRIANGLE_FAN;
if (no_polygons_mode)
skip_draw = GL_TRUE;
break;
default:
SET_GL_ERROR(GL_INVALID_ENUM)
break;
}
if (!skip_draw) {
if (mvp_modified) {
matrix4x4_multiply(mvp_matrix, projection_matrix, modelview_matrix);
mvp_modified = GL_FALSE;
}
if (tex_unit->texture_array_state) {
if (!(textures[texture2d_idx].valid))
return;
if (tex_unit->color_array_state) {
sceGxmSetVertexProgram(gxm_context, texture2d_rgba_vertex_program_patched);
sceGxmSetFragmentProgram(gxm_context, texture2d_rgba_fragment_program_patched);
void *alpha_buffer;
sceGxmReserveFragmentDefaultUniformBuffer(gxm_context, &alpha_buffer);
sceGxmSetUniformDataF(alpha_buffer, texture2d_rgba_alpha_cut, 0, 1, &alpha_ref);
float alpha_operation = (float)alpha_op;
sceGxmSetUniformDataF(alpha_buffer, texture2d_rgba_alpha_op, 0, 1, &alpha_operation);
float env_mode = (float)tex_unit->env_mode;
sceGxmSetUniformDataF(alpha_buffer, texture2d_rgba_tex_env, 0, 1, &env_mode);
float fogmode = (float)internal_fog_mode;
sceGxmSetUniformDataF(alpha_buffer, texture2d_rgba_fog_mode, 0, 1, &fogmode);
sceGxmSetUniformDataF(alpha_buffer, texture2d_rgba_fog_color, 0, 4, &fog_color.r);
sceGxmSetUniformDataF(alpha_buffer, texture2d_rgba_tex_env_color, 0, 4, &texenv_color.r);
sceGxmSetUniformDataF(alpha_buffer, texture2d_rgba_fog_near, 0, 1, (const float *)&fog_near);
sceGxmSetUniformDataF(alpha_buffer, texture2d_rgba_fog_far, 0, 1, (const float *)&fog_far);
sceGxmSetUniformDataF(alpha_buffer, texture2d_rgba_fog_density, 0, 1, (const float *)&fog_density);
} else {
sceGxmSetVertexProgram(gxm_context, texture2d_vertex_program_patched);
sceGxmSetFragmentProgram(gxm_context, texture2d_fragment_program_patched);
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, &current_color.r);
float env_mode = (float)tex_unit->env_mode;
sceGxmSetUniformDataF(alpha_buffer, texture2d_tex_env, 0, 1, &env_mode);
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 if (tex_unit->color_array_state && (tex_unit->color_array.num == 3)) {
sceGxmSetVertexProgram(gxm_context, rgb_vertex_program_patched);
sceGxmSetFragmentProgram(gxm_context, rgba_fragment_program_patched);
} else {
sceGxmSetVertexProgram(gxm_context, rgba_vertex_program_patched);
sceGxmSetFragmentProgram(gxm_context, rgba_fragment_program_patched);
}
void *vertex_wvp_buffer;
sceGxmReserveVertexDefaultUniformBuffer(gxm_context, &vertex_wvp_buffer);
if (tex_unit->texture_array_state) {
if (tex_unit->color_array_state) {
sceGxmSetUniformDataF(vertex_wvp_buffer, texture2d_rgba_wvp, 0, 16, (const float *)mvp_matrix);
float clipplane0 = (float)clip_plane0;
sceGxmSetUniformDataF(vertex_wvp_buffer, texture2d_rgba_clip_plane0, 0, 1, &clipplane0);
sceGxmSetUniformDataF(vertex_wvp_buffer, texture2d_rgba_clip_plane0_eq, 0, 4, &clip_plane0_eq.x);
sceGxmSetUniformDataF(vertex_wvp_buffer, texture2d_rgba_mv, 0, 16, (const float *)modelview_matrix);
} else {
sceGxmSetUniformDataF(vertex_wvp_buffer, texture2d_wvp, 0, 16, (const float *)mvp_matrix);
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);
}
sceGxmSetFragmentTexture(gxm_context, 0, &textures[texture2d_idx].gxm_tex);
vector3f *vertices = NULL;
vector2f *uv_map = NULL;
vector4f *colors = NULL;
uint16_t *indices;
if (index_array_unit >= 0)
indices = (uint16_t *)((uint32_t)gpu_buffers[index_array_unit].ptr + (uint32_t)gl_indices);
else {
indices = (uint16_t *)gpu_pool_memalign(count * sizeof(uint16_t), sizeof(uint16_t));
memcpy_neon(indices, gl_indices, sizeof(uint16_t) * count);
}
if (vertex_array_unit >= 0) {
vertices = (vector3f *)((uint32_t)gpu_buffers[vertex_array_unit].ptr + (uint32_t)tex_unit->vertex_array.pointer);
uv_map = (vector2f *)((uint32_t)gpu_buffers[vertex_array_unit].ptr + (uint32_t)tex_unit->texture_array.pointer);
if (tex_unit->color_array_state)
colors = (vector4f *)((uint32_t)gpu_buffers[vertex_array_unit].ptr + (uint32_t)tex_unit->color_array.pointer);
} else {
int n = 0, j = 0;
uint64_t vertex_count_int = 0;
uint16_t *ptr_idx = (uint16_t *)gl_indices;
while (j < count) {
if (ptr_idx[j] >= vertex_count_int)
vertex_count_int = ptr_idx[j] + 1;
j++;
}
vertices = (vector3f *)gpu_pool_memalign(vertex_count_int * sizeof(vector3f), sizeof(vector3f));
uv_map = (vector2f *)gpu_pool_memalign(vertex_count_int * sizeof(vector2f), sizeof(vector2f));
colors = (vector4f *)gpu_pool_memalign(vertex_count_int * sizeof(vector4f), sizeof(vector4f));
if (tex_unit->vertex_array.stride == 0)
memcpy_neon(vertices, tex_unit->vertex_array.pointer, vertex_count_int * (tex_unit->vertex_array.size * tex_unit->vertex_array.num));
if (tex_unit->texture_array.stride == 0)
memcpy_neon(uv_map, tex_unit->texture_array.pointer, vertex_count_int * (tex_unit->texture_array.size * tex_unit->texture_array.num));
if (tex_unit->color_array_state && (tex_unit->color_array.stride == 0))
memcpy_neon(colors, tex_unit->color_array.pointer, vertex_count_int * (tex_unit->color_array.size * tex_unit->color_array.num));
if ((tex_unit->vertex_array.stride != 0) || (tex_unit->texture_array.stride != 0)) {
if (tex_unit->vertex_array.stride != 0)
memset(vertices, 0, (vertex_count_int * sizeof(texture2d_vertex)));
uint8_t *ptr = ((uint8_t *)tex_unit->vertex_array.pointer);
uint8_t *ptr_tex = ((uint8_t *)tex_unit->texture_array.pointer);
for (n = 0; n < vertex_count_int; n++) {
if (tex_unit->vertex_array.stride != 0)
memcpy_neon(&vertices[n], ptr, tex_unit->vertex_array.size * tex_unit->vertex_array.num);
if (tex_unit->texture_array.stride != 0)
memcpy_neon(&uv_map[n], ptr_tex, tex_unit->texture_array.size * tex_unit->texture_array.num);
ptr += tex_unit->vertex_array.stride;
ptr_tex += tex_unit->texture_array.stride;
}
}
}
sceGxmSetVertexStream(gxm_context, 0, vertices);
sceGxmSetVertexStream(gxm_context, 1, uv_map);
if (tex_unit->color_array_state)
sceGxmSetVertexStream(gxm_context, 2, colors);
sceGxmDraw(gxm_context, gxm_p, SCE_GXM_INDEX_FORMAT_U16, indices, count);
} else if (tex_unit->color_array_state) {
if (tex_unit->color_array.num == 3)
sceGxmSetUniformDataF(vertex_wvp_buffer, rgb_wvp, 0, 16, (const float *)mvp_matrix);
else
sceGxmSetUniformDataF(vertex_wvp_buffer, rgba_wvp, 0, 16, (const float *)mvp_matrix);
vector3f *vertices = NULL;
uint8_t *colors = NULL;
uint16_t *indices;
if (index_array_unit >= 0)
indices = (uint16_t *)((uint32_t)gpu_buffers[index_array_unit].ptr + (uint32_t)gl_indices);
else {
indices = (uint16_t *)gpu_pool_memalign(count * sizeof(uint16_t), sizeof(uint16_t));
memcpy_neon(indices, gl_indices, sizeof(uint16_t) * count);
}
if (vertex_array_unit >= 0) {
colors = (uint8_t *)((uint32_t)gpu_buffers[vertex_array_unit].ptr + (uint32_t)tex_unit->color_array.pointer);
vertices = (vector3f *)((uint32_t)gpu_buffers[vertex_array_unit].ptr + (uint32_t)tex_unit->vertex_array.pointer);
} else {
int n = 0, j = 0;
uint64_t vertex_count_int = 0;
uint16_t *ptr_idx = (uint16_t *)gl_indices;
while (j < count) {
if (ptr_idx[j] >= vertex_count_int)
vertex_count_int = ptr_idx[j] + 1;
j++;
}
vertices = (vector3f *)gpu_pool_memalign(vertex_count_int * sizeof(vector3f), sizeof(vector3f));
colors = (uint8_t *)gpu_pool_memalign(vertex_count_int * tex_unit->color_array.num * tex_unit->color_array.size, tex_unit->color_array.num * tex_unit->color_array.size);
if (tex_unit->vertex_array.stride == 0)
memcpy_neon(vertices, tex_unit->vertex_array.pointer, vertex_count_int * (tex_unit->vertex_array.size * tex_unit->vertex_array.num));
if (tex_unit->color_array.stride == 0)
memcpy_neon(colors, tex_unit->color_array.pointer, vertex_count_int * (tex_unit->color_array.size * tex_unit->color_array.num));
if ((tex_unit->vertex_array.stride != 0) || (tex_unit->color_array.stride != 0)) {
if (tex_unit->vertex_array.stride != 0)
memset(vertices, 0, (vertex_count_int * sizeof(texture2d_vertex)));
uint8_t *ptr = ((uint8_t *)tex_unit->vertex_array.pointer);
uint8_t *ptr_clr = ((uint8_t *)tex_unit->color_array.pointer);
for (n = 0; n < vertex_count_int; n++) {
if (tex_unit->vertex_array.stride != 0)
memcpy_neon(&vertices[n], ptr, tex_unit->vertex_array.size * tex_unit->vertex_array.num);
if (tex_unit->color_array.stride != 0)
memcpy_neon(&colors[n * tex_unit->color_array.num * tex_unit->color_array.size], ptr_clr, tex_unit->color_array.size * tex_unit->color_array.num);
ptr += tex_unit->vertex_array.stride;
ptr_clr += tex_unit->color_array.stride;
}
}
}
sceGxmSetVertexStream(gxm_context, 0, vertices);
sceGxmSetVertexStream(gxm_context, 1, colors);
sceGxmDraw(gxm_context, gxm_p, SCE_GXM_INDEX_FORMAT_U16, indices, count);
} else {
sceGxmSetUniformDataF(vertex_wvp_buffer, rgba_wvp, 0, 16, (const float *)mvp_matrix);
vector3f *vertices = NULL;
vector4f *colors = NULL;
uint16_t *indices;
if (index_array_unit >= 0)
indices = (uint16_t *)((uint32_t)gpu_buffers[index_array_unit].ptr + (uint32_t)gl_indices);
else {
indices = (uint16_t *)gpu_pool_memalign(count * sizeof(uint16_t), sizeof(uint16_t));
memcpy_neon(indices, gl_indices, sizeof(uint16_t) * count);
}
int n = 0, j = 0;
uint64_t vertex_count_int = 0;
uint16_t *ptr_idx = (uint16_t *)gl_indices;
while (j < count) {
if (ptr_idx[j] >= vertex_count_int)
vertex_count_int = ptr_idx[j] + 1;
j++;
}
if (vertex_array_unit >= 0)
vertices = (vector3f *)((uint32_t)gpu_buffers[vertex_array_unit].ptr + (uint32_t)tex_unit->vertex_array.pointer);
else
vertices = (vector3f *)gpu_pool_memalign(vertex_count_int * sizeof(vector3f), sizeof(vector3f));
colors = (vector4f *)gpu_pool_memalign(vertex_count_int * tex_unit->color_array.num * tex_unit->color_array.size, tex_unit->color_array.num * tex_unit->color_array.size);
if ((!vertex_array_unit) && tex_unit->vertex_array.stride == 0)
memcpy_neon(vertices, tex_unit->vertex_array.pointer, vertex_count_int * (tex_unit->vertex_array.size * tex_unit->vertex_array.num));
if ((!vertex_array_unit) && tex_unit->vertex_array.stride != 0)
memset(vertices, 0, (vertex_count_int * sizeof(texture2d_vertex)));
uint8_t *ptr = ((uint8_t *)tex_unit->vertex_array.pointer);
for (n = 0; n < vertex_count_int; n++) {
if ((!vertex_array_unit) && tex_unit->vertex_array.stride != 0)
memcpy_neon(&vertices[n], ptr, tex_unit->vertex_array.size * tex_unit->vertex_array.num);
memcpy_neon(&colors[n], &current_color.r, sizeof(vector4f));
if (!vertex_array_unit)
ptr += tex_unit->vertex_array.stride;
}
sceGxmSetVertexStream(gxm_context, 0, vertices);
sceGxmSetVertexStream(gxm_context, 1, colors);
sceGxmDraw(gxm_context, gxm_p, SCE_GXM_INDEX_FORMAT_U16, indices, count);
}
}
}
}
void glEnableClientState(GLenum array) {
texture_unit *tex_unit = &texture_units[client_texture_unit];
switch (array) {
case GL_VERTEX_ARRAY:
tex_unit->vertex_array_state = GL_TRUE;
break;
case GL_COLOR_ARRAY:
tex_unit->color_array_state = GL_TRUE;
break;
case GL_TEXTURE_COORD_ARRAY:
tex_unit->texture_array_state = GL_TRUE;
break;
default:
SET_GL_ERROR(GL_INVALID_ENUM)
break;
}
}
void glDisableClientState(GLenum array) {
texture_unit *tex_unit = &texture_units[client_texture_unit];
switch (array) {
case GL_VERTEX_ARRAY:
tex_unit->vertex_array_state = GL_FALSE;
break;
case GL_COLOR_ARRAY:
tex_unit->color_array_state = GL_FALSE;
break;
case GL_TEXTURE_COORD_ARRAY:
tex_unit->texture_array_state = GL_FALSE;
break;
default:
SET_GL_ERROR(GL_INVALID_ENUM)
break;
}
}
void glClientActiveTexture(GLenum texture) {
#ifndef SKIP_ERROR_HANDLING
if ((texture < GL_TEXTURE0) && (texture > GL_TEXTURE31)) {
SET_GL_ERROR(GL_INVALID_ENUM)
} else
#endif
client_texture_unit = texture - GL_TEXTURE0;
}
// VGL_EXT_gpu_objects_array extension implementation
void vglVertexPointer(GLint size, GLenum type, GLsizei stride, GLuint count, const GLvoid *pointer) {
#ifndef SKIP_ERROR_HANDLING
if ((stride < 0) || (size < 2) || (size > 4)) {
SET_GL_ERROR(GL_INVALID_VALUE)
}
#endif
texture_unit *tex_unit = &texture_units[client_texture_unit];
int bpe;
switch (type) {
case GL_FLOAT:
bpe = sizeof(GLfloat);
break;
case GL_SHORT:
bpe = sizeof(GLshort);
break;
default:
SET_GL_ERROR(GL_INVALID_ENUM)
break;
}
tex_unit->vertex_object = gpu_pool_memalign(count * bpe * size, bpe * size);
if (stride == 0)
memcpy_neon(tex_unit->vertex_object, pointer, count * bpe * size);
else {
int i;
uint8_t *dst = (uint8_t *)tex_unit->vertex_object;
uint8_t *src = (uint8_t *)pointer;
for (i = 0; i < count; i++) {
memcpy_neon(dst, src, bpe * size);
dst += (bpe * size);
src += stride;
}
}
}
void vglColorPointer(GLint size, GLenum type, GLsizei stride, GLuint count, const GLvoid *pointer) {
#ifndef SKIP_ERROR_HANDLING
if ((stride < 0) || (size < 3) || (size > 4)) {
SET_GL_ERROR(GL_INVALID_VALUE)
}
#endif
texture_unit *tex_unit = &texture_units[client_texture_unit];
int bpe;
switch (type) {
case GL_FLOAT:
bpe = sizeof(GLfloat);
break;
case GL_SHORT:
bpe = sizeof(GLshort);
break;
case GL_UNSIGNED_BYTE:
bpe = sizeof(uint8_t);
break;
default:
SET_GL_ERROR(GL_INVALID_ENUM)
break;
}
tex_unit->color_object = gpu_pool_memalign(count * bpe * size, bpe * size);
tex_unit->color_object_type = type;
if (stride == 0)
memcpy_neon(tex_unit->color_object, pointer, count * bpe * size);
else {
int i;
uint8_t *dst = (uint8_t *)tex_unit->color_object;
uint8_t *src = (uint8_t *)pointer;
for (i = 0; i < count; i++) {
memcpy_neon(dst, src, bpe * size);
dst += (bpe * size);
src += stride;
}
}
}
void vglTexCoordPointer(GLint size, GLenum type, GLsizei stride, GLuint count, const GLvoid *pointer) {
#ifndef SKIP_ERROR_HANDLING
if ((stride < 0) || (size < 2) || (size > 4)) {
SET_GL_ERROR(GL_INVALID_VALUE)
}
#endif
texture_unit *tex_unit = &texture_units[client_texture_unit];
int bpe;
switch (type) {
case GL_FLOAT:
bpe = sizeof(GLfloat);
break;
case GL_SHORT:
bpe = sizeof(GLshort);
break;
default:
SET_GL_ERROR(GL_INVALID_ENUM)
break;
}
tex_unit->texture_object = gpu_pool_memalign(count * bpe * size, bpe * size);
if (stride == 0)
memcpy_neon(tex_unit->texture_object, pointer, count * bpe * size);
else {
int i;
uint8_t *dst = (uint8_t *)tex_unit->texture_object;
uint8_t *src = (uint8_t *)pointer;
for (i = 0; i < count; i++) {
memcpy_neon(dst, src, bpe * size);
dst += (bpe * size);
src += stride;
}
}
}
void vglIndexPointer(GLenum type, GLsizei stride, GLuint count, const GLvoid *pointer) {
#ifndef SKIP_ERROR_HANDLING
if (stride < 0) {
SET_GL_ERROR(GL_INVALID_VALUE)
}
#endif
texture_unit *tex_unit = &texture_units[client_texture_unit];
int bpe;
switch (type) {
case GL_FLOAT:
bpe = sizeof(GLfloat);
break;
case GL_SHORT:
bpe = sizeof(GLshort);
break;
default:
SET_GL_ERROR(GL_INVALID_ENUM)
break;
}
tex_unit->index_object = gpu_pool_memalign(count * bpe, bpe);
if (stride == 0)
memcpy_neon(tex_unit->index_object, pointer, count * bpe);
else {
int i;
uint8_t *dst = (uint8_t *)tex_unit->index_object;
uint8_t *src = (uint8_t *)pointer;
for (i = 0; i < count; i++) {
memcpy_neon(dst, src, bpe);
dst += bpe;
src += stride;
}
}
}
void vglVertexPointerMapped(const GLvoid *pointer) {
texture_unit *tex_unit = &texture_units[client_texture_unit];
tex_unit->vertex_object = (GLvoid *)pointer;
}
void vglColorPointerMapped(GLenum type, const GLvoid *pointer) {
texture_unit *tex_unit = &texture_units[client_texture_unit];
tex_unit->color_object = (GLvoid *)pointer;
tex_unit->color_object_type = type;
}
void vglTexCoordPointerMapped(const GLvoid *pointer) {
texture_unit *tex_unit = &texture_units[client_texture_unit];
tex_unit->texture_object = (GLvoid *)pointer;
}
void vglIndexPointerMapped(const GLvoid *pointer) {
texture_unit *tex_unit = &texture_units[client_texture_unit];
tex_unit->index_object = (GLvoid *)pointer;
}
void vglDrawObjects(GLenum mode, GLsizei count, GLboolean implicit_wvp) {
SceGxmPrimitiveType gxm_p;
texture_unit *tex_unit = &texture_units[client_texture_unit];
int texture2d_idx = tex_unit->tex_id;
#ifndef SKIP_ERROR_HANDLING
if (phase == MODEL_CREATION) {
SET_GL_ERROR(GL_INVALID_OPERATION)
} else if (count < 0) {
SET_GL_ERROR(GL_INVALID_VALUE)
}
#endif
GLboolean skip_draw = GL_FALSE;
switch (mode) {
case GL_POINTS:
gxm_p = SCE_GXM_PRIMITIVE_POINTS;
break;
case GL_LINES:
gxm_p = SCE_GXM_PRIMITIVE_LINES;
break;
case GL_TRIANGLES:
gxm_p = SCE_GXM_PRIMITIVE_TRIANGLES;
if (no_polygons_mode)
skip_draw = GL_TRUE;
break;
case GL_TRIANGLE_STRIP:
gxm_p = SCE_GXM_PRIMITIVE_TRIANGLE_STRIP;
if (no_polygons_mode)
skip_draw = GL_TRUE;
break;
case GL_TRIANGLE_FAN:
gxm_p = SCE_GXM_PRIMITIVE_TRIANGLE_FAN;
if (no_polygons_mode)
skip_draw = GL_TRUE;
break;
default:
SET_GL_ERROR(GL_INVALID_ENUM)
break;
}
if (!skip_draw) {
if (cur_program != 0) {
_vglDrawObjects_CustomShadersIMPL(mode, count, implicit_wvp);
sceGxmSetFragmentTexture(gxm_context, 0, &textures[texture2d_idx].gxm_tex);
// TEXUNIT1 support for custom shaders
texture_unit *tex_unit2 = &texture_units[client_texture_unit + 1];
int texture2d_idx2 = tex_unit2->tex_id;
if (textures[texture2d_idx2].valid)
sceGxmSetFragmentTexture(gxm_context, 1, &textures[texture2d_idx2].gxm_tex);
sceGxmDraw(gxm_context, gxm_p, SCE_GXM_INDEX_FORMAT_U16, tex_unit->index_object, count);
} else {
if (tex_unit->vertex_array_state) {
if (mvp_modified) {
matrix4x4_multiply(mvp_matrix, projection_matrix, modelview_matrix);
mvp_modified = GL_FALSE;
}
if (tex_unit->texture_array_state) {
if (!(textures[texture2d_idx].valid))
return;
if (tex_unit->color_array_state) {
if (tex_unit->color_object_type == GL_FLOAT)
sceGxmSetVertexProgram(gxm_context, texture2d_rgba_vertex_program_patched);
else
sceGxmSetVertexProgram(gxm_context, texture2d_rgba_u8n_vertex_program_patched);
sceGxmSetFragmentProgram(gxm_context, texture2d_rgba_fragment_program_patched);
void *alpha_buffer;
sceGxmReserveFragmentDefaultUniformBuffer(gxm_context, &alpha_buffer);
sceGxmSetUniformDataF(alpha_buffer, texture2d_rgba_alpha_cut, 0, 1, &alpha_ref);
float alpha_operation = (float)alpha_op;
sceGxmSetUniformDataF(alpha_buffer, texture2d_rgba_alpha_op, 0, 1, &alpha_operation);
float env_mode = (float)tex_unit->env_mode;
sceGxmSetUniformDataF(alpha_buffer, texture2d_rgba_tex_env, 0, 1, &env_mode);
float fogmode = (float)internal_fog_mode;
sceGxmSetUniformDataF(alpha_buffer, texture2d_rgba_fog_mode, 0, 1, &fogmode);
sceGxmSetUniformDataF(alpha_buffer, texture2d_rgba_fog_color, 0, 4, &fog_color.r);
sceGxmSetUniformDataF(alpha_buffer, texture2d_rgba_tex_env_color, 0, 4, &texenv_color.r);
sceGxmSetUniformDataF(alpha_buffer, texture2d_rgba_fog_near, 0, 1, (const float *)&fog_near);
sceGxmSetUniformDataF(alpha_buffer, texture2d_rgba_fog_far, 0, 1, (const float *)&fog_far);
sceGxmSetUniformDataF(alpha_buffer, texture2d_rgba_fog_density, 0, 1, (const float *)&fog_density);
} else {
sceGxmSetVertexProgram(gxm_context, texture2d_vertex_program_patched);
sceGxmSetFragmentProgram(gxm_context, texture2d_fragment_program_patched);
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, &current_color.r);
float env_mode = (float)tex_unit->env_mode;
sceGxmSetUniformDataF(alpha_buffer, texture2d_tex_env, 0, 1, &env_mode);
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_tint_color, 0, 4, &current_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 if (tex_unit->color_array_state && (tex_unit->color_array.num == 3)) {
if (tex_unit->color_object_type == GL_FLOAT)
sceGxmSetVertexProgram(gxm_context, rgb_vertex_program_patched);
else
sceGxmSetVertexProgram(gxm_context, rgb_u8n_vertex_program_patched);
sceGxmSetFragmentProgram(gxm_context, rgba_fragment_program_patched);
} else {
if (tex_unit->color_object_type == GL_FLOAT)
sceGxmSetVertexProgram(gxm_context, rgba_vertex_program_patched);
else
sceGxmSetVertexProgram(gxm_context, rgba_u8n_vertex_program_patched);
sceGxmSetFragmentProgram(gxm_context, rgba_fragment_program_patched);
}
void *vertex_wvp_buffer;
sceGxmReserveVertexDefaultUniformBuffer(gxm_context, &vertex_wvp_buffer);
if (tex_unit->texture_array_state) {
if (tex_unit->color_array_state) {
sceGxmSetUniformDataF(vertex_wvp_buffer, texture2d_rgba_wvp, 0, 16, (const float *)mvp_matrix);
float clipplane0 = (float)clip_plane0;
sceGxmSetUniformDataF(vertex_wvp_buffer, texture2d_rgba_clip_plane0, 0, 1, &clipplane0);
sceGxmSetUniformDataF(vertex_wvp_buffer, texture2d_rgba_clip_plane0_eq, 0, 4, &clip_plane0_eq.x);
sceGxmSetUniformDataF(vertex_wvp_buffer, texture2d_rgba_mv, 0, 16, (const float *)modelview_matrix);
} else {
sceGxmSetUniformDataF(vertex_wvp_buffer, texture2d_wvp, 0, 16, (const float *)mvp_matrix);
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);
}
sceGxmSetFragmentTexture(gxm_context, 0, &textures[texture2d_idx].gxm_tex);
sceGxmSetVertexStream(gxm_context, 0, tex_unit->vertex_object);
sceGxmSetVertexStream(gxm_context, 1, tex_unit->texture_object);
if (tex_unit->color_array_state)
sceGxmSetVertexStream(gxm_context, 2, tex_unit->color_object);
sceGxmDraw(gxm_context, gxm_p, SCE_GXM_INDEX_FORMAT_U16, tex_unit->index_object, count);
} else if (tex_unit->color_array_state) {
if (tex_unit->color_array.num == 3)
sceGxmSetUniformDataF(vertex_wvp_buffer, rgb_wvp, 0, 16, (const float *)mvp_matrix);
else
sceGxmSetUniformDataF(vertex_wvp_buffer, rgba_wvp, 0, 16, (const float *)mvp_matrix);
sceGxmSetVertexStream(gxm_context, 0, tex_unit->vertex_object);
sceGxmSetVertexStream(gxm_context, 1, tex_unit->color_object);
sceGxmDraw(gxm_context, gxm_p, SCE_GXM_INDEX_FORMAT_U16, tex_unit->index_object, count);
} else {
sceGxmSetUniformDataF(vertex_wvp_buffer, rgba_wvp, 0, 16, (const float *)mvp_matrix);
vector4f *colors = (vector4f *)gpu_pool_memalign(count * sizeof(vector4f), sizeof(vector4f));
int n;
for (n = 0; n < count; n++) {
memcpy_neon(&colors[n], &current_color.r, sizeof(vector4f));
}
sceGxmSetVertexStream(gxm_context, 0, tex_unit->vertex_object);
sceGxmSetVertexStream(gxm_context, 1, colors);
sceGxmDraw(gxm_context, gxm_p, SCE_GXM_INDEX_FORMAT_U16, tex_unit->index_object, count);
}
}
}
}
}
size_t vglMemFree(vglMemType type) {
if (type >= VGL_MEM_TYPE_COUNT)
return 0;
return mempool_get_free_space(type);
}
void *vglAlloc(uint32_t size, vglMemType type) {
if (type >= VGL_MEM_TYPE_COUNT)
return NULL;
return mempool_alloc(size, type);
}
void vglFree(void *addr) {
mempool_free(addr, VGL_MEM_RAM); // Type is discarded so we just pass a random one
}
void vglUseExtraMem(GLboolean use) {
use_extra_mem = use;
}
GLboolean vglHasRuntimeShaderCompiler(void) {
return is_shark_online;
}