mirror of https://github.com/xemu-project/xemu.git
share more graphics state proper or something
This commit is contained in:
parent
7116f4eb13
commit
41fda5fc25
466
hw/xbox/nv2a.c
466
hw/xbox/nv2a.c
|
@ -683,21 +683,11 @@ typedef struct Surface {
|
||||||
|
|
||||||
typedef struct KelvinState {
|
typedef struct KelvinState {
|
||||||
hwaddr dma_notifies;
|
hwaddr dma_notifies;
|
||||||
hwaddr dma_a, dma_b;
|
|
||||||
hwaddr dma_state;
|
hwaddr dma_state;
|
||||||
hwaddr dma_color;
|
|
||||||
hwaddr dma_zeta;
|
|
||||||
hwaddr dma_vertex_a, dma_vertex_b;
|
hwaddr dma_vertex_a, dma_vertex_b;
|
||||||
hwaddr dma_semaphore;
|
hwaddr dma_semaphore;
|
||||||
unsigned int semaphore_offset;
|
unsigned int semaphore_offset;
|
||||||
|
|
||||||
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;
|
unsigned int vertexshader_start_slot;
|
||||||
unsigned int vertexshader_load_slot;
|
unsigned int vertexshader_load_slot;
|
||||||
|
@ -706,9 +696,6 @@ typedef struct KelvinState {
|
||||||
unsigned int constant_load_slot;
|
unsigned int constant_load_slot;
|
||||||
VertexShaderConstant constants[NV2A_VERTEXSHADER_CONSTANTS];
|
VertexShaderConstant constants[NV2A_VERTEXSHADER_CONSTANTS];
|
||||||
|
|
||||||
bool fragment_program_dirty;
|
|
||||||
GLuint gl_fragment_program;
|
|
||||||
|
|
||||||
GLenum gl_primitive_mode;
|
GLenum gl_primitive_mode;
|
||||||
|
|
||||||
VertexAttribute vertex_attributes[NV2A_VERTEXSHADER_ATTRIBUTES];
|
VertexAttribute vertex_attributes[NV2A_VERTEXSHADER_ATTRIBUTES];
|
||||||
|
@ -719,8 +706,6 @@ typedef struct KelvinState {
|
||||||
unsigned int array_batch_length;
|
unsigned int array_batch_length;
|
||||||
uint32_t array_batch[NV2A_MAX_BATCH_LENGTH];
|
uint32_t array_batch[NV2A_MAX_BATCH_LENGTH];
|
||||||
|
|
||||||
Texture textures[NV2A_MAX_TEXTURES];
|
|
||||||
|
|
||||||
bool use_vertex_program;
|
bool use_vertex_program;
|
||||||
bool enable_vertex_program_write;
|
bool enable_vertex_program_write;
|
||||||
} KelvinState;
|
} KelvinState;
|
||||||
|
@ -763,16 +748,56 @@ typedef struct GraphicsSubchannel {
|
||||||
typedef struct GraphicsContext {
|
typedef struct GraphicsContext {
|
||||||
bool channel_3d;
|
bool channel_3d;
|
||||||
unsigned int subchannel;
|
unsigned int subchannel;
|
||||||
|
|
||||||
GraphicsSubchannel subchannel_data[NV2A_NUM_SUBCHANNELS];
|
|
||||||
|
|
||||||
GloContext *gl_context;
|
|
||||||
|
|
||||||
GLuint gl_framebuffer;
|
|
||||||
GLuint gl_renderbuffer;
|
|
||||||
} GraphicsContext;
|
} GraphicsContext;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct PGRAPHState {
|
||||||
|
QemuMutex lock;
|
||||||
|
|
||||||
|
uint32_t pending_interrupts;
|
||||||
|
uint32_t enabled_interrupts;
|
||||||
|
QemuCond interrupt_cond;
|
||||||
|
|
||||||
|
hwaddr context_table;
|
||||||
|
hwaddr context_address;
|
||||||
|
|
||||||
|
|
||||||
|
unsigned int trapped_method;
|
||||||
|
unsigned int trapped_subchannel;
|
||||||
|
unsigned int trapped_channel_id;
|
||||||
|
uint32_t trapped_data[2];
|
||||||
|
uint32_t notify_source;
|
||||||
|
|
||||||
|
bool fifo_access;
|
||||||
|
QemuCond fifo_access_cond;
|
||||||
|
|
||||||
|
unsigned int channel_id;
|
||||||
|
bool channel_valid;
|
||||||
|
GraphicsContext context[NV2A_NUM_CHANNELS];
|
||||||
|
|
||||||
|
|
||||||
|
hwaddr dma_color, dma_zeta;
|
||||||
|
Surface surface_color, surface_zeta;
|
||||||
|
unsigned int surface_x, surface_y;
|
||||||
|
unsigned int surface_width, surface_height;
|
||||||
|
uint32_t color_mask;
|
||||||
|
|
||||||
|
hwaddr dma_a, dma_b;
|
||||||
|
Texture textures[NV2A_MAX_TEXTURES];
|
||||||
|
|
||||||
|
bool fragment_shader_dirty;
|
||||||
|
GLuint gl_fragment_shader;
|
||||||
|
GLuint gl_program;
|
||||||
|
|
||||||
|
|
||||||
|
GloContext *gl_context;
|
||||||
|
GLuint gl_framebuffer;
|
||||||
|
GLuint gl_renderbuffer;
|
||||||
|
GraphicsSubchannel subchannel_data[NV2A_NUM_SUBCHANNELS];
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t regs[0x2000];
|
||||||
|
} PGRAPHState;
|
||||||
|
|
||||||
|
|
||||||
typedef struct CacheEntry {
|
typedef struct CacheEntry {
|
||||||
|
@ -886,32 +911,7 @@ typedef struct NV2AState {
|
||||||
uint32_t regs[0x1000];
|
uint32_t regs[0x1000];
|
||||||
} pfb;
|
} pfb;
|
||||||
|
|
||||||
struct {
|
struct PGRAPHState pgraph;
|
||||||
QemuMutex lock;
|
|
||||||
|
|
||||||
uint32_t pending_interrupts;
|
|
||||||
uint32_t enabled_interrupts;
|
|
||||||
QemuCond interrupt_cond;
|
|
||||||
|
|
||||||
hwaddr context_table;
|
|
||||||
hwaddr context_address;
|
|
||||||
|
|
||||||
|
|
||||||
unsigned int trapped_method;
|
|
||||||
unsigned int trapped_subchannel;
|
|
||||||
unsigned int trapped_channel_id;
|
|
||||||
uint32_t trapped_data[2];
|
|
||||||
uint32_t notify_source;
|
|
||||||
|
|
||||||
bool fifo_access;
|
|
||||||
QemuCond fifo_access_cond;
|
|
||||||
|
|
||||||
unsigned int channel_id;
|
|
||||||
bool channel_valid;
|
|
||||||
GraphicsContext context[NV2A_NUM_CHANNELS];
|
|
||||||
|
|
||||||
uint32_t regs[0x2000];
|
|
||||||
} pgraph;
|
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
uint32_t pending_interrupts;
|
uint32_t pending_interrupts;
|
||||||
|
@ -1073,30 +1073,19 @@ static void load_graphics_object(NV2AState *d, hwaddr instance_address,
|
||||||
}
|
}
|
||||||
assert(glGetError() == GL_NO_ERROR);
|
assert(glGetError() == GL_NO_ERROR);
|
||||||
|
|
||||||
/* fragment program */
|
|
||||||
glGenProgramsARB(1, &kelvin->gl_fragment_program);
|
|
||||||
kelvin->fragment_program_dirty = true;
|
|
||||||
|
|
||||||
/* generate textures */
|
|
||||||
for (i = 0; i < NV2A_MAX_TEXTURES; i++) {
|
|
||||||
Texture *texture = &kelvin->textures[i];
|
|
||||||
glGenTextures(1, &texture->gl_texture);
|
|
||||||
glGenTextures(1, &texture->gl_texture_rect);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static GraphicsObject* lookup_graphics_object(GraphicsContext *ctx,
|
static GraphicsObject* lookup_graphics_object(PGRAPHState *s,
|
||||||
hwaddr instance_address)
|
hwaddr instance_address)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
for (i=0; i<NV2A_NUM_SUBCHANNELS; i++) {
|
for (i=0; i<NV2A_NUM_SUBCHANNELS; i++) {
|
||||||
if (ctx->subchannel_data[i].object_instance == instance_address) {
|
if (s->subchannel_data[i].object_instance == instance_address) {
|
||||||
return &ctx->subchannel_data[i].object;
|
return &s->subchannel_data[i].object;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1275,7 +1264,7 @@ static void kelvin_bind_vertexshader(KelvinState *kelvin)
|
||||||
|
|
||||||
/* Check we're within resource limits */
|
/* Check we're within resource limits */
|
||||||
GLint native;
|
GLint native;
|
||||||
glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB,
|
glGetProgramivARB(GL_VERTEX_PROGRAM_ARB,
|
||||||
GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB,
|
GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB,
|
||||||
&native);
|
&native);
|
||||||
assert(native);
|
assert(native);
|
||||||
|
@ -1300,12 +1289,12 @@ static void kelvin_bind_vertexshader(KelvinState *kelvin)
|
||||||
assert(glGetError() == GL_NO_ERROR);
|
assert(glGetError() == GL_NO_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void kelvin_bind_textures(NV2AState *d, KelvinState *kelvin)
|
static void pgraph_bind_textures(NV2AState *d)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i=0; i<NV2A_MAX_TEXTURES; i++) {
|
for (i=0; i<NV2A_MAX_TEXTURES; i++) {
|
||||||
Texture *texture = &kelvin->textures[i];
|
Texture *texture = &d->pgraph.textures[i];
|
||||||
|
|
||||||
if (texture->dimensionality != 2) continue;
|
if (texture->dimensionality != 2) continue;
|
||||||
|
|
||||||
|
@ -1314,6 +1303,7 @@ static void kelvin_bind_textures(NV2AState *d, KelvinState *kelvin)
|
||||||
|
|
||||||
assert(texture->color_format
|
assert(texture->color_format
|
||||||
< sizeof(kelvin_color_format_map)/sizeof(ColorFormatInfo));
|
< sizeof(kelvin_color_format_map)/sizeof(ColorFormatInfo));
|
||||||
|
|
||||||
ColorFormatInfo f = kelvin_color_format_map[texture->color_format];
|
ColorFormatInfo f = kelvin_color_format_map[texture->color_format];
|
||||||
assert(f.bytes_per_pixel != 0);
|
assert(f.bytes_per_pixel != 0);
|
||||||
|
|
||||||
|
@ -1360,9 +1350,9 @@ static void kelvin_bind_textures(NV2AState *d, KelvinState *kelvin)
|
||||||
hwaddr dma_len;
|
hwaddr dma_len;
|
||||||
uint8_t *texture_data;
|
uint8_t *texture_data;
|
||||||
if (texture->dma_select) {
|
if (texture->dma_select) {
|
||||||
texture_data = nv_dma_map(d, kelvin->dma_b, &dma_len);
|
texture_data = nv_dma_map(d, d->pgraph.dma_b, &dma_len);
|
||||||
} else {
|
} else {
|
||||||
texture_data = nv_dma_map(d, kelvin->dma_a, &dma_len);
|
texture_data = nv_dma_map(d, d->pgraph.dma_a, &dma_len);
|
||||||
}
|
}
|
||||||
assert(texture->offset < dma_len);
|
assert(texture->offset < dma_len);
|
||||||
texture_data += texture->offset;
|
texture_data += texture->offset;
|
||||||
|
@ -1410,64 +1400,89 @@ static void kelvin_bind_textures(NV2AState *d, KelvinState *kelvin)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void kelvin_bind_fragment_shader(NV2AState *d, KelvinState *kelvin)
|
static void pgraph_bind_fragment_shader(PGRAPHState *pg)
|
||||||
{
|
{
|
||||||
const char *shader_code = "!!ARBfp1.0\n"
|
const char *shader_code = "\n"
|
||||||
"TEX result.color, fragment.texcoord[0], texture[0], RECT;\n"
|
"uniform sampler2DRect texSamp0;\n"
|
||||||
"END\n";
|
"void main() {\n"
|
||||||
|
" gl_FragColor = texture2DRect(texSamp0, gl_TexCoord[0].st);\n"
|
||||||
|
//" gl_FragColor = vec4(1, 0, 0, 1);\n"
|
||||||
|
"}\n";
|
||||||
|
|
||||||
|
if (pg->fragment_shader_dirty) {
|
||||||
glEnable(GL_FRAGMENT_PROGRAM_ARB);
|
glShaderSource(pg->gl_fragment_shader, 1, &shader_code, 0);
|
||||||
glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, kelvin->gl_fragment_program);
|
glCompileShader(pg->gl_fragment_shader);
|
||||||
|
|
||||||
if (kelvin->fragment_program_dirty) {
|
|
||||||
|
|
||||||
glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB,
|
|
||||||
GL_PROGRAM_FORMAT_ASCII_ARB,
|
|
||||||
strlen(shader_code),
|
|
||||||
shader_code);
|
|
||||||
|
|
||||||
/* Check it compiled */
|
/* Check it compiled */
|
||||||
GLint pos;
|
GLint compiled = 0;
|
||||||
glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &pos);
|
glGetShaderiv(pg->gl_fragment_shader, GL_COMPILE_STATUS, &compiled);
|
||||||
if (pos != -1) {
|
if (!compiled) {
|
||||||
fprintf(stderr, "nv2a: Fragment shader compilation failed:\n"
|
GLchar log[1024];
|
||||||
" pos %d, %s\n",
|
glGetShaderInfoLog(pg->gl_fragment_shader, 1024, NULL, log);
|
||||||
pos, glGetString(GL_PROGRAM_ERROR_STRING_ARB));
|
fprintf(stderr, "nv2a: Fragment shader compilation failed: %s\n", log);
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
kelvin->fragment_program_dirty = false;
|
/* re-link the program */
|
||||||
|
glLinkProgram(pg->gl_program);
|
||||||
|
GLint linked = 0;
|
||||||
|
glGetProgramiv(pg->gl_program, GL_LINK_STATUS, &linked);
|
||||||
|
if(!linked) {
|
||||||
|
GLchar log[1024];
|
||||||
|
glGetProgramInfoLog(pg->gl_program, 1024, NULL, log);
|
||||||
|
fprintf(stderr, "nv2a: Fragment shader linking failed: %s\n", log);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
glValidateProgram(pg->gl_program);
|
||||||
|
GLint valid = 0;
|
||||||
|
glGetProgramiv(pg->gl_program, GL_VALIDATE_STATUS, &valid);
|
||||||
|
if (!valid) {
|
||||||
|
GLchar log[1024];
|
||||||
|
glGetProgramInfoLog(pg->gl_program, 1024, NULL, log);
|
||||||
|
fprintf(stderr, "nv2a: Fragment shader validation failed: %s\n", log);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
glUseProgram(pg->gl_program);
|
||||||
|
|
||||||
|
GLint texSamp0Loc = glGetUniformLocation(pg->gl_program, "texSamp0");
|
||||||
|
glUniform1i(texSamp0Loc, 0);
|
||||||
|
|
||||||
|
|
||||||
|
pg->fragment_shader_dirty = false;
|
||||||
|
} else {
|
||||||
|
glUseProgram(pg->gl_program);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void kelvin_update_surface(NV2AState *d, KelvinState *kelvin, bool upload)
|
static void pgraph_update_surface(NV2AState *d, bool upload)
|
||||||
{
|
{
|
||||||
if (kelvin->surface_color.format != 0 && kelvin->color_mask
|
if (d->pgraph.surface_color.format != 0 && d->pgraph.color_mask
|
||||||
&& (upload || kelvin->surface_color.draw_dirty)) {
|
&& (upload || d->pgraph.surface_color.draw_dirty)) {
|
||||||
|
|
||||||
/* There's a bunch of bugs that could cause us to hit this function
|
/* There's a bunch of bugs that could cause us to hit this function
|
||||||
* at the wrong time and get a invalid dma object.
|
* at the wrong time and get a invalid dma object.
|
||||||
* Check that it's sane. */
|
* Check that it's sane. */
|
||||||
DMAObject color_dma = nv_dma_load(d, kelvin->dma_color);
|
DMAObject color_dma = nv_dma_load(d, d->pgraph.dma_color);
|
||||||
assert(color_dma.dma_class == NV_DMA_IN_MEMORY_CLASS);
|
assert(color_dma.dma_class == NV_DMA_IN_MEMORY_CLASS);
|
||||||
|
|
||||||
|
|
||||||
assert(color_dma.address + kelvin->surface_color.offset != 0);
|
assert(color_dma.address + d->pgraph.surface_color.offset != 0);
|
||||||
assert(kelvin->surface_color.offset <= color_dma.limit);
|
assert(d->pgraph.surface_color.offset <= color_dma.limit);
|
||||||
assert(kelvin->surface_color.offset
|
assert(d->pgraph.surface_color.offset
|
||||||
+ kelvin->surface_color.pitch * kelvin->surface_height
|
+ d->pgraph.surface_color.pitch * d->pgraph.surface_height
|
||||||
<= color_dma.limit + 1);
|
<= color_dma.limit + 1);
|
||||||
|
|
||||||
|
|
||||||
hwaddr color_len;
|
hwaddr color_len;
|
||||||
uint8_t *color_data = nv_dma_map(d, kelvin->dma_color, &color_len);
|
uint8_t *color_data = nv_dma_map(d, d->pgraph.dma_color, &color_len);
|
||||||
|
|
||||||
GLenum gl_format;
|
GLenum gl_format;
|
||||||
GLenum gl_type;
|
GLenum gl_type;
|
||||||
unsigned int bytes_per_pixel;
|
unsigned int bytes_per_pixel;
|
||||||
switch (kelvin->surface_color.format) {
|
switch (d->pgraph.surface_color.format) {
|
||||||
case NV097_SET_SURFACE_FORMAT_COLOR_LE_R5G6B5:
|
case NV097_SET_SURFACE_FORMAT_COLOR_LE_R5G6B5:
|
||||||
bytes_per_pixel = 2;
|
bytes_per_pixel = 2;
|
||||||
gl_format = GL_RGB;
|
gl_format = GL_RGB;
|
||||||
|
@ -1484,82 +1499,83 @@ static void kelvin_update_surface(NV2AState *d, KelvinState *kelvin, bool upload
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO */
|
/* TODO */
|
||||||
assert(kelvin->surface_x == 0 && kelvin->surface_y == 0);
|
assert(d->pgraph.surface_x == 0 && d->pgraph.surface_y == 0);
|
||||||
|
|
||||||
if (upload && memory_region_test_and_clear_dirty(d->vram,
|
if (upload && memory_region_test_and_clear_dirty(d->vram,
|
||||||
color_dma.address
|
color_dma.address
|
||||||
+ kelvin->surface_color.offset,
|
+ d->pgraph.surface_color.offset,
|
||||||
kelvin->surface_color.pitch
|
d->pgraph.surface_color.pitch
|
||||||
* kelvin->surface_height,
|
* d->pgraph.surface_height,
|
||||||
DIRTY_MEMORY_NV2A)) {
|
DIRTY_MEMORY_NV2A)) {
|
||||||
/* surface modified (or moved) by the cpu.
|
/* surface modified (or moved) by the cpu.
|
||||||
* copy it into the opengl renderbuffer */
|
* copy it into the opengl renderbuffer */
|
||||||
assert(!kelvin->surface_color.draw_dirty);
|
assert(!d->pgraph.surface_color.draw_dirty);
|
||||||
|
|
||||||
assert(kelvin->surface_color.pitch % bytes_per_pixel == 0);
|
assert(d->pgraph.surface_color.pitch % bytes_per_pixel == 0);
|
||||||
|
|
||||||
glDisable(GL_FRAGMENT_PROGRAM_ARB);
|
glDisable(GL_FRAGMENT_PROGRAM_ARB);
|
||||||
|
glUseProgram(0);
|
||||||
|
|
||||||
int rl, pa;
|
int rl, pa;
|
||||||
glGetIntegerv(GL_UNPACK_ROW_LENGTH, &rl);
|
glGetIntegerv(GL_UNPACK_ROW_LENGTH, &rl);
|
||||||
glGetIntegerv(GL_UNPACK_ALIGNMENT, &pa);
|
glGetIntegerv(GL_UNPACK_ALIGNMENT, &pa);
|
||||||
glPixelStorei(GL_UNPACK_ROW_LENGTH,
|
glPixelStorei(GL_UNPACK_ROW_LENGTH,
|
||||||
kelvin->surface_color.pitch / bytes_per_pixel);
|
d->pgraph.surface_color.pitch / bytes_per_pixel);
|
||||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||||
|
|
||||||
/* glDrawPixels is crazy deprecated, but there really isn't
|
/* glDrawPixels is crazy deprecated, but there really isn't
|
||||||
* an easy alternative */
|
* an easy alternative */
|
||||||
|
|
||||||
glWindowPos2i(0, kelvin->surface_height);
|
glWindowPos2i(0, d->pgraph.surface_height);
|
||||||
glPixelZoom(1, -1);
|
glPixelZoom(1, -1);
|
||||||
glDrawPixels(kelvin->surface_width,
|
glDrawPixels(d->pgraph.surface_width,
|
||||||
kelvin->surface_height,
|
d->pgraph.surface_height,
|
||||||
gl_format, gl_type,
|
gl_format, gl_type,
|
||||||
color_data + kelvin->surface_color.offset);
|
color_data + d->pgraph.surface_color.offset);
|
||||||
assert(glGetError() == GL_NO_ERROR);
|
assert(glGetError() == GL_NO_ERROR);
|
||||||
|
|
||||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, rl);
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, rl);
|
||||||
glPixelStorei(GL_UNPACK_ALIGNMENT, pa);
|
glPixelStorei(GL_UNPACK_ALIGNMENT, pa);
|
||||||
|
|
||||||
uint8_t *out = color_data + kelvin->surface_color.offset;
|
uint8_t *out = color_data + d->pgraph.surface_color.offset;
|
||||||
NV2A_DPRINTF("upload_surface 0x%llx - 0x%llx, "
|
NV2A_DPRINTF("upload_surface 0x%llx - 0x%llx, "
|
||||||
"(0x%llx - 0x%llx, %d %d, %d %d, %d) - %x %x %x %x\n",
|
"(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, color_dma.address + color_dma.limit,
|
||||||
color_dma.address + kelvin->surface_color.offset,
|
color_dma.address + d->pgraph.surface_color.offset,
|
||||||
color_dma.address + kelvin->surface_color.pitch * kelvin->surface_height,
|
color_dma.address + d->pgraph.surface_color.pitch * d->pgraph.surface_height,
|
||||||
kelvin->surface_x, kelvin->surface_y,
|
d->pgraph.surface_x, d->pgraph.surface_y,
|
||||||
kelvin->surface_width, kelvin->surface_height,
|
d->pgraph.surface_width, d->pgraph.surface_height,
|
||||||
kelvin->surface_color.pitch,
|
d->pgraph.surface_color.pitch,
|
||||||
out[0], out[1], out[2], out[3]);
|
out[0], out[1], out[2], out[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!upload && kelvin->surface_color.draw_dirty) {
|
if (!upload && d->pgraph.surface_color.draw_dirty) {
|
||||||
/* read the opengl renderbuffer into the surface */
|
/* read the opengl renderbuffer into the surface */
|
||||||
|
|
||||||
glo_readpixels(gl_format, gl_type,
|
glo_readpixels(gl_format, gl_type,
|
||||||
bytes_per_pixel, kelvin->surface_color.pitch,
|
bytes_per_pixel, d->pgraph.surface_color.pitch,
|
||||||
kelvin->surface_width, kelvin->surface_height,
|
d->pgraph.surface_width, d->pgraph.surface_height,
|
||||||
color_data + kelvin->surface_color.offset);
|
color_data + d->pgraph.surface_color.offset);
|
||||||
assert(glGetError() == GL_NO_ERROR);
|
assert(glGetError() == GL_NO_ERROR);
|
||||||
|
|
||||||
memory_region_set_client_dirty(d->vram,
|
memory_region_set_client_dirty(d->vram,
|
||||||
color_dma.address
|
color_dma.address
|
||||||
+ kelvin->surface_color.offset,
|
+ d->pgraph.surface_color.offset,
|
||||||
kelvin->surface_color.pitch
|
d->pgraph.surface_color.pitch
|
||||||
* kelvin->surface_height,
|
* d->pgraph.surface_height,
|
||||||
DIRTY_MEMORY_VGA);
|
DIRTY_MEMORY_VGA);
|
||||||
|
|
||||||
kelvin->surface_color.draw_dirty = false;
|
d->pgraph.surface_color.draw_dirty = false;
|
||||||
|
|
||||||
uint8_t *out = color_data + kelvin->surface_color.offset;
|
uint8_t *out = color_data + d->pgraph.surface_color.offset;
|
||||||
NV2A_DPRINTF("read_surface 0x%llx - 0x%llx, "
|
NV2A_DPRINTF("read_surface 0x%llx - 0x%llx, "
|
||||||
"(0x%llx - 0x%llx, %d %d, %d %d, %d) - %x %x %x %x\n",
|
"(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, color_dma.address + color_dma.limit,
|
||||||
color_dma.address + kelvin->surface_color.offset,
|
color_dma.address + d->pgraph.surface_color.offset,
|
||||||
color_dma.address + kelvin->surface_color.pitch * kelvin->surface_height,
|
color_dma.address + d->pgraph.surface_color.pitch * d->pgraph.surface_height,
|
||||||
kelvin->surface_x, kelvin->surface_y,
|
d->pgraph.surface_x, d->pgraph.surface_y,
|
||||||
kelvin->surface_width, kelvin->surface_height,
|
d->pgraph.surface_width, d->pgraph.surface_height,
|
||||||
kelvin->surface_color.pitch,
|
d->pgraph.surface_color.pitch,
|
||||||
out[0], out[1], out[2], out[3]);
|
out[0], out[1], out[2], out[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1568,11 +1584,12 @@ static void kelvin_update_surface(NV2AState *d, KelvinState *kelvin, bool upload
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void pgraph_context_init(GraphicsContext *context)
|
static void pgraph_gl_init(PGRAPHState *pg)
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
context->gl_context = glo_context_create(GLO_FF_DEFAULT);
|
pg->gl_context = glo_context_create(GLO_FF_DEFAULT);
|
||||||
assert(context->gl_context);
|
assert(pg->gl_context);
|
||||||
|
|
||||||
/* Check context capabilities */
|
/* Check context capabilities */
|
||||||
const GLubyte *extensions = glGetString(GL_EXTENSIONS);
|
const GLubyte *extensions = glGetString(GL_EXTENSIONS);
|
||||||
|
@ -1601,48 +1618,54 @@ static void pgraph_context_init(GraphicsContext *context)
|
||||||
glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &max_vertex_attributes);
|
glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &max_vertex_attributes);
|
||||||
assert(max_vertex_attributes >= NV2A_VERTEXSHADER_ATTRIBUTES);
|
assert(max_vertex_attributes >= NV2A_VERTEXSHADER_ATTRIBUTES);
|
||||||
|
|
||||||
glGenFramebuffersEXT(1, &context->gl_framebuffer);
|
glGenFramebuffersEXT(1, &pg->gl_framebuffer);
|
||||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, context->gl_framebuffer);
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, pg->gl_framebuffer);
|
||||||
|
|
||||||
glGenRenderbuffersEXT(1, &context->gl_renderbuffer);
|
glGenRenderbuffersEXT(1, &pg->gl_renderbuffer);
|
||||||
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, context->gl_renderbuffer);
|
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, pg->gl_renderbuffer);
|
||||||
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA8,
|
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA8,
|
||||||
640, 480);
|
640, 480);
|
||||||
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
|
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
|
||||||
GL_COLOR_ATTACHMENT0_EXT,
|
GL_COLOR_ATTACHMENT0_EXT,
|
||||||
GL_RENDERBUFFER_EXT,
|
GL_RENDERBUFFER_EXT,
|
||||||
context->gl_renderbuffer);
|
pg->gl_renderbuffer);
|
||||||
|
|
||||||
assert(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT)
|
assert(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT)
|
||||||
== GL_FRAMEBUFFER_COMPLETE_EXT);
|
== GL_FRAMEBUFFER_COMPLETE_EXT);
|
||||||
|
|
||||||
|
|
||||||
glViewport(0, 0, 640, 480);
|
glViewport(0, 0, 640, 480);
|
||||||
|
//glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
|
||||||
|
|
||||||
|
/* fragment shader */
|
||||||
|
// glGenProgramsARB(1, &pg->gl_fragment_program);
|
||||||
|
pg->fragment_shader_dirty = true;
|
||||||
|
pg->gl_fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||||
|
pg->gl_program = glCreateProgram();
|
||||||
|
glAttachShader(pg->gl_program, pg->gl_fragment_shader);
|
||||||
|
|
||||||
|
/* generate textures */
|
||||||
|
for (i = 0; i < NV2A_MAX_TEXTURES; i++) {
|
||||||
|
Texture *texture = &pg->textures[i];
|
||||||
|
glGenTextures(1, &texture->gl_texture);
|
||||||
|
glGenTextures(1, &texture->gl_texture_rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
assert(glGetError() == GL_NO_ERROR);
|
assert(glGetError() == GL_NO_ERROR);
|
||||||
|
|
||||||
glo_set_current(NULL);
|
glo_set_current(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pgraph_context_set_current(GraphicsContext *context)
|
static void pgraph_gl_destroy(PGRAPHState *pg)
|
||||||
{
|
{
|
||||||
if (context) {
|
glo_set_current(pg->gl_context);
|
||||||
glo_set_current(context->gl_context);
|
|
||||||
} else {
|
|
||||||
glo_set_current(NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void pgraph_context_destroy(GraphicsContext *context)
|
glDeleteRenderbuffersEXT(1, &pg->gl_renderbuffer);
|
||||||
{
|
glDeleteFramebuffersEXT(1, &pg->gl_framebuffer);
|
||||||
glo_set_current(context->gl_context);
|
|
||||||
|
|
||||||
glDeleteRenderbuffersEXT(1, &context->gl_renderbuffer);
|
|
||||||
glDeleteFramebuffersEXT(1, &context->gl_framebuffer);
|
|
||||||
|
|
||||||
glo_set_current(NULL);
|
glo_set_current(NULL);
|
||||||
|
|
||||||
glo_context_destroy(context->gl_context);
|
glo_context_destroy(pg->gl_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pgraph_method(NV2AState *d,
|
static void pgraph_method(NV2AState *d,
|
||||||
|
@ -1651,7 +1674,6 @@ static void pgraph_method(NV2AState *d,
|
||||||
uint32_t parameter)
|
uint32_t parameter)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
GraphicsContext *context;
|
|
||||||
GraphicsSubchannel *subchannel_data;
|
GraphicsSubchannel *subchannel_data;
|
||||||
GraphicsObject *object;
|
GraphicsObject *object;
|
||||||
|
|
||||||
|
@ -1660,11 +1682,12 @@ static void pgraph_method(NV2AState *d,
|
||||||
VertexShader *vertexshader;
|
VertexShader *vertexshader;
|
||||||
VertexShaderConstant *constant;
|
VertexShaderConstant *constant;
|
||||||
|
|
||||||
qemu_mutex_lock(&d->pgraph.lock);
|
PGRAPHState *pg = &d->pgraph;
|
||||||
|
|
||||||
assert(d->pgraph.channel_valid);
|
qemu_mutex_lock(&pg->lock);
|
||||||
context = &d->pgraph.context[d->pgraph.channel_id];
|
|
||||||
subchannel_data = &context->subchannel_data[subchannel];
|
assert(pg->channel_valid);
|
||||||
|
subchannel_data = &pg->subchannel_data[subchannel];
|
||||||
object = &subchannel_data->object;
|
object = &subchannel_data->object;
|
||||||
|
|
||||||
ContextSurfaces2DState *context_surfaces_2d
|
ContextSurfaces2DState *context_surfaces_2d
|
||||||
|
@ -1676,12 +1699,12 @@ static void pgraph_method(NV2AState *d,
|
||||||
|
|
||||||
pgraph_method_log(subchannel, object->graphics_class, method, parameter);
|
pgraph_method_log(subchannel, object->graphics_class, method, parameter);
|
||||||
|
|
||||||
pgraph_context_set_current(context);
|
glo_set_current(pg->gl_context);
|
||||||
|
|
||||||
if (method == NV_SET_OBJECT) {
|
if (method == NV_SET_OBJECT) {
|
||||||
subchannel_data->object_instance = parameter;
|
subchannel_data->object_instance = parameter;
|
||||||
|
|
||||||
qemu_mutex_unlock(&d->pgraph.lock);
|
qemu_mutex_unlock(&pg->lock);
|
||||||
//qemu_mutex_lock_iothread();
|
//qemu_mutex_lock_iothread();
|
||||||
load_graphics_object(d, parameter, object);
|
load_graphics_object(d, parameter, object);
|
||||||
//qemu_mutex_unlock_iothread();
|
//qemu_mutex_unlock_iothread();
|
||||||
|
@ -1731,7 +1754,7 @@ static void pgraph_method(NV2AState *d,
|
||||||
/* I guess this kicks it off? */
|
/* I guess this kicks it off? */
|
||||||
if (image_blit->operation == NV09F_SET_OPERATION_SRCCOPY) {
|
if (image_blit->operation == NV09F_SET_OPERATION_SRCCOPY) {
|
||||||
GraphicsObject *context_surfaces_obj =
|
GraphicsObject *context_surfaces_obj =
|
||||||
lookup_graphics_object(context, image_blit->context_surfaces);
|
lookup_graphics_object(pg, image_blit->context_surfaces);
|
||||||
assert(context_surfaces_obj);
|
assert(context_surfaces_obj);
|
||||||
assert(context_surfaces_obj->graphics_class
|
assert(context_surfaces_obj->graphics_class
|
||||||
== NV_CONTEXT_SURFACES_2D);
|
== NV_CONTEXT_SURFACES_2D);
|
||||||
|
@ -1816,33 +1839,33 @@ static void pgraph_method(NV2AState *d,
|
||||||
|
|
||||||
case NV097_WAIT_FOR_IDLE:
|
case NV097_WAIT_FOR_IDLE:
|
||||||
glFinish();
|
glFinish();
|
||||||
kelvin_update_surface(d, kelvin, false);
|
pgraph_update_surface(d, false);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NV097_FLIP_STALL:
|
case NV097_FLIP_STALL:
|
||||||
kelvin_update_surface(d, kelvin, false);
|
pgraph_update_surface(d, false);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NV097_SET_CONTEXT_DMA_NOTIFIES:
|
case NV097_SET_CONTEXT_DMA_NOTIFIES:
|
||||||
kelvin->dma_notifies = parameter;
|
kelvin->dma_notifies = parameter;
|
||||||
break;
|
break;
|
||||||
case NV097_SET_CONTEXT_DMA_A:
|
case NV097_SET_CONTEXT_DMA_A:
|
||||||
kelvin->dma_a = parameter;
|
pg->dma_a = parameter;
|
||||||
break;
|
break;
|
||||||
case NV097_SET_CONTEXT_DMA_B:
|
case NV097_SET_CONTEXT_DMA_B:
|
||||||
kelvin->dma_b = parameter;
|
pg->dma_b = parameter;
|
||||||
break;
|
break;
|
||||||
case NV097_SET_CONTEXT_DMA_STATE:
|
case NV097_SET_CONTEXT_DMA_STATE:
|
||||||
kelvin->dma_state = parameter;
|
kelvin->dma_state = parameter;
|
||||||
break;
|
break;
|
||||||
case NV097_SET_CONTEXT_DMA_COLOR:
|
case NV097_SET_CONTEXT_DMA_COLOR:
|
||||||
/* try to get any straggling draws in before the surface's changed :/ */
|
/* try to get any straggling draws in before the surface's changed :/ */
|
||||||
kelvin_update_surface(d, kelvin, false);
|
pgraph_update_surface(d, false);
|
||||||
|
|
||||||
kelvin->dma_color = parameter;
|
pg->dma_color = parameter;
|
||||||
break;
|
break;
|
||||||
case NV097_SET_CONTEXT_DMA_ZETA:
|
case NV097_SET_CONTEXT_DMA_ZETA:
|
||||||
kelvin->dma_zeta = parameter;
|
pg->dma_zeta = parameter;
|
||||||
break;
|
break;
|
||||||
case NV097_SET_CONTEXT_DMA_VERTEX_A:
|
case NV097_SET_CONTEXT_DMA_VERTEX_A:
|
||||||
kelvin->dma_vertex_a = parameter;
|
kelvin->dma_vertex_a = parameter;
|
||||||
|
@ -1855,49 +1878,49 @@ static void pgraph_method(NV2AState *d,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NV097_SET_SURFACE_CLIP_HORIZONTAL:
|
case NV097_SET_SURFACE_CLIP_HORIZONTAL:
|
||||||
kelvin_update_surface(d, kelvin, false);
|
pgraph_update_surface(d, false);
|
||||||
|
|
||||||
kelvin->surface_x =
|
pg->surface_x =
|
||||||
GET_MASK(parameter, NV097_SET_SURFACE_CLIP_HORIZONTAL_X);
|
GET_MASK(parameter, NV097_SET_SURFACE_CLIP_HORIZONTAL_X);
|
||||||
kelvin->surface_width =
|
pg->surface_width =
|
||||||
GET_MASK(parameter, NV097_SET_SURFACE_CLIP_HORIZONTAL_WIDTH);
|
GET_MASK(parameter, NV097_SET_SURFACE_CLIP_HORIZONTAL_WIDTH);
|
||||||
break;
|
break;
|
||||||
case NV097_SET_SURFACE_CLIP_VERTICAL:
|
case NV097_SET_SURFACE_CLIP_VERTICAL:
|
||||||
kelvin_update_surface(d, kelvin, false);
|
pgraph_update_surface(d, false);
|
||||||
|
|
||||||
kelvin->surface_y =
|
pg->surface_y =
|
||||||
GET_MASK(parameter, NV097_SET_SURFACE_CLIP_VERTICAL_Y);
|
GET_MASK(parameter, NV097_SET_SURFACE_CLIP_VERTICAL_Y);
|
||||||
kelvin->surface_height =
|
pg->surface_height =
|
||||||
GET_MASK(parameter, NV097_SET_SURFACE_CLIP_VERTICAL_HEIGHT);
|
GET_MASK(parameter, NV097_SET_SURFACE_CLIP_VERTICAL_HEIGHT);
|
||||||
break;
|
break;
|
||||||
case NV097_SET_SURFACE_FORMAT:
|
case NV097_SET_SURFACE_FORMAT:
|
||||||
kelvin_update_surface(d, kelvin, false);
|
pgraph_update_surface(d, false);
|
||||||
|
|
||||||
kelvin->surface_color.format =
|
pg->surface_color.format =
|
||||||
GET_MASK(parameter, NV097_SET_SURFACE_FORMAT_COLOR);
|
GET_MASK(parameter, NV097_SET_SURFACE_FORMAT_COLOR);
|
||||||
kelvin->surface_zeta.format =
|
pg->surface_zeta.format =
|
||||||
GET_MASK(parameter, NV097_SET_SURFACE_FORMAT_ZETA);
|
GET_MASK(parameter, NV097_SET_SURFACE_FORMAT_ZETA);
|
||||||
break;
|
break;
|
||||||
case NV097_SET_SURFACE_PITCH:
|
case NV097_SET_SURFACE_PITCH:
|
||||||
kelvin_update_surface(d, kelvin, false);
|
pgraph_update_surface(d, false);
|
||||||
|
|
||||||
kelvin->surface_color.pitch =
|
pg->surface_color.pitch =
|
||||||
GET_MASK(parameter, NV097_SET_SURFACE_PITCH_COLOR);
|
GET_MASK(parameter, NV097_SET_SURFACE_PITCH_COLOR);
|
||||||
kelvin->surface_zeta.pitch =
|
pg->surface_zeta.pitch =
|
||||||
GET_MASK(parameter, NV097_SET_SURFACE_PITCH_ZETA);
|
GET_MASK(parameter, NV097_SET_SURFACE_PITCH_ZETA);
|
||||||
break;
|
break;
|
||||||
case NV097_SET_SURFACE_COLOR_OFFSET:
|
case NV097_SET_SURFACE_COLOR_OFFSET:
|
||||||
kelvin_update_surface(d, kelvin, false);
|
pgraph_update_surface(d, false);
|
||||||
|
|
||||||
kelvin->surface_color.offset = parameter;
|
pg->surface_color.offset = parameter;
|
||||||
break;
|
break;
|
||||||
case NV097_SET_SURFACE_ZETA_OFFSET:
|
case NV097_SET_SURFACE_ZETA_OFFSET:
|
||||||
kelvin_update_surface(d, kelvin, false);
|
pgraph_update_surface(d, false);
|
||||||
|
|
||||||
kelvin->surface_zeta.offset = parameter;
|
pg->surface_zeta.offset = parameter;
|
||||||
break;
|
break;
|
||||||
case NV097_SET_COLOR_MASK:
|
case NV097_SET_COLOR_MASK:
|
||||||
kelvin->color_mask = parameter;
|
pg->color_mask = parameter;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NV097_SET_VIEWPORT_OFFSET ...
|
case NV097_SET_VIEWPORT_OFFSET ...
|
||||||
|
@ -2056,7 +2079,7 @@ static void pgraph_method(NV2AState *d,
|
||||||
} else {
|
} else {
|
||||||
assert(parameter <= NV097_SET_BEGIN_END_OP_POLYGON);
|
assert(parameter <= NV097_SET_BEGIN_END_OP_POLYGON);
|
||||||
|
|
||||||
kelvin_update_surface(d, kelvin, true);
|
pgraph_update_surface(d, true);
|
||||||
|
|
||||||
if (kelvin->use_vertex_program) {
|
if (kelvin->use_vertex_program) {
|
||||||
glEnable(GL_VERTEX_PROGRAM_ARB);
|
glEnable(GL_VERTEX_PROGRAM_ARB);
|
||||||
|
@ -2065,9 +2088,9 @@ static void pgraph_method(NV2AState *d,
|
||||||
glDisable(GL_VERTEX_PROGRAM_ARB);
|
glDisable(GL_VERTEX_PROGRAM_ARB);
|
||||||
}
|
}
|
||||||
|
|
||||||
kelvin_bind_fragment_shader(d, kelvin);
|
pgraph_bind_fragment_shader(pg);
|
||||||
|
|
||||||
kelvin_bind_textures(d, kelvin);
|
pgraph_bind_textures(d);
|
||||||
kelvin_bind_vertex_attribute_offsets(d, kelvin);
|
kelvin_bind_vertex_attribute_offsets(d, kelvin);
|
||||||
|
|
||||||
|
|
||||||
|
@ -2076,67 +2099,65 @@ static void pgraph_method(NV2AState *d,
|
||||||
kelvin->array_batch_length = 0;
|
kelvin->array_batch_length = 0;
|
||||||
kelvin->inline_vertex_data_length = 0;
|
kelvin->inline_vertex_data_length = 0;
|
||||||
}
|
}
|
||||||
kelvin->surface_color.draw_dirty = true;
|
pg->surface_color.draw_dirty = true;
|
||||||
break;
|
break;
|
||||||
CASE_4(NV097_SET_TEXTURE_OFFSET, 64):
|
CASE_4(NV097_SET_TEXTURE_OFFSET, 64):
|
||||||
slot = (class_method - NV097_SET_TEXTURE_OFFSET) / 64;
|
slot = (class_method - NV097_SET_TEXTURE_OFFSET) / 64;
|
||||||
|
pg->textures[slot].offset = parameter;
|
||||||
kelvin->textures[slot].offset = parameter;
|
pg->textures[slot].dirty = true;
|
||||||
|
|
||||||
kelvin->textures[slot].dirty = true;
|
|
||||||
break;
|
break;
|
||||||
CASE_4(NV097_SET_TEXTURE_FORMAT, 64):
|
CASE_4(NV097_SET_TEXTURE_FORMAT, 64):
|
||||||
slot = (class_method - NV097_SET_TEXTURE_FORMAT) / 64;
|
slot = (class_method - NV097_SET_TEXTURE_FORMAT) / 64;
|
||||||
|
|
||||||
kelvin->textures[slot].dma_select =
|
pg->textures[slot].dma_select =
|
||||||
GET_MASK(parameter, NV097_SET_TEXTURE_FORMAT_CONTEXT_DMA) == 2;
|
GET_MASK(parameter, NV097_SET_TEXTURE_FORMAT_CONTEXT_DMA) == 2;
|
||||||
kelvin->textures[slot].dimensionality =
|
pg->textures[slot].dimensionality =
|
||||||
GET_MASK(parameter, NV097_SET_TEXTURE_FORMAT_DIMENSIONALITY);
|
GET_MASK(parameter, NV097_SET_TEXTURE_FORMAT_DIMENSIONALITY);
|
||||||
kelvin->textures[slot].color_format =
|
pg->textures[slot].color_format =
|
||||||
GET_MASK(parameter, NV097_SET_TEXTURE_FORMAT_COLOR);
|
GET_MASK(parameter, NV097_SET_TEXTURE_FORMAT_COLOR);
|
||||||
kelvin->textures[slot].log_width =
|
pg->textures[slot].log_width =
|
||||||
GET_MASK(parameter, NV097_SET_TEXTURE_FORMAT_BASE_SIZE_U);
|
GET_MASK(parameter, NV097_SET_TEXTURE_FORMAT_BASE_SIZE_U);
|
||||||
kelvin->textures[slot].log_height =
|
pg->textures[slot].log_height =
|
||||||
GET_MASK(parameter, NV097_SET_TEXTURE_FORMAT_BASE_SIZE_V);
|
GET_MASK(parameter, NV097_SET_TEXTURE_FORMAT_BASE_SIZE_V);
|
||||||
|
|
||||||
kelvin->textures[slot].dirty = true;
|
pg->textures[slot].dirty = true;
|
||||||
break;
|
break;
|
||||||
CASE_4(NV097_SET_TEXTURE_CONTROL0, 64):
|
CASE_4(NV097_SET_TEXTURE_CONTROL0, 64):
|
||||||
slot = (class_method - NV097_SET_TEXTURE_CONTROL0) / 64;
|
slot = (class_method - NV097_SET_TEXTURE_CONTROL0) / 64;
|
||||||
|
|
||||||
kelvin->textures[slot].enabled =
|
pg->textures[slot].enabled =
|
||||||
parameter & NV097_SET_TEXTURE_CONTROL0_ENABLE;
|
parameter & NV097_SET_TEXTURE_CONTROL0_ENABLE;
|
||||||
kelvin->textures[slot].min_mipmap_level =
|
pg->textures[slot].min_mipmap_level =
|
||||||
GET_MASK(parameter, NV097_SET_TEXTURE_CONTROL0_MIN_LOD_CLAMP);
|
GET_MASK(parameter, NV097_SET_TEXTURE_CONTROL0_MIN_LOD_CLAMP);
|
||||||
kelvin->textures[slot].max_mipmap_level =
|
pg->textures[slot].max_mipmap_level =
|
||||||
GET_MASK(parameter, NV097_SET_TEXTURE_CONTROL0_MAX_LOD_CLAMP);
|
GET_MASK(parameter, NV097_SET_TEXTURE_CONTROL0_MAX_LOD_CLAMP);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
CASE_4(NV097_SET_TEXTURE_CONTROL1, 64):
|
CASE_4(NV097_SET_TEXTURE_CONTROL1, 64):
|
||||||
slot = (class_method - NV097_SET_TEXTURE_CONTROL1) / 64;
|
slot = (class_method - NV097_SET_TEXTURE_CONTROL1) / 64;
|
||||||
|
|
||||||
kelvin->textures[slot].pitch =
|
pg->textures[slot].pitch =
|
||||||
GET_MASK(parameter, NV097_SET_TEXTURE_CONTROL1_IMAGE_PITCH);
|
GET_MASK(parameter, NV097_SET_TEXTURE_CONTROL1_IMAGE_PITCH);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
CASE_4(NV097_SET_TEXTURE_FILTER, 64):
|
CASE_4(NV097_SET_TEXTURE_FILTER, 64):
|
||||||
slot = (class_method - NV097_SET_TEXTURE_FILTER) / 64;
|
slot = (class_method - NV097_SET_TEXTURE_FILTER) / 64;
|
||||||
|
|
||||||
kelvin->textures[slot].min_filter =
|
pg->textures[slot].min_filter =
|
||||||
GET_MASK(parameter, NV097_SET_TEXTURE_FILTER_MIN);
|
GET_MASK(parameter, NV097_SET_TEXTURE_FILTER_MIN);
|
||||||
kelvin->textures[slot].mag_filter =
|
pg->textures[slot].mag_filter =
|
||||||
GET_MASK(parameter, NV097_SET_TEXTURE_FILTER_MAG);
|
GET_MASK(parameter, NV097_SET_TEXTURE_FILTER_MAG);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
CASE_4(NV097_SET_TEXTURE_IMAGE_RECT, 64):
|
CASE_4(NV097_SET_TEXTURE_IMAGE_RECT, 64):
|
||||||
slot = (class_method - NV097_SET_TEXTURE_IMAGE_RECT) / 64;
|
slot = (class_method - NV097_SET_TEXTURE_IMAGE_RECT) / 64;
|
||||||
|
|
||||||
kelvin->textures[slot].rect_width =
|
pg->textures[slot].rect_width =
|
||||||
GET_MASK(parameter, NV097_SET_TEXTURE_IMAGE_RECT_WIDTH);
|
GET_MASK(parameter, NV097_SET_TEXTURE_IMAGE_RECT_WIDTH);
|
||||||
kelvin->textures[slot].rect_height =
|
pg->textures[slot].rect_height =
|
||||||
GET_MASK(parameter, NV097_SET_TEXTURE_IMAGE_RECT_HEIGHT);
|
GET_MASK(parameter, NV097_SET_TEXTURE_IMAGE_RECT_HEIGHT);
|
||||||
|
|
||||||
kelvin->textures[slot].dirty = true;
|
pg->textures[slot].dirty = true;
|
||||||
break;
|
break;
|
||||||
case NV097_ARRAY_ELEMENT16:
|
case NV097_ARRAY_ELEMENT16:
|
||||||
assert(kelvin->array_batch_length < NV2A_MAX_BATCH_LENGTH);
|
assert(kelvin->array_batch_length < NV2A_MAX_BATCH_LENGTH);
|
||||||
|
@ -2172,7 +2193,7 @@ static void pgraph_method(NV2AState *d,
|
||||||
break;
|
break;
|
||||||
case NV097_BACK_END_WRITE_SEMAPHORE_RELEASE: {
|
case NV097_BACK_END_WRITE_SEMAPHORE_RELEASE: {
|
||||||
|
|
||||||
kelvin_update_surface(d, kelvin, false);
|
pgraph_update_surface(d, false);
|
||||||
|
|
||||||
//qemu_mutex_unlock(&d->pgraph.lock);
|
//qemu_mutex_unlock(&d->pgraph.lock);
|
||||||
//qemu_mutex_lock_iothread();
|
//qemu_mutex_lock_iothread();
|
||||||
|
@ -2191,11 +2212,11 @@ static void pgraph_method(NV2AState *d,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NV097_SET_ZSTENCIL_CLEAR_VALUE:
|
case NV097_SET_ZSTENCIL_CLEAR_VALUE:
|
||||||
d->pgraph.regs[NV_PGRAPH_ZSTENCILCLEARVALUE] = parameter;
|
pg->regs[NV_PGRAPH_ZSTENCILCLEARVALUE] = parameter;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NV097_SET_COLOR_CLEAR_VALUE:
|
case NV097_SET_COLOR_CLEAR_VALUE:
|
||||||
d->pgraph.regs[NV_PGRAPH_COLORCLEARVALUE] = parameter;
|
pg->regs[NV_PGRAPH_COLORCLEARVALUE] = parameter;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NV097_CLEAR_SURFACE:
|
case NV097_CLEAR_SURFACE:
|
||||||
|
@ -2213,7 +2234,7 @@ static void pgraph_method(NV2AState *d,
|
||||||
|
|
||||||
if (parameter & (NV097_CLEAR_SURFACE_COLOR)) {
|
if (parameter & (NV097_CLEAR_SURFACE_COLOR)) {
|
||||||
gl_mask |= GL_COLOR_BUFFER_BIT;
|
gl_mask |= GL_COLOR_BUFFER_BIT;
|
||||||
kelvin_update_surface(d, kelvin, true);
|
pgraph_update_surface(d, true);
|
||||||
|
|
||||||
uint32_t clear_color = d->pgraph.regs[NV_PGRAPH_COLORCLEARVALUE];
|
uint32_t clear_color = d->pgraph.regs[NV_PGRAPH_COLORCLEARVALUE];
|
||||||
glClearColor( ((clear_color >> 16) & 0xFF) / 255.0f, /* red */
|
glClearColor( ((clear_color >> 16) & 0xFF) / 255.0f, /* red */
|
||||||
|
@ -2233,10 +2254,10 @@ static void pgraph_method(NV2AState *d,
|
||||||
NV_PGRAPH_CLEARRECTY_YMIN);
|
NV_PGRAPH_CLEARRECTY_YMIN);
|
||||||
unsigned int ymax = GET_MASK(d->pgraph.regs[NV_PGRAPH_CLEARRECTY],
|
unsigned int ymax = GET_MASK(d->pgraph.regs[NV_PGRAPH_CLEARRECTY],
|
||||||
NV_PGRAPH_CLEARRECTY_YMAX);
|
NV_PGRAPH_CLEARRECTY_YMAX);
|
||||||
glScissor(xmin, kelvin->surface_height-ymax, xmax-xmin, ymax-ymin);
|
glScissor(xmin, pg->surface_height-ymax, xmax-xmin, ymax-ymin);
|
||||||
|
|
||||||
NV2A_DPRINTF("------------------CLEAR 0x%x %d,%d - %d,%d ---------------\n",
|
NV2A_DPRINTF("------------------CLEAR 0x%x %d,%d - %d,%d %x---------------\n",
|
||||||
parameter, xmin, ymin, xmax, ymax);
|
parameter, xmin, ymin, xmax, ymax, d->pgraph.regs[NV_PGRAPH_COLORCLEARVALUE]);
|
||||||
|
|
||||||
glClear(gl_mask);
|
glClear(gl_mask);
|
||||||
|
|
||||||
|
@ -2244,15 +2265,15 @@ static void pgraph_method(NV2AState *d,
|
||||||
|
|
||||||
|
|
||||||
if (parameter & NV097_CLEAR_SURFACE_COLOR) {
|
if (parameter & NV097_CLEAR_SURFACE_COLOR) {
|
||||||
kelvin->surface_color.draw_dirty = true;
|
pg->surface_color.draw_dirty = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NV097_SET_CLEAR_RECT_HORIZONTAL:
|
case NV097_SET_CLEAR_RECT_HORIZONTAL:
|
||||||
d->pgraph.regs[NV_PGRAPH_CLEARRECTX] = parameter;
|
pg->regs[NV_PGRAPH_CLEARRECTX] = parameter;
|
||||||
break;
|
break;
|
||||||
case NV097_SET_CLEAR_RECT_VERTICAL:
|
case NV097_SET_CLEAR_RECT_VERTICAL:
|
||||||
d->pgraph.regs[NV_PGRAPH_CLEARRECTY] = parameter;
|
pg->regs[NV_PGRAPH_CLEARRECTY] = parameter;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NV097_SET_TRANSFORM_EXECUTION_MODE:
|
case NV097_SET_TRANSFORM_EXECUTION_MODE:
|
||||||
|
@ -3906,16 +3927,13 @@ static int nv2a_initfn(PCIDevice *dev)
|
||||||
qemu_cond_init(&d->pgraph.fifo_access_cond);
|
qemu_cond_init(&d->pgraph.fifo_access_cond);
|
||||||
|
|
||||||
/* fire up graphics contexts */
|
/* fire up graphics contexts */
|
||||||
for (i=0; i<NV2A_NUM_CHANNELS; i++) {
|
pgraph_gl_init(&d->pgraph);
|
||||||
pgraph_context_init(&d->pgraph.context[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void nv2a_exitfn(PCIDevice *dev)
|
static void nv2a_exitfn(PCIDevice *dev)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
NV2AState *d;
|
NV2AState *d;
|
||||||
d = NV2A_DEVICE(dev);
|
d = NV2A_DEVICE(dev);
|
||||||
|
|
||||||
|
@ -3927,9 +3945,7 @@ static void nv2a_exitfn(PCIDevice *dev)
|
||||||
qemu_cond_destroy(&d->pgraph.interrupt_cond);
|
qemu_cond_destroy(&d->pgraph.interrupt_cond);
|
||||||
qemu_cond_destroy(&d->pgraph.fifo_access_cond);
|
qemu_cond_destroy(&d->pgraph.fifo_access_cond);
|
||||||
|
|
||||||
for (i=0; i<NV2A_NUM_CHANNELS; i++) {
|
pgraph_gl_destroy(&d->pgraph);
|
||||||
pgraph_context_destroy(&d->pgraph.context[i]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void nv2a_class_init(ObjectClass *klass, void *data)
|
static void nv2a_class_init(ObjectClass *klass, void *data)
|
||||||
|
|
Loading…
Reference in New Issue