/// <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; }