util: Support all SRGB formats.
[mesa.git] / src / gallium / auxiliary / util / u_simple_shaders.c
index f06d13c2c4ae00c231a0d78869cb3e9f5326ad86..019dda767d0e0f9d96be6aab508b40c7773f3785 100644 (file)
@@ -2,6 +2,7 @@
  *
  * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
  * All Rights Reserved.
+ * Copyright 2009 Marek Olšák <maraeo@gmail.com>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the
  * Simple vertex/fragment shader generators.
  *  
  * @author Brian Paul
+           Marek Olšák
  */
 
 
 #include "pipe/p_context.h"
-#include "pipe/p_debug.h"
-#include "pipe/p_defines.h"
-#include "pipe/p_inlines.h"
-#include "pipe/p_winsys.h"
 #include "pipe/p_shader_tokens.h"
-
-#include "util/u_memory.h"
 #include "util/u_simple_shaders.h"
-
-#include "tgsi/tgsi_build.h"
-#include "tgsi/tgsi_dump.h"
-#include "tgsi/tgsi_parse.h"
+#include "util/u_debug.h"
+#include "tgsi/tgsi_ureg.h"
 
 
 
 /**
  * Make simple vertex pass-through shader.
+ * \param num_attribs  number of attributes to pass through
+ * \param semantic_names  array of semantic names for each attribute
+ * \param semantic_indexes  array of semantic indexes for each attribute
  */
 void *
 util_make_vertex_passthrough_shader(struct pipe_context *pipe,
                                     uint num_attribs,
                                     const uint *semantic_names,
-                                    const uint *semantic_indexes,
-                                    struct pipe_shader_state *shader)
-                                    
+                                    const uint *semantic_indexes)
 {
-   uint maxTokens = 100;
-   struct tgsi_token *tokens;
-   struct tgsi_header *header;
-   struct tgsi_processor *processor;
-   struct tgsi_full_declaration decl;
-   struct tgsi_full_instruction inst;
-   const uint procType = TGSI_PROCESSOR_VERTEX;
-   uint ti, i;
+   struct ureg_program *ureg;
+   uint i;
 
-   tokens = (struct tgsi_token *) MALLOC(maxTokens * sizeof(tokens[0]));
+   ureg = ureg_create( TGSI_PROCESSOR_VERTEX );
+   if (ureg == NULL)
+      return NULL;
 
-   /* shader header
-    */
-   *(struct tgsi_version *) &tokens[0] = tgsi_build_version();
+   for (i = 0; i < num_attribs; i++) {
+      struct ureg_src src;
+      struct ureg_dst dst;
+
+      src = ureg_DECL_vs_input( ureg, i );
+      
+      dst = ureg_DECL_output( ureg,
+                              semantic_names[i],
+                              semantic_indexes[i]);
+      
+      ureg_MOV( ureg, dst, src );
+   }
 
-   header = (struct tgsi_header *) &tokens[1];
-   *header = tgsi_build_header();
+   ureg_END( ureg );
 
-   processor = (struct tgsi_processor *) &tokens[2];
-   *processor = tgsi_build_processor( procType, header );
+   return ureg_create_shader_and_destroy( ureg, pipe );
+}
 
-   ti = 3;
 
-   /* declare inputs */
-   for (i = 0; i < num_attribs; i++) {
-      decl = tgsi_default_full_declaration();
-      decl.Declaration.File = TGSI_FILE_INPUT;
-
     decl.Declaration.Semantic = 1;
-      decl.Semantic.SemanticName = semantic_names[i];
-      decl.Semantic.SemanticIndex = semantic_indexes[i];
-
-      decl.DeclarationRange.First = 
-      decl.DeclarationRange.Last = i;
-      ti += tgsi_build_full_declaration(&decl,
-                                        &tokens[ti],
-                                        header,
-                                        maxTokens - ti);
-   }
+/**
+ * Make simple fragment texture shader:
+ *  IMM {0,0,0,1}                         // (if writemask != 0xf)
+ *  MOV OUT[0], IMM[0]                    // (if writemask != 0xf)
+ *  TEX OUT[0].writemask, IN[0], SAMP[0], 2D;
*  END;
+ */
+void *
+util_make_fragment_tex_shader_writemask(struct pipe_context *pipe,
+                                        unsigned tex_target,
+                                        unsigned writemask )
+{
+   struct ureg_program *ureg;
+   struct ureg_src sampler;
+   struct ureg_src tex;
+   struct ureg_dst out;
 
-   /* declare outputs */
-   for (i = 0; i < num_attribs; i++) {
-      decl = tgsi_default_full_declaration();
-      decl.Declaration.File = TGSI_FILE_OUTPUT;
-      decl.Declaration.Semantic = 1;
-      decl.Semantic.SemanticName = semantic_names[i];
-      decl.Semantic.SemanticIndex = semantic_indexes[i];
-      decl.DeclarationRange.First = 
-         decl.DeclarationRange.Last = i;
-      ti += tgsi_build_full_declaration(&decl,
-                                        &tokens[ti],
-                                        header,
-                                        maxTokens - ti);
-   }
+   ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT );
+   if (ureg == NULL)
+      return NULL;
+   
+   sampler = ureg_DECL_sampler( ureg, 0 );
 
-   /* emit MOV instructions */
-   for (i = 0; i < num_attribs; i++) {
-      /* MOVE out[i], in[i]; */
-      inst = tgsi_default_full_instruction();
-      inst.Instruction.Opcode = TGSI_OPCODE_MOV;
-      inst.Instruction.NumDstRegs = 1;
-      inst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_OUTPUT;
-      inst.FullDstRegisters[0].DstRegister.Index = i;
-      inst.Instruction.NumSrcRegs = 1;
-      inst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_INPUT;
-      inst.FullSrcRegisters[0].SrcRegister.Index = i;
-      ti += tgsi_build_full_instruction(&inst,
-                                        &tokens[ti],
-                                        header,
-                                        maxTokens - ti );
-   }
+   tex = ureg_DECL_fs_input( ureg, 
+                             TGSI_SEMANTIC_GENERIC, 0, 
+                             TGSI_INTERPOLATE_PERSPECTIVE );
+
+   out = ureg_DECL_output( ureg, 
+                           TGSI_SEMANTIC_COLOR,
+                           0 );
 
-   /* END instruction */
-   inst = tgsi_default_full_instruction();
-   inst.Instruction.Opcode = TGSI_OPCODE_END;
-   inst.Instruction.NumDstRegs = 0;
-   inst.Instruction.NumSrcRegs = 0;
-   ti += tgsi_build_full_instruction(&inst,
-                                     &tokens[ti],
-                                     header,
-                                     maxTokens - ti );
+   if (writemask != TGSI_WRITEMASK_XYZW) {
+      struct ureg_src imm = ureg_imm4f( ureg, 0, 0, 0, 1 );
 
-#if 0 /*debug*/
-   tgsi_dump(tokens, 0);
-#endif
+      ureg_MOV( ureg, out, imm );
+   }
 
-   shader->tokens = tokens;
-   /*shader->num_tokens = ti;*/
+   ureg_TEX( ureg, 
+             ureg_writemask(out, writemask),
+             tex_target, tex, sampler );
+   ureg_END( ureg );
 
-   return pipe->create_vs_state(pipe, shader);
+   return ureg_create_shader_and_destroy( ureg, pipe );
 }
 
 
+/**
+ * Make a simple fragment shader that sets the output color to a color
+ * taken from a texture.
+ * \param tex_target  one of PIPE_TEXTURE_x
+ */
+void *
+util_make_fragment_tex_shader(struct pipe_context *pipe, unsigned tex_target )
+{
+   return util_make_fragment_tex_shader_writemask( pipe,
+                                                   tex_target,
+                                                   TGSI_WRITEMASK_XYZW );
+}
 
 
 /**
- * Make simple fragment texture shader:
- *  TEX OUT[0], IN[0], SAMP[0], 2D;
- *  END;
+ * Make a simple fragment texture shader which reads an X component from
+ * a texture and writes it as depth.
  */
 void *
-util_make_fragment_tex_shader(struct pipe_context *pipe,
-                              struct pipe_shader_state *shader)
+util_make_fragment_tex_shader_writedepth(struct pipe_context *pipe,
+                                         unsigned tex_target)
 {
-   uint maxTokens = 100;
-   struct tgsi_token *tokens;
-   struct tgsi_header *header;
-   struct tgsi_processor *processor;
-   struct tgsi_full_declaration decl;
-   struct tgsi_full_instruction inst;
-   const uint procType = TGSI_PROCESSOR_FRAGMENT;
-   uint ti;
-
-   tokens = (struct tgsi_token *) MALLOC(maxTokens * sizeof(tokens[0]));
-
-   /* shader header
-    */
-   *(struct tgsi_version *) &tokens[0] = tgsi_build_version();
-
-   header = (struct tgsi_header *) &tokens[1];
-   *header = tgsi_build_header();
-
-   processor = (struct tgsi_processor *) &tokens[2];
-   *processor = tgsi_build_processor( procType, header );
-
-   ti = 3;
-
-   /* declare TEX[0] input */
-   decl = tgsi_default_full_declaration();
-   decl.Declaration.File = TGSI_FILE_INPUT;
-   /* XXX this could be linear... */
-   decl.Declaration.Interpolate = TGSI_INTERPOLATE_PERSPECTIVE;
-   decl.Declaration.Semantic = 1;
-   decl.Semantic.SemanticName = TGSI_SEMANTIC_GENERIC;
-   decl.Semantic.SemanticIndex = 0;
-   decl.DeclarationRange.First = 
-   decl.DeclarationRange.Last = 0;
-   ti += tgsi_build_full_declaration(&decl,
-                                     &tokens[ti],
-                                     header,
-                                     maxTokens - ti);
-
-   /* declare color[0] output */
-   decl = tgsi_default_full_declaration();
-   decl.Declaration.File = TGSI_FILE_OUTPUT;
-   decl.Declaration.Semantic = 1;
-   decl.Semantic.SemanticName = TGSI_SEMANTIC_COLOR;
-   decl.Semantic.SemanticIndex = 0;
-   decl.DeclarationRange.First = 
-   decl.DeclarationRange.Last = 0;
-   ti += tgsi_build_full_declaration(&decl,
-                                     &tokens[ti],
-                                     header,
-                                     maxTokens - ti);
-
-   /* declare sampler */
-   decl = tgsi_default_full_declaration();
-   decl.Declaration.File = TGSI_FILE_SAMPLER;
-   decl.DeclarationRange.First = 
-   decl.DeclarationRange.Last = 0;
-   ti += tgsi_build_full_declaration(&decl,
-                                     &tokens[ti],
-                                     header,
-                                     maxTokens - ti);
-
-   /* TEX instruction */
-   inst = tgsi_default_full_instruction();
-   inst.Instruction.Opcode = TGSI_OPCODE_TEX;
-   inst.Instruction.NumDstRegs = 1;
-   inst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_OUTPUT;
-   inst.FullDstRegisters[0].DstRegister.Index = 0;
-   inst.Instruction.NumSrcRegs = 2;
-   inst.InstructionExtTexture.Texture = TGSI_TEXTURE_2D;
-   inst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_INPUT;
-   inst.FullSrcRegisters[0].SrcRegister.Index = 0;
-   inst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER;
-   inst.FullSrcRegisters[1].SrcRegister.Index = 0;
-   ti += tgsi_build_full_instruction(&inst,
-                                     &tokens[ti],
-                                     header,
-                                     maxTokens - ti );
-
-   /* END instruction */
-   inst = tgsi_default_full_instruction();
-   inst.Instruction.Opcode = TGSI_OPCODE_END;
-   inst.Instruction.NumDstRegs = 0;
-   inst.Instruction.NumSrcRegs = 0;
-   ti += tgsi_build_full_instruction(&inst,
-                                     &tokens[ti],
-                                     header,
-                                     maxTokens - ti );
-
-#if 0 /*debug*/
-   tgsi_dump(tokens, 0);
-#endif
-
-   shader->tokens = tokens;
-   /*shader->num_tokens = ti;*/
-
-   return pipe->create_fs_state(pipe, shader);
-}
+   struct ureg_program *ureg;
+   struct ureg_src sampler;
+   struct ureg_src tex;
+   struct ureg_dst out, depth;
+   struct ureg_src imm;
+
+   ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT );
+   if (ureg == NULL)
+      return NULL;
+
+   sampler = ureg_DECL_sampler( ureg, 0 );
+
+   tex = ureg_DECL_fs_input( ureg,
+                             TGSI_SEMANTIC_GENERIC, 0,
+                             TGSI_INTERPOLATE_PERSPECTIVE );
 
+   out = ureg_DECL_output( ureg,
+                           TGSI_SEMANTIC_COLOR,
+                           0 );
 
+   depth = ureg_DECL_output( ureg,
+                             TGSI_SEMANTIC_POSITION,
+                             0 );
 
+   imm = ureg_imm4f( ureg, 0, 0, 0, 1 );
+
+   ureg_MOV( ureg, out, imm );
+
+   ureg_TEX( ureg,
+             ureg_writemask(depth, TGSI_WRITEMASK_Z),
+             tex_target, tex, sampler );
+   ureg_END( ureg );
+
+   return ureg_create_shader_and_destroy( ureg, pipe );
+}
 
 
 /**
  * Make simple fragment color pass-through shader.
  */
 void *
-util_make_fragment_passthrough_shader(struct pipe_context *pipe,
-                                      struct pipe_shader_state *shader)
+util_make_fragment_passthrough_shader(struct pipe_context *pipe)
 {
-   uint maxTokens = 40;
-   struct tgsi_token *tokens;
-   struct tgsi_header *header;
-   struct tgsi_processor *processor;
-   struct tgsi_full_declaration decl;
-   struct tgsi_full_instruction inst;
-   const uint procType = TGSI_PROCESSOR_FRAGMENT;
-   uint ti;
-
-   tokens = (struct tgsi_token *) MALLOC(maxTokens * sizeof(tokens[0]));
-
-   /* shader header
-    */
-   *(struct tgsi_version *) &tokens[0] = tgsi_build_version();
-
-   header = (struct tgsi_header *) &tokens[1];
-   *header = tgsi_build_header();
-
-   processor = (struct tgsi_processor *) &tokens[2];
-   *processor = tgsi_build_processor( procType, header );
-
-   ti = 3;
-
-   /* declare input */
-   decl = tgsi_default_full_declaration();
-   decl.Declaration.File = TGSI_FILE_INPUT;
-   decl.Declaration.Semantic = 1;
-   decl.Semantic.SemanticName = TGSI_SEMANTIC_COLOR;
-   decl.Semantic.SemanticIndex = 0;
-   decl.DeclarationRange.First = 
-      decl.DeclarationRange.Last = 0;
-   ti += tgsi_build_full_declaration(&decl,
-                                     &tokens[ti],
-                                     header,
-                                     maxTokens - ti);
-
-   /* declare output */
-   decl = tgsi_default_full_declaration();
-   decl.Declaration.File = TGSI_FILE_OUTPUT;
-   decl.Declaration.Semantic = 1;
-   decl.Semantic.SemanticName = TGSI_SEMANTIC_COLOR;
-   decl.Semantic.SemanticIndex = 0;
-   decl.DeclarationRange.First = 
-      decl.DeclarationRange.Last = 0;
-   ti += tgsi_build_full_declaration(&decl,
-                                     &tokens[ti],
-                                     header,
-                                     maxTokens - ti);
-
-
-   /* MOVE out[0], in[0]; */
-   inst = tgsi_default_full_instruction();
-   inst.Instruction.Opcode = TGSI_OPCODE_MOV;
-   inst.Instruction.NumDstRegs = 1;
-   inst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_OUTPUT;
-   inst.FullDstRegisters[0].DstRegister.Index = 0;
-   inst.Instruction.NumSrcRegs = 1;
-   inst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_INPUT;
-   inst.FullSrcRegisters[0].SrcRegister.Index = 0;
-   ti += tgsi_build_full_instruction(&inst,
-                                     &tokens[ti],
-                                     header,
-                                     maxTokens - ti );
-
-   /* END instruction */
-   inst = tgsi_default_full_instruction();
-   inst.Instruction.Opcode = TGSI_OPCODE_END;
-   inst.Instruction.NumDstRegs = 0;
-   inst.Instruction.NumSrcRegs = 0;
-   ti += tgsi_build_full_instruction(&inst,
-                                     &tokens[ti],
-                                     header,
-                                     maxTokens - ti );
-
-   assert(ti < maxTokens);
-
-#if 0 /*debug*/
-   tgsi_dump(tokens, 0);
-#endif
-
-   shader->tokens = tokens;
-   /*shader->num_tokens = ti;*/
-
-   return pipe->create_fs_state(pipe, shader);
+   return util_make_fragment_clonecolor_shader(pipe, 1);
 }
 
+
+/**
+ * Make a fragment shader that copies the input color to N output colors.
+ */
+void *
+util_make_fragment_clonecolor_shader(struct pipe_context *pipe, int num_cbufs)
+{
+   struct ureg_program *ureg;
+   struct ureg_src src;
+   struct ureg_dst dst[PIPE_MAX_COLOR_BUFS];
+   int i;
+
+   assert(num_cbufs <= PIPE_MAX_COLOR_BUFS);
+
+   ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT );
+   if (ureg == NULL)
+      return NULL;
+
+   src = ureg_DECL_fs_input( ureg, TGSI_SEMANTIC_COLOR, 0, 
+                             TGSI_INTERPOLATE_PERSPECTIVE );
+
+   for (i = 0; i < num_cbufs; i++)
+      dst[i] = ureg_DECL_output( ureg, TGSI_SEMANTIC_COLOR, i );
+
+   for (i = 0; i < num_cbufs; i++)
+      ureg_MOV( ureg, dst[i], src );
+
+   ureg_END( ureg );
+
+   return ureg_create_shader_and_destroy( ureg, pipe );
+}