/// <summary> /// Return the operation(s) to perform at the beginning or end of a /// scan line, given a dest and source word. /// </summary> private EdgeStrategy GetEdgeStrategy(CombinerFlags dstMask, CombinerFlags srcMask) { int lookup = (((int)_direction << 6) | (((int)dstMask & 0x6) << 3) | // XXX (((int)srcMask & 0x6) << 1) | // XXX ((_leftOver ? 1 : 0) << 1) | ((_extraSrcWord && _xOffset > 0) ? 1 : 0)); EdgeStrategy result = _rscTable[lookup]; #if TRACING_ENABLED if (Trace.TraceOn) { Trace.Log(LogType.RasterOp, "RasterOp: EdgeStrategy lookup {0:x3} --> {1}", lookup, result); } #endif #if DEBUG // Draw attention for debugging; should throw an exception in release version... if (result == EdgeStrategy.Unknown) { Console.WriteLine("==> Unknown edge strategy {0:x3}! <==", lookup); } #endif return(result); }
private RasterOp() { _ropShifter = new Shifter(); // Our own private Idaho _srcFifo = new Queue <ROpWord>(16); // 4 quads (hardware limit) _destFifo = new Queue <ROpWord>(4); // 1 quad _halfPipe = new ROpWord(); // 1 word, for overlap _rdsTable = new CombinerFlags[512]; // 9 bit index _rscTable = new EdgeStrategy[128]; // 7 bit index LoadRasterOpROMs(); }
/// <summary> /// </summary> /// <param name="browser"></param> /// <exception cref="System.NotImplementedException" /> /// <exception cref="System.ArgumentOutOfRangeException" /> /// <returns> /// </returns> public static IWebDriver Init(SupportedBrowsers.Browser browser) { Logger.Debug($"Attempting to start browser: {browser}"); IBrowserStrategy browserStrategy; switch (browser) { case SupportedBrowsers.Browser.Firefox: browserStrategy = new FirefoxStrategy(); break; case SupportedBrowsers.Browser.Chrome: browserStrategy = new ChromeStrategy(); break; case SupportedBrowsers.Browser.Iexplore: browserStrategy = new InternetExplorerStrategy(); break; case SupportedBrowsers.Browser.Phantomjs: browserStrategy = new PhantomjsStrategy(); break; case SupportedBrowsers.Browser.Chromeemulation: browserStrategy = new ChromeEmulationStrategy(); break; case SupportedBrowsers.Browser.Edge: browserStrategy = new EdgeStrategy(); break; case SupportedBrowsers.Browser.Opera: case SupportedBrowsers.Browser.Safari: throw new NotImplementedException(); default: throw new ArgumentOutOfRangeException(nameof(browser), browser, null); } var webDriver = string.IsNullOrWhiteSpace(DriverProvider.Grid) ? browserStrategy.GetDriver() : new RemoteWebDriver(new Uri(DriverProvider.Grid), browserStrategy.GetOptions()); Logger.Debug($"Started browser: {browser}"); return(webDriver); }
/// <summary> /// Aligns and combines the Source and Destination words to produce a RasterOp /// result word. Called during DestFetch as each word arrives to avoid /// complications from the delay in the overlapped Fetch/Store cycle. /// </summary> private ROpWord ComputeResult(ROpWord dest) { ROpWord src = dest; // init to silence the Xamarin compiler... EdgeStrategy e = EdgeStrategy.NoPopNoPeek; // assume nothing! n/a in non-edge cases anyway ushort aligned, combined; #if TRACING_ENABLED if (Trace.TraceOn) { Trace.Log(LogType.RasterOp, "RasterOp: Result dest word: {0}", dest); } #endif #region Align Words // The Emperor has made a critical error, and the time for our word // alignment has come. Admiral Ackbar will explain the plan of attack: // // 1. At the start of a scanline, our source FIFO is aligned and the // half-pipeline register is "primed". This means we should be // guaranteed to have at least the first edge word in the FIFO; // 2. If the source spans the quad but the destination doesn't (or // vice versa), we have to account for the "two edges into one" // problem - pull in the extra source word (source L+R -> dest B) // or hold the source word one extra cycle (dest L+R <- source B); // 3. In all other modes, we should be able to just pop the next word // so the FIFOs move in lock step (while in the source region), he // said, handwaving furiously. // // The RSC03 ROM tells the hardware how to cope with the source FIFO; here // we use a lookup table to deal with all the complicated edge alignment // rules outlined above. // // Many Bothans died to bring us this information... // Look at the destination word to find our edges and set the _leftOver flag switch (dest.Mask) { // Outside the first edge: return dest unmodified, don't touch the source FIFO case CombinerFlags.DontMask: return(dest); // Outside the second edge: return dest unmodified, but pop the source word too. // In some cases we do legitimately clear the last source word, so test for that. case CombinerFlags.Leftover: if (_srcFifo.Count > 0) { src = _srcFifo.Dequeue(); #if DEBUG src.Mask = SrcWordMask(src.Index); // for debugging, not necessary otherwise #endif #if TRACING_ENABLED if (Trace.TraceOn) { Trace.Log(LogType.RasterOp, "RasterOp: Dropped src word: {0}", src); } #endif } return(dest); // Full word (any phase): should always have a matching source word case CombinerFlags.FullWord: try { src = _srcFifo.Dequeue(); #if DEBUG src.Mask = SrcWordMask(src.Index); // for debugging, not necessary otherwise #endif } catch (InvalidOperationException) { #if DEBUG Console.WriteLine("Source FIFO empty at Full word!"); // continuing will probably fail... #else throw new InvalidOperationException("Source FIFO empty and Result expected"); #endif } break; // Left edge: flag the beginning or end of the update region // Right edge: opposite of left, flag the other end :-) case CombinerFlags.LeftEdge: case CombinerFlags.RightEdge: _leftOver = (dest.Mask == CombinerFlags.LeftEdge && _direction == Direction.RightToLeft) || (dest.Mask == CombinerFlags.RightEdge && _direction == Direction.LeftToRight); if (_srcFifo.Count > 0) { src = _srcFifo.Peek(); src.Mask = SrcWordMask(src.Index); e = GetEdgeStrategy(dest.Mask, src.Mask); } else if (_leftOver && (_extraSrcWord || _xOffset > 0)) { // At the end of a line (either direction) we are peeking forward // but have run out of source words. In this case we copy the half- // pipeline register (in essence, not popping the second edge word) // to provide enough bits to complete the line. src = _halfPipe; } else { #if DEBUG Console.WriteLine("Source FIFO empty at {0} word!", dest.Mask); // continuing will probably fail... #else throw new InvalidOperationException("Source FIFO empty and Result expected"); #endif } break; // Both edges in one word case CombinerFlags.Both: _leftOver = true; // But... but... it's false too! Ow, my head. try { src = _srcFifo.Peek(); src.Mask = SrcWordMask(src.Index); e = GetEdgeStrategy(dest.Mask, src.Mask); } catch (InvalidOperationException) { #if DEBUG Console.WriteLine("Source FIFO empty at Both edges word!"); // continuing will probably fail.. #else throw new InvalidOperationException("Source FIFO empty and Result expected"); #endif } break; // Should never happen if our RDS00 ROM table is correct! case CombinerFlags.Invalid: throw new InvalidOperationException("RasterOp Destination result word has Invalid mask"); } // Pop the current word? if (e == EdgeStrategy.PopPeek || e == EdgeStrategy.PopNoPeek) { _srcFifo.Dequeue(); // Mask was already set } // Peek ahead to the next? if (e == EdgeStrategy.PopPeek || e == EdgeStrategy.NoPopPeek) { src = _srcFifo.Dequeue(); src.Mask = SrcWordMask(src.Index); } #if TRACING_ENABLED if (Trace.TraceOn) { Trace.Log(LogType.RasterOp, "RasterOp: Next source word: {0}", src); } #endif #endregion #region Align Bits // The destination word is in the update region and our source word is aligned. // If bit alignment is needed, feed the saved word from the half pipe to the // shifter with the current word. Note that the MSB of the combined shifter // inputs is always the leftmost pixel in the update region (so, dependent upon // the direction of transfer). if (_xOffset != 0) { if (_direction == Direction.LeftToRight) { #if TRACING_ENABLED if (Trace.TraceOn) { Trace.Log(LogType.RasterOp, "RasterOp: Result xtra (hi): {0:x4}", _halfPipe); } #endif _ropShifter.Shift(src.Data, _halfPipe.Data); } else { #if TRACING_ENABLED if (Trace.TraceOn) { Trace.Log(LogType.RasterOp, "RasterOp: Result xtra (lo): {0:x4}", _halfPipe); } #endif _ropShifter.Shift(_halfPipe.Data, src.Data); } // Save the current source word _halfPipe = src; // Grab the aligned source word from the shifter aligned = _ropShifter.ShifterOutput; } else { // Already in alignment aligned = src.Data; } #if TRACING_ENABLED if (Trace.TraceOn) { Trace.Log(LogType.RasterOp, "RasterOp: Result aligned: {0:x4}", aligned); } #endif #endregion #region Combine 'em // Finally! Combine source & dest words using the appropriate mask switch (dest.Mask) { case CombinerFlags.LeftEdge: combined = Combine(dest.Data, aligned, _leftEdgeMask); break; case CombinerFlags.RightEdge: combined = Combine(dest.Data, aligned, _rightEdgeMask); break; case CombinerFlags.Both: combined = Combine(dest.Data, aligned, _bothEdgesMask); break; case CombinerFlags.FullWord: combined = Combine(dest.Data, aligned, 0xffff); break; default: combined = dest.Data; // This can't actually happen (silence a warning) break; } #if TRACING_ENABLED if (Trace.TraceOn) { Trace.Log(LogType.RasterOp, "RasterOp: Result combined: {0:x4} (func={1})", combined, _function); } #endif #endregion // For debugging, we return the ROpWord, updated with the combined result. // At some point when this is fully debugged, the dest FIFO could be a // simple queue of ushorts, which could improve efficiency. dest.Data = combined; return(dest); }