mirror of https://github.com/xemu-project/xemu.git
290 lines
9.1 KiB
C
290 lines
9.1 KiB
C
/*
|
|
* Geforce NV2A PGRAPH OpenGL Renderer
|
|
*
|
|
* Copyright (c) 2012 espes
|
|
* Copyright (c) 2015 Jannik Vogel
|
|
* Copyright (c) 2018-2024 Matt Borgerson
|
|
*
|
|
* This library 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; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library 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
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#ifndef HW_XBOX_NV2A_PGRAPH_GL_RENDERER_H
|
|
#define HW_XBOX_NV2A_PGRAPH_GL_RENDERER_H
|
|
|
|
#include "qemu/osdep.h"
|
|
#include "qemu/thread.h"
|
|
#include "qemu/queue.h"
|
|
#include "qemu/lru.h"
|
|
|
|
#include "hw/hw.h"
|
|
|
|
#include "hw/xbox/nv2a/nv2a_int.h"
|
|
#include "hw/xbox/nv2a/nv2a_regs.h"
|
|
#include "hw/xbox/nv2a/pgraph/surface.h"
|
|
#include "hw/xbox/nv2a/pgraph/texture.h"
|
|
#include "hw/xbox/nv2a/pgraph/shaders.h"
|
|
|
|
#include "gloffscreen.h"
|
|
#include "constants.h"
|
|
|
|
typedef struct SurfaceBinding {
|
|
QTAILQ_ENTRY(SurfaceBinding) entry;
|
|
MemAccessCallback *access_cb;
|
|
|
|
hwaddr vram_addr;
|
|
|
|
SurfaceShape shape;
|
|
uintptr_t dma_addr;
|
|
uintptr_t dma_len;
|
|
bool color;
|
|
bool swizzle;
|
|
|
|
unsigned int width;
|
|
unsigned int height;
|
|
unsigned int pitch;
|
|
size_t size;
|
|
|
|
bool cleared;
|
|
int frame_time;
|
|
int draw_time;
|
|
bool draw_dirty;
|
|
bool download_pending;
|
|
bool upload_pending;
|
|
|
|
GLuint gl_buffer;
|
|
SurfaceFormatInfo fmt;
|
|
} SurfaceBinding;
|
|
|
|
typedef struct TextureBinding {
|
|
unsigned int refcnt;
|
|
int draw_time;
|
|
uint64_t data_hash;
|
|
unsigned int scale;
|
|
unsigned int min_filter;
|
|
unsigned int mag_filter;
|
|
unsigned int addru;
|
|
unsigned int addrv;
|
|
unsigned int addrp;
|
|
uint32_t border_color;
|
|
bool border_color_set;
|
|
GLenum gl_target;
|
|
GLuint gl_texture;
|
|
} TextureBinding;
|
|
|
|
typedef struct ShaderBinding {
|
|
GLuint gl_program;
|
|
GLenum gl_primitive_mode;
|
|
|
|
GLint psh_constant_loc[9][2];
|
|
GLint alpha_ref_loc;
|
|
|
|
GLint bump_mat_loc[NV2A_MAX_TEXTURES];
|
|
GLint bump_scale_loc[NV2A_MAX_TEXTURES];
|
|
GLint bump_offset_loc[NV2A_MAX_TEXTURES];
|
|
GLint tex_scale_loc[NV2A_MAX_TEXTURES];
|
|
|
|
GLint surface_size_loc;
|
|
GLint clip_range_loc;
|
|
|
|
GLint vsh_constant_loc[NV2A_VERTEXSHADER_CONSTANTS];
|
|
uint32_t vsh_constants[NV2A_VERTEXSHADER_CONSTANTS][4];
|
|
|
|
GLint inv_viewport_loc;
|
|
GLint ltctxa_loc[NV2A_LTCTXA_COUNT];
|
|
GLint ltctxb_loc[NV2A_LTCTXB_COUNT];
|
|
GLint ltc1_loc[NV2A_LTC1_COUNT];
|
|
|
|
GLint fog_color_loc;
|
|
GLint fog_param_loc;
|
|
GLint light_infinite_half_vector_loc[NV2A_MAX_LIGHTS];
|
|
GLint light_infinite_direction_loc[NV2A_MAX_LIGHTS];
|
|
GLint light_local_position_loc[NV2A_MAX_LIGHTS];
|
|
GLint light_local_attenuation_loc[NV2A_MAX_LIGHTS];
|
|
|
|
GLint clip_region_loc[8];
|
|
|
|
GLint material_alpha_loc;
|
|
} ShaderBinding;
|
|
|
|
typedef struct ShaderLruNode {
|
|
LruNode node;
|
|
bool cached;
|
|
void *program;
|
|
size_t program_size;
|
|
GLenum program_format;
|
|
ShaderState state;
|
|
ShaderBinding *binding;
|
|
QemuThread *save_thread;
|
|
} ShaderLruNode;
|
|
|
|
typedef struct VertexKey {
|
|
size_t count;
|
|
size_t stride;
|
|
hwaddr addr;
|
|
|
|
GLboolean gl_normalize;
|
|
GLuint gl_type;
|
|
} VertexKey;
|
|
|
|
typedef struct VertexLruNode {
|
|
LruNode node;
|
|
VertexKey key;
|
|
bool initialized;
|
|
|
|
GLuint gl_buffer;
|
|
} VertexLruNode;
|
|
|
|
typedef struct TextureKey {
|
|
TextureShape state;
|
|
hwaddr texture_vram_offset;
|
|
hwaddr texture_length;
|
|
hwaddr palette_vram_offset;
|
|
hwaddr palette_length;
|
|
} TextureKey;
|
|
|
|
typedef struct TextureLruNode {
|
|
LruNode node;
|
|
TextureKey key;
|
|
TextureBinding *binding;
|
|
bool possibly_dirty;
|
|
} TextureLruNode;
|
|
|
|
typedef struct QueryReport {
|
|
QSIMPLEQ_ENTRY(QueryReport) entry;
|
|
bool clear;
|
|
uint32_t parameter;
|
|
unsigned int query_count;
|
|
GLuint *queries;
|
|
} QueryReport;
|
|
|
|
typedef struct PGRAPHGLState {
|
|
GLuint gl_framebuffer;
|
|
GLuint gl_display_buffer;
|
|
GLint gl_display_buffer_internal_format;
|
|
GLsizei gl_display_buffer_width;
|
|
GLsizei gl_display_buffer_height;
|
|
GLenum gl_display_buffer_format;
|
|
GLenum gl_display_buffer_type;
|
|
|
|
Lru element_cache;
|
|
VertexLruNode *element_cache_entries;
|
|
GLuint gl_inline_array_buffer;
|
|
GLuint gl_memory_buffer;
|
|
GLuint gl_vertex_array;
|
|
GLuint gl_inline_buffer[NV2A_VERTEXSHADER_ATTRIBUTES];
|
|
|
|
QTAILQ_HEAD(, SurfaceBinding) surfaces;
|
|
SurfaceBinding *color_binding, *zeta_binding;
|
|
bool downloads_pending;
|
|
QemuEvent downloads_complete;
|
|
bool download_dirty_surfaces_pending;
|
|
QemuEvent dirty_surfaces_download_complete; // common
|
|
|
|
TextureBinding *texture_binding[NV2A_MAX_TEXTURES];
|
|
Lru texture_cache;
|
|
TextureLruNode *texture_cache_entries;
|
|
|
|
Lru shader_cache;
|
|
ShaderLruNode *shader_cache_entries;
|
|
ShaderBinding *shader_binding;
|
|
QemuMutex shader_cache_lock;
|
|
QemuThread shader_disk_thread;
|
|
|
|
unsigned int zpass_pixel_count_result;
|
|
unsigned int gl_zpass_pixel_count_query_count;
|
|
GLuint *gl_zpass_pixel_count_queries;
|
|
QSIMPLEQ_HEAD(, QueryReport) report_queue;
|
|
|
|
bool shader_cache_writeback_pending;
|
|
QemuEvent shader_cache_writeback_complete;
|
|
|
|
struct s2t_rndr {
|
|
GLuint fbo, vao, vbo, prog;
|
|
GLuint tex_loc, surface_size_loc;
|
|
} s2t_rndr;
|
|
|
|
struct disp_rndr {
|
|
GLuint fbo, vao, vbo, prog;
|
|
GLuint display_size_loc;
|
|
GLuint line_offset_loc;
|
|
GLuint tex_loc;
|
|
GLuint pvideo_tex;
|
|
GLint pvideo_enable_loc;
|
|
GLint pvideo_tex_loc;
|
|
GLint pvideo_in_pos_loc;
|
|
GLint pvideo_pos_loc;
|
|
GLint pvideo_scale_loc;
|
|
GLint pvideo_color_key_enable_loc;
|
|
GLint pvideo_color_key_loc;
|
|
GLint palette_loc[256];
|
|
} disp_rndr;
|
|
|
|
GLfloat supported_aliased_line_width_range[2];
|
|
GLfloat supported_smooth_line_width_range[2];
|
|
} PGRAPHGLState;
|
|
|
|
extern GloContext *g_nv2a_context_render;
|
|
extern GloContext *g_nv2a_context_display;
|
|
|
|
unsigned int pgraph_gl_bind_inline_array(NV2AState *d);
|
|
void pgraph_gl_bind_shaders(PGRAPHState *pg);
|
|
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_download_dirty_surfaces(NV2AState *d);
|
|
void pgraph_gl_clear_report_value(NV2AState *d);
|
|
void pgraph_gl_clear_surface(NV2AState *d, uint32_t parameter);
|
|
void pgraph_gl_draw_begin(NV2AState *d);
|
|
void pgraph_gl_draw_end(NV2AState *d);
|
|
void pgraph_gl_flush_draw(NV2AState *d);
|
|
void pgraph_gl_get_report(NV2AState *d, uint32_t parameter);
|
|
void pgraph_gl_image_blit(NV2AState *d);
|
|
void pgraph_gl_mark_textures_possibly_dirty(NV2AState *d, hwaddr addr, hwaddr size);
|
|
void pgraph_gl_process_pending_reports(NV2AState *d);
|
|
void pgraph_gl_surface_flush(NV2AState *d);
|
|
void pgraph_gl_surface_update(NV2AState *d, bool upload, bool color_write, bool zeta_write);
|
|
void pgraph_gl_sync(NV2AState *d);
|
|
void pgraph_gl_update_entire_memory_buffer(NV2AState *d);
|
|
void pgraph_gl_init_display(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_shaders(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_textures(NV2AState *d);
|
|
void pgraph_gl_finalize_textures(PGRAPHState *pg);
|
|
void pgraph_gl_init_buffers(NV2AState *d);
|
|
void pgraph_gl_finalize_buffers(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);
|
|
void pgraph_gl_set_surface_dirty(PGRAPHState *pg, bool color, bool zeta);
|
|
void pgraph_gl_surface_download_if_dirty(NV2AState *d, SurfaceBinding *surface);
|
|
SurfaceBinding *pgraph_gl_surface_get(NV2AState *d, hwaddr addr);
|
|
SurfaceBinding *pgraph_gl_surface_get_within(NV2AState *d, hwaddr addr);
|
|
void pgraph_gl_surface_invalidate(NV2AState *d, SurfaceBinding *e);
|
|
void pgraph_gl_unbind_surface(NV2AState *d, bool color);
|
|
void pgraph_gl_upload_surface_data(NV2AState *d, SurfaceBinding *surface, bool force);
|
|
void pgraph_gl_shader_cache_to_disk(ShaderLruNode *snode);
|
|
bool pgraph_gl_shader_load_from_memory(ShaderLruNode *snode);
|
|
void pgraph_gl_shader_write_cache_reload_list(PGRAPHState *pg);
|
|
void pgraph_gl_set_surface_scale_factor(NV2AState *d, unsigned int scale);
|
|
unsigned int pgraph_gl_get_surface_scale_factor(NV2AState *d);
|
|
int pgraph_gl_get_framebuffer_surface(NV2AState *d);
|
|
|
|
#endif
|