/src/com/adobe/utils/AGALMiniAssembler.as
ActionScript | 792 lines | 586 code | 81 blank | 125 comment | 90 complexity | 9da226f8ed97059ae9470cf75ece9ff8 MD5 | raw file
1/*
2Copyright (c) 2011, Adobe Systems Incorporated
3All rights reserved.
4
5Redistribution and use in source and binary forms, with or without
6modification, are permitted provided that the following conditions are
7met:
8
9* Redistributions of source code must retain the above copyright notice,
10this list of conditions and the following disclaimer.
11
12* Redistributions in binary form must reproduce the above copyright
13notice, this list of conditions and the following disclaimer in the
14documentation and/or other materials provided with the distribution.
15
16* Neither the name of Adobe Systems Incorporated nor the names of its
17contributors may be used to endorse or promote products derived from
18this software without specific prior written permission.
19
20THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
21IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31*/
32package com.adobe.utils
33{
34 // ===========================================================================
35 // Imports
36 // ---------------------------------------------------------------------------
37 import flash.display3D.*;
38 import flash.utils.*;
39
40 // ===========================================================================
41 // Class
42 // 我们可以通过字符串指令来获得一个AGAL二进制流
43 public class AGALMiniAssembler
44 { // ======================================================================
45 // Constants
46 // ----------------------------------------------------------------------
47 protected static const REGEXP_OUTER_SPACES:RegExp = /^\s+|\s+$/g;
48
49 // ======================================================================
50 // Properties
51 // ----------------------------------------------------------------------
52 // AGAL bytes and error buffer
53 private var _agalcode:ByteArray = null;
54 private var _error:String = "";
55
56 private var debugEnabled:Boolean = false;
57
58 private static var initialized:Boolean = false;
59 public var verbose:Boolean = false;
60
61 // ======================================================================
62 // Getters
63 // ----------------------------------------------------------------------
64 public function get error():String { return _error; }
65 public function get agalcode():ByteArray { return _agalcode; }
66
67 // ======================================================================
68 // Constructor
69 // ----------------------------------------------------------------------
70 public function AGALMiniAssembler( debugging:Boolean = false ):void
71 {
72 debugEnabled = debugging;
73 if ( !initialized )
74 init();
75 }
76 // ======================================================================
77 // Methods
78 // ----------------------------------------------------------------------
79
80 public function assemble2( ctx3d : Context3D, version:uint, vertexsrc:String, fragmentsrc:String ) : Program3D
81 {
82 var agalvertex : ByteArray = assemble ( VERTEX, vertexsrc, version );
83 var agalfragment : ByteArray = assemble ( FRAGMENT, fragmentsrc, version );
84 var prog : Program3D = ctx3d.createProgram();
85 prog.upload(agalvertex,agalfragment);
86 return prog;
87 }
88
89 public function assemble( mode:String, source:String, version:uint=1 ):ByteArray
90 {
91 var start:uint = getTimer();
92
93 _agalcode = new ByteArray();
94 _error = "";
95
96 var isFrag:Boolean = false;
97
98 if ( mode == FRAGMENT )
99 isFrag = true;
100 else if ( mode != VERTEX )
101 _error = 'ERROR: mode needs to be "' + FRAGMENT + '" or "' + VERTEX + '" but is "' + mode + '".';
102
103 agalcode.endian = Endian.LITTLE_ENDIAN;
104 agalcode.writeByte( 0xa0 ); // tag version
105 agalcode.writeUnsignedInt( version ); // AGAL version, big endian, bit pattern will be 0x01000000
106 agalcode.writeByte( 0xa1 ); // tag program id
107 agalcode.writeByte( isFrag ? 1 : 0 ); // vertex or fragment
108
109 initregmap(version);
110
111 var lines:Array = source.replace( /[\f\n\r\v]+/g, "\n" ).split( "\n" );
112 var nest:int = 0;
113 var nops:int = 0;
114 var i:int;
115 var lng:int = lines.length;
116
117 for ( i = 0; i < lng && _error == ""; i++ )
118 {
119 var line:String = new String( lines[i] );
120 line = line.replace( REGEXP_OUTER_SPACES, "" );
121
122 // remove comments
123 var startcomment:int = line.search( "//" );
124 if ( startcomment != -1 )
125 line = line.slice( 0, startcomment );
126
127 // grab options
128 var optsi:int = line.search( /<.*>/g );
129 var opts:Array;
130 if ( optsi != -1 )
131 {
132 opts = line.slice( optsi ).match( /([\w\.\-\+]+)/gi );
133 line = line.slice( 0, optsi );
134 }
135
136 // find opcode
137 var opCode:Array = line.match( /^\w{3}/ig );
138 if ( !opCode )
139 {
140 if ( line.length >= 3 )
141 trace( "warning: bad line "+i+": "+lines[i] );
142 continue;
143 }
144 var opFound:OpCode = OPMAP[ opCode[0] ];
145
146 // if debug is enabled, output the opcodes
147 if ( debugEnabled )
148 trace( opFound );
149
150 if ( opFound == null )
151 {
152 if ( line.length >= 3 )
153 trace( "warning: bad line "+i+": "+lines[i] );
154 continue;
155 }
156
157 line = line.slice( line.search( opFound.name ) + opFound.name.length );
158
159 if ( ( opFound.flags & OP_VERSION2 ) && version<2 )
160 {
161 _error = "error: opcode requires version 2.";
162 break;
163 }
164
165 if ( ( opFound.flags & OP_VERT_ONLY ) && isFrag )
166 {
167 _error = "error: opcode is only allowed in vertex programs.";
168 break;
169 }
170
171 if ( ( opFound.flags & OP_FRAG_ONLY ) && !isFrag )
172 {
173 _error = "error: opcode is only allowed in fragment programs.";
174 break;
175 }
176 if ( verbose )
177 trace( "emit opcode=" + opFound );
178
179 agalcode.writeUnsignedInt( opFound.emitCode );
180 nops++;
181
182 if ( nops > MAX_OPCODES )
183 {
184 _error = "error: too many opcodes. maximum is "+MAX_OPCODES+".";
185 break;
186 }
187
188 // get operands, use regexp
189 var regs:Array;
190
191 // will match both syntax
192 regs = line.match( /vc\[([vof][acostdip]?)(\d*)?(\.[xyzw](\+\d{1,3})?)?\](\.[xyzw]{1,4})?|([vof][acostdip]?)(\d*)?(\.[xyzw]{1,4})?/gi );
193
194 if ( !regs || regs.length != opFound.numRegister )
195 {
196 _error = "error: wrong number of operands. found "+regs.length+" but expected "+opFound.numRegister+".";
197 break;
198 }
199
200 var badreg:Boolean = false;
201 var pad:uint = 64 + 64 + 32;
202 var regLength:uint = regs.length;
203
204 for ( var j:int = 0; j < regLength; j++ )
205 {
206 var isRelative:Boolean = false;
207 var relreg:Array = regs[ j ].match( /\[.*\]/ig );
208 if ( relreg && relreg.length > 0 )
209 {
210 regs[ j ] = regs[ j ].replace( relreg[ 0 ], "0" );
211
212 if ( verbose )
213 trace( "IS REL" );
214 isRelative = true;
215 }
216
217 var res:Array = regs[j].match( /^\b[A-Za-z]{1,2}/ig );
218 if ( !res )
219 {
220 _error = "error: could not parse operand "+j+" ("+regs[j]+").";
221 badreg = true;
222 break;
223 }
224 var regFound:Register = REGMAP[ res[ 0 ] ];
225
226 // if debug is enabled, output the registers
227 if ( debugEnabled )
228 trace( regFound );
229
230 if ( regFound == null )
231 {
232 _error = "error: could not find register name for operand "+j+" ("+regs[j]+").";
233 badreg = true;
234 break;
235 }
236
237 if ( isFrag )
238 {
239 if ( !( regFound.flags & REG_FRAG ) )
240 {
241 _error = "error: register operand "+j+" ("+regs[j]+") only allowed in vertex programs.";
242 badreg = true;
243 break;
244 }
245 if ( isRelative )
246 {
247 _error = "error: register operand "+j+" ("+regs[j]+") relative adressing not allowed in fragment programs.";
248 badreg = true;
249 break;
250 }
251 }
252 else
253 {
254 if ( !( regFound.flags & REG_VERT ) )
255 {
256 _error = "error: register operand "+j+" ("+regs[j]+") only allowed in fragment programs.";
257 badreg = true;
258 break;
259 }
260 }
261
262 regs[j] = regs[j].slice( regs[j].search( regFound.name ) + regFound.name.length );
263 //trace( "REGNUM: " +regs[j] );
264 var idxmatch:Array = isRelative ? relreg[0].match( /\d+/ ) : regs[j].match( /\d+/ );
265 var regidx:uint = 0;
266
267 if ( idxmatch )
268 regidx = uint( idxmatch[0] );
269
270 if ( regFound.range < regidx )
271 {
272 _error = "error: register operand "+j+" ("+regs[j]+") index exceeds limit of "+(regFound.range+1)+".";
273 badreg = true;
274 break;
275 }
276
277 var regmask:uint = 0;
278 var maskmatch:Array = regs[j].match( /(\.[xyzw]{1,4})/ );
279 var isDest:Boolean = ( j == 0 && !( opFound.flags & OP_NO_DEST ) );
280 var isSampler:Boolean = ( j == 2 && ( opFound.flags & OP_SPECIAL_TEX ) );
281 var reltype:uint = 0;
282 var relsel:uint = 0;
283 var reloffset:int = 0;
284
285 if ( isDest && isRelative )
286 {
287 _error = "error: relative can not be destination";
288 badreg = true;
289 break;
290 }
291
292 if ( maskmatch )
293 {
294 regmask = 0;
295 var cv:uint;
296 var maskLength:uint = maskmatch[0].length;
297 for ( var k:int = 1; k < maskLength; k++ )
298 {
299 cv = maskmatch[0].charCodeAt(k) - "x".charCodeAt(0);
300 if ( cv > 2 )
301 cv = 3;
302 if ( isDest )
303 regmask |= 1 << cv;
304 else
305 regmask |= cv << ( ( k - 1 ) << 1 );
306 }
307 if ( !isDest )
308 for ( ; k <= 4; k++ )
309 regmask |= cv << ( ( k - 1 ) << 1 ); // repeat last
310 }
311 else
312 {
313 regmask = isDest ? 0xf : 0xe4; // id swizzle or mask
314 }
315
316 if ( isRelative )
317 {
318 var relname:Array = relreg[0].match( /[A-Za-z]{1,2}/ig );
319 var regFoundRel:Register = REGMAP[ relname[0]];
320 if ( regFoundRel == null )
321 {
322 _error = "error: bad index register";
323 badreg = true;
324 break;
325 }
326 reltype = regFoundRel.emitCode;
327 var selmatch:Array = relreg[0].match( /(\.[xyzw]{1,1})/ );
328 if ( selmatch.length==0 )
329 {
330 _error = "error: bad index register select";
331 badreg = true;
332 break;
333 }
334 relsel = selmatch[0].charCodeAt(1) - "x".charCodeAt(0);
335 if ( relsel > 2 )
336 relsel = 3;
337 var relofs:Array = relreg[0].match( /\+\d{1,3}/ig );
338 if ( relofs.length > 0 )
339 reloffset = relofs[0];
340 if ( reloffset < 0 || reloffset > 255 )
341 {
342 _error = "error: index offset "+reloffset+" out of bounds. [0..255]";
343 badreg = true;
344 break;
345 }
346 if ( verbose )
347 trace( "RELATIVE: type="+reltype+"=="+relname[0]+" sel="+relsel+"=="+selmatch[0]+" idx="+regidx+" offset="+reloffset );
348 }
349
350 if ( verbose )
351 trace( " emit argcode="+regFound+"["+regidx+"]["+regmask+"]" );
352 if ( isDest )
353 {
354 agalcode.writeShort( regidx );
355 agalcode.writeByte( regmask );
356 agalcode.writeByte( regFound.emitCode );
357 pad -= 32;
358 } else
359 {
360 if ( isSampler )
361 {
362 if ( verbose )
363 trace( " emit sampler" );
364 var samplerbits:uint = 5; // type 5
365 var optsLength:uint = opts == null ? 0 : opts.length;
366 var bias:Number = 0;
367 for ( k = 0; k<optsLength; k++ )
368 {
369 if ( verbose )
370 trace( " opt: "+opts[k] );
371 var optfound:Sampler = SAMPLEMAP [opts[k]];
372 if ( optfound == null )
373 {
374 // todo check that it's a number...
375 //trace( "Warning, unknown sampler option: "+opts[k] );
376 bias = Number(opts[k]);
377 if ( verbose )
378 trace( " bias: " + bias );
379 }
380 else
381 {
382 if ( optfound.flag != SAMPLER_SPECIAL_SHIFT )
383 samplerbits &= ~( 0xf << optfound.flag );
384 samplerbits |= uint( optfound.mask ) << uint( optfound.flag );
385 }
386 }
387 agalcode.writeShort( regidx );
388 agalcode.writeByte(int(bias*8.0));
389 agalcode.writeByte(0);
390 agalcode.writeUnsignedInt( samplerbits );
391
392 if ( verbose )
393 trace( " bits: " + ( samplerbits - 5 ) );
394 pad -= 64;
395 }
396 else
397 {
398 if ( j == 0 )
399 {
400 agalcode.writeUnsignedInt( 0 );
401 pad -= 32;
402 }
403 agalcode.writeShort( regidx );
404 agalcode.writeByte( reloffset );
405 agalcode.writeByte( regmask );
406 agalcode.writeByte( regFound.emitCode );
407 agalcode.writeByte( reltype );
408 agalcode.writeShort( isRelative ? ( relsel | ( 1 << 15 ) ) : 0 );
409
410 pad -= 64;
411 }
412 }
413 }
414
415 // pad unused regs
416 for ( j = 0; j < pad; j += 8 )
417 agalcode.writeByte( 0 );
418
419 if ( badreg )
420 break;
421 }
422
423 if ( _error != "" )
424 {
425 _error += "\n at line " + i + " " + lines[i];
426 agalcode.length = 0;
427 trace( _error );
428 }
429
430 // trace the bytecode bytes if debugging is enabled
431 if ( debugEnabled )
432 {
433 var dbgLine:String = "generated bytecode:";
434 var agalLength:uint = agalcode.length;
435 for ( var index:uint = 0; index < agalLength; index++ )
436 {
437 if ( !( index % 16 ) )
438 dbgLine += "\n";
439 if ( !( index % 4 ) )
440 dbgLine += " ";
441
442 var byteStr:String = agalcode[ index ].toString( 16 );
443 if ( byteStr.length < 2 )
444 byteStr = "0" + byteStr;
445
446 dbgLine += byteStr;
447 }
448 trace( dbgLine );
449 }
450
451 if ( verbose )
452 trace( "AGALMiniAssembler.assemble time: " + ( ( getTimer() - start ) / 1000 ) + "s" );
453
454 return agalcode;
455 }
456
457 private function initregmap ( version:uint ) : void {
458 // version changes limits
459 REGMAP[ VA ] = new Register( VA, "vertex attribute", 0x0, 7, REG_VERT | REG_READ );
460 REGMAP[ VC ] = new Register( VC, "vertex constant", 0x1, version==1?127:250, REG_VERT | REG_READ );
461 REGMAP[ VT ] = new Register( VT, "vertex temporary", 0x2, version==1?7:27, REG_VERT | REG_WRITE | REG_READ );
462 REGMAP[ VO ] = new Register( VO, "vertex output", 0x3, 0, REG_VERT | REG_WRITE );
463 REGMAP[ VI ] = new Register( VI, "varying", 0x4, version==1?7:11, REG_VERT | REG_FRAG | REG_READ | REG_WRITE );
464 REGMAP[ FC ] = new Register( FC, "fragment constant", 0x1, version==1?27:63, REG_FRAG | REG_READ );
465 REGMAP[ FT ] = new Register( FT, "fragment temporary", 0x2, version==1?7:27, REG_FRAG | REG_WRITE | REG_READ );
466 REGMAP[ FS ] = new Register( FS, "texture sampler", 0x5, 7, REG_FRAG | REG_READ );
467 REGMAP[ FO ] = new Register( FO, "fragment output", 0x3, version==1?0:3, REG_FRAG | REG_WRITE );
468 REGMAP[ FD ] = new Register( FD, "fragment depth output",0x6, version==1?-1:0, REG_FRAG | REG_WRITE );
469
470 // aliases
471 REGMAP[ "op" ] = REGMAP[ VO ];
472 REGMAP[ "i" ] = REGMAP[ VI ];
473 REGMAP[ "v" ] = REGMAP[ VI ];
474 REGMAP[ "oc" ] = REGMAP[ FO ];
475 REGMAP[ "fi" ] = REGMAP[ VI ];
476 }
477
478 static private function init():void
479 {
480 initialized = true;
481
482 // Fill the dictionaries with opcodes and registers
483 OPMAP[ MOV ] = new OpCode( MOV, 2, 0x00, 0 );
484 OPMAP[ ADD ] = new OpCode( ADD, 3, 0x01, 0 );
485 OPMAP[ SUB ] = new OpCode( SUB, 3, 0x02, 0 );
486 OPMAP[ MUL ] = new OpCode( MUL, 3, 0x03, 0 );
487 OPMAP[ DIV ] = new OpCode( DIV, 3, 0x04, 0 );
488 OPMAP[ RCP ] = new OpCode( RCP, 2, 0x05, 0 );
489 OPMAP[ MIN ] = new OpCode( MIN, 3, 0x06, 0 );
490 OPMAP[ MAX ] = new OpCode( MAX, 3, 0x07, 0 );
491 OPMAP[ FRC ] = new OpCode( FRC, 2, 0x08, 0 );
492 OPMAP[ SQT ] = new OpCode( SQT, 2, 0x09, 0 );
493 OPMAP[ RSQ ] = new OpCode( RSQ, 2, 0x0a, 0 );
494 OPMAP[ POW ] = new OpCode( POW, 3, 0x0b, 0 );
495 OPMAP[ LOG ] = new OpCode( LOG, 2, 0x0c, 0 );
496 OPMAP[ EXP ] = new OpCode( EXP, 2, 0x0d, 0 );
497 OPMAP[ NRM ] = new OpCode( NRM, 2, 0x0e, 0 );
498 OPMAP[ SIN ] = new OpCode( SIN, 2, 0x0f, 0 );
499 OPMAP[ COS ] = new OpCode( COS, 2, 0x10, 0 );
500 OPMAP[ CRS ] = new OpCode( CRS, 3, 0x11, 0 );
501 OPMAP[ DP3 ] = new OpCode( DP3, 3, 0x12, 0 );
502 OPMAP[ DP4 ] = new OpCode( DP4, 3, 0x13, 0 );
503 OPMAP[ ABS ] = new OpCode( ABS, 2, 0x14, 0 );
504 OPMAP[ NEG ] = new OpCode( NEG, 2, 0x15, 0 );
505 OPMAP[ SAT ] = new OpCode( SAT, 2, 0x16, 0 );
506 OPMAP[ M33 ] = new OpCode( M33, 3, 0x17, OP_SPECIAL_MATRIX );
507 OPMAP[ M44 ] = new OpCode( M44, 3, 0x18, OP_SPECIAL_MATRIX );
508 OPMAP[ M34 ] = new OpCode( M34, 3, 0x19, OP_SPECIAL_MATRIX );
509 OPMAP[ DDX ] = new OpCode( DDX, 2, 0x1a, OP_VERSION2 | OP_FRAG_ONLY );
510 OPMAP[ DDY ] = new OpCode( DDY, 2, 0x1b, OP_VERSION2 | OP_FRAG_ONLY );
511 OPMAP[ IFE ] = new OpCode( IFE, 2, 0x1c, OP_NO_DEST | OP_VERSION2 | OP_INCNEST | OP_SCALAR );
512 OPMAP[ INE ] = new OpCode( INE, 2, 0x1d, OP_NO_DEST | OP_VERSION2 | OP_INCNEST | OP_SCALAR );
513 OPMAP[ IFG ] = new OpCode( IFG, 2, 0x1e, OP_NO_DEST | OP_VERSION2 | OP_INCNEST | OP_SCALAR );
514 OPMAP[ IFL ] = new OpCode( IFL, 2, 0x1f, OP_NO_DEST | OP_VERSION2 | OP_INCNEST | OP_SCALAR );
515 OPMAP[ ELS ] = new OpCode( ELS, 0, 0x20, OP_NO_DEST | OP_VERSION2 | OP_INCNEST | OP_DECNEST | OP_SCALAR );
516 OPMAP[ EIF ] = new OpCode( EIF, 0, 0x21, OP_NO_DEST | OP_VERSION2 | OP_DECNEST | OP_SCALAR );
517 // space
518 OPMAP[ TED ] = new OpCode( TED, 3, 0x26, OP_FRAG_ONLY | OP_SPECIAL_TEX | OP_VERSION2);
519 OPMAP[ KIL ] = new OpCode( KIL, 1, 0x27, OP_NO_DEST | OP_FRAG_ONLY );
520 OPMAP[ TEX ] = new OpCode( TEX, 3, 0x28, OP_FRAG_ONLY | OP_SPECIAL_TEX );
521 OPMAP[ SGE ] = new OpCode( SGE, 3, 0x29, 0 );
522 OPMAP[ SLT ] = new OpCode( SLT, 3, 0x2a, 0 );
523 OPMAP[ SGN ] = new OpCode( SGN, 2, 0x2b, 0 );
524 OPMAP[ SEQ ] = new OpCode( SEQ, 3, 0x2c, 0 );
525 OPMAP[ SNE ] = new OpCode( SNE, 3, 0x2d, 0 );
526
527
528 SAMPLEMAP[ RGBA ] = new Sampler( RGBA, SAMPLER_TYPE_SHIFT, 0 );
529 SAMPLEMAP[ DXT1 ] = new Sampler( DXT1, SAMPLER_TYPE_SHIFT, 1 );
530 SAMPLEMAP[ DXT5 ] = new Sampler( DXT5, SAMPLER_TYPE_SHIFT, 2 );
531 SAMPLEMAP[ VIDEO ] = new Sampler( VIDEO, SAMPLER_TYPE_SHIFT, 3 );
532 SAMPLEMAP[ D2 ] = new Sampler( D2, SAMPLER_DIM_SHIFT, 0 );
533 SAMPLEMAP[ D3 ] = new Sampler( D3, SAMPLER_DIM_SHIFT, 2 );
534 SAMPLEMAP[ CUBE ] = new Sampler( CUBE, SAMPLER_DIM_SHIFT, 1 );
535 SAMPLEMAP[ MIPNEAREST ] = new Sampler( MIPNEAREST, SAMPLER_MIPMAP_SHIFT, 1 );
536 SAMPLEMAP[ MIPLINEAR ] = new Sampler( MIPLINEAR, SAMPLER_MIPMAP_SHIFT, 2 );
537 SAMPLEMAP[ MIPNONE ] = new Sampler( MIPNONE, SAMPLER_MIPMAP_SHIFT, 0 );
538 SAMPLEMAP[ NOMIP ] = new Sampler( NOMIP, SAMPLER_MIPMAP_SHIFT, 0 );
539 SAMPLEMAP[ NEAREST ] = new Sampler( NEAREST, SAMPLER_FILTER_SHIFT, 0 );
540 SAMPLEMAP[ LINEAR ] = new Sampler( LINEAR, SAMPLER_FILTER_SHIFT, 1 );
541 SAMPLEMAP[ CENTROID ] = new Sampler( CENTROID, SAMPLER_SPECIAL_SHIFT, 1 << 0 );
542 SAMPLEMAP[ SINGLE ] = new Sampler( SINGLE, SAMPLER_SPECIAL_SHIFT, 1 << 1 );
543 SAMPLEMAP[ DEPTH ] = new Sampler( DEPTH, SAMPLER_SPECIAL_SHIFT, 1 << 2 );
544 SAMPLEMAP[ REPEAT ] = new Sampler( REPEAT, SAMPLER_REPEAT_SHIFT, 1 );
545 SAMPLEMAP[ WRAP ] = new Sampler( WRAP, SAMPLER_REPEAT_SHIFT, 1 );
546 SAMPLEMAP[ CLAMP ] = new Sampler( CLAMP, SAMPLER_REPEAT_SHIFT, 0 );
547 }
548
549 // ======================================================================
550 // Constants
551 // ----------------------------------------------------------------------
552 private static const OPMAP:Dictionary = new Dictionary();
553 private static const REGMAP:Dictionary = new Dictionary();
554 private static const SAMPLEMAP:Dictionary = new Dictionary();
555
556 private static const MAX_NESTING:int = 4;
557 private static const MAX_OPCODES:int = 256;
558
559 private static const FRAGMENT:String = "fragment";
560 private static const VERTEX:String = "vertex";
561
562 // masks and shifts
563 private static const SAMPLER_TYPE_SHIFT:uint = 8;
564 private static const SAMPLER_DIM_SHIFT:uint = 12;
565 private static const SAMPLER_SPECIAL_SHIFT:uint = 16;
566 private static const SAMPLER_REPEAT_SHIFT:uint = 20;
567 private static const SAMPLER_MIPMAP_SHIFT:uint = 24;
568 private static const SAMPLER_FILTER_SHIFT:uint = 28;
569
570 // regmap flags
571 private static const REG_WRITE:uint = 0x1;
572 private static const REG_READ:uint = 0x2;
573 private static const REG_FRAG:uint = 0x20;
574 private static const REG_VERT:uint = 0x40;
575
576 // opmap flags
577 private static const OP_SCALAR:uint = 0x1;
578 private static const OP_SPECIAL_TEX:uint = 0x8;
579 private static const OP_SPECIAL_MATRIX:uint = 0x10;
580 private static const OP_FRAG_ONLY:uint = 0x20;
581 private static const OP_VERT_ONLY:uint = 0x40;
582 private static const OP_NO_DEST:uint = 0x80;
583 private static const OP_VERSION2:uint = 0x100;
584 private static const OP_INCNEST:uint = 0x200;
585 private static const OP_DECNEST:uint = 0x400;
586
587 // opcodes
588 private static const MOV:String = "mov";
589 private static const ADD:String = "add";
590 private static const SUB:String = "sub";
591 private static const MUL:String = "mul";
592 private static const DIV:String = "div";
593 private static const RCP:String = "rcp";
594 private static const MIN:String = "min";
595 private static const MAX:String = "max";
596 private static const FRC:String = "frc";
597 private static const SQT:String = "sqt";
598 private static const RSQ:String = "rsq";
599 private static const POW:String = "pow";
600 private static const LOG:String = "log";
601 private static const EXP:String = "exp";
602 private static const NRM:String = "nrm";
603 private static const SIN:String = "sin";
604 private static const COS:String = "cos";
605 private static const CRS:String = "crs";
606 private static const DP3:String = "dp3";
607 private static const DP4:String = "dp4";
608 private static const ABS:String = "abs";
609 private static const NEG:String = "neg";
610 private static const SAT:String = "sat";
611 private static const M33:String = "m33";
612 private static const M44:String = "m44";
613 private static const M34:String = "m34";
614 private static const DDX:String = "ddx";
615 private static const DDY:String = "ddy";
616 private static const IFE:String = "ife";
617 private static const INE:String = "ine";
618 private static const IFG:String = "ifg";
619 private static const IFL:String = "ifl";
620 private static const ELS:String = "els";
621 private static const EIF:String = "eif";
622 private static const TED:String = "ted";
623 private static const KIL:String = "kil";
624 private static const TEX:String = "tex";
625 private static const SGE:String = "sge";
626 private static const SLT:String = "slt";
627 private static const SGN:String = "sgn";
628 private static const SEQ:String = "seq";
629 private static const SNE:String = "sne";
630
631 // registers
632 private static const VA:String = "va";
633 private static const VC:String = "vc";
634 private static const VT:String = "vt";
635 private static const VO:String = "vo";
636 private static const VI:String = "vi";
637 private static const FC:String = "fc";
638 private static const FT:String = "ft";
639 private static const FS:String = "fs";
640 private static const FO:String = "fo";
641 private static const FD:String = "fd";
642
643 // samplers
644 private static const D2:String = "2d";
645 private static const D3:String = "3d";
646 private static const CUBE:String = "cube";
647 private static const MIPNEAREST:String = "mipnearest";
648 private static const MIPLINEAR:String = "miplinear";
649 private static const MIPNONE:String = "mipnone";
650 private static const NOMIP:String = "nomip";
651 private static const NEAREST:String = "nearest";
652 private static const LINEAR:String = "linear";
653 private static const CENTROID:String = "centroid";
654 private static const SINGLE:String = "single";
655 private static const DEPTH:String = "depth";
656 private static const REPEAT:String = "repeat";
657 private static const WRAP:String = "wrap";
658 private static const CLAMP:String = "clamp";
659 private static const RGBA:String = "rgba";
660 private static const DXT1:String = "dxt1";
661 private static const DXT5:String = "dxt5";
662 private static const VIDEO:String = "video";
663 }
664}
665
666// ================================================================================
667// Helper Classes
668// --------------------------------------------------------------------------------
669{
670 // ===========================================================================
671 // Class
672 // ---------------------------------------------------------------------------
673 class OpCode
674 {
675 // ======================================================================
676 // Properties
677 // ----------------------------------------------------------------------
678 private var _emitCode:uint;
679 private var _flags:uint;
680 private var _name:String;
681 private var _numRegister:uint;
682
683 // ======================================================================
684 // Getters
685 // ----------------------------------------------------------------------
686 public function get emitCode():uint { return _emitCode; }
687 public function get flags():uint { return _flags; }
688 public function get name():String { return _name; }
689 public function get numRegister():uint { return _numRegister; }
690
691 // ======================================================================
692 // Constructor
693 // ----------------------------------------------------------------------
694 public function OpCode( name:String, numRegister:uint, emitCode:uint, flags:uint)
695 {
696 _name = name;
697 _numRegister = numRegister;
698 _emitCode = emitCode;
699 _flags = flags;
700 }
701
702 // ======================================================================
703 // Methods
704 // ----------------------------------------------------------------------
705 public function toString():String
706 {
707 return "[OpCode name=\""+_name+"\", numRegister="+_numRegister+", emitCode="+_emitCode+", flags="+_flags+"]";
708 }
709 }
710
711 // ===========================================================================
712 // Class
713 // ---------------------------------------------------------------------------
714 class Register
715 {
716 // ======================================================================
717 // Properties
718 // ----------------------------------------------------------------------
719 private var _emitCode:uint;
720 private var _name:String;
721 private var _longName:String;
722 private var _flags:uint;
723 private var _range:uint;
724
725 // ======================================================================
726 // Getters
727 // ----------------------------------------------------------------------
728 public function get emitCode():uint { return _emitCode; }
729 public function get longName():String { return _longName; }
730 public function get name():String { return _name; }
731 public function get flags():uint { return _flags; }
732 public function get range():uint { return _range; }
733
734 // ======================================================================
735 // Constructor
736 // ----------------------------------------------------------------------
737 public function Register( name:String, longName:String, emitCode:uint, range:uint, flags:uint)
738 {
739 _name = name;
740 _longName = longName;
741 _emitCode = emitCode;
742 _range = range;
743 _flags = flags;
744 }
745
746 // ======================================================================
747 // Methods
748 // ----------------------------------------------------------------------
749 public function toString():String
750 {
751 return "[Register name=\""+_name+"\", longName=\""+_longName+"\", emitCode="+_emitCode+", range="+_range+", flags="+ _flags+"]";
752 }
753 }
754
755 // ===========================================================================
756 // Class
757 // ---------------------------------------------------------------------------
758 class Sampler
759 {
760 // ======================================================================
761 // Properties
762 // ----------------------------------------------------------------------
763 private var _flag:uint;
764 private var _mask:uint;
765 private var _name:String;
766
767 // ======================================================================
768 // Getters
769 // ----------------------------------------------------------------------
770 public function get flag():uint { return _flag; }
771 public function get mask():uint { return _mask; }
772 public function get name():String { return _name; }
773
774 // ======================================================================
775 // Constructor
776 // ----------------------------------------------------------------------
777 public function Sampler( name:String, flag:uint, mask:uint )
778 {
779 _name = name;
780 _flag = flag;
781 _mask = mask;
782 }
783
784 // ======================================================================
785 // Methods
786 // ----------------------------------------------------------------------
787 public function toString():String
788 {
789 return "[Sampler name=\""+_name+"\", flag=\""+_flag+"\", mask="+mask+"]";
790 }
791 }
792}