mirror of https://github.com/xemu-project/xemu.git
nv2a/gl: Improve renderer teardown
This commit is contained in:
parent
c1eb48b62f
commit
84dd112186
|
@ -102,6 +102,33 @@ void pgraph_gl_init_display_renderer(NV2AState *d)
|
|||
assert(glGetError() == GL_NO_ERROR);
|
||||
}
|
||||
|
||||
void pgraph_gl_finalize_display(PGRAPHState *pg)
|
||||
{
|
||||
PGRAPHGLState *r = pg->gl_renderer_state;
|
||||
|
||||
glo_set_current(g_nv2a_context_display);
|
||||
|
||||
glDeleteTextures(1, &r->gl_display_buffer);
|
||||
r->gl_display_buffer = 0;
|
||||
|
||||
glDeleteProgram(r->disp_rndr.prog);
|
||||
r->disp_rndr.prog = 0;
|
||||
|
||||
glDeleteVertexArrays(1, &r->disp_rndr.vao);
|
||||
r->disp_rndr.vao = 0;
|
||||
|
||||
glDeleteBuffers(1, &r->disp_rndr.vbo);
|
||||
r->disp_rndr.vbo = 0;
|
||||
|
||||
glDeleteFramebuffers(1, &r->disp_rndr.fbo);
|
||||
r->disp_rndr.fbo = 0;
|
||||
|
||||
glDeleteTextures(1, &r->disp_rndr.pvideo_tex);
|
||||
r->disp_rndr.pvideo_tex = 0;
|
||||
|
||||
glo_set_current(g_nv2a_context_render);
|
||||
}
|
||||
|
||||
static uint8_t *convert_texture_data__CR8YB8CB8YA8(const uint8_t *data,
|
||||
unsigned int width,
|
||||
unsigned int height,
|
||||
|
|
|
@ -33,24 +33,63 @@ static void nv2a_gl_context_init(void)
|
|||
g_nv2a_context_display = glo_context_create();
|
||||
}
|
||||
|
||||
static void pgraph_gl_init(NV2AState *d)
|
||||
{
|
||||
PGRAPHState *pg = &d->pgraph;
|
||||
|
||||
pg->gl_renderer_state = g_malloc0(sizeof(*pg->gl_renderer_state));
|
||||
|
||||
/* fire up opengl */
|
||||
glo_set_current(g_nv2a_context_render);
|
||||
|
||||
#ifdef DEBUG_NV2A_GL
|
||||
gl_debug_initialize();
|
||||
#endif
|
||||
|
||||
/* DXT textures */
|
||||
assert(glo_check_extension("GL_EXT_texture_compression_s3tc"));
|
||||
/* Internal RGB565 texture format */
|
||||
assert(glo_check_extension("GL_ARB_ES2_compatibility"));
|
||||
|
||||
pgraph_gl_init_surfaces(pg);
|
||||
pgraph_gl_init_reports(d);
|
||||
pgraph_gl_init_texture_cache(d);
|
||||
pgraph_gl_init_vertex_cache(d);
|
||||
pgraph_gl_init_shader_cache(pg);
|
||||
|
||||
glo_set_current(g_nv2a_context_display);
|
||||
pgraph_gl_init_display_renderer(d);
|
||||
|
||||
pgraph_gl_update_entire_memory_buffer(d);
|
||||
|
||||
glo_set_current(NULL);
|
||||
|
||||
pg->uniform_attrs = 0;
|
||||
pg->swizzle_attrs = 0;
|
||||
}
|
||||
|
||||
static void pgraph_gl_init_thread(NV2AState *d)
|
||||
{
|
||||
glo_set_current(g_nv2a_context_render);
|
||||
}
|
||||
|
||||
static void pgraph_gl_deinit(NV2AState *d)
|
||||
static void pgraph_gl_finalize(NV2AState *d)
|
||||
{
|
||||
PGRAPHState *pg = &d->pgraph;
|
||||
|
||||
glo_set_current(g_nv2a_context_render);
|
||||
|
||||
pgraph_gl_deinit_surfaces(pg);
|
||||
pgraph_gl_deinit_shader_cache(pg);
|
||||
pgraph_gl_deinit_texture_cache(pg);
|
||||
pgraph_gl_finalize_surfaces(pg);
|
||||
pgraph_gl_finalize_shaders(pg);
|
||||
pgraph_gl_finalize_textures(pg);
|
||||
pgraph_gl_finalize_reports(pg);
|
||||
pgraph_gl_finalize_vertex(pg);
|
||||
pgraph_gl_finalize_display(pg);
|
||||
|
||||
glo_set_current(NULL);
|
||||
glo_context_destroy(g_nv2a_context_render);
|
||||
glo_context_destroy(g_nv2a_context_display);
|
||||
|
||||
g_free(pg->gl_renderer_state);
|
||||
pg->gl_renderer_state = NULL;
|
||||
}
|
||||
|
||||
static void pgraph_gl_flip_stall(NV2AState *d)
|
||||
|
@ -136,36 +175,6 @@ static void pgraph_gl_pre_shutdown_wait(NV2AState *d)
|
|||
qemu_event_wait(&r->shader_cache_writeback_complete);
|
||||
}
|
||||
|
||||
static void pgraph_gl_init(NV2AState *d)
|
||||
{
|
||||
PGRAPHState *pg = &d->pgraph;
|
||||
|
||||
pg->gl_renderer_state = g_malloc(sizeof(PGRAPHGLState));
|
||||
|
||||
/* fire up opengl */
|
||||
glo_set_current(g_nv2a_context_render);
|
||||
|
||||
#ifdef DEBUG_NV2A_GL
|
||||
gl_debug_initialize();
|
||||
#endif
|
||||
|
||||
/* DXT textures */
|
||||
assert(glo_check_extension("GL_EXT_texture_compression_s3tc"));
|
||||
/* Internal RGB565 texture format */
|
||||
assert(glo_check_extension("GL_ARB_ES2_compatibility"));
|
||||
|
||||
pgraph_gl_init_surfaces(pg);
|
||||
pgraph_gl_init_reports(d);
|
||||
pgraph_gl_init_texture_cache(d);
|
||||
pgraph_gl_init_vertex_cache(d);
|
||||
pgraph_gl_init_shader_cache(pg);
|
||||
|
||||
glo_set_current(g_nv2a_context_display);
|
||||
pgraph_gl_init_display_renderer(d);
|
||||
|
||||
glo_set_current(NULL);
|
||||
}
|
||||
|
||||
static PGRAPHRenderer pgraph_gl_renderer = {
|
||||
.type = CONFIG_DISPLAY_RENDERER_OPENGL,
|
||||
.name = "OpenGL",
|
||||
|
@ -173,7 +182,7 @@ static PGRAPHRenderer pgraph_gl_renderer = {
|
|||
.init = pgraph_gl_init,
|
||||
.early_context_init = nv2a_gl_context_init,
|
||||
.init_thread = pgraph_gl_init_thread,
|
||||
.finalize = pgraph_gl_deinit,
|
||||
.finalize = pgraph_gl_finalize,
|
||||
.clear_report_value = pgraph_gl_clear_report_value,
|
||||
.clear_surface = pgraph_gl_clear_surface,
|
||||
.draw_begin = pgraph_gl_draw_begin,
|
||||
|
|
|
@ -240,9 +240,6 @@ void pgraph_gl_bind_textures(NV2AState *d);
|
|||
void pgraph_gl_bind_vertex_attributes(NV2AState *d, unsigned int min_element, unsigned int max_element, bool inline_data, unsigned int inline_stride, unsigned int provoking_element);
|
||||
bool pgraph_gl_check_surface_to_texture_compatibility(const SurfaceBinding *surface, const TextureShape *shape);
|
||||
GLuint pgraph_gl_compile_shader(const char *vs_src, const char *fs_src);
|
||||
void pgraph_gl_deinit_shader_cache(PGRAPHState *pg);
|
||||
void pgraph_gl_deinit_surfaces(PGRAPHState *pg);
|
||||
void pgraph_gl_deinit_texture_cache(PGRAPHState *pg);
|
||||
void pgraph_gl_download_dirty_surfaces(NV2AState *d);
|
||||
void pgraph_gl_clear_report_value(NV2AState *d);
|
||||
void pgraph_gl_clear_surface(NV2AState *d, uint32_t parameter);
|
||||
|
@ -258,11 +255,17 @@ void pgraph_gl_surface_update(NV2AState *d, bool upload, bool color_write, bool
|
|||
void pgraph_gl_sync(NV2AState *d);
|
||||
void pgraph_gl_update_entire_memory_buffer(NV2AState *d);
|
||||
void pgraph_gl_init_display_renderer(NV2AState *d);
|
||||
void pgraph_gl_finalize_display(PGRAPHState *pg);
|
||||
void pgraph_gl_init_reports(NV2AState *d);
|
||||
void pgraph_gl_finalize_reports(PGRAPHState *pg);
|
||||
void pgraph_gl_init_shader_cache(PGRAPHState *pg);
|
||||
void pgraph_gl_finalize_shaders(PGRAPHState *pg);
|
||||
void pgraph_gl_init_surfaces(PGRAPHState *pg);
|
||||
void pgraph_gl_finalize_surfaces(PGRAPHState *pg);
|
||||
void pgraph_gl_init_texture_cache(NV2AState *d);
|
||||
void pgraph_gl_finalize_textures(PGRAPHState *pg);
|
||||
void pgraph_gl_init_vertex_cache(NV2AState *d);
|
||||
void pgraph_gl_finalize_vertex(PGRAPHState *pg);
|
||||
void pgraph_gl_process_pending_downloads(NV2AState *d);
|
||||
void pgraph_gl_reload_surface_scale_factor(PGRAPHState *pg);
|
||||
void pgraph_gl_render_surface_to_texture(NV2AState *d, SurfaceBinding *surface, TextureBinding *texture, TextureShape *texture_shape, int texture_unit);
|
||||
|
|
|
@ -109,3 +109,23 @@ void pgraph_gl_get_report(NV2AState *d, uint32_t parameter)
|
|||
r->gl_zpass_pixel_count_query_count = 0;
|
||||
r->gl_zpass_pixel_count_queries = NULL;
|
||||
}
|
||||
|
||||
void pgraph_gl_finalize_reports(PGRAPHState *pg)
|
||||
{
|
||||
PGRAPHGLState *r = pg->gl_renderer_state;
|
||||
|
||||
QueryReport *report, *next;
|
||||
QSIMPLEQ_FOREACH_SAFE (report, &r->report_queue, entry, next) {
|
||||
if (report->query_count) {
|
||||
glDeleteQueries(report->query_count, report->queries);
|
||||
}
|
||||
QSIMPLEQ_REMOVE_HEAD(&r->report_queue, entry);
|
||||
g_free(report);
|
||||
}
|
||||
|
||||
if (r->gl_zpass_pixel_count_query_count) {
|
||||
glDeleteQueries(r->gl_zpass_pixel_count_query_count,
|
||||
r->gl_zpass_pixel_count_queries);
|
||||
r->gl_zpass_pixel_count_query_count = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -581,13 +581,15 @@ void pgraph_gl_init_shader_cache(PGRAPHState *pg)
|
|||
shader_reload_lru_from_disk, pg, QEMU_THREAD_JOINABLE);
|
||||
}
|
||||
|
||||
void pgraph_gl_deinit_shader_cache(PGRAPHState *pg)
|
||||
void pgraph_gl_finalize_shaders(PGRAPHState *pg)
|
||||
{
|
||||
PGRAPHGLState *r = pg->gl_renderer_state;
|
||||
|
||||
// Clear out shader cache
|
||||
pgraph_gl_shader_write_cache_reload_list(pg);
|
||||
pgraph_gl_shader_write_cache_reload_list(pg); // FIXME: also flushes, rename for clarity
|
||||
free(r->shader_cache_entries);
|
||||
r->shader_cache_entries = NULL;
|
||||
|
||||
qemu_mutex_destroy(&r->shader_cache_lock);
|
||||
}
|
||||
|
||||
|
|
|
@ -162,6 +162,23 @@ static void init_render_to_texture(PGRAPHState *pg)
|
|||
glGenFramebuffers(1, &r->s2t_rndr.fbo);
|
||||
}
|
||||
|
||||
static void finalize_render_to_texture(PGRAPHState *pg)
|
||||
{
|
||||
PGRAPHGLState *r = pg->gl_renderer_state;
|
||||
|
||||
glDeleteProgram(r->s2t_rndr.prog);
|
||||
r->s2t_rndr.prog = 0;
|
||||
|
||||
glDeleteVertexArrays(1, &r->s2t_rndr.vao);
|
||||
r->s2t_rndr.vao = 0;
|
||||
|
||||
glDeleteBuffers(1, &r->s2t_rndr.vbo);
|
||||
r->s2t_rndr.vbo = 0;
|
||||
|
||||
glDeleteFramebuffers(1, &r->s2t_rndr.fbo);
|
||||
r->s2t_rndr.fbo = 0;
|
||||
}
|
||||
|
||||
static bool surface_to_texture_can_fastpath(SurfaceBinding *surface,
|
||||
TextureShape *shape)
|
||||
{
|
||||
|
@ -1365,21 +1382,11 @@ void pgraph_gl_init_surfaces(PGRAPHState *pg)
|
|||
init_render_to_texture(pg);
|
||||
}
|
||||
|
||||
void pgraph_gl_deinit_surfaces(PGRAPHState *pg)
|
||||
{
|
||||
PGRAPHGLState *r = pg->gl_renderer_state;
|
||||
|
||||
glDeleteFramebuffers(1, &r->gl_framebuffer);
|
||||
// TODO: clear out surfaces
|
||||
}
|
||||
|
||||
void pgraph_gl_surface_flush(NV2AState *d)
|
||||
static void flush_surfaces(NV2AState *d)
|
||||
{
|
||||
PGRAPHState *pg = &d->pgraph;
|
||||
PGRAPHGLState *r = pg->gl_renderer_state;
|
||||
|
||||
bool update_surface = (r->color_binding || r->zeta_binding);
|
||||
|
||||
/* Clear last surface shape to force recreation of buffers at next draw */
|
||||
pg->surface_color.draw_dirty = false;
|
||||
pg->surface_zeta.draw_dirty = false;
|
||||
|
@ -1391,6 +1398,28 @@ void pgraph_gl_surface_flush(NV2AState *d)
|
|||
QTAILQ_FOREACH_SAFE(s, &r->surfaces, entry, next) {
|
||||
pgraph_gl_surface_invalidate(d, s);
|
||||
}
|
||||
}
|
||||
|
||||
void pgraph_gl_finalize_surfaces(PGRAPHState *pg)
|
||||
{
|
||||
NV2AState *d = container_of(pg, NV2AState, pgraph);
|
||||
PGRAPHGLState *r = pg->gl_renderer_state;
|
||||
|
||||
flush_surfaces(d);
|
||||
glDeleteFramebuffers(1, &r->gl_framebuffer);
|
||||
r->gl_framebuffer = 0;
|
||||
|
||||
finalize_render_to_texture(pg);
|
||||
}
|
||||
|
||||
void pgraph_gl_surface_flush(NV2AState *d)
|
||||
{
|
||||
PGRAPHState *pg = &d->pgraph;
|
||||
PGRAPHGLState *r = pg->gl_renderer_state;
|
||||
|
||||
bool update_surface = (r->color_binding || r->zeta_binding);
|
||||
|
||||
flush_surfaces(d);
|
||||
|
||||
pgraph_gl_reload_surface_scale_factor(pg);
|
||||
|
||||
|
|
|
@ -809,11 +809,16 @@ void pgraph_gl_init_texture_cache(NV2AState *d)
|
|||
r->texture_cache.post_node_evict = texture_cache_entry_post_evict;
|
||||
}
|
||||
|
||||
void pgraph_gl_deinit_texture_cache(PGRAPHState *pg)
|
||||
void pgraph_gl_finalize_textures(PGRAPHState *pg)
|
||||
{
|
||||
PGRAPHGLState *r = pg->gl_renderer_state;
|
||||
|
||||
// Clear out texture cache
|
||||
for (int i = 0; i < NV2A_MAX_TEXTURES; i++) {
|
||||
r->texture_binding[i] = NULL;
|
||||
}
|
||||
|
||||
lru_flush(&r->texture_cache);
|
||||
free(r->texture_cache_entries);
|
||||
|
||||
r->texture_cache_entries = NULL;
|
||||
}
|
||||
|
|
|
@ -245,14 +245,15 @@ static bool vertex_cache_entry_compare(Lru *lru, LruNode *node, void *key)
|
|||
return memcmp(&vnode->key, key, sizeof(VertexKey));
|
||||
}
|
||||
|
||||
static const size_t element_cache_size = 50*1024;
|
||||
|
||||
void pgraph_gl_init_vertex_cache(NV2AState *d)
|
||||
{
|
||||
PGRAPHState *pg = &d->pgraph;
|
||||
PGRAPHGLState *r = pg->gl_renderer_state;
|
||||
|
||||
const size_t element_cache_size = 50*1024;
|
||||
lru_init(&r->element_cache);
|
||||
r->element_cache_entries = malloc(element_cache_size * sizeof(VertexLruNode));
|
||||
r->element_cache_entries = g_malloc_n(element_cache_size, sizeof(VertexLruNode));
|
||||
assert(r->element_cache_entries != NULL);
|
||||
GLuint element_cache_buffers[element_cache_size];
|
||||
glGenBuffers(element_cache_size, element_cache_buffers);
|
||||
|
@ -281,3 +282,30 @@ void pgraph_gl_init_vertex_cache(NV2AState *d)
|
|||
|
||||
assert(glGetError() == GL_NO_ERROR);
|
||||
}
|
||||
|
||||
void pgraph_gl_finalize_vertex(PGRAPHState *pg)
|
||||
{
|
||||
PGRAPHGLState *r = pg->gl_renderer_state;
|
||||
|
||||
GLuint element_cache_buffers[element_cache_size];
|
||||
for (int i = 0; i < element_cache_size; i++) {
|
||||
element_cache_buffers[i] = r->element_cache_entries[i].gl_buffer;
|
||||
}
|
||||
glDeleteBuffers(element_cache_size, element_cache_buffers);
|
||||
lru_flush(&r->element_cache);
|
||||
|
||||
g_free(r->element_cache_entries);
|
||||
r->element_cache_entries = NULL;
|
||||
|
||||
glDeleteBuffers(NV2A_VERTEXSHADER_ATTRIBUTES, r->gl_inline_buffer);
|
||||
memset(r->gl_inline_buffer, 0, sizeof(r->gl_inline_buffer));
|
||||
|
||||
glDeleteBuffers(1, &r->gl_inline_array_buffer);
|
||||
r->gl_inline_array_buffer = 0;
|
||||
|
||||
glDeleteBuffers(1, &r->gl_memory_buffer);
|
||||
r->gl_memory_buffer = 0;
|
||||
|
||||
glDeleteVertexArrays(1, &r->gl_vertex_array);
|
||||
r->gl_vertex_array = 0;
|
||||
}
|
Loading…
Reference in New Issue