mirror of https://github.com/xemu-project/xemu.git
nv2a: Implement SET_LINE_WIDTH
This commit is contained in:
parent
a242964793
commit
58fcee1f12
|
@ -503,6 +503,7 @@
|
|||
# define NV_PGRAPH_SETUPRASTER_POINTSMOOTHENABLE (1 << 9)
|
||||
# define NV_PGRAPH_SETUPRASTER_LINESMOOTHENABLE (1 << 10)
|
||||
# define NV_PGRAPH_SETUPRASTER_POLYSMOOTHENABLE (1 << 11)
|
||||
# define NV_PGRAPH_SETUPRASTER_LINEWIDTH 0x001ff000
|
||||
# define NV_PGRAPH_SETUPRASTER_CULLCTRL 0x00600000
|
||||
# define NV_PGRAPH_SETUPRASTER_CULLCTRL_FRONT 1
|
||||
# define NV_PGRAPH_SETUPRASTER_CULLCTRL_BACK 2
|
||||
|
@ -1009,6 +1010,7 @@
|
|||
# define NV097_SET_SHADE_MODE 0x0000037C
|
||||
# define NV097_SET_SHADE_MODE_V_FLAT 0x1D00
|
||||
# define NV097_SET_SHADE_MODE_V_SMOOTH 0x1D01
|
||||
# define NV097_SET_LINE_WIDTH 0x00000380
|
||||
# define NV097_SET_POLYGON_OFFSET_SCALE_FACTOR 0x00000384
|
||||
# define NV097_SET_POLYGON_OFFSET_BIAS 0x00000388
|
||||
# define NV097_SET_FRONT_POLYGON_MODE 0x0000038C
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "hw/xbox/nv2a/nv2a_int.h"
|
||||
#include "debug.h"
|
||||
#include "renderer.h"
|
||||
#include <math.h>
|
||||
|
||||
void pgraph_gl_clear_surface(NV2AState *d, uint32_t parameter)
|
||||
{
|
||||
|
@ -131,6 +132,32 @@ void pgraph_gl_clear_surface(NV2AState *d, uint32_t parameter)
|
|||
pg->clearing = false;
|
||||
}
|
||||
|
||||
static float clamp_line_width_to_device_limits(PGRAPHState *pg, float width,
|
||||
bool smooth)
|
||||
{
|
||||
PGRAPHGLState *r = pg->gl_renderer_state;
|
||||
float min_width;
|
||||
float max_width;
|
||||
float granularity;
|
||||
|
||||
if (smooth) {
|
||||
min_width = r->limits.smooth_line_width.range[0];
|
||||
max_width = r->limits.smooth_line_width.range[1];
|
||||
granularity = r->limits.smooth_line_width.granularity;
|
||||
} else {
|
||||
min_width = r->limits.aliased_line_width.range[0];
|
||||
max_width = r->limits.aliased_line_width.range[1];
|
||||
granularity = r->limits.aliased_line_width.granularity;
|
||||
}
|
||||
|
||||
if (granularity != 0.0f) {
|
||||
float steps = roundf((width - min_width) / granularity);
|
||||
width = min_width + steps * granularity;
|
||||
}
|
||||
|
||||
return fminf(fmaxf(min_width, width), max_width);
|
||||
}
|
||||
|
||||
void pgraph_gl_draw_begin(NV2AState *d)
|
||||
{
|
||||
PGRAPHState *pg = &d->pgraph;
|
||||
|
@ -310,13 +337,14 @@ void pgraph_gl_draw_begin(NV2AState *d)
|
|||
bool anti_aliasing = GET_MASK(pgraph_reg_r(pg, NV_PGRAPH_ANTIALIASING), NV_PGRAPH_ANTIALIASING_ENABLE);
|
||||
|
||||
/* Edge Antialiasing */
|
||||
float line_width = pgraph_get_line_width(pg) * pg->surface_scale_factor;
|
||||
if (!anti_aliasing && pgraph_reg_r(pg, NV_PGRAPH_SETUPRASTER) &
|
||||
NV_PGRAPH_SETUPRASTER_LINESMOOTHENABLE) {
|
||||
glEnable(GL_LINE_SMOOTH);
|
||||
glLineWidth(MIN(r->supported_smooth_line_width_range[1], pg->surface_scale_factor));
|
||||
glLineWidth(clamp_line_width_to_device_limits(pg, line_width, true));
|
||||
} else {
|
||||
glDisable(GL_LINE_SMOOTH);
|
||||
glLineWidth(MIN(r->supported_aliased_line_width_range[1], pg->surface_scale_factor));
|
||||
glLineWidth(clamp_line_width_to_device_limits(pg, line_width, false));
|
||||
}
|
||||
if (!anti_aliasing && pgraph_reg_r(pg, NV_PGRAPH_SETUPRASTER) &
|
||||
NV_PGRAPH_SETUPRASTER_POLYSMOOTHENABLE) {
|
||||
|
|
|
@ -52,8 +52,12 @@ static void pgraph_gl_init(NV2AState *d, Error **errp)
|
|||
/* Internal RGB565 texture format */
|
||||
assert(glo_check_extension("GL_ARB_ES2_compatibility"));
|
||||
|
||||
glGetFloatv(GL_SMOOTH_LINE_WIDTH_RANGE, r->supported_smooth_line_width_range);
|
||||
glGetFloatv(GL_ALIASED_LINE_WIDTH_RANGE, r->supported_aliased_line_width_range);
|
||||
glGetFloatv(GL_SMOOTH_LINE_WIDTH_RANGE, r->limits.smooth_line_width.range);
|
||||
glGetFloatv(GL_SMOOTH_LINE_WIDTH_GRANULARITY,
|
||||
&r->limits.smooth_line_width.granularity);
|
||||
glGetFloatv(GL_ALIASED_LINE_WIDTH_RANGE,
|
||||
r->limits.aliased_line_width.range);
|
||||
r->limits.aliased_line_width.granularity = 1.0;
|
||||
|
||||
pgraph_gl_init_surfaces(pg);
|
||||
pgraph_gl_init_reports(d);
|
||||
|
|
|
@ -234,8 +234,12 @@ typedef struct PGRAPHGLState {
|
|||
GLint palette_loc[256];
|
||||
} disp_rndr;
|
||||
|
||||
GLfloat supported_aliased_line_width_range[2];
|
||||
GLfloat supported_smooth_line_width_range[2];
|
||||
struct {
|
||||
struct {
|
||||
float range[2];
|
||||
float granularity;
|
||||
} smooth_line_width, aliased_line_width;
|
||||
} limits;
|
||||
} PGRAPHGLState;
|
||||
|
||||
extern GloContext *g_nv2a_context_render;
|
||||
|
|
|
@ -68,6 +68,7 @@ DEF_METHOD(NV097, SET_STENCIL_OP_FAIL)
|
|||
DEF_METHOD(NV097, SET_STENCIL_OP_ZFAIL)
|
||||
DEF_METHOD(NV097, SET_STENCIL_OP_ZPASS)
|
||||
DEF_METHOD(NV097, SET_SHADE_MODE)
|
||||
DEF_METHOD(NV097, SET_LINE_WIDTH)
|
||||
DEF_METHOD(NV097, SET_POLYGON_OFFSET_SCALE_FACTOR)
|
||||
DEF_METHOD(NV097, SET_POLYGON_OFFSET_BIAS)
|
||||
DEF_METHOD(NV097, SET_FRONT_POLYGON_MODE)
|
||||
|
|
|
@ -28,15 +28,6 @@
|
|||
#include "swizzle.h"
|
||||
#include "nv2a_vsh_emulator.h"
|
||||
|
||||
#define PG_GET_MASK(reg, mask) GET_MASK(pgraph_reg_r(pg, reg), mask)
|
||||
#define PG_SET_MASK(reg, mask, value) \
|
||||
do { \
|
||||
uint32_t rv = pgraph_reg_r(pg, reg); \
|
||||
SET_MASK(rv, mask, value); \
|
||||
pgraph_reg_w(pg, reg, rv); \
|
||||
} while (0)
|
||||
|
||||
|
||||
NV2AState *g_nv2a;
|
||||
|
||||
uint64_t pgraph_read(void *opaque, hwaddr addr, unsigned int size)
|
||||
|
@ -1532,6 +1523,14 @@ DEF_METHOD(NV097, SET_SHADE_MODE)
|
|||
}
|
||||
}
|
||||
|
||||
DEF_METHOD(NV097, SET_LINE_WIDTH)
|
||||
{
|
||||
if (parameter < 0x200) {
|
||||
PG_SET_MASK(NV_PGRAPH_SETUPRASTER, NV_PGRAPH_SETUPRASTER_LINEWIDTH,
|
||||
parameter);
|
||||
}
|
||||
}
|
||||
|
||||
DEF_METHOD(NV097, SET_POLYGON_OFFSET_SCALE_FACTOR)
|
||||
{
|
||||
pgraph_reg_w(pg, NV_PGRAPH_ZOFFSETFACTOR, parameter);
|
||||
|
|
|
@ -297,6 +297,14 @@ static inline void pgraph_reg_w(PGRAPHState *pg, unsigned int r, uint32_t v)
|
|||
pg->regs_[r] = v;
|
||||
}
|
||||
|
||||
#define PG_GET_MASK(reg, mask) GET_MASK(pgraph_reg_r(pg, reg), mask)
|
||||
#define PG_SET_MASK(reg, mask, value) \
|
||||
do { \
|
||||
uint32_t rv = pgraph_reg_r(pg, reg); \
|
||||
SET_MASK(rv, mask, value); \
|
||||
pgraph_reg_w(pg, reg, rv); \
|
||||
} while (0)
|
||||
|
||||
void pgraph_clear_dirty_reg_map(PGRAPHState *pg);
|
||||
|
||||
static inline bool pgraph_is_reg_dirty(PGRAPHState *pg, unsigned int reg)
|
||||
|
@ -369,6 +377,13 @@ static inline void pgraph_apply_scaling_factor(PGRAPHState *pg,
|
|||
*height *= pg->surface_scale_factor;
|
||||
}
|
||||
|
||||
static inline float pgraph_get_line_width(PGRAPHState *pg)
|
||||
{
|
||||
uint32_t line_width =
|
||||
PG_GET_MASK(NV_PGRAPH_SETUPRASTER, NV_PGRAPH_SETUPRASTER_LINEWIDTH);
|
||||
return line_width / 8.0f; /* 6.3 format */
|
||||
}
|
||||
|
||||
void pgraph_get_clear_color(PGRAPHState *pg, float rgba[4]);
|
||||
void pgraph_get_clear_depth_stencil_value(PGRAPHState *pg, float *depth, int *stencil);
|
||||
|
||||
|
|
|
@ -1521,7 +1521,8 @@ static void begin_draw(PGRAPHState *pg)
|
|||
|
||||
if (r->pipeline_binding->has_dynamic_line_width) {
|
||||
float line_width =
|
||||
clamp_line_width_to_device_limits(pg, pg->surface_scale_factor);
|
||||
pgraph_get_line_width(pg) * pg->surface_scale_factor;
|
||||
line_width = clamp_line_width_to_device_limits(pg, line_width);
|
||||
vkCmdSetLineWidth(r->command_buffer, line_width);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue