mirror of https://github.com/xemu-project/xemu.git
nv2a: clear rectangles; fix surface upload; start unfucking pgraph state
This commit is contained in:
parent
35c578eedf
commit
ca76432648
hw/xbox
138
hw/xbox/nv2a.c
138
hw/xbox/nv2a.c
|
@ -252,6 +252,12 @@
|
|||
#define NV_PGRAPH_CHANNEL_CTX_TRIGGER 0x00000788
|
||||
# define NV_PGRAPH_CHANNEL_CTX_TRIGGER_READ_IN (1 << 0)
|
||||
# define NV_PGRAPH_CHANNEL_CTX_TRIGGER_WRITE_OUT (1 << 1)
|
||||
#define NV_PGRAPH_CLEARRECTX 0x00001864
|
||||
# define NV_PGRAPH_CLEARRECTX_XMIN 0x00000FFF
|
||||
# define NV_PGRAPH_CLEARRECTX_XMAX 0x0FFF0000
|
||||
#define NV_PGRAPH_CLEARRECTY 0x00001868
|
||||
# define NV_PGRAPH_CLEARRECTY_YMIN 0x00000FFF
|
||||
# define NV_PGRAPH_CLEARRECTY_YMAX 0x0FFF0000
|
||||
#define NV_PGRAPH_COLORCLEARVALUE 0x0000186C
|
||||
#define NV_PGRAPH_ZSTENCILCLEARVALUE 0x00001A88
|
||||
|
||||
|
@ -277,6 +283,8 @@
|
|||
#define NV_PFB_CFG0 0x00000200
|
||||
# define NV_PFB_CFG0_PART 0x00000003
|
||||
#define NV_PFB_CSTATUS 0x0000020C
|
||||
#define NV_PFB_WBC 0x00000410
|
||||
# define NV_PFB_WBC_FLUSH (1 << 16)
|
||||
|
||||
|
||||
#define NV_PRAMDAC_NVPLL_COEFF 0x00000500
|
||||
|
@ -476,6 +484,8 @@
|
|||
# define NV097_CLEAR_SURFACE_G (1 << 5)
|
||||
# define NV097_CLEAR_SURFACE_B (1 << 6)
|
||||
# define NV097_CLEAR_SURFACE_A (1 << 7)
|
||||
# define NV097_SET_CLEAR_RECT_HORIZONTAL 0x00971D98
|
||||
# define NV097_SET_CLEAR_RECT_VERTICAL 0x00971D9C
|
||||
# define NV097_SET_TRANSFORM_EXECUTION_MODE 0x00971E94
|
||||
# define NV097_SET_TRANSFORM_PROGRAM_CXT_WRITE_EN 0x00971E98
|
||||
# define NV097_SET_TRANSFORM_PROGRAM_LOAD 0x00971E9C
|
||||
|
@ -666,8 +676,6 @@ typedef struct Texture {
|
|||
typedef struct Surface {
|
||||
bool draw_dirty;
|
||||
unsigned int pitch;
|
||||
unsigned int x, y;
|
||||
unsigned int width, height;
|
||||
unsigned int format;
|
||||
|
||||
hwaddr offset;
|
||||
|
@ -685,6 +693,10 @@ typedef struct KelvinState {
|
|||
|
||||
Surface surface_color;
|
||||
Surface surface_zeta;
|
||||
unsigned int surface_x, surface_y;
|
||||
unsigned int surface_width, surface_height;
|
||||
|
||||
|
||||
uint32_t color_mask;
|
||||
|
||||
unsigned int vertexshader_start_slot;
|
||||
|
@ -754,9 +766,6 @@ typedef struct GraphicsContext {
|
|||
|
||||
GraphicsSubchannel subchannel_data[NV2A_NUM_SUBCHANNELS];
|
||||
|
||||
uint32_t zstencil_clear_value;
|
||||
uint32_t color_clear_value;
|
||||
|
||||
GloContext *gl_context;
|
||||
|
||||
GLuint gl_framebuffer;
|
||||
|
@ -873,6 +882,10 @@ typedef struct NV2AState {
|
|||
uint32_t alarm_time;
|
||||
} ptimer;
|
||||
|
||||
struct {
|
||||
uint32_t regs[0x1000];
|
||||
} pfb;
|
||||
|
||||
struct {
|
||||
QemuMutex lock;
|
||||
|
||||
|
@ -896,6 +909,8 @@ typedef struct NV2AState {
|
|||
unsigned int channel_id;
|
||||
bool channel_valid;
|
||||
GraphicsContext context[NV2A_NUM_CHANNELS];
|
||||
|
||||
uint32_t regs[0x2000];
|
||||
} pgraph;
|
||||
|
||||
struct {
|
||||
|
@ -1442,7 +1457,7 @@ static void kelvin_update_surface(NV2AState *d, KelvinState *kelvin, bool upload
|
|||
assert(color_dma.address + kelvin->surface_color.offset != 0);
|
||||
assert(kelvin->surface_color.offset <= color_dma.limit);
|
||||
assert(kelvin->surface_color.offset
|
||||
+ kelvin->surface_color.pitch * kelvin->surface_color.height
|
||||
+ kelvin->surface_color.pitch * kelvin->surface_height
|
||||
<= color_dma.limit + 1);
|
||||
|
||||
|
||||
|
@ -1469,13 +1484,13 @@ static void kelvin_update_surface(NV2AState *d, KelvinState *kelvin, bool upload
|
|||
}
|
||||
|
||||
/* TODO */
|
||||
assert(kelvin->surface_color.x == 0 && kelvin->surface_color.y == 0);
|
||||
assert(kelvin->surface_x == 0 && kelvin->surface_y == 0);
|
||||
|
||||
if (upload && memory_region_test_and_clear_dirty(d->vram,
|
||||
color_dma.address
|
||||
+ kelvin->surface_color.offset,
|
||||
kelvin->surface_color.pitch
|
||||
* kelvin->surface_color.height,
|
||||
* kelvin->surface_height,
|
||||
DIRTY_MEMORY_NV2A)) {
|
||||
/* surface modified (or moved) by the cpu.
|
||||
* copy it into the opengl renderbuffer */
|
||||
|
@ -1483,6 +1498,8 @@ static void kelvin_update_surface(NV2AState *d, KelvinState *kelvin, bool upload
|
|||
|
||||
assert(kelvin->surface_color.pitch % bytes_per_pixel == 0);
|
||||
|
||||
glDisable(GL_FRAGMENT_PROGRAM_ARB);
|
||||
|
||||
int rl, pa;
|
||||
glGetIntegerv(GL_UNPACK_ROW_LENGTH, &rl);
|
||||
glGetIntegerv(GL_UNPACK_ALIGNMENT, &pa);
|
||||
|
@ -1493,15 +1510,27 @@ static void kelvin_update_surface(NV2AState *d, KelvinState *kelvin, bool upload
|
|||
/* glDrawPixels is crazy deprecated, but there really isn't
|
||||
* an easy alternative */
|
||||
|
||||
glRasterPos2i(0, 0);
|
||||
glDrawPixels(kelvin->surface_color.width,
|
||||
kelvin->surface_color.height,
|
||||
glWindowPos2i(0, kelvin->surface_height);
|
||||
glPixelZoom(1, -1);
|
||||
glDrawPixels(kelvin->surface_width,
|
||||
kelvin->surface_height,
|
||||
gl_format, gl_type,
|
||||
color_data + kelvin->surface_color.offset);
|
||||
assert(glGetError() == GL_NO_ERROR);
|
||||
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, rl);
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, pa);
|
||||
|
||||
uint8_t *out = color_data + kelvin->surface_color.offset;
|
||||
NV2A_DPRINTF("upload_surface 0x%llx - 0x%llx, "
|
||||
"(0x%llx - 0x%llx, %d %d, %d %d, %d) - %x %x %x %x\n",
|
||||
color_dma.address, color_dma.address + color_dma.limit,
|
||||
color_dma.address + kelvin->surface_color.offset,
|
||||
color_dma.address + kelvin->surface_color.pitch * kelvin->surface_height,
|
||||
kelvin->surface_x, kelvin->surface_y,
|
||||
kelvin->surface_width, kelvin->surface_height,
|
||||
kelvin->surface_color.pitch,
|
||||
out[0], out[1], out[2], out[3]);
|
||||
}
|
||||
|
||||
if (!upload && kelvin->surface_color.draw_dirty) {
|
||||
|
@ -1509,7 +1538,7 @@ static void kelvin_update_surface(NV2AState *d, KelvinState *kelvin, bool upload
|
|||
|
||||
glo_readpixels(gl_format, gl_type,
|
||||
bytes_per_pixel, kelvin->surface_color.pitch,
|
||||
kelvin->surface_color.width, kelvin->surface_color.height,
|
||||
kelvin->surface_width, kelvin->surface_height,
|
||||
color_data + kelvin->surface_color.offset);
|
||||
assert(glGetError() == GL_NO_ERROR);
|
||||
|
||||
|
@ -1517,7 +1546,7 @@ static void kelvin_update_surface(NV2AState *d, KelvinState *kelvin, bool upload
|
|||
color_dma.address
|
||||
+ kelvin->surface_color.offset,
|
||||
kelvin->surface_color.pitch
|
||||
* kelvin->surface_color.height,
|
||||
* kelvin->surface_height,
|
||||
DIRTY_MEMORY_VGA);
|
||||
|
||||
kelvin->surface_color.draw_dirty = false;
|
||||
|
@ -1527,9 +1556,9 @@ static void kelvin_update_surface(NV2AState *d, KelvinState *kelvin, bool upload
|
|||
"(0x%llx - 0x%llx, %d %d, %d %d, %d) - %x %x %x %x\n",
|
||||
color_dma.address, color_dma.address + color_dma.limit,
|
||||
color_dma.address + kelvin->surface_color.offset,
|
||||
color_dma.address + kelvin->surface_color.pitch * kelvin->surface_color.height,
|
||||
kelvin->surface_color.x, kelvin->surface_color.y,
|
||||
kelvin->surface_color.width, kelvin->surface_color.height,
|
||||
color_dma.address + kelvin->surface_color.pitch * kelvin->surface_height,
|
||||
kelvin->surface_x, kelvin->surface_y,
|
||||
kelvin->surface_width, kelvin->surface_height,
|
||||
kelvin->surface_color.pitch,
|
||||
out[0], out[1], out[2], out[3]);
|
||||
}
|
||||
|
@ -1830,17 +1859,17 @@ static void pgraph_method(NV2AState *d,
|
|||
case NV097_SET_SURFACE_CLIP_HORIZONTAL:
|
||||
kelvin_update_surface(d, kelvin, false);
|
||||
|
||||
kelvin->surface_color.x =
|
||||
kelvin->surface_x =
|
||||
GET_MASK(parameter, NV097_SET_SURFACE_CLIP_HORIZONTAL_X);
|
||||
kelvin->surface_color.width =
|
||||
kelvin->surface_width =
|
||||
GET_MASK(parameter, NV097_SET_SURFACE_CLIP_HORIZONTAL_WIDTH);
|
||||
break;
|
||||
case NV097_SET_SURFACE_CLIP_VERTICAL:
|
||||
kelvin_update_surface(d, kelvin, false);
|
||||
|
||||
kelvin->surface_color.y =
|
||||
kelvin->surface_y =
|
||||
GET_MASK(parameter, NV097_SET_SURFACE_CLIP_VERTICAL_Y);
|
||||
kelvin->surface_color.height =
|
||||
kelvin->surface_height =
|
||||
GET_MASK(parameter, NV097_SET_SURFACE_CLIP_VERTICAL_HEIGHT);
|
||||
break;
|
||||
case NV097_SET_SURFACE_FORMAT:
|
||||
|
@ -2166,15 +2195,11 @@ static void pgraph_method(NV2AState *d,
|
|||
break;
|
||||
}
|
||||
case NV097_SET_ZSTENCIL_CLEAR_VALUE:
|
||||
context->zstencil_clear_value = parameter;
|
||||
d->pgraph.regs[NV_PGRAPH_ZSTENCILCLEARVALUE] = parameter;
|
||||
break;
|
||||
|
||||
case NV097_SET_COLOR_CLEAR_VALUE:
|
||||
glClearColor( ((parameter >> 16) & 0xFF) / 255.0f, /* red */
|
||||
((parameter >> 8) & 0xFF) / 255.0f, /* green */
|
||||
(parameter & 0xFF) / 255.0f, /* blue */
|
||||
((parameter >> 24) & 0xFF) / 255.0f);/* alpha */
|
||||
context->color_clear_value = parameter;
|
||||
d->pgraph.regs[NV_PGRAPH_COLORCLEARVALUE] = parameter;
|
||||
break;
|
||||
|
||||
case NV097_CLEAR_SURFACE:
|
||||
|
@ -2189,17 +2214,51 @@ static void pgraph_method(NV2AState *d,
|
|||
if (parameter & NV097_CLEAR_SURFACE_STENCIL) {
|
||||
gl_mask |= GL_STENCIL_BUFFER_BIT;
|
||||
}
|
||||
|
||||
if (parameter & (NV097_CLEAR_SURFACE_COLOR)) {
|
||||
gl_mask |= GL_COLOR_BUFFER_BIT;
|
||||
kelvin_update_surface(d, kelvin, true);
|
||||
|
||||
uint32_t clear_color = d->pgraph.regs[NV_PGRAPH_COLORCLEARVALUE];
|
||||
glClearColor( ((clear_color >> 16) & 0xFF) / 255.0f, /* red */
|
||||
((clear_color >> 8) & 0xFF) / 255.0f, /* green */
|
||||
(clear_color & 0xFF) / 255.0f, /* blue */
|
||||
((clear_color >> 24) & 0xFF) / 255.0f);/* alpha */
|
||||
|
||||
}
|
||||
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
|
||||
unsigned int xmin = GET_MASK(d->pgraph.regs[NV_PGRAPH_CLEARRECTX],
|
||||
NV_PGRAPH_CLEARRECTX_XMIN);
|
||||
unsigned int xmax = GET_MASK(d->pgraph.regs[NV_PGRAPH_CLEARRECTX],
|
||||
NV_PGRAPH_CLEARRECTX_XMAX);
|
||||
unsigned int ymin = GET_MASK(d->pgraph.regs[NV_PGRAPH_CLEARRECTY],
|
||||
NV_PGRAPH_CLEARRECTY_YMIN);
|
||||
unsigned int ymax = GET_MASK(d->pgraph.regs[NV_PGRAPH_CLEARRECTY],
|
||||
NV_PGRAPH_CLEARRECTY_YMAX);
|
||||
glScissor(xmin, kelvin->surface_height-ymax, xmax-xmin, ymax-ymin);
|
||||
|
||||
NV2A_DPRINTF("------------------CLEAR 0x%x %d,%d - %d,%d ---------------\n",
|
||||
parameter, xmin, ymin, xmax, ymax);
|
||||
|
||||
glClear(gl_mask);
|
||||
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
|
||||
|
||||
if (parameter & NV097_CLEAR_SURFACE_COLOR) {
|
||||
kelvin->surface_color.draw_dirty = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case NV097_SET_CLEAR_RECT_HORIZONTAL:
|
||||
d->pgraph.regs[NV_PGRAPH_CLEARRECTX] = parameter;
|
||||
break;
|
||||
case NV097_SET_CLEAR_RECT_VERTICAL:
|
||||
d->pgraph.regs[NV_PGRAPH_CLEARRECTY] = parameter;
|
||||
break;
|
||||
|
||||
case NV097_SET_TRANSFORM_EXECUTION_MODE:
|
||||
kelvin->use_vertex_program = (parameter & 3) == 2;
|
||||
break;
|
||||
|
@ -3014,7 +3073,7 @@ static void prmvio_write(void *opaque, hwaddr addr,
|
|||
|
||||
|
||||
static uint64_t pfb_read(void *opaque,
|
||||
hwaddr addr, unsigned int size)
|
||||
hwaddr addr, unsigned int size)
|
||||
{
|
||||
NV2AState *d = opaque;
|
||||
|
||||
|
@ -3027,7 +3086,11 @@ static uint64_t pfb_read(void *opaque,
|
|||
case NV_PFB_CSTATUS:
|
||||
r = memory_region_size(d->vram);
|
||||
break;
|
||||
case NV_PFB_WBC:
|
||||
r = 0; /* Flush not pending. */
|
||||
break;
|
||||
default:
|
||||
r = d->pfb.regs[addr];
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -3035,9 +3098,17 @@ static uint64_t pfb_read(void *opaque,
|
|||
return r;
|
||||
}
|
||||
static void pfb_write(void *opaque, hwaddr addr,
|
||||
uint64_t val, unsigned int size)
|
||||
uint64_t val, unsigned int size)
|
||||
{
|
||||
NV2AState *d = opaque;
|
||||
|
||||
reg_log_write(NV_PFB, addr, val);
|
||||
|
||||
switch (addr) {
|
||||
default:
|
||||
d->pfb.regs[addr] = val;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -3097,13 +3168,8 @@ static uint64_t pgraph_read(void *opaque,
|
|||
case NV_PGRAPH_CHANNEL_CTX_POINTER:
|
||||
r = d->pgraph.context_address >> 4;
|
||||
break;
|
||||
case NV_PGRAPH_COLORCLEARVALUE:
|
||||
r = d->pgraph.context[d->pgraph.channel_id].color_clear_value;
|
||||
break;
|
||||
case NV_PGRAPH_ZSTENCILCLEARVALUE:
|
||||
r = d->pgraph.context[d->pgraph.channel_id].zstencil_clear_value;
|
||||
break;
|
||||
default:
|
||||
r = d->pgraph.regs[addr];
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -3181,10 +3247,8 @@ static void pgraph_write(void *opaque, hwaddr addr,
|
|||
|
||||
qemu_mutex_unlock(&d->pgraph.lock);
|
||||
break;
|
||||
case NV_PGRAPH_ZSTENCILCLEARVALUE:
|
||||
d->pgraph.context[d->pgraph.channel_id].zstencil_clear_value = val;
|
||||
break;
|
||||
default:
|
||||
d->pgraph.regs[addr] = val;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue