summaryrefslogtreecommitdiffstats
path: root/src/gallium
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium')
-rw-r--r--src/gallium/drivers/svga/svga_state_fs.c50
-rw-r--r--src/gallium/drivers/svga/svga_state_vs.c49
2 files changed, 95 insertions, 4 deletions
diff --git a/src/gallium/drivers/svga/svga_state_fs.c b/src/gallium/drivers/svga/svga_state_fs.c
index c95d82fc00e..8503b03eed4 100644
--- a/src/gallium/drivers/svga/svga_state_fs.c
+++ b/src/gallium/drivers/svga/svga_state_fs.c
@@ -26,7 +26,9 @@
#include "util/u_inlines.h"
#include "pipe/p_defines.h"
#include "util/u_math.h"
+#include "util/u_memory.h"
#include "util/u_bitmask.h"
+#include "tgsi/tgsi_ureg.h"
#include "svga_context.h"
#include "svga_state.h"
@@ -66,6 +68,38 @@ static struct svga_shader_result *search_fs_key( struct svga_fragment_shader *fs
}
+/**
+ * If we fail to compile a fragment shader (because it uses too many
+ * registers, for example) we'll use a dummy/fallback shader that
+ * simply emits a constant color.
+ */
+static const struct tgsi_token *
+get_dummy_fragment_shader(void)
+{
+ static const float red[4] = { 1.0, 0.0, 0.0, 0.0 };
+ struct ureg_program *ureg;
+ const struct tgsi_token *tokens;
+ struct ureg_src src;
+ struct ureg_dst dst;
+ unsigned num_tokens;
+
+ ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT);
+ if (!ureg)
+ return NULL;
+
+ dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0);
+ src = ureg_DECL_immediate(ureg, red, 4);
+ ureg_MOV(ureg, dst, src);
+ ureg_END(ureg);
+
+ tokens = ureg_get_tokens(ureg, &num_tokens);
+
+ ureg_destroy(ureg);
+
+ return tokens;
+}
+
+
static enum pipe_error compile_fs( struct svga_context *svga,
struct svga_fragment_shader *fs,
const struct svga_fs_compile_key *key,
@@ -76,8 +110,20 @@ static enum pipe_error compile_fs( struct svga_context *svga,
result = svga_translate_fragment_program( fs, key );
if (result == NULL) {
- ret = PIPE_ERROR; /* some problem during translation */
- goto fail;
+ /* some problem during translation, try the dummy shader */
+ const struct tgsi_token *dummy = get_dummy_fragment_shader();
+ if (!dummy) {
+ ret = PIPE_ERROR_OUT_OF_MEMORY;
+ goto fail;
+ }
+ debug_printf("Failed to compile fragment shader, using dummy shader instead.\n");
+ FREE((void *) fs->base.tokens);
+ fs->base.tokens = dummy;
+ result = svga_translate_fragment_program(fs, key);
+ if (result == NULL) {
+ ret = PIPE_ERROR;
+ goto fail;
+ }
}
result->id = util_bitmask_add(svga->fs_bm);
diff --git a/src/gallium/drivers/svga/svga_state_vs.c b/src/gallium/drivers/svga/svga_state_vs.c
index b82e68556e4..3cb0cdb9697 100644
--- a/src/gallium/drivers/svga/svga_state_vs.c
+++ b/src/gallium/drivers/svga/svga_state_vs.c
@@ -27,8 +27,10 @@
#include "pipe/p_defines.h"
#include "util/u_format.h"
#include "util/u_math.h"
+#include "util/u_memory.h"
#include "util/u_bitmask.h"
#include "translate/translate.h"
+#include "tgsi/tgsi_ureg.h"
#include "svga_context.h"
#include "svga_state.h"
@@ -65,6 +67,37 @@ static struct svga_shader_result *search_vs_key( struct svga_vertex_shader *vs,
}
+/**
+ * If we fail to compile a vertex shader we'll use a dummy/fallback shader
+ * that simply emits a (0,0,0,1) vertex position.
+ */
+static const struct tgsi_token *
+get_dummy_vertex_shader(void)
+{
+ static const float zero[4] = { 0.0, 0.0, 0.0, 1.0 };
+ struct ureg_program *ureg;
+ const struct tgsi_token *tokens;
+ struct ureg_src src;
+ struct ureg_dst dst;
+ unsigned num_tokens;
+
+ ureg = ureg_create(TGSI_PROCESSOR_VERTEX);
+ if (!ureg)
+ return NULL;
+
+ dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0);
+ src = ureg_DECL_immediate(ureg, zero, 4);
+ ureg_MOV(ureg, dst, src);
+ ureg_END(ureg);
+
+ tokens = ureg_get_tokens(ureg, &num_tokens);
+
+ ureg_destroy(ureg);
+
+ return tokens;
+}
+
+
static enum pipe_error compile_vs( struct svga_context *svga,
struct svga_vertex_shader *vs,
const struct svga_vs_compile_key *key,
@@ -75,8 +108,20 @@ static enum pipe_error compile_vs( struct svga_context *svga,
result = svga_translate_vertex_program( vs, key );
if (result == NULL) {
- ret = PIPE_ERROR_OUT_OF_MEMORY;
- goto fail;
+ /* some problem during translation, try the dummy shader */
+ const struct tgsi_token *dummy = get_dummy_vertex_shader();
+ if (!dummy) {
+ ret = PIPE_ERROR_OUT_OF_MEMORY;
+ goto fail;
+ }
+ debug_printf("Failed to compile vertex shader, using dummy shader instead.\n");
+ FREE((void *) vs->base.tokens);
+ vs->base.tokens = dummy;
+ result = svga_translate_vertex_program(vs, key);
+ if (result == NULL) {
+ ret = PIPE_ERROR;
+ goto fail;
+ }
}
result->id = util_bitmask_add(svga->vs_bm);