ESCAPE_COPY_2BMP Code Example (Compact 7)

3/12/2014

The ESCAPE_COPY_2BMP sequence is sent by the RDC client immediately after the ESCAPE_DEC3 sequence to copy dirty rectangles from the decoder surface to the shadow bitmap. A dirty rectangle is a list of changed rectangles on the screen. A shadow bitmap is a device-compatible bitmap that is created by the display driver during the initialization of the RemoteFX component. The shadow surface represents the video memory that belongs to the full physical screen and can be used as an off-screen buffer to update the primary display surface. Calling the ESCAPE_COPY_2BMP invokes the RDC client to blit the dirty rectangles to the correct location in a temporary frame buffer and then to blit all the updated rectangles to an output frame buffer.

The ESCAPE_COPY_2BMP call relies on the process of transferring the bitmaps, first to an off-screen graphical frame buffer (or surface), before they are rendered on the screen by the RDC client. The RDC client is responsible for copying the contents of the shadow bitmap to the destination (video memory). To achieve optimal performance from RemoteFX, we recommend that your display driver supports video memory and hardware-accelerated blitting operations, which are considerably faster than software.

If you do not implement hardware-accelerated graphics, Compact 7 uses the GDI to draw UI objects pixel-by-pixel onto the primary display surface, performing all the operations in software and resulting in reduced performance on the device.

The following code example shows the structure declaration that is required for this escape function.

Important

For readability, the following code examples do not contain security or error handling. Do not use the following code examples in a production environment.

typedef struct RECT { 
    LONG left; 
    LONG top; 
    LONG right; 
    LONG bottom; 
};
struct copy_rectangle_2bmp
{
    ULONG  transX;
    ULONG  transY;
    ULONG  rect_count;
    RECT*  rects;
};

struct esc_copy_rectangle_2bmp_in 
{
    struct _hdr hdr;
    struct copy_rectangle_2bmp copy2bmp;
    HBITMAP hbitmap;
};

The following code example shows how the ESCAPE_COPY_2BMP sequence is implemented in the display driver. The esc_copy_2bmp function validates the escape parameters and escape header that are received from the RDC client to ensure that the input buffer is from a trusted source.

BOOL esc_copy_2bmp(
              SURFOBJ*    pso,
              ULONG       iEsc,
              ULONG       cjIn,
              PVOID       pvIn
              )
{
    struct esc_copy_rectangle_2bmp_in*     p_in        = NULL;
    BOOL    status                                     = FALSE;
    do {
        if (
            (!pvIn)
            ||
            (cjIn != sizeof(*p_in)))
        {
            break;
        }
        p_in = (struct esc_copy_rectangle_2bmp_in*)pvIn;

        if (
            (p_in->hdr.code  != iEsc)
            ||
            (p_in->hdr.magic != ESCAPE_MAGIN_IN)
            ||
            (p_in->hdr.size != sizeof(*p_in)))
        {
            break;
        }
        HBITMAP hBitmap = p_in->hbitmap;
        // TO DO: The SetBitmapBits API is provided just for reference here. The 
        // display driver should implement the functionality to map the hbitmap
        // to the surface created by the display driver. Use the bitmap handle 
        // to move decoded data from the decode buffer to the shadow surface.   
        SetBitmapBits(hBitmap,_OutBuf.size,_OutBuf.buffer);           
        status = TRUE;
    } while (0);
    return status;
}

The RDC client uses the ESCAPE_COPY_2BMP escape sequence to move decoded data from the decode buffer to the shadow surface. Hardware acceleration is recommended in transferring the decoded bitmap to the shadow surface. The RDC client is responsible for presenting the shadow bitmap content into the primary display surface.

The SetBitmapBits function is a high-level API that is used in the preceding code example to move the bits from the decode buffer to the shadow surface. The display driver implements the functionality to map the hbitmap to the surface that is created by the display driver. The bitmap handle is used to move decoded data from the decode buffer to the shadow surface. We recommend that the display driver also implements hardware-accelerated BitBlt to transfer the shadow bitmap to the primary display surface.

The RD Virtualization Host and RD Session Host send different types of rectangle coordinates to the device running Compact 7 in the RemoteFX-encoded data stream. In the case of the RD Virtualization Host, each decode call on the RDC client provides the driver with the list of all dirty rectangles and the exact rectangle coordinates of the rectangles. These coordinates (for example, 240, 320, 264, or 356), are used to determine where the bitmap needs to be placed on the screen.

In the case of the RD Session Host, each decode call provides only one dirty rectangle with coordinates starting from (0,0). These coordinates effectively describe the size of the bitmap that needs to be updated on the screen. To correctly place the bitmap on the screen, a destination rectangle is required to calculate the dirty region. This information is sent to the display driver in the transX and transY members of the copy_rectangle_2bmp structure. If the display driver implements the ESCAPE_COPY_2BMP sequence, the bitmap is placed on the screen by using the transX and transY coordinates together with rect_count and rects information.

Note

The previous sample display driver does not calculate the dirty region because the SetBitmapBits function does not need that information when the device is connected to the RD Virtualization Host. You may need to add additional functionality to meet the requirements of your specific device.

See Also

Concepts

Implement a RemoteFX Display Driver