diff --git a/src/mesa/main/buffers.c b/src/mesa/main/buffers.c index fb30b59..5ad9221 100644 --- a/src/mesa/main/buffers.c +++ b/src/mesa/main/buffers.c @@ -439,8 +439,12 @@ _mesa_drawbuffers(GLcontext *ctx, GLuint n, const GLenum *buffers, } } - if (newState) - FLUSH_VERTICES(ctx, _NEW_BUFFERS); + if (newState) { + int _state = _NEW_BUFFERS; + if (ctx->FragmentProgram._DrawBuffersConvert) + _state |= _NEW_PROGRAM; + FLUSH_VERTICES(ctx, _state); + } } diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index 688172a..bd0d04e 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -1840,6 +1840,11 @@ struct gl_fragment_program_state /** Cache of fixed-function programs */ struct gl_program_cache *Cache; + + /* for ARB_draw_buffers should mesa convert COLOR->DATA[0-n] + or should we just let the driver do it */ + GLboolean _DrawBuffersConvert; + }; diff --git a/src/mesa/main/state.c b/src/mesa/main/state.c index b971cc9..2d0f45c 100644 --- a/src/mesa/main/state.c +++ b/src/mesa/main/state.c @@ -541,6 +541,9 @@ _mesa_update_state_locked( GLcontext *ctx ) _NEW_ARRAY | _NEW_LIGHT | _NEW_POINT | _NEW_RENDERMODE | _NEW_PROGRAM); } + if (ctx->FragmentProgram._DrawBuffersConvert) { + prog_flags |= _NEW_BUFFERS; + } if (ctx->VertexProgram._MaintainTnlProgram) { prog_flags |= (_NEW_ARRAY | _NEW_TEXTURE | _NEW_TEXTURE_MATRIX | _NEW_TRANSFORM | _NEW_POINT | diff --git a/src/mesa/main/texenvprogram.c b/src/mesa/main/texenvprogram.c index 7b8a8b8..ae34b83 100644 --- a/src/mesa/main/texenvprogram.c +++ b/src/mesa/main/texenvprogram.c @@ -1543,6 +1543,9 @@ create_new_program(GLcontext *ctx, struct state_key *key, p.program->FogOption = GL_NONE; } + if (ctx->FragmentProgram._DrawBuffersConvert) { + _mesa_append_color_to_data_output(ctx, p.program); + } /* Notify driver the fragment program has (actually) changed. */ diff --git a/src/mesa/shader/arbprogparse.c b/src/mesa/shader/arbprogparse.c index 6373529..040ce0b 100644 --- a/src/mesa/shader/arbprogparse.c +++ b/src/mesa/shader/arbprogparse.c @@ -123,7 +123,6 @@ _mesa_parse_arb_fragment_program(GLcontext* ctx, GLenum target, } program->OriginUpperLeft = state.option.OriginUpperLeft; program->PixelCenterInteger = state.option.PixelCenterInteger; - program->UsesKill = state.fragment.UsesKill; if (program->FogOption) @@ -147,6 +146,10 @@ _mesa_parse_arb_fragment_program(GLcontext* ctx, GLenum target, program->FogOption = GL_NONE; } + if (ctx->FragmentProgram._DrawBuffersConvert) { + _mesa_append_color_to_data_output(ctx, program); + } + #if DEBUG_FP printf("____________Fragment program %u ________\n", program->Base.Id); _mesa_print_program(&program->Base); diff --git a/src/mesa/shader/programopt.c b/src/mesa/shader/programopt.c index fb2ebe6..cc6d1e7 100644 --- a/src/mesa/shader/programopt.c +++ b/src/mesa/shader/programopt.c @@ -223,9 +223,74 @@ _mesa_insert_mvp_code(GLcontext *ctx, struct gl_vertex_program *vprog) else _mesa_insert_mvp_mad_code( ctx, vprog ); } + +void +_mesa_append_color_to_data_output(GLcontext *ctx, struct gl_fragment_program *fprog) +{ + const GLuint origLen = fprog->Base.NumInstructions; + GLuint newLen, numInstr; + struct prog_instruction *newInst, *inst; + int outputTemp; + int i; + + if (ctx->DrawBuffer->_NumColorDrawBuffers < 2) + return; + + /* if the fragprog doesn't write to COLOR */ + if (!(fprog->Base.OutputsWritten & BITFIELD64_BIT(FRAG_RESULT_COLOR))) + return; + + /* we'll translate the COLOR write to a temp and then + write DATA0, DATA1 etc */ + numInstr = ctx->DrawBuffer->_NumColorDrawBuffers; + newLen = origLen + numInstr; + + newInst = _mesa_alloc_instructions(newLen); + if (!newInst) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, + "glProgramString(adding drawbuffers"); + return; + } + outputTemp = fprog->Base.NumTemporaries++; + + _mesa_copy_instructions(newInst, fprog->Base.Instructions, origLen); + inst = newInst; + for (i = 0; i < origLen; i++) { + if (inst->Opcode == OPCODE_END) + break; + if (inst->DstReg.File == PROGRAM_OUTPUT && + inst->DstReg.Index == FRAG_RESULT_COLOR) { + inst->DstReg.File = PROGRAM_TEMPORARY; + inst->DstReg.Index = outputTemp; + } + inst++; + } + assert(inst->Opcode == OPCODE_END); + + _mesa_init_instructions(inst, numInstr); + + fprog->Base.OutputsWritten &= BITFIELD64_BIT(FRAG_RESULT_COLOR); + for (i = 0; i < numInstr; i++) { + inst->Opcode = OPCODE_MOV; + inst->DstReg.File = PROGRAM_OUTPUT; + inst->DstReg.Index = FRAG_RESULT_DATA0 + i; + inst->DstReg.WriteMask = WRITEMASK_XYZW; + inst->SrcReg[0].File = PROGRAM_TEMPORARY; + inst->SrcReg[0].Index = outputTemp; + inst->SrcReg[0].Swizzle = SWIZZLE_NOOP; + fprog->Base.OutputsWritten |= BITFIELD64_BIT(FRAG_RESULT_DATA0 + i); + inst++; + } + inst->Opcode = OPCODE_END; + inst++; + /* free old instructions */ + _mesa_free_instructions(fprog->Base.Instructions, origLen); + fprog->Base.Instructions = newInst; + fprog->Base.NumInstructions = inst - newInst; +} diff --git a/src/mesa/shader/programopt.h b/src/mesa/shader/programopt.h index 21fac07..00dc4c4 100644 --- a/src/mesa/shader/programopt.h +++ b/src/mesa/shader/programopt.h @@ -48,5 +48,6 @@ _mesa_nop_fragment_program(GLcontext *ctx, struct gl_fragment_program *prog); extern void _mesa_nop_vertex_program(GLcontext *ctx, struct gl_vertex_program *prog); - +extern void +_mesa_append_color_to_data_output(GLcontext *ctx, struct gl_fragment_program *fprog); #endif /* PROGRAMOPT_H */ diff --git a/src/mesa/state_tracker/st_atom_shader.c b/src/mesa/state_tracker/st_atom_shader.c index ad151ed..163d888 100644 --- a/src/mesa/state_tracker/st_atom_shader.c +++ b/src/mesa/state_tracker/st_atom_shader.c @@ -38,6 +38,7 @@ #include "main/imports.h" #include "main/mtypes.h" #include "shader/program.h" +#include "shader/programopt.h" #include "pipe/p_context.h" #include "pipe/p_shader_tokens.h" diff --git a/src/mesa/state_tracker/st_cb_fbo.c b/src/mesa/state_tracker/st_cb_fbo.c index d50970f..bd016c0 100644 --- a/src/mesa/state_tracker/st_cb_fbo.c +++ b/src/mesa/state_tracker/st_cb_fbo.c @@ -612,6 +612,10 @@ st_DrawBuffers(GLcontext *ctx, GLsizei count, const GLenum *buffers) st_manager_add_color_renderbuffer(ctx->st, fb, idx); } + + ctx->st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM; + if (count > 1) + fprintf(stderr,"db %d %x\n", count, ctx->st->dirty.st); check_create_front_buffers(ctx, ctx->DrawBuffer); } diff --git a/src/mesa/state_tracker/st_context.c b/src/mesa/state_tracker/st_context.c index 0a1503f..e25f078 100644 --- a/src/mesa/state_tracker/st_context.c +++ b/src/mesa/state_tracker/st_context.c @@ -170,7 +170,7 @@ st_create_context_priv( GLcontext *ctx, struct pipe_context *pipe ) /* Need these flags: */ st->ctx->FragmentProgram._MaintainTexEnvProgram = GL_TRUE; - + st->ctx->FragmentProgram._DrawBuffersConvert = GL_TRUE; st->ctx->VertexProgram._MaintainTnlProgram = GL_TRUE; st->pixel_xfer.cache = _mesa_new_program_cache(); diff --git a/src/mesa/state_tracker/st_program.h b/src/mesa/state_tracker/st_program.h index 1b3f75c..55727be 100644 --- a/src/mesa/state_tracker/st_program.h +++ b/src/mesa/state_tracker/st_program.h @@ -58,6 +58,9 @@ struct st_fragment_program /** Program prefixed with glBitmap prologue */ struct st_fragment_program *bitmap_program; uint bitmap_sampler; + + /* number of colorbuffers this was compiler for */ + uint num_color_buffers; };