diff --git a/hw/xbox/Makefile.objs b/hw/xbox/Makefile.objs
index 84f900713e..636660cd1c 100644
--- a/hw/xbox/Makefile.objs
+++ b/hw/xbox/Makefile.objs
@@ -2,7 +2,7 @@ obj-y += xbox.o chihiro.o
obj-y += xbox_pci.o acpi_xbox.o
obj-y += amd_smbus.o smbus_xbox_smc.o smbus_cx25871.o smbus_adm1032.o
obj-y += nvnet.o
-obj-y += nv2a.o nv2a_vsh.o nv2a_psh.o nv2a_shaders.o
+obj-y += nv2a.o nv2a_vsh.o nv2a_psh.o nv2a_shaders.o nv2a_debug.o
obj-y += swizzle.o g-lru-cache.o
obj-y += mcpx_apu.o mcpx_aci.o
obj-y += lpc47m157.o
diff --git a/hw/xbox/nv2a.c b/hw/xbox/nv2a.c
index 5a87e29b51..32a35e00c0 100644
--- a/hw/xbox/nv2a.c
+++ b/hw/xbox/nv2a.c
@@ -34,87 +34,10 @@
#include "hw/xbox/swizzle.h"
#include "hw/xbox/u_format_r11g11b10f.h"
#include "hw/xbox/nv2a_shaders.h"
+#include "hw/xbox/nv2a_debug.h"
#include "hw/xbox/nv2a.h"
-// #define DEBUG_NV2A
-#ifdef DEBUG_NV2A
-# define NV2A_DPRINTF(format, ...) printf("nv2a: " format, ## __VA_ARGS__)
-#else
-# define NV2A_DPRINTF(format, ...) do { } while (0)
-#endif
-
-// #define DEBUG_NV2A_GL
-#ifdef DEBUG_NV2A_GL
-
-static void gl_debug_message(bool cc, const char *fmt, ...)
-{
- size_t n;
- char buffer[1024];
- va_list ap;
- va_start(ap, fmt);
- n = vsnprintf(buffer, sizeof(buffer), fmt, ap);
- assert(n <= sizeof(buffer));
- va_end(ap);
- glDebugMessageInsert(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_MARKER,
- 0, GL_DEBUG_SEVERITY_NOTIFICATION, n, buffer);
- if (cc) {
- fwrite(buffer, sizeof(char), n, stdout);
- fputc('\n', stdout);
- }
-}
-
-static void gl_debug_group_begin(const char *fmt, ...)
-{
- size_t n;
- char buffer[1024];
- va_list ap;
- va_start(ap, fmt);
- n = vsnprintf(buffer, sizeof(buffer), fmt, ap);
- assert(n <= sizeof(buffer));
- va_end(ap);
-
- /* Check for errors before entering group */
- assert(glGetError() == GL_NO_ERROR);
- glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0, n, buffer);
-}
-
-static void gl_debug_group_end(void)
-{
- /* Check for errors when leaving group */
- assert(glGetError() == GL_NO_ERROR);
- glPopDebugGroup();
-}
-
-static void gl_debug_label(GLenum target, GLuint name, const char *fmt, ...)
-{
- size_t n;
- char buffer[1024];
- va_list ap;
- va_start(ap, fmt);
- n = vsnprintf(buffer, sizeof(buffer), fmt, ap);
- assert(n <= sizeof(buffer));
- va_end(ap);
-
- glObjectLabel(target, name, n, buffer);
-}
-
-# define NV2A_GL_DPRINTF(cc, format, ...) \
- gl_debug_message(cc, "nv2a: " format, ## __VA_ARGS__)
-# define NV2A_GL_DGROUP_BEGIN(format, ...) \
- gl_debug_group_begin("nv2a: " format, ## __VA_ARGS__)
-# define NV2A_GL_DGROUP_END() \
- gl_debug_group_end()
-# define NV2A_GL_DLABEL(target, name, format, ...) \
- gl_debug_label(target, name, "nv2a: { " format " }", ## __VA_ARGS__)
-
-#else
-# define NV2A_GL_DPRINTF(cc, format, ...) do { } while (0)
-# define NV2A_GL_DGROUP_BEGIN(format, ...) do { } while (0)
-# define NV2A_GL_DGROUP_END() do { } while (0)
-# define NV2A_GL_DLABEL(target, name, format, ...) do { } while (0)
-#endif
-
#define USE_TEXTURE_CACHE
#define NV_NUM_BLOCKS 21
@@ -1269,6 +1192,24 @@ static const SurfaceColorFormatInfo kelvin_surface_color_format_map[] = {
{4, GL_RGBA8, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV},
};
+#define NV2A_VERTEX_ATTR_POSITION 0
+#define NV2A_VERTEX_ATTR_WEIGHT 1
+#define NV2A_VERTEX_ATTR_NORMAL 2
+#define NV2A_VERTEX_ATTR_DIFFUSE 3
+#define NV2A_VERTEX_ATTR_SPECULAR 4
+#define NV2A_VERTEX_ATTR_FOG 5
+#define NV2A_VERTEX_ATTR_POINT_SIZE 6
+#define NV2A_VERTEX_ATTR_BACK_DIFFUSE 7
+#define NV2A_VERTEX_ATTR_BACK_SPECULAR 8
+#define NV2A_VERTEX_ATTR_TEXTURE0 9
+#define NV2A_VERTEX_ATTR_TEXTURE1 10
+#define NV2A_VERTEX_ATTR_TEXTURE2 11
+#define NV2A_VERTEX_ATTR_TEXTURE3 12
+#define NV2A_VERTEX_ATTR_RESERVED1 13
+#define NV2A_VERTEX_ATTR_RESERVED2 14
+#define NV2A_VERTEX_ATTR_RESERVED3 15
+
+
#define NV2A_CRYSTAL_FREQ 13500000
#define NV2A_NUM_CHANNELS 32
#define NV2A_NUM_SUBCHANNELS 8
@@ -4864,7 +4805,7 @@ static void pgraph_method(NV2AState *d,
pg->draw_arrays_max_count = MAX(pg->draw_arrays_max_count, start + count);
- assert(pg->draw_arrays_length < sizeof(pg->gl_draw_arrays_start) / sizeof(pg->gl_draw_arrays_start[0]));
+ assert(pg->draw_arrays_length < ARRAYSIZE(pg->gl_draw_arrays_start));
/* Attempt to connect primitives */
if (pg->draw_arrays_length > 0) {
diff --git a/hw/xbox/nv2a.h b/hw/xbox/nv2a.h
index 281e4cbbad..24b665aad7 100644
--- a/hw/xbox/nv2a.h
+++ b/hw/xbox/nv2a.h
@@ -22,4 +22,4 @@
void nv2a_init(PCIBus *bus, int devfn, MemoryRegion *ram);
-#endif
\ No newline at end of file
+#endif
diff --git a/hw/xbox/nv2a_debug.c b/hw/xbox/nv2a_debug.c
new file mode 100644
index 0000000000..63f107644d
--- /dev/null
+++ b/hw/xbox/nv2a_debug.c
@@ -0,0 +1,81 @@
+/*
+ * QEMU Geforce NV2A debug helpers
+ *
+ * Copyright (c) 2015 Jannik Vogel
+ * Copyright (c) 2012 espes
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 or
+ * (at your option) version 3 of the License.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see .
+ */
+
+#include "hw/xbox/nv2a_debug.h"
+
+#ifdef DEBUG_NV2A_GL
+
+#include
+#include
+#include
+
+void gl_debug_message(bool cc, const char *fmt, ...)
+{
+ size_t n;
+ char buffer[1024];
+ va_list ap;
+ va_start(ap, fmt);
+ n = vsnprintf(buffer, sizeof(buffer), fmt, ap);
+ assert(n <= sizeof(buffer));
+ va_end(ap);
+ glDebugMessageInsert(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_MARKER,
+ 0, GL_DEBUG_SEVERITY_NOTIFICATION, n, buffer);
+ if (cc) {
+ fwrite(buffer, sizeof(char), n, stdout);
+ fputc('\n', stdout);
+ }
+}
+
+void gl_debug_group_begin(const char *fmt, ...)
+{
+ size_t n;
+ char buffer[1024];
+ va_list ap;
+ va_start(ap, fmt);
+ n = vsnprintf(buffer, sizeof(buffer), fmt, ap);
+ assert(n <= sizeof(buffer));
+ va_end(ap);
+
+ /* Check for errors before entering group */
+ assert(glGetError() == GL_NO_ERROR);
+ glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0, n, buffer);
+}
+
+void gl_debug_group_end(void)
+{
+ /* Check for errors when leaving group */
+ assert(glGetError() == GL_NO_ERROR);
+ glPopDebugGroup();
+}
+
+void gl_debug_label(GLenum target, GLuint name, const char *fmt, ...)
+{
+ size_t n;
+ char buffer[1024];
+ va_list ap;
+ va_start(ap, fmt);
+ n = vsnprintf(buffer, sizeof(buffer), fmt, ap);
+ assert(n <= sizeof(buffer));
+ va_end(ap);
+
+ glObjectLabel(target, name, n, buffer);
+}
+
+#endif
diff --git a/hw/xbox/nv2a_debug.h b/hw/xbox/nv2a_debug.h
new file mode 100644
index 0000000000..2ec727845b
--- /dev/null
+++ b/hw/xbox/nv2a_debug.h
@@ -0,0 +1,58 @@
+/*
+ * QEMU Geforce NV2A debug helpers
+ *
+ * Copyright (c) 2015 Jannik Vogel
+ * Copyright (c) 2012 espes
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 or
+ * (at your option) version 3 of the License.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see .
+ */
+
+#ifndef HW_NV2A_DEBUG_H
+#define HW_NV2A_DEBUG_H
+
+// #define DEBUG_NV2A
+#ifdef DEBUG_NV2A
+# define NV2A_DPRINTF(format, ...) printf("nv2a: " format, ## __VA_ARGS__)
+#else
+# define NV2A_DPRINTF(format, ...) do { } while (0)
+#endif
+
+// #define DEBUG_NV2A_GL
+#ifdef DEBUG_NV2A_GL
+
+#include
+#include "gl/gloffscreen.h"
+
+void gl_debug_message(bool cc, const char *fmt, ...);
+void gl_debug_group_begin(const char *fmt, ...);
+void gl_debug_group_end(void);
+void gl_debug_label(GLenum target, GLuint name, const char *fmt, ...);
+
+# define NV2A_GL_DPRINTF(cc, format, ...) \
+ gl_debug_message(cc, "nv2a: " format, ## __VA_ARGS__)
+# define NV2A_GL_DGROUP_BEGIN(format, ...) \
+ gl_debug_group_begin("nv2a: " format, ## __VA_ARGS__)
+# define NV2A_GL_DGROUP_END() \
+ gl_debug_group_end()
+# define NV2A_GL_DLABEL(target, name, format, ...) \
+ gl_debug_label(target, name, "nv2a: { " format " }", ## __VA_ARGS__)
+
+#else
+# define NV2A_GL_DPRINTF(cc, format, ...) do { } while (0)
+# define NV2A_GL_DGROUP_BEGIN(format, ...) do { } while (0)
+# define NV2A_GL_DGROUP_END() do { } while (0)
+# define NV2A_GL_DLABEL(target, name, format, ...) do { } while (0)
+#endif
+
+#endif
diff --git a/hw/xbox/nv2a_shaders.c b/hw/xbox/nv2a_shaders.c
index 7e5495b158..936d9cad4b 100644
--- a/hw/xbox/nv2a_shaders.c
+++ b/hw/xbox/nv2a_shaders.c
@@ -19,16 +19,10 @@
*/
#include "qemu-common.h"
+#include "hw/xbox/nv2a_debug.h"
#include "hw/xbox/nv2a_shaders_common.h"
#include "hw/xbox/nv2a_shaders.h"
-// #define NV2A_DEBUG
-#ifdef NV2A_DEBUG
-# define NV2A_DPRINTF(format, ...) printf("nv2a: " format, ## __VA_ARGS__)
-#else
-# define NV2A_DPRINTF(format, ...) do { } while (0)
-#endif
-
static void generate_geometry_shader_pass_vertex(QString* s, const char* v)
{
qstring_append_fmt(s, " gl_Position = gl_in[%s].gl_Position;\n", v);
@@ -90,24 +84,34 @@ static QString* generate_fixed_function(const ShaderState state,
qstring_append(s,
"#version 330\n"
"\n"
-"in vec4 position;\n"
-"in vec4 weight;\n"
-"in vec3 normal;\n"
-"in vec4 diffuse;\n"
-"in vec4 specular;\n"
-"in float fogCoord;\n"
-"in vec4 backDiffuse;\n"
-"in vec4 backSpecular;\n"
-"in vec4 texture0;\n"
-"in vec4 texture1;\n"
-"in vec4 texture2;\n"
-"in vec4 texture3;\n"
+"#define position v0\n"
+"#define weight v1\n"
+"#define normal v2.xyz\n"
+"#define diffuse v3\n"
+"#define specular v4\n"
+"#define fogCoord v5.x\n"
+"#define pointSize v6\n"
+"#define backDiffuse v7\n"
+"#define backSpecular v8\n"
+"#define texture0 v9\n"
+"#define texture1 v10\n"
+"#define texture2 v11\n"
+"#define texture3 v12\n"
+"#define reserved1 v13\n"
+"#define reserved2 v14\n"
+"#define reserved3 v15\n"
"\n");
- qstring_append(s, STRUCT_VERTEX_DATA);
+ for(i = 0; i < 16; i++) {
+ qstring_append_fmt(s, "in vec4 v%d;\n", i);
+ }
+
+ qstring_append(s, "\n"
+ STRUCT_VERTEX_DATA);
qstring_append_fmt(s, "noperspective out VertexData %c_vtx;\n", out_prefix);
qstring_append_fmt(s, "#define vtx %c_vtx", out_prefix);
+
qstring_append(s,
"\n"
/* FIXME: Add these uniforms using code when they are used */
@@ -280,10 +284,42 @@ static QString* generate_fixed_function(const ShaderState state,
return s;
}
+static GLuint create_gl_shader(GLenum gl_shader_type,
+ const char *code,
+ const char *name)
+{
+ GLint compiled = 0;
+
+ NV2A_GL_DGROUP_BEGIN("Creating new %s", name);
+
+ GLuint shader = glCreateShader(gl_shader_type);
+ glShaderSource(shader, 1, &code, 0);
+ glCompileShader(shader);
+
+ /* Check it compiled */
+ compiled = 0;
+ glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
+ if (!compiled) {
+ GLchar* log;
+ GLint log_length;
+ glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_length);
+ log = g_malloc(log_length * sizeof(GLchar));
+ glGetShaderInfoLog(shader, log_length, NULL, log);
+ fprintf(stderr, "nv2a: %s compilation failed: %s\n", name, log);
+ g_free(log);
+
+ NV2A_GL_DGROUP_END();
+ abort();
+ }
+
+ NV2A_GL_DGROUP_END();
+
+ return shader;
+}
+
ShaderBinding* generate_shaders(const ShaderState state)
{
int i, j;
- GLint compiled = 0;
bool with_geom = state.primitive_mode == PRIM_TYPE_QUADS;
char vtx_prefix = with_geom ? 'v' : 'g';
@@ -308,56 +344,24 @@ ShaderBinding* generate_shaders(const ShaderState state)
if (vertex_shader_code) {
const char* vertex_shader_code_str = qstring_get_str(vertex_shader_code);
- GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER);
+ GLuint vertex_shader = create_gl_shader(GL_VERTEX_SHADER,
+ vertex_shader_code_str,
+ "vertex shader");
glAttachShader(program, vertex_shader);
- glShaderSource(vertex_shader, 1, &vertex_shader_code_str, 0);
- glCompileShader(vertex_shader);
-
- NV2A_DPRINTF("bind new vertex shader, code:\n%s\n", vertex_shader_code_str);
-
- /* Check it compiled */
- compiled = 0;
- glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &compiled);
- if (!compiled) {
- GLchar log[1024];
- glGetShaderInfoLog(vertex_shader, 1024, NULL, log);
- fprintf(stderr, "nv2a: vertex shader compilation failed: %s\n", log);
- abort();
- }
-
QDECREF(vertex_shader_code);
}
- if (state.fixed_function) {
- /* bind fixed function vertex attributes */
- glBindAttribLocation(program, NV2A_VERTEX_ATTR_POSITION, "position");
- glBindAttribLocation(program, NV2A_VERTEX_ATTR_WEIGHT, "weight");
- glBindAttribLocation(program, NV2A_VERTEX_ATTR_DIFFUSE, "diffuse");
- glBindAttribLocation(program, NV2A_VERTEX_ATTR_SPECULAR, "specular");
- glBindAttribLocation(program, NV2A_VERTEX_ATTR_FOG, "fog");
- glBindAttribLocation(program, NV2A_VERTEX_ATTR_BACK_DIFFUSE, "backDiffuse");
- glBindAttribLocation(program, NV2A_VERTEX_ATTR_BACK_SPECULAR, "backSpecular");
- glBindAttribLocation(program, NV2A_VERTEX_ATTR_TEXTURE0, "texture0");
- glBindAttribLocation(program, NV2A_VERTEX_ATTR_TEXTURE1, "texture1");
- glBindAttribLocation(program, NV2A_VERTEX_ATTR_TEXTURE2, "texture2");
- glBindAttribLocation(program, NV2A_VERTEX_ATTR_TEXTURE3, "texture3");
- } else if (state.vertex_program) {
- /* Bind attributes for transform program*/
- char tmp[8];
- for(i = 0; i < 16; i++) {
- snprintf(tmp, sizeof(tmp), "v%d", i);
- glBindAttribLocation(program, i, tmp);
- }
- } else {
- assert(false);
+ /* Bind attributes for vertices */
+ char tmp[8];
+ for(i = 0; i < 16; i++) {
+ snprintf(tmp, sizeof(tmp), "v%d", i);
+ glBindAttribLocation(program, i, tmp);
}
/* generate a fragment shader from register combiners */
- GLuint fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
- glAttachShader(program, fragment_shader);
QString *fragment_shader_code = psh_translate(state.combiner_control,
state.shader_stage_program,
@@ -374,46 +378,24 @@ ShaderBinding* generate_shaders(const ShaderState state)
const char *fragment_shader_code_str = qstring_get_str(fragment_shader_code);
- NV2A_DPRINTF("bind new fragment shader, code:\n%s\n", fragment_shader_code_str);
-
- glShaderSource(fragment_shader, 1, &fragment_shader_code_str, 0);
- glCompileShader(fragment_shader);
-
- /* Check it compiled */
- glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &compiled);
- if (!compiled) {
- GLchar log[1024];
- glGetShaderInfoLog(fragment_shader, 1024, NULL, log);
- fprintf(stderr, "nv2a: fragment shader compilation failed: %s\n", log);
- abort();
- }
+ GLuint fragment_shader = create_gl_shader(GL_FRAGMENT_SHADER,
+ fragment_shader_code_str,
+ "fragment shader");
+ glAttachShader(program, fragment_shader);
QDECREF(fragment_shader_code);
if (with_geom) {
- GLuint geometry_shader = glCreateShader(GL_GEOMETRY_SHADER);
- glAttachShader(program, geometry_shader);
-
QString* geometry_shader_code =
generate_geometry_shader(state.primitive_mode);
const char* geometry_shader_code_str =
qstring_get_str(geometry_shader_code);
- NV2A_DPRINTF("bind geometry shader, code:\n%s\n", geometry_shader_code_str);
-
- glShaderSource(geometry_shader, 1, &geometry_shader_code_str, 0);
- glCompileShader(geometry_shader);
-
- /* Check it compiled */
- compiled = 0;
- glGetShaderiv(geometry_shader, GL_COMPILE_STATUS, &compiled);
- if (!compiled) {
- GLchar log[2048];
- glGetShaderInfoLog(geometry_shader, 2048, NULL, log);
- fprintf(stderr, "nv2a: geometry shader compilation failed: %s\n", log);
- abort();
- }
+ GLuint geometry_shader = create_gl_shader(GL_GEOMETRY_SHADER,
+ geometry_shader_code_str,
+ "geometry shader");
+ glAttachShader(program, geometry_shader);
QDECREF(geometry_shader_code);
}
diff --git a/hw/xbox/nv2a_shaders.h b/hw/xbox/nv2a_shaders.h
index 54d40fb4cc..56f82b8707 100644
--- a/hw/xbox/nv2a_shaders.h
+++ b/hw/xbox/nv2a_shaders.h
@@ -27,23 +27,6 @@
#include "nv2a_vsh.h"
#include "nv2a_psh.h"
-#define NV2A_VERTEX_ATTR_POSITION 0
-#define NV2A_VERTEX_ATTR_WEIGHT 1
-#define NV2A_VERTEX_ATTR_NORMAL 2
-#define NV2A_VERTEX_ATTR_DIFFUSE 3
-#define NV2A_VERTEX_ATTR_SPECULAR 4
-#define NV2A_VERTEX_ATTR_FOG 5
-#define NV2A_VERTEX_ATTR_POINT_SIZE 6
-#define NV2A_VERTEX_ATTR_BACK_DIFFUSE 7
-#define NV2A_VERTEX_ATTR_BACK_SPECULAR 8
-#define NV2A_VERTEX_ATTR_TEXTURE0 9
-#define NV2A_VERTEX_ATTR_TEXTURE1 10
-#define NV2A_VERTEX_ATTR_TEXTURE2 11
-#define NV2A_VERTEX_ATTR_TEXTURE3 12
-#define NV2A_VERTEX_ATTR_RESERVED1 13
-#define NV2A_VERTEX_ATTR_RESERVED2 14
-#define NV2A_VERTEX_ATTR_RESERVED3 15
-
#define NV2A_MAX_TRANSFORM_PROGRAM_LENGTH 136
#define NV2A_VERTEXSHADER_CONSTANTS 192