Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions hw/xbox/nv2a/nv2a_regs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
32 changes: 30 additions & 2 deletions hw/xbox/nv2a/pgraph/gl/draw.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down
8 changes: 6 additions & 2 deletions hw/xbox/nv2a/pgraph/gl/renderer.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
8 changes: 6 additions & 2 deletions hw/xbox/nv2a/pgraph/gl/renderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions hw/xbox/nv2a/pgraph/methods.h.inc
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
17 changes: 8 additions & 9 deletions hw/xbox/nv2a/pgraph/pgraph.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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);
Expand Down
15 changes: 15 additions & 0 deletions hw/xbox/nv2a/pgraph/pgraph.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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);

Expand Down
3 changes: 2 additions & 1 deletion hw/xbox/nv2a/pgraph/vk/draw.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
Expand Down