206 lines
5.6 KiB
C
206 lines
5.6 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/>.
|
|
*/
|
|
|
|
/*
|
|
* framebuffers.c:
|
|
* Implementation for framebuffers related functions
|
|
*/
|
|
|
|
#include "shared.h"
|
|
|
|
static framebuffer framebuffers[BUFFERS_NUM]; // Framebuffers array
|
|
|
|
framebuffer *active_read_fb = NULL; // Current readback framebuffer in use
|
|
framebuffer *active_write_fb = NULL; // Current write framebuffer in use
|
|
|
|
uint32_t get_color_from_texture(uint32_t type) {
|
|
uint32_t res = 0;
|
|
switch (type) {
|
|
case GL_RGB:
|
|
res = SCE_GXM_COLOR_FORMAT_U8U8U8_BGR;
|
|
break;
|
|
case GL_RGBA:
|
|
res = SCE_GXM_COLOR_FORMAT_U8U8U8U8_ABGR;
|
|
break;
|
|
case GL_LUMINANCE:
|
|
res = SCE_GXM_COLOR_FORMAT_U8_R;
|
|
break;
|
|
case GL_LUMINANCE_ALPHA:
|
|
res = SCE_GXM_COLOR_FORMAT_U8U8_GR;
|
|
break;
|
|
case GL_INTENSITY:
|
|
res = SCE_GXM_COLOR_FORMAT_U8_R;
|
|
break;
|
|
case GL_ALPHA:
|
|
res = SCE_GXM_COLOR_FORMAT_U8_A;
|
|
break;
|
|
default:
|
|
vgl_error = GL_INVALID_ENUM;
|
|
break;
|
|
}
|
|
return res;
|
|
}
|
|
|
|
/*
|
|
* ------------------------------
|
|
* - IMPLEMENTATION STARTS HERE -
|
|
* ------------------------------
|
|
*/
|
|
|
|
void glGenFramebuffers(GLsizei n, GLuint *ids) {
|
|
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 (!framebuffers[i].active) {
|
|
ids[j++] = (GLuint)&framebuffers[i];
|
|
framebuffers[i].active = 1;
|
|
framebuffers[i].depth_buffer_addr = NULL;
|
|
framebuffers[i].stencil_buffer_addr = NULL;
|
|
}
|
|
if (j >= n)
|
|
break;
|
|
}
|
|
}
|
|
|
|
void glDeleteFramebuffers(GLsizei n, GLuint *framebuffers) {
|
|
#ifndef SKIP_ERROR_HANDLING
|
|
if (n < 0) {
|
|
SET_GL_ERROR(GL_INVALID_VALUE)
|
|
}
|
|
#endif
|
|
while (n > 0) {
|
|
framebuffer *fb = (framebuffer *)framebuffers[n--];
|
|
fb->active = 0;
|
|
if (fb->target) {
|
|
sceGxmDestroyRenderTarget(fb->target);
|
|
fb->target = NULL;
|
|
}
|
|
if (fb->depth_buffer_addr) {
|
|
mempool_free(fb->depth_buffer_addr, fb->depth_buffer_mem_type);
|
|
mempool_free(fb->stencil_buffer_addr, fb->stencil_buffer_mem_type);
|
|
fb->depth_buffer_addr = NULL;
|
|
fb->stencil_buffer_addr = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
void glBindFramebuffer(GLenum target, GLuint fb) {
|
|
switch (target) {
|
|
case GL_DRAW_FRAMEBUFFER:
|
|
active_write_fb = (framebuffer *)fb;
|
|
break;
|
|
case GL_READ_FRAMEBUFFER:
|
|
active_read_fb = (framebuffer *)fb;
|
|
break;
|
|
case GL_FRAMEBUFFER:
|
|
active_write_fb = active_read_fb = (framebuffer *)fb;
|
|
break;
|
|
default:
|
|
SET_GL_ERROR(GL_INVALID_ENUM)
|
|
break;
|
|
}
|
|
}
|
|
|
|
void glFramebufferTexture(GLenum target, GLenum attachment, GLuint tex_id, GLint level) {
|
|
// Detecting requested framebuffer
|
|
framebuffer *fb = NULL;
|
|
switch (target) {
|
|
case GL_DRAW_FRAMEBUFFER:
|
|
case GL_FRAMEBUFFER:
|
|
fb = active_write_fb;
|
|
break;
|
|
case GL_READ_FRAMEBUFFER:
|
|
fb = active_read_fb;
|
|
break;
|
|
default:
|
|
SET_GL_ERROR(GL_INVALID_ENUM)
|
|
break;
|
|
}
|
|
|
|
// Aliasing to make code more readable
|
|
texture *tex = &textures[tex_id];
|
|
|
|
// Extracting texture sizes
|
|
fb->width = sceGxmTextureGetWidth(&tex->gxm_tex);
|
|
fb->height = sceGxmTextureGetHeight(&tex->gxm_tex);
|
|
|
|
// Detecting requested attachment
|
|
switch (attachment) {
|
|
case GL_COLOR_ATTACHMENT0:
|
|
|
|
// Allocating colorbuffer
|
|
sceGxmColorSurfaceInit(
|
|
&fb->colorbuffer,
|
|
get_color_from_texture(tex->type),
|
|
SCE_GXM_COLOR_SURFACE_LINEAR,
|
|
msaa_mode == SCE_GXM_MULTISAMPLE_NONE ? SCE_GXM_COLOR_SURFACE_SCALE_NONE : SCE_GXM_COLOR_SURFACE_SCALE_MSAA_DOWNSCALE,
|
|
SCE_GXM_OUTPUT_REGISTER_SIZE_32BIT,
|
|
fb->width,
|
|
fb->height,
|
|
fb->width,
|
|
sceGxmTextureGetData(&tex->gxm_tex));
|
|
|
|
// Allocating depth and stencil buffer (FIXME: This probably shouldn't be here)
|
|
initDepthStencilBuffer(fb->width, fb->height, &fb->depthbuffer, &fb->depth_buffer_addr, &fb->stencil_buffer_addr, &fb->depth_buffer_mem_type, &fb->stencil_buffer_mem_type);
|
|
|
|
// Creating rendertarget
|
|
SceGxmRenderTargetParams renderTargetParams;
|
|
memset(&renderTargetParams, 0, sizeof(SceGxmRenderTargetParams));
|
|
renderTargetParams.flags = 0;
|
|
renderTargetParams.width = sceGxmTextureGetWidth(&tex->gxm_tex);
|
|
renderTargetParams.height = sceGxmTextureGetHeight(&tex->gxm_tex);
|
|
renderTargetParams.scenesPerFrame = 1;
|
|
renderTargetParams.multisampleMode = msaa_mode;
|
|
renderTargetParams.multisampleLocations = 0;
|
|
renderTargetParams.driverMemBlock = -1;
|
|
sceGxmCreateRenderTarget(&renderTargetParams, &fb->target);
|
|
break;
|
|
default:
|
|
SET_GL_ERROR(GL_INVALID_ENUM)
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* vgl* */
|
|
|
|
void vglTexImageDepthBuffer(GLenum target) {
|
|
// Setting some aliases to make code more readable
|
|
texture_unit *tex_unit = &texture_units[server_texture_unit];
|
|
int texture2d_idx = tex_unit->tex_id;
|
|
texture *tex = &textures[texture2d_idx];
|
|
|
|
switch (target) {
|
|
case GL_TEXTURE_2D:
|
|
{
|
|
if (active_read_fb)
|
|
sceGxmTextureInitLinear(&tex->gxm_tex, active_read_fb->depth_buffer_addr, SCE_GXM_TEXTURE_FORMAT_DF32M, active_read_fb->width, active_read_fb->height, 0);
|
|
else
|
|
sceGxmTextureInitLinear(&tex->gxm_tex, gxm_depth_surface_addr, SCE_GXM_TEXTURE_FORMAT_DF32M, DISPLAY_WIDTH, DISPLAY_HEIGHT, 0);
|
|
tex->valid = 1;
|
|
}
|
|
break;
|
|
default:
|
|
SET_GL_ERROR(GL_INVALID_ENUM)
|
|
break;
|
|
}
|
|
}
|