/// <summary>
        /// Method to send nested frames
        /// </summary>
        /// <param name="surf">The surface that the frames belong to</param>
        /// <param name="colors">The color to fill the surface</param>
        /// <param name="rects">The rectangles to be filled in the surface</param>
        public void SendNestedFrames(Surface surf, RDPGFX_COLOR32[] colors, RDPGFX_RECT16[] rects)
        {
            uint fid1 = MakeStartFramePdu();
            uint fid2 = MakeStartFramePdu();
            MakeSolidFillPdu(surf.Id, colors[0], new RDPGFX_RECT16[] { rects[0] });
            MakeSolidFillPdu(surf.Id, colors[1], new RDPGFX_RECT16[] { rects[1] });
            MakeEndFramePdu(fid2);
            MakeEndFramePdu(fid1);

            PackAndSendServerPdu();
            //ExpectFrameAck(fid2);
            //ExpectFrameAck(fid1);
        }
        /// <summary>
        /// Encode bitmap data by RFX Progressive codec (one tile in one rfx_progressive_datablock frame).
        /// </summary>
        /// <param name="image"> The bitmap image to be sent </param>
        /// <param name="surf"> The surface that bitmap image is sent to </param>
        /// <param name="pixFormat">The pixel format to draw surface.</param>
        /// <param name="hasSync">Indicates if sync block exists in FRX Progressive bitmap stream.</param>
        /// <param name="hasContext">Indicates if context block exists in FRX Progressive bitmap stream.</param>
        /// <param name="quality">The target encoded quality.</param>
        /// <param name="bProg">Indicates if encode progressively</param>
        /// <param name="bSubDiff">Indicates if sub-diffing with last frame of this surface</param>
        /// <param name="bReduceExtrapolate">Indicates if use Reduce Extrapolate method in DWT step.</param>
        /// <returns> A list of layer byte stream, each layer is built by a dictionary with frameId and byte stream frame pair </returns>
        public List<Dictionary<uint, byte[]>> RfxProgressiveCodecEncode(Surface surf, Image image, PixelFormat pixFormat, bool hasSync, bool hasContext,                                                  
            ImageQuality_Values quality, bool bProg, bool bSubDiff, bool bReduceExtrapolate)
        {
            bool multipleTileInRegion = true;
            List<Dictionary<TileIndex, EncodedTile>> layerTileList = new List<Dictionary<TileIndex,EncodedTile>>();

            if (image == null)  return null;

            uint fid = 0;
            List<Dictionary<uint, byte[]>> layerDataList = new List<Dictionary<uint, byte[]>>();  // To save different layer data encoded by RFX Prog Codec.
            RdpegfxRfxProgCodecBlockManagerDecorator blockMngr = new RdpegfxRfxProgCodecBlockManagerDecorator(currentTestType);

            surf.UpdateFromBitmap((System.Drawing.Bitmap)image);
            Dictionary<TileIndex, EncodedTile[]> tileDict = surf.ProgressiveEncode(quality, bProg, bSubDiff, bReduceExtrapolate, false);
            if(multipleTileInRegion)
            {
                layerTileList = ConvertTileDictToLayer(tileDict);
            }

            if (this.bcgrAdapter.SimulatedScreen != null)
            {
                this.bcgrAdapter.SimulatedScreen.RenderProgressiveCodec(surf.Id, tileDict, (ushort)image.Width, (ushort)image.Height);
            }

            if (bProg)  // Progressive codec is enabled
            {

                for (int i = 0; i < layerTileList.Count; i++)
                {
                    Dictionary<uint, byte[]> tileFrameDict = new Dictionary<uint, byte[]>();

                    fid = MakeStartFramePdu();
                    RFXProgCodecBlockType blockType = i == 0 ? RFXProgCodecBlockType.WBT_TILE_PROGRESSIVE_FIRST : RFXProgCodecBlockType.WBT_TILE_PROGRESSIVE_UPGRADE;
                    byte[] tileUpgradeData = blockMngr.PackRfxProgCodecDataBlock(hasSync, hasContext, bSubDiff, bReduceExtrapolate, layerTileList[i], blockType);
                    MakeWireToSurfacePdu2(surf.Id, pixFormat, tileUpgradeData);

                    MakeEndFramePdu(fid);

                    // Save frame into encoded tile first frame Dictionary
                    tileFrameDict.Add(fid, EncodePdusToSent());

                    // Add tile first frames into layer data list
                    layerDataList.Add(tileFrameDict);
                }
            }
            else  // Non-progressive encoding(i.e. tile_simple)
            {

                Dictionary<uint, byte[]> tileSimpleFrameDict = new Dictionary<uint, byte[]>();
                fid = MakeStartFramePdu();

                foreach (Dictionary<TileIndex, EncodedTile> layerTileDict in layerTileList)
                {
                    byte[] tileUpgradeData = blockMngr.PackRfxProgCodecDataBlock(hasSync, hasContext, bSubDiff, bReduceExtrapolate, layerTileDict, RFXProgCodecBlockType.WBT_TILE_SIMPLE);
                    MakeWireToSurfacePdu2(surf.Id, pixFormat, tileUpgradeData);
                }

                MakeEndFramePdu(fid);

                // Save frame into encoded tile simple frame Dictionary
                tileSimpleFrameDict.Add(fid, EncodePdusToSent());

                // Add tile first frames into layer data list
                layerDataList.Add(tileSimpleFrameDict);
            }
            return layerDataList;
        }
        /// <summary>
        /// Send clearcodec encoded glyph in batch (make sure glyphnum + startGlyphRect.right is not bigger than surf.width)
        /// </summary>
        /// <param name="surf">This is used to indicate the target surface id.</param>
        /// <param name="startGlyphIdx">This is used to indicate the start index of graph batch to be put in client graph cache.</param>
        /// <param name="startGlyphPos">The start position of glyph batch, which will be sent in clearcodec, relative to the surface. </param>
        /// <param name="glyphNum"> The glyph number in batch. </param>
        /// <param name="glyph"> The residual layer image to be sent. </param>
        /// <returns> Frame Id </returns>
        public uint SendClearCodecGlyphInBatch(Surface surf, ushort startGlyphIdx, RDPGFX_POINT16 startGlyphPos, ushort glyphNum, Image glyph)
        {
            uint fid = MakeStartFramePdu();

            ushort glyphIdx = startGlyphIdx;
            RDPGFX_RECT16 glyphRect = new RDPGFX_RECT16(startGlyphPos.x, startGlyphPos.y,
                                            (ushort)(startGlyphPos.x + glyph.Width),
                                            (ushort)(startGlyphPos.y + glyph.Height));

            // Pack multiple w2s_1 PDU into a frame.
            for (ushort i = 0; i < glyphNum; i++)
            {
                ClearCodec_BitmapStream ccStream = new ClearCodec_BitmapStream(ClearCodec_BitmapStream.CLEARCODEC_FLAG_GLYPH_INDEX, glyphIdx);
                ccStream.LoadResidualBitmap((Bitmap)glyph);
                ccStream.seqNumber = egfxServer.Get_ClearCodecBitmapStream_SeqNum();
                MakeWireToSurfacePdu1(surf.Id, CodecType.RDPGFX_CODECID_CLEARCODEC, PixelFormat.PIXEL_FORMAT_XRGB_8888,
                                        glyphRect, ccStream.Encode());
                glyphIdx++;
                glyphRect.left++;
                glyphRect.right++;
            }

            MakeEndFramePdu(fid);

            PackAndSendServerPdu();

            if (this.bcgrAdapter.SimulatedScreen != null)
            {
                this.bcgrAdapter.SimulatedScreen.RenderClearCodecBatch(surf.Id, startGlyphIdx, startGlyphPos, glyphNum, glyph);
            }

            return fid;
        }
        /// <summary>
        /// Method to copy bitmap of a rectangle in surface to other position
        /// </summary>
        /// <param name="surf">The source surface where the rectangle to be copied.</param>
        /// <param name="srcRect">The rectangle to be copied.</param>
        /// <param name="destPos">The position array that rectangle is copied to.</param>
        /// <returns> Frame Id </returns>
        public uint IntraSurfaceCopy(Surface surf, RDPGFX_RECT16 srcRect, RDPGFX_POINT16[] destPos)
        {
            uint fid = MakeStartFramePdu();
            MakeSurfaceToSurfacePdu(surf.Id, surf.Id, srcRect, destPos);
            MakeEndFramePdu(fid);

            PackAndSendServerPdu();

            return fid;
        }
        /// <summary>
        /// Method to implement SurfaceToCache functionality
        /// </summary>
        /// <param name="surf">The surface to be filled.</param>
        /// <param name="cacheRect">The rectangle to be cached on the surface.</param>
        /// <param name="cacheKey">The cacheKey of rectangle bitmap data on client.</param>
        /// <param name="cacheSlot">Specify a cacheslot</param>
        /// <param name="fillColor">The color that rectangle to be filled.</param>
        public uint CacheSurface(Surface surf, RDPGFX_RECT16 cacheRect, ulong cacheKey, ushort? cacheSlot, RDPGFX_COLOR32? fillColor = null)
        {
            uint fid = MakeStartFramePdu();

            if (fillColor != null)
            {
                // Send solid fill request to client to fill cacheRect of surface with color.
                RDPGFX_RECT16[] rects = { cacheRect };
                MakeSolidFillPdu(surf.Id, fillColor.Value, rects);
            }

            if (cacheSlot == null)
            {
                cacheSlot = 1;
            }

            if (currentTestType == RdpegfxNegativeTypes.CacheManagement_Default_ExceedMaxCacheSlot)
            {
                // 25600 is the max cache slots number for default cache size.
                for (ushort index = 1; index <= 25601; ++index)
                {
                    cacheSlot = index;
                    MakeSurfaceToCachePdu(surf.Id, cacheKey, cacheSlot.Value, cacheRect);
                    if (index % 100 == 0)
                        PackAndSendServerPdu();
                }
            }
            else if (currentTestType == RdpegfxNegativeTypes.CacheManagement_SmallCache_ExceedMaxCacheSlot)
            {
                // 12800 is the max cache slots number for small cache size.
                for (ushort index = 1; index <= 12801; ++index)
                {
                    cacheSlot = index;
                    MakeSurfaceToCachePdu(surf.Id, cacheKey, cacheSlot.Value, cacheRect);
                    if (index % 100 == 0)
                        PackAndSendServerPdu();
                }
            }
            else if (currentTestType == RdpegfxNegativeTypes.CacheManagement_ThinCient_ExceedMaxCacheslot)
            {
                // 4096 is the max cache slots number for thin client cache size.
                for (ushort index = 1; index <= 4097; ++index)
                {
                    cacheSlot = index;
                    MakeSurfaceToCachePdu(surf.Id, cacheKey, cacheSlot.Value, cacheRect);
                    if (index % 100 == 0)
                        PackAndSendServerPdu();
                }
            }
            else if (currentTestType == RdpegfxNegativeTypes.CacheManagement_Default_ExceedMaxCacheSize)
            {
                // Every cache slot has the size of 1MB here,
                // 100MB is the max cache size for default flag, cache 101 MB here which exceeds max cache size.
                for (ushort index = 1; index <= 101; ++index)
                {
                    cacheSlot = index;
                    MakeSurfaceToCachePdu(surf.Id, cacheKey, cacheSlot.Value, cacheRect);
                }
            }
            else if (currentTestType == RdpegfxNegativeTypes.CacheManagement_SmallCache_ExceedMaxCacheSize)
            {
                // Every cache slot has the size of 1MB here,
                // 50MB is the max cache size for SmallCache flag, cache 51 MB here which exceeds max cache size.
                for (ushort index = 1; index <= 51; ++index)
                {
                    cacheSlot = index;
                    MakeSurfaceToCachePdu(surf.Id, cacheKey, cacheSlot.Value, cacheRect);
                }
            }
            else if (currentTestType == RdpegfxNegativeTypes.CacheManagement_ThinClient_ExceedMaxCacheSize)
            {
                // Every cache slot has the size of 1MB here,
                // 16MB is the max cache size for SmallCache flag, cache 17 MB here which exceeds max cache size.
                for (ushort index = 1; index <= 17; ++index)
                {
                    cacheSlot = index;
                    MakeSurfaceToCachePdu(surf.Id, cacheKey, cacheSlot.Value, cacheRect);
                }
            }
            else
            {
                MakeSurfaceToCachePdu(surf.Id, cacheKey, cacheSlot.Value, cacheRect);
            }

            if (currentTestType == RdpegfxNegativeTypes.CacheManagement_Delete_InexistentCacheSlot)
            {
                // Delete an inexistent cache slot.
                MakeEvictCacheEntryPdu(0xfefe);    // 0xfefe is an inexistent cache slot.
            }

            MakeEndFramePdu(fid);
            PackAndSendServerPdu();
            return fid;
        }
        /// <summary>
        /// Method to implement SurfaceToCache and CacheToSurface functionality.
        /// </summary>
        /// <param name="surf">The surface to be filled.</param>
        /// <param name="cacheRect">The rectangle to be cached on the surface.</param>
        /// <param name="cacheKey">The cacheKey of rectangle bitmap data on client.</param>
        /// <param name="destPoints">This is used to specify destination points of source rectangle bitmap to be copied </param>
        /// <param name="cacheSlot">Specify a cacheslot</param>
        /// <param name="fillColor">The color that rectangle to be filled.</param>
        /// <returns> Frame Id </returns>
        public uint FillSurfaceByCachedBitmap(Surface surf, RDPGFX_RECT16 cacheRect, ulong cacheKey, RDPGFX_POINT16[] destPoints, ushort? cacheSlot, RDPGFX_COLOR32? fillColor = null)
        {
            uint fid = MakeStartFramePdu();

            if (fillColor != null)
            {
                // Send solid fill request to client to fill cacheRect of surface with color
                RDPGFX_RECT16[] rects = { cacheRect };
                MakeSolidFillPdu(surf.Id, fillColor.Value, rects);
            }

            // Copy a rectangle bitmap data to cache and move it from cache to other positions of surface.
            if (cacheSlot == null)
            {
                cacheSlot = 1;  //set slot# to 1
            }
            MakeSurfaceToCachePdu(surf.Id, cacheKey, cacheSlot.Value, cacheRect);

            if (currentTestType == RdpegfxNegativeTypes.CacheManagement_CacheToSurface_InexistentCacheSlot)
            {
                cacheSlot = (ushort)(cacheSlot.Value + 1);
            }
            ushort sid = surf.Id;
            if (currentTestType == RdpegfxNegativeTypes.CacheManagement_CacheToSurface_InexistentSurface)
            {
                sid++;
            }
            MakeCacheToSurfacePdu(cacheSlot.Value, sid, destPoints);

            MakeEndFramePdu(fid);

            PackAndSendServerPdu();
            return fid;
        }
        /// <summary>
        /// Method to copy bitmap of a rectangle in a surface to other position in another surface
        /// </summary>
        /// <param name="surf">The source surface where the rectangle to be copied.</param>
        /// <param name="srcRect">The rectangle to be copied.</param>
        /// <param name="fillColor">The color of rectangle to be filled.</param>
        /// <param name="surfDest">The destination surface where the rectangle is copied to.</param>
        /// <param name="destPos">The position array that rectangle is copied to.</param>
        /// <returns> Frame Id </returns>
        public uint InterSurfaceCopy(Surface surfSrc, RDPGFX_RECT16 srcRect, RDPGFX_COLOR32 fillColor, Surface surfDest, RDPGFX_POINT16[] destPos)
        {
            uint fid = MakeStartFramePdu();
            RDPGFX_RECT16[] rects = { srcRect };
            MakeSolidFillPdu(surfSrc.Id, fillColor, rects);
            MakeSurfaceToSurfacePdu(surfSrc.Id, surfDest.Id, srcRect, destPos);
            if (currentTestType != RdpegfxNegativeTypes.SurfaceManagement_InterSurfaceCopy_DestPtsCount_Mismatch)
            {
                MakeEndFramePdu(fid);
            }

            PackAndSendServerPdu();

            return fid;
        }
        /// <summary>
        /// Method to solidfill a surface with color
        /// </summary>
        /// <param name="surf">The surface to be filled.</param>
        /// <param name="color">The color to fill the surface.</param>
        /// <param name="rects">The rectangles to be filled in the surface.</param>
        /// <param name="frameId">Specify the frame Id.</param>
        /// <returns> Frame Id </returns>
        public uint SolidFillSurface(Surface surf, RDPGFX_COLOR32 color, RDPGFX_RECT16[] rects, uint? frameId = null)
        {
            uint fid = MakeStartFramePdu(frameId);
            MakeSolidFillPdu(surf.Id, color, rects);
            MakeEndFramePdu(fid);

            PackAndSendServerPdu();
            return fid;
        }
        /// <summary>
        /// Method to implement CacheToSurface functionality.
        /// </summary>
        /// <param name="surf">The surface to be filled.</param>
        /// <param name="cacheSlot">Cache slot of bitmap</param>
        /// <param name="destPoints">This is used to specify destination points of source rectangle bitmap to be copied</param>
        /// <returns>Frame Id</returns>
        public uint FillSurfaceByCachedBitmap(Surface surf, ushort cacheSlot, RDPGFX_POINT16[] destPoints)
        {
            uint fid = MakeStartFramePdu();
            MakeCacheToSurfacePdu(cacheSlot, surf.Id, destPoints);

            MakeEndFramePdu(fid);

            PackAndSendServerPdu();
            return fid;
        }
        public void RDPEGFX_SurfaceToScreen_PositiveTest_MultiSurfaceOverlap()
        {
            uint fid;

            this.TestSite.Log.Add(LogEntryKind.Comment, "Do capability exchange.");
            // Init for capability exchange
            RDPEGFX_CapabilityExchange();

            RDPGFX_RECT16 verifyRect = RdpegfxTestUtility.ConvertToRect(RdpegfxTestUtility.surfPos, RdpegfxTestUtility.surfWidth, RdpegfxTestUtility.surfHeight);

            // Init Data for test
            RDPGFX_POINT16[] positions = new RDPGFX_POINT16[4];
            positions[0] = new RDPGFX_POINT16(RdpegfxTestUtility.surfPos.x, RdpegfxTestUtility.surfPos.y);
            positions[1] = new RDPGFX_POINT16((ushort)(RdpegfxTestUtility.surfPos.x + RdpegfxTestUtility.surfWidth/2), RdpegfxTestUtility.surfPos.y);
            positions[2] = new RDPGFX_POINT16(RdpegfxTestUtility.surfPos.x, (ushort)(RdpegfxTestUtility.surfPos.y + RdpegfxTestUtility.surfHeight / 2));
            positions[3] = new RDPGFX_POINT16(RdpegfxTestUtility.surfPos.x, RdpegfxTestUtility.surfPos.y);

            ushort[] widths = new ushort[4];
            widths[0] = RdpegfxTestUtility.surfWidth;
            widths[1] = (ushort)(RdpegfxTestUtility.surfWidth / 2);
            widths[2] = RdpegfxTestUtility.surfWidth;
            widths[3] = (ushort)(RdpegfxTestUtility.surfWidth / 2);

            ushort[] heights = new ushort[4];
            heights[0] = (ushort)(RdpegfxTestUtility.surfHeight / 2);
            heights[1] = RdpegfxTestUtility.surfHeight;
            heights[2] = (ushort)(RdpegfxTestUtility.surfHeight / 2);
            heights[3] = RdpegfxTestUtility.surfHeight;

            Color[] colors = new Color[4];
            colors[0] = Color.Green;
            colors[1] = Color.Blue;
            colors[2] = Color.Red;
            colors[3] = Color.Yellow;

            Surface[] surfaces = new Surface[4];
            // Test the overlap
            for (int i = 0; i < positions.Length; i++)
            {
                this.TestSite.Log.Add(LogEntryKind.Comment, "Create a surface and fill it with color: {0}.", colors[i]);
                // Create & output a surface
                RDPGFX_RECT16 surfRect = RdpegfxTestUtility.ConvertToRect(positions[i], widths[i], heights[i]);
                surfaces[i] = this.rdpegfxAdapter.CreateAndOutputSurface(surfRect, PixelFormat.PIXEL_FORMAT_XRGB_8888);
                this.TestSite.Assert.IsNotNull(surfaces[i], "Surface {0} is created", surfaces[i].Id);

                // Send solid fill request to client to fill surface with green color
                RDPGFX_RECT16 fillSurfRect = RdpegfxTestUtility.ConvertToRect(RdpegfxTestUtility.imgPos, widths[i], heights[i]);
                RDPGFX_RECT16[] fillRects = { fillSurfRect };  // Relative to surface
                fid = this.rdpegfxAdapter.SolidFillSurface(surfaces[i], RdpegfxTestUtility.ToRdpgfx_Color32(colors[i]), fillRects);
                this.TestSite.Log.Add(LogEntryKind.Debug, "Surface is filled with solid color in frame: {0}", fid);

                // Expect the client to send a frame acknowledge pdu
                // If the server receives the message, it indicates that the client has been successfully decoded the logical frame of graphics commands
                this.rdpegfxAdapter.ExpectFrameAck(fid);

                this.TestSite.Log.Add(LogEntryKind.Comment, "Verify output on SUT Display if the verifySUTDisplay entry in PTF config is true.");
                this.VerifySUTDisplay(false, verifyRect);
            }
            // Delete the surface
            for (int i = 0; i < surfaces.Length; i++)
            {
                if (surfaces[i] != null)
                {
                    this.rdpegfxAdapter.DeleteSurface(surfaces[i].Id);
                    this.TestSite.Log.Add(LogEntryKind.Debug, "Surface {0} is deleted", surfaces[i].Id);
                }
            }
        }
        Dictionary<ushort, Surface> surfList = new Dictionary<ushort, Surface>(); // surfList includes the previous and current surfaces for RFX progressive encoding

        #endregion Fields

        #region Methods

        /// <summary>
        /// Create a new surface
        /// </summary>
        /// <param name="w">Width</param>
        /// <param name="h">Heigth</param>
        /// <param name="surfaceId">Specify the surface ID, if this value is null, the method will use a self-generated ID</param>
        /// <returns></returns>
        public Surface CreateSurface(ushort w, ushort h, ushort? surfaceId = null)
        {
            if (surfList.Count >= 0xff)  // too much surface is created!
            {
                return null;
            }

            if (surfaceId == null)
            {
                surfaceId = maxId;
                maxId++;
                while (surfList.ContainsKey(maxId))
                {
                    maxId++;
                }
            }
            Surface newSuf = new Surface(surfaceId.Value, w, h);
            surfList.Add(newSuf.Id, newSuf);

            return newSuf;
        }
 /// <summary>
 /// Create a Surface
 /// </summary>
 /// <param name="surfaceId"></param>
 /// <param name="width"></param>
 /// <param name="height"></param>
 public void CreateSurface(ushort surfaceId, ushort width, ushort height, PixelFormat pixelFormat = PixelFormat.PIXEL_FORMAT_XRGB_8888)
 {
     Surface sur = new Surface(this, surfaceId, width, height, pixelFormat);
     this.surfaceDic.Add(surfaceId, sur);
 }
        /// <summary>
        /// Draw an image for surface, which has a bitmap in surface.
        /// </summary>
        /// <param name="surf"> Indicate the size of surface image </param>
        /// <param name="bgcolor"> Indicate the background color of surface image </param>
        /// <param name="pic"> The bitmap to be drawn in surface image </param>
        /// <param name="picPos"> The bitmap position in surface </param>
        /// <returns> A surface image </returns>
        public static Bitmap DrawSurfImage(Surface surf, Color bgcolor, Bitmap pic, RDPGFX_POINT16 picPos)
        {
            Bitmap bitmap = new Bitmap(surf.Width, surf.Height);
            Graphics g = Graphics.FromImage(bitmap);
            SolidBrush pixelBrush = new SolidBrush(bgcolor);
            g.FillRectangle(pixelBrush, 0, 0, surf.Width, surf.Height);
            for (int x = picPos.x; (x < surf.Width) && (x < (picPos.x + pic.Width)); x++)
            {
                for (int y = picPos.y; (y < surf.Height) && (y < (picPos.y + pic.Height)); y++)
                {
                    Color c = pic.GetPixel(x - picPos.x, y - picPos.y);
                    bitmap.SetPixel(x, y, c);
                }
            }

            return bitmap;
        }
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="surface">The surface contains this tile</param>
 /// <param name="index">The index of this tile in surface</param>
 public TileState(Surface surface, TileIndex index)
 {
     NewFrame = surface.CurrentFrame;
     LastFrame = surface.LastFrame;
     Index = index;
 }