mirror of
https://github.com/libretro/RetroArch.git
synced 2024-11-28 02:30:35 +00:00
Start adding gl1_renderchain.c
This commit is contained in:
parent
3ab26b6738
commit
60d96b60b5
@ -2162,7 +2162,7 @@ static bool gl_set_shader(void *data,
|
||||
|
||||
if (textures > gl->textures) /* Have to reinit a bit. */
|
||||
{
|
||||
if (gl->hw_render_use &&
|
||||
if (gl->hw_render_use && gl->fbo_inited &&
|
||||
gl->renderchain_driver->deinit_hw_render)
|
||||
gl->renderchain_driver->deinit_hw_render(gl);
|
||||
|
||||
|
320
gfx/drivers_renderchain/gl1_renderchain.c
Normal file
320
gfx/drivers_renderchain/gl1_renderchain.c
Normal file
@ -0,0 +1,320 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
|
||||
* Copyright (C) 2011-2017 - Daniel De Matteis
|
||||
* Copyright (C) 2012-2015 - Michael Lelli
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* RetroArch 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 RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma comment(lib, "opengl32")
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <retro_common_api.h>
|
||||
#include <libretro.h>
|
||||
|
||||
#include <compat/strl.h>
|
||||
#include <gfx/scaler/scaler.h>
|
||||
#include <formats/image.h>
|
||||
#include <retro_inline.h>
|
||||
#include <retro_miscellaneous.h>
|
||||
#include <retro_math.h>
|
||||
#include <string/stdstring.h>
|
||||
|
||||
#include <gfx/gl_capabilities.h>
|
||||
#include <gfx/video_frame.h>
|
||||
|
||||
#include "../video_driver.h"
|
||||
#include "../video_shader_parse.h"
|
||||
#include "../common/gl_common.h"
|
||||
|
||||
#include "../../driver.h"
|
||||
#include "../../configuration.h"
|
||||
#include "../../verbosity.h"
|
||||
|
||||
#if defined(_WIN32) && !defined(_XBOX)
|
||||
#include "../common/win32_common.h"
|
||||
#endif
|
||||
|
||||
typedef struct gl1_renderchain
|
||||
{
|
||||
void *empty;
|
||||
} gl1_renderchain_t;
|
||||
|
||||
#define gl1_bind_fb(id) glBindFramebuffer(RARCH_GL_FRAMEBUFFER, id)
|
||||
|
||||
/* Prototypes */
|
||||
static void gl1_renderchain_bind_backbuffer(void)
|
||||
{
|
||||
gl1_bind_fb(0);
|
||||
}
|
||||
|
||||
void context_bind_hw_render(bool enable);
|
||||
|
||||
GLenum min_filter_to_mag(GLenum type);
|
||||
|
||||
void gl1_renderchain_free(void *data)
|
||||
{
|
||||
gl_t *gl = (gl_t*)data;
|
||||
(void)gl;
|
||||
}
|
||||
|
||||
static void gl1_renderchain_bind_prev_texture(
|
||||
void *data,
|
||||
const struct video_tex_info *tex_info)
|
||||
{
|
||||
gl_t *gl = (gl_t*)data;
|
||||
|
||||
memmove(gl->prev_info + 1, gl->prev_info,
|
||||
sizeof(*tex_info) * (gl->textures - 1));
|
||||
memcpy(&gl->prev_info[0], tex_info,
|
||||
sizeof(*tex_info));
|
||||
}
|
||||
|
||||
static void gl1_renderchain_viewport_info(
|
||||
void *data, struct video_viewport *vp)
|
||||
{
|
||||
unsigned width, height;
|
||||
unsigned top_y, top_dist;
|
||||
gl_t *gl = (gl_t*)data;
|
||||
|
||||
video_driver_get_size(&width, &height);
|
||||
|
||||
*vp = gl->vp;
|
||||
vp->full_width = width;
|
||||
vp->full_height = height;
|
||||
|
||||
/* Adjust as GL viewport is bottom-up. */
|
||||
top_y = vp->y + vp->height;
|
||||
top_dist = height - top_y;
|
||||
vp->y = top_dist;
|
||||
}
|
||||
|
||||
static bool gl1_renderchain_read_viewport(
|
||||
void *data, uint8_t *buffer, bool is_idle)
|
||||
{
|
||||
unsigned num_pixels = 0;
|
||||
gl_t *gl = (gl_t*)data;
|
||||
|
||||
if (!gl)
|
||||
return false;
|
||||
|
||||
context_bind_hw_render(false);
|
||||
|
||||
num_pixels = gl->vp.width * gl->vp.height;
|
||||
|
||||
{
|
||||
/* Use slow synchronous readbacks. Use this with plain screenshots
|
||||
as we don't really care about performance in this case. */
|
||||
|
||||
/* GLES2 only guarantees GL_RGBA/GL_UNSIGNED_BYTE
|
||||
* readbacks so do just that.
|
||||
* GLES2 also doesn't support reading back data
|
||||
* from front buffer, so render a cached frame
|
||||
* and have gl_frame() do the readback while it's
|
||||
* in the back buffer.
|
||||
*
|
||||
* Keep codepath similar for GLES and desktop GL.
|
||||
*/
|
||||
gl->readback_buffer_screenshot = malloc(num_pixels * sizeof(uint32_t));
|
||||
|
||||
if (!gl->readback_buffer_screenshot)
|
||||
goto error;
|
||||
|
||||
if (!is_idle)
|
||||
video_driver_cached_frame();
|
||||
|
||||
video_frame_convert_rgba_to_bgr(
|
||||
(const void*)gl->readback_buffer_screenshot,
|
||||
buffer,
|
||||
num_pixels);
|
||||
|
||||
free(gl->readback_buffer_screenshot);
|
||||
gl->readback_buffer_screenshot = NULL;
|
||||
}
|
||||
|
||||
context_bind_hw_render(true);
|
||||
return true;
|
||||
|
||||
error:
|
||||
context_bind_hw_render(true);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void gl1_renderchain_free_internal(void *data)
|
||||
{
|
||||
gl1_renderchain_t *cg_data = (gl1_renderchain_t*)data;
|
||||
|
||||
if (!cg_data)
|
||||
return;
|
||||
|
||||
free(cg_data);
|
||||
}
|
||||
|
||||
static void *gl1_renderchain_new(void)
|
||||
{
|
||||
gl1_renderchain_t *renderchain = (gl1_renderchain_t*)calloc(1, sizeof(*renderchain));
|
||||
if (!renderchain)
|
||||
return NULL;
|
||||
|
||||
return renderchain;
|
||||
}
|
||||
|
||||
static void gl1_renderchain_ff_vertex(const void *data)
|
||||
{
|
||||
const struct video_coords *coords = (const struct video_coords*)data;
|
||||
/* Fall back to fixed function-style if needed and possible. */
|
||||
glClientActiveTexture(GL_TEXTURE1);
|
||||
glTexCoordPointer(2, GL_FLOAT, 0, coords->lut_tex_coord);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glClientActiveTexture(GL_TEXTURE0);
|
||||
glVertexPointer(2, GL_FLOAT, 0, coords->vertex);
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glColorPointer(4, GL_FLOAT, 0, coords->color);
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
glTexCoordPointer(2, GL_FLOAT, 0, coords->tex_coord);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
|
||||
static void gl1_renderchain_ff_matrix(const void *data)
|
||||
{
|
||||
math_matrix_4x4 ident;
|
||||
const math_matrix_4x4 *mat = (const math_matrix_4x4*)data;
|
||||
|
||||
/* Fall back to fixed function-style if needed and possible. */
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadMatrixf(mat->data);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
matrix_4x4_identity(ident);
|
||||
glLoadMatrixf(ident.data);
|
||||
}
|
||||
|
||||
static void gl1_renderchain_disable_client_arrays(void)
|
||||
{
|
||||
if (gl_query_core_context_in_use())
|
||||
return;
|
||||
|
||||
glClientActiveTexture(GL_TEXTURE1);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glClientActiveTexture(GL_TEXTURE0);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
|
||||
static void gl1_renderchain_restore_default_state(void *data)
|
||||
{
|
||||
gl_t *gl = (gl_t*)data;
|
||||
if (!gl)
|
||||
return;
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_CULL_FACE);
|
||||
glDisable(GL_DITHER);
|
||||
}
|
||||
|
||||
static void gl1_renderchain_copy_frame(
|
||||
void *data,
|
||||
video_frame_info_t *video_info,
|
||||
const void *frame,
|
||||
unsigned width, unsigned height, unsigned pitch)
|
||||
{
|
||||
gl_t *gl = (gl_t*)data;
|
||||
const GLvoid *data_buf = frame;
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, video_pixel_get_alignment(pitch));
|
||||
|
||||
if (gl->base_size == 2 && !gl->have_es2_compat)
|
||||
{
|
||||
/* Convert to 32-bit textures on desktop GL.
|
||||
*
|
||||
* It is *much* faster (order of magnitude on my setup)
|
||||
* to use a custom SIMD-optimized conversion routine
|
||||
* than letting GL do it. */
|
||||
video_frame_convert_rgb16_to_rgb32(
|
||||
&gl->scaler,
|
||||
gl->conv_buffer,
|
||||
frame,
|
||||
width,
|
||||
height,
|
||||
pitch);
|
||||
data_buf = gl->conv_buffer;
|
||||
}
|
||||
else
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, pitch / gl->base_size);
|
||||
|
||||
glTexSubImage2D(GL_TEXTURE_2D,
|
||||
0, 0, 0, width, height, gl->texture_type,
|
||||
gl->texture_fmt, data_buf);
|
||||
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||
}
|
||||
|
||||
static void gl1_renderchain_readback(void *data,
|
||||
unsigned alignment,
|
||||
unsigned fmt, unsigned type,
|
||||
void *src)
|
||||
{
|
||||
gl_t *gl = (gl_t*)data;
|
||||
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, alignment);
|
||||
glPixelStorei(GL_PACK_ROW_LENGTH, 0);
|
||||
glReadBuffer(GL_BACK);
|
||||
|
||||
glReadPixels(gl->vp.x, gl->vp.y,
|
||||
gl->vp.width, gl->vp.height,
|
||||
(GLenum)fmt, (GLenum)type, (GLvoid*)src);
|
||||
}
|
||||
|
||||
gl_renderchain_driver_t gl2_renderchain = {
|
||||
NULL, /* init_textures_reference */
|
||||
NULL, /* fence_iterate */
|
||||
NULL, /* fence_free */
|
||||
gl1_renderchain_readback,
|
||||
NULL, /* renderchain_init_pbo */
|
||||
NULL, /* renderchain_bind_pbo */
|
||||
NULL, /* renderchain_unbind_pbo */
|
||||
gl1_renderchain_copy_frame,
|
||||
gl1_renderchain_restore_default_state,
|
||||
NULL, /* new_vao */
|
||||
NULL, /* free_vao */
|
||||
NULL, /* bind_vao */
|
||||
NULL, /* unbind_vao */
|
||||
gl1_renderchain_disable_client_arrays, /* disable_client_arrays */
|
||||
gl1_renderchain_ff_vertex, /* ff_vertex */
|
||||
gl1_renderchain_ff_matrix,
|
||||
gl1_renderchain_bind_backbuffer,
|
||||
NULL, /* deinit_fbo */
|
||||
gl1_renderchain_viewport_info,
|
||||
gl1_renderchain_read_viewport,
|
||||
gl1_renderchain_bind_prev_texture,
|
||||
gl1_renderchain_free_internal,
|
||||
gl1_renderchain_new,
|
||||
NULL, /* renderchain_init */
|
||||
NULL, /* init_hw_render */
|
||||
gl1_renderchain_free,
|
||||
NULL, /* deinit_hw_render */
|
||||
NULL, /* start_render */
|
||||
NULL, /* check_fbo_dimensions */
|
||||
NULL, /* recompute_pass_sizes */
|
||||
NULL, /* renderchain_render */
|
||||
"gl1",
|
||||
};
|
Loading…
Reference in New Issue
Block a user