Revert "[3.0] Remove/move experimental features"
[platform/core/uifw/dali-core.git] / build / scripts / generate-shader-strings.pl
1 #!/usr/bin/perl -w
2
3 ###############################################################################
4
5 use strict;
6 use FileHandle;
7 use Getopt::Long;
8 use Pod::Usage;
9
10 ###############################################################################
11
12 sub OpenFileForWriting
13 {
14   my($fileName) = shift;
15
16   my $fh = FileHandle->new;
17   if (!$fh->open("> $fileName"))
18   {
19     die "Can't open $fileName for writing: $!\n";
20   }
21   return $fh;
22 }
23
24 ###############################################################################
25
26 sub CloseFile
27 {
28   my($fh) = shift;
29   $fh->close;
30 }
31
32 ###############################################################################
33
34 sub GenerateHeaderFileHeader
35 {
36   my($headerFile) = shift;
37   my $time=localtime();
38   print $headerFile <<"H_HEADER_END";
39 //
40 // Automatically Generated on $time
41 //
42
43 #ifndef __DALI_GENERATED_SHADERS_H_
44 #define __DALI_GENERATED_SHADERS_H_
45
46 namespace Dali
47 {
48 namespace Internal
49 {
50
51 H_HEADER_END
52 }
53
54 ###############################################################################
55
56 sub GenerateHeaderFileFooter
57 {
58   my($headerFile) = shift;
59   print $headerFile <<"H_FOOTER_END";
60
61 } // namespace Internal
62 } // namespace Dali
63
64 #endif // __DALI_GENERATED_SHADERS_H_
65 H_FOOTER_END
66 }
67
68 ###############################################################################
69
70 sub GenerateSourceFileHeader
71 {
72   my($sourceFile) = shift;
73   my $time=localtime();
74   print $sourceFile <<"CPP_HEADER_END";
75 //
76 // Automatically Generated on $time
77 //
78
79 namespace Dali
80 {
81 namespace Internal
82 {
83
84 CPP_HEADER_END
85 }
86
87 ###############################################################################
88
89 sub GenerateSourceFileFooter
90 {
91   my($sourceFile) = shift;
92   print $sourceFile <<"CPP_FOOTER_END";
93 } // namespace Internal
94 } // namespace Dali
95 CPP_FOOTER_END
96 }
97
98 ###############################################################################
99
100 my %shaders=();
101
102 sub GenerateStringsFromFile
103 {
104   my($file) = shift;
105   my($dir) = shift;
106
107   my $shadername = $file;
108   $shadername =~ s/-([a-z])/uc($1)/eg;
109   $shadername =~ s/^([a-z])/uc($1)/e;
110   $shadername =~ s/\.txt$//;
111
112   my $state = 0;
113
114   my $shader="";
115   open MEM, "$dir/$file" || die "Can't open $file for reading: $!\n";
116   while(<MEM>)
117   {
118     chomp;
119     if ($state == 0)
120     {
121       if (/<VertexShader>/)
122       {
123         $state = 1;
124         $shader = "";
125       }
126       elsif (/<FragmentShader>/)
127       {
128         $state = 1;
129         $shader = "";
130       }
131     }
132     elsif ($state == 1)
133     {
134       if (m!</VertexShader>!)
135       {
136         $state = 0;
137         $shaders{$shadername}->{"vertex"} = $shader;
138       }
139       elsif( m!</FragmentShader>!)
140       {
141         $state = 0;
142         $shaders{$shadername}->{"fragment"} = $shader;
143       }
144       else
145       {
146         ## Accumulate
147         $shader .= "$_\n";
148 #       print $sourceFile "\"$_\\n\"\n";
149       }
150     }
151   }
152   close MEM;
153 }
154
155 ###############################################################################
156
157 sub GetShaderFiles
158 {
159   my ($dir) = shift;
160   opendir (DIR, $dir) || die "Can't open $dir for reading: $!\n";
161   my @shaderFiles = grep { /\.txt$/ && -f "$dir/$_" } readdir DIR;
162   closedir DIR;
163   return @shaderFiles;
164 }
165
166 ###############################################################################
167
168 sub PrintSourceLine
169 {
170     my $sourceFile=shift;
171     my $line=shift;
172     chomp $line;
173     $line =~ s!//.*$!!; # Strip out comments
174     $line =~ s!\s*$!!; # Strip out trailing space
175     if( $line !~ m!^\s*$! )
176     {
177         print $sourceFile "\"$line\\n\"\n";
178     }
179 }
180
181 sub PrintMacroLine
182 {
183     my $sourceFile=shift;
184     my $line=shift;
185     chomp $line;
186     $line =~ s!//.*$!!; # Strip out comments
187     $line =~ s!\s*$!!; # Strip out trailing space
188     if( $line !~ m!^\s*$! )
189     {
190         print $sourceFile "\"$line\\n\" \\\n";
191     }
192 }
193
194
195 sub PrintShaderProgramWithMacros
196 {
197     my $sourceFile=shift;
198     my $shadername=shift;
199     my $SHADERNAME=$shadername;
200     $SHADERNAME =~ s/([A-Z])/_$1/g;
201     substr($SHADERNAME,0,1)="";
202     $SHADERNAME = uc($SHADERNAME);
203
204     my $program_type=shift;
205     my $ProgramType=ucfirst($program_type);
206     my $PROGRAM_TYPE=uc($program_type);
207     my $custom=shift;
208
209     my @lines=split(/\n/, $shaders{$shadername}->{$program_type} );
210
211     print $sourceFile "#define ${SHADERNAME}_PREFIX_${PROGRAM_TYPE} \\\n";
212     LINE: while( scalar(@lines) )
213     {
214         last LINE if $lines[0] =~ /main()/;
215         PrintMacroLine($sourceFile, shift(@lines));
216     }
217     print $sourceFile "\n\n";
218
219     print $sourceFile "#define ${SHADERNAME}_POSTFIX_${PROGRAM_TYPE} \\\n";
220     LINE: while( scalar(@lines) )
221     {
222         PrintMacroLine($sourceFile, shift(@lines));
223     }
224     print $sourceFile "\n\n";
225
226     if($custom)
227     {
228         print $sourceFile "extern const char* const Custom${shadername}Prefix${ProgramType};\n";
229         print $sourceFile "const char* const Custom${shadername}Prefix${ProgramType}(\n";
230         print $sourceFile "  ${SHADERNAME}_PREFIX_${PROGRAM_TYPE}\n";
231         print $sourceFile ");\n\n";
232
233         print $sourceFile "extern const char* const Custom${shadername}Postfix${ProgramType};\n";
234         print $sourceFile "const char* const Custom${shadername}Postfix${ProgramType}(\n";
235         print $sourceFile "  ${SHADERNAME}_POSTFIX_${PROGRAM_TYPE}\n";
236         print $sourceFile ");\n\n";
237     }
238     print $sourceFile "extern const char* const ${shadername}${ProgramType};\n";
239     print $sourceFile "const char* const ${shadername}${ProgramType}(\n";
240     print $sourceFile "  ${SHADERNAME}_PREFIX_${PROGRAM_TYPE}\n";
241     print $sourceFile "  ${SHADERNAME}_POSTFIX_${PROGRAM_TYPE}\n";
242     print $sourceFile ");\n\n";
243
244 }
245
246 sub PrintShaderProgram
247 {
248     my $sourceFile=shift;
249     my $shadername=shift;
250     my $program_type=shift;
251     my $custom=shift;
252     my $ProgramType=ucfirst($program_type);
253
254     my @lines=split(/\n/, $shaders{$shadername}->{$program_type} );
255
256     print $sourceFile "const char* const ${shadername}${ProgramType}(\n";
257     for my $i (0..scalar(@lines)-1)
258     {
259         PrintSourceLine($sourceFile, $lines[$i]);
260     }
261     print $sourceFile ");\n\n";
262
263     if( $custom )
264     {
265         print $sourceFile "const char* const Custom${shadername}Prefix${ProgramType}(\n";
266       LINE:
267         while( scalar(@lines) )
268         {
269             last LINE if $lines[0] =~ /main()/;
270             PrintSourceLine($sourceFile, shift(@lines));
271         }
272         print $sourceFile ");\n\n";
273
274         print $sourceFile "const char* const Custom${shadername}Postfix${ProgramType}(\n";
275
276         while( scalar(@lines) )
277         {
278             PrintSourceLine($sourceFile, shift(@lines));
279         }
280         print $sourceFile ");\n\n";
281     }
282 }
283
284
285 sub PrintShaderSources
286 {
287   my($headerFile) = shift;
288   my($sourceFile) = shift;
289   my $shadername;
290
291   # Strings are now in memory. Dump them back out again:
292   foreach $shadername (sort(keys(%shaders)))
293   {
294     print $headerFile "extern const char* const ${shadername}Vertex;\n";
295     print $headerFile "extern const char* const ${shadername}Fragment;\n";
296
297     my $custom = 0;
298     if( $shadername !~ /TextDistanceField/ || $shadername eq "TextDistanceField" )
299     {
300         print $headerFile "extern const char* const Custom${shadername}PrefixVertex;\n";
301         print $headerFile "extern const char* const Custom${shadername}PostfixVertex;\n";
302         print $headerFile "extern const char* const Custom${shadername}PrefixFragment;\n";
303         print $headerFile "extern const char* const Custom${shadername}PostfixFragment;\n";
304         $custom = 1;
305     }
306     PrintShaderProgramWithMacros($sourceFile, $shadername, "vertex", $custom);
307     PrintShaderProgramWithMacros($sourceFile, $shadername, "fragment", $custom);
308   }
309 }
310
311 ###############################################################################
312
313 my($optHelp);
314 my($optMan);
315 my($shaderDir) = "";
316 my($fileName) = "";
317
318 GetOptions(
319   "help"           => \$optHelp,
320   "man"            => \$optMan,
321   "shader-dir=s"   => \$shaderDir,
322   "file-name=s"  => \$fileName
323 ) or pod2usage(2);
324
325 pod2usage(1) if $optHelp;
326 pod2usage(-exitstatus => 0, -verbose => 2) if $optMan;
327
328 if ($shaderDir eq "" || $fileName eq "")
329 {
330   pod2usage(1);
331 }
332 else
333 {
334   my $dir = $shaderDir;
335   my @shaderFiles = GetShaderFiles($dir);
336
337   my $headerFile = OpenFileForWriting("$fileName.h");
338   my $sourceFile = OpenFileForWriting("$fileName.cpp");
339
340   GenerateHeaderFileHeader($headerFile);
341   GenerateSourceFileHeader($sourceFile);
342
343   my $file;
344   foreach $file (@shaderFiles)
345   {
346     GenerateStringsFromFile($file, $dir);
347   }
348
349   PrintShaderSources($headerFile, $sourceFile);
350
351   GenerateHeaderFileFooter($headerFile);
352   GenerateSourceFileFooter($sourceFile);
353
354   CloseFile($headerFile);
355   CloseFile($sourceFile);
356 }
357
358 ###############################################################################
359
360 __END__
361
362 =head1 NAME
363
364 generate-shader-strings.pl - Given a shader directory and a file name, this script generates a header and source file where all the shaders in the directory are stored as vertex and fragment shader const char arrays.
365
366 =head1 SYNOPSIS
367
368 generate-shader-strings.pl -s=<shader-dir> -f=<file-name>
369
370 generate-shader-strings.pl -shader-dir=<shader-dir> -file-name=<file-name>
371
372 =head1 DESCRIPTION
373
374 Given a shader directory and a file name, this script generates a header and source file where all the shaders in the directory are stored as vertex and fragment shader const char arrays.
375
376 The shader files in the specified directory should have the suffix ".txt" and the vertex and fragment shaders should be encapsulated within <VertexShader>*</VertexShader> and <FragmentShader>*</FragmentShader> respectively in this text file.
377
378 The generated source files will be called <file-name>.h and <file-name>.cpp.
379
380 =head1 OPTIONS
381
382 =over 36
383
384 =item B<-s|--shader-dir=<shader-directory>>
385
386 The directory the shader files should be loaded from.
387
388 =item B<-f|--file-name>
389
390 The name of the output files.