#include "main/imports.h"
#include "main/enums.h"
-#include "shader/prog_parameter.h"
-#include "shader/program.h"
+#include "main/shaderobj.h"
+#include "program/prog_parameter.h"
+#include "program/program.h"
+#include "program/programopt.h"
#include "tnl/tnl.h"
+#include "talloc.h"
#include "brw_context.h"
-#include "brw_util.h"
+#include "brw_wm.h"
-static void brwBindProgram( GLcontext *ctx,
+static void brwBindProgram( struct gl_context *ctx,
GLenum target,
struct gl_program *prog )
{
}
}
-static struct gl_program *brwNewProgram( GLcontext *ctx,
+static struct gl_program *brwNewProgram( struct gl_context *ctx,
GLenum target,
GLuint id )
{
}
}
-static void brwDeleteProgram( GLcontext *ctx,
+static void brwDeleteProgram( struct gl_context *ctx,
struct gl_program *prog )
{
-
_mesa_delete_program( ctx, prog );
}
-static GLboolean brwIsProgramNative( GLcontext *ctx,
+static GLboolean brwIsProgramNative( struct gl_context *ctx,
GLenum target,
struct gl_program *prog )
{
return GL_TRUE;
}
-static void brwProgramStringNotify( GLcontext *ctx,
- GLenum target,
- struct gl_program *prog )
+static void
+shader_error(struct gl_context *ctx, struct gl_program *prog, const char *msg)
{
+ struct gl_shader_program *shader;
+
+ shader = _mesa_lookup_shader_program(ctx, prog->Id);
+
+ if (shader) {
+ shader->InfoLog = talloc_strdup_append(shader->InfoLog, msg);
+ shader->LinkStatus = GL_FALSE;
+ }
+}
+
+static GLboolean brwProgramStringNotify( struct gl_context *ctx,
+ GLenum target,
+ struct gl_program *prog )
+{
+ struct brw_context *brw = brw_context(ctx);
+ int i;
+
if (target == GL_FRAGMENT_PROGRAM_ARB) {
- struct brw_context *brw = brw_context(ctx);
- struct brw_fragment_program *p = (struct brw_fragment_program *)prog;
- struct brw_fragment_program *fp = (struct brw_fragment_program *)brw->fragment_program;
- if (p == fp)
+ struct gl_fragment_program *fprog = (struct gl_fragment_program *) prog;
+ struct brw_fragment_program *newFP = brw_fragment_program(fprog);
+ const struct brw_fragment_program *curFP =
+ brw_fragment_program_const(brw->fragment_program);
+ struct gl_shader_program *shader_program;
+
+ if (fprog->FogOption) {
+ _mesa_append_fog_code(ctx, fprog);
+ fprog->FogOption = GL_NONE;
+ }
+
+ if (newFP == curFP)
brw->state.dirty.brw |= BRW_NEW_FRAGMENT_PROGRAM;
- p->id = brw->program_id++;
- p->param_state = p->program.Base.Parameters->StateFlags;
+ newFP->id = brw->program_id++;
+ newFP->isGLSL = brw_wm_is_glsl(fprog);
+
+ /* Don't reject fragment shaders for their Mesa IR state when we're
+ * using the new FS backend.
+ */
+ shader_program = _mesa_lookup_shader_program(ctx, prog->Id);
+ if (shader_program
+ && shader_program->_LinkedShaders[MESA_SHADER_FRAGMENT]) {
+ return GL_TRUE;
+ }
}
else if (target == GL_VERTEX_PROGRAM_ARB) {
- struct brw_context *brw = brw_context(ctx);
- struct brw_vertex_program *p = (struct brw_vertex_program *)prog;
- struct brw_vertex_program *vp = (struct brw_vertex_program *)brw->vertex_program;
- if (p == vp)
+ struct gl_vertex_program *vprog = (struct gl_vertex_program *) prog;
+ struct brw_vertex_program *newVP = brw_vertex_program(vprog);
+ const struct brw_vertex_program *curVP =
+ brw_vertex_program_const(brw->vertex_program);
+
+ if (newVP == curVP)
brw->state.dirty.brw |= BRW_NEW_VERTEX_PROGRAM;
- p->id = brw->program_id++;
- p->param_state = p->program.Base.Parameters->StateFlags;
+ if (newVP->program.IsPositionInvariant) {
+ _mesa_insert_mvp_code(ctx, &newVP->program);
+ }
+ newVP->id = brw->program_id++;
/* Also tell tnl about it:
*/
_tnl_program_string(ctx, target, prog);
}
+
+ /* Reject programs with subroutines, which are totally broken at the moment
+ * (all program flows return when any program flow returns, and
+ * the VS also hangs if a function call calls a function.
+ *
+ * See piglit glsl-{vs,fs}-functions-[23] tests.
+ */
+ for (i = 0; i < prog->NumInstructions; i++) {
+ struct prog_instruction *inst = prog->Instructions + i;
+ int r;
+
+ if (prog->Instructions[i].Opcode == OPCODE_CAL) {
+ shader_error(ctx, prog,
+ "i965 driver doesn't yet support uninlined function "
+ "calls. Move to using a single return statement at "
+ "the end of the function to work around it.\n");
+ return GL_FALSE;
+ }
+
+ if (prog->Instructions[i].Opcode == OPCODE_RET) {
+ shader_error(ctx, prog,
+ "i965 driver doesn't yet support \"return\" "
+ "from main().\n");
+ return GL_FALSE;
+ }
+
+ for (r = 0; r < _mesa_num_inst_src_regs(inst->Opcode); r++) {
+ if (prog->Instructions[i].SrcReg[r].RelAddr &&
+ prog->Instructions[i].SrcReg[r].File == PROGRAM_INPUT) {
+ shader_error(ctx, prog,
+ "Variable indexing of shader inputs unsupported\n");
+ return GL_FALSE;
+ }
+ }
+
+ if (target == GL_FRAGMENT_PROGRAM_ARB &&
+ prog->Instructions[i].DstReg.RelAddr &&
+ prog->Instructions[i].DstReg.File == PROGRAM_OUTPUT) {
+ shader_error(ctx, prog,
+ "Variable indexing of FS outputs unsupported\n");
+ return GL_FALSE;
+ }
+ if (target == GL_FRAGMENT_PROGRAM_ARB) {
+ if ((prog->Instructions[i].DstReg.RelAddr &&
+ prog->Instructions[i].DstReg.File == PROGRAM_TEMPORARY) ||
+ (prog->Instructions[i].SrcReg[0].RelAddr &&
+ prog->Instructions[i].SrcReg[0].File == PROGRAM_TEMPORARY) ||
+ (prog->Instructions[i].SrcReg[1].RelAddr &&
+ prog->Instructions[i].SrcReg[1].File == PROGRAM_TEMPORARY) ||
+ (prog->Instructions[i].SrcReg[2].RelAddr &&
+ prog->Instructions[i].SrcReg[2].File == PROGRAM_TEMPORARY)) {
+ shader_error(ctx, prog,
+ "Variable indexing of variable arrays in the FS "
+ "unsupported\n");
+ return GL_FALSE;
+ }
+ }
+ }
+
+ return GL_TRUE;
}
void brwInitFragProgFuncs( struct dd_function_table *functions )
functions->DeleteProgram = brwDeleteProgram;
functions->IsProgramNative = brwIsProgramNative;
functions->ProgramStringNotify = brwProgramStringNotify;
+
+ functions->NewShader = brw_new_shader;
+ functions->NewShaderProgram = brw_new_shader_program;
+ functions->CompileShader = brw_compile_shader;
+ functions->LinkShader = brw_link_shader;
}