wfreerdp-server: win8 dxgi initial support

This commit is contained in:
Corey C 2012-09-16 17:38:33 -04:00
parent a32636b877
commit 2a07ebec23
6 changed files with 252 additions and 26 deletions

View File

@ -26,6 +26,8 @@ add_executable(wfreerdp-server
wf_peer.h
wf_info.c
wf_info.h
wf_dxgi.c
wf_dxgi.h
wfreerdp.c
wfreerdp.h)
@ -42,6 +44,12 @@ else()
freerdp-codec
freerdp-channels)
freerdp-channels
d3d11.lib
dxgi.lib
dxguid.lib)
endif()

View File

@ -124,6 +124,28 @@ wfInfo* wf_info_get_instance()
return wfInfoInstance;
}
void wf_info_get_screen_info(wfInfo* wfi)
{
HDC dc;
int currentScreenBPP;
int currentScreenPixHeight;
int currentScreenPixWidth;
/*
* Will have to come back to this for supporting non primary displays and multimonitor setups
*/
dc = GetDC(NULL);
currentScreenPixHeight = GetDeviceCaps(dc, VERTRES);
currentScreenPixWidth = GetDeviceCaps(dc, HORZRES);
currentScreenBPP = GetDeviceCaps(dc, BITSPIXEL);
ReleaseDC(NULL, dc);
wfi->height = currentScreenPixHeight;
wfi->width = currentScreenPixWidth;
wfi->bitsPerPix = currentScreenBPP;
_tprintf(_T("Detected current screen settings: %dx%dx%d\n"), wfi->height, wfi->width, wfi->bitsPerPix);
}
void wf_info_mirror_init(wfInfo* wfi, wfPeerContext* context)
{
if (wf_info_lock(wfi) > 0)

View File

@ -20,11 +20,24 @@
#ifndef WF_INFO_H
#define WF_INFO_H
#define CINTERFACE
#include <D3D11.h>
#include <dxgi1_2.h>
#include <freerdp/codec/rfx.h>
struct wf_peer_context;
typedef struct wf_peer_context wfPeerContext;
struct wf_dxgi_info
{
ID3D11Device* Device;
ID3D11DeviceContext* DeviceContext;
IDXGIOutputDuplication* DeskDupl;
ID3D11Texture2D* AcquiredDesktopImage;
};
typedef struct wf_dxgi_info wfDxgiInfo;
struct wf_info
{
STREAM* s;
@ -46,6 +59,8 @@ struct wf_info
RFX_CONTEXT* rfx_context;
unsigned long lastUpdate;
unsigned long nextUpdate;
wfDxgiInfo dxgi;
};
typedef struct wf_info wfInfo;
@ -53,6 +68,8 @@ int wf_info_lock(wfInfo* wfi);
int wf_info_try_lock(wfInfo* wfi, DWORD dwMilliseconds);
int wf_info_unlock(wfInfo* wfi);
void wf_info_get_screen_info(wfInfo* wfi);
wfInfo* wf_info_get_instance();
void wf_info_mirror_init(wfInfo* wfi, wfPeerContext* context);
void wf_info_subscriber_release(wfInfo* wfi, wfPeerContext* context);

View File

@ -172,39 +172,22 @@ void wf_disp_change_print_status(LONG status)
BOOL wf_update_mirror_drv(wfInfo* context, int unload)
{
HDC dc;
BOOL status;
DWORD* extHdr;
WORD drvExtraSaved;
DEVMODE* deviceMode;
int currentScreenBPP;
int currentScreenPixHeight;
int currentScreenPixWidth;
LONG disp_change_status;
DWORD dmf_devmodewext_magic_sig = 0xDF20C0DE;
if (!unload)
{
/*
* Will have to come back to this for supporting non primary displays and multimonitor setups
*/
dc = GetDC(NULL);
currentScreenPixHeight = GetDeviceCaps(dc, VERTRES);
currentScreenPixWidth = GetDeviceCaps(dc, HORZRES);
currentScreenBPP = GetDeviceCaps(dc, BITSPIXEL);
ReleaseDC(NULL, dc);
context->height = currentScreenPixHeight;
context->width = currentScreenPixWidth;
context->bitsPerPix = currentScreenBPP;
_tprintf(_T("Detected current screen settings: %dx%dx%d\n"), currentScreenPixHeight, currentScreenPixWidth, currentScreenBPP);
wf_info_get_screen_info(context);
}
else
{
currentScreenPixHeight = 0;
currentScreenPixWidth = 0;
currentScreenBPP = 0;
context->height = 0;
context->width = 0;
context->bitsPerPix = 0;
}
deviceMode = (DEVMODE*) malloc(sizeof(DEVMODE) + EXT_DEVMODE_SIZE_MAX);
@ -219,9 +202,9 @@ BOOL wf_update_mirror_drv(wfInfo* context, int unload)
deviceMode->dmSize = sizeof(DEVMODE);
deviceMode->dmDriverExtra = drvExtraSaved;
deviceMode->dmPelsWidth = currentScreenPixWidth;
deviceMode->dmPelsHeight = currentScreenPixHeight;
deviceMode->dmBitsPerPel = currentScreenBPP;
deviceMode->dmPelsWidth = context->height;
deviceMode->dmPelsHeight = context->width;
deviceMode->dmBitsPerPel = context->bitsPerPix;
deviceMode->dmPosition.x = 0;
deviceMode->dmPosition.y = 0;

View File

@ -31,17 +31,22 @@
#include "wf_input.h"
#include "wf_mirage.h"
#include "wf_dxgi.h"
#include "wf_peer.h"
BOOL win8;
void wf_peer_context_new(freerdp_peer* client, wfPeerContext* context)
{
context->info = wf_info_get_instance();
if(win8)
{
wf_info_get_screen_info(context->info);
wf_dxgi_init(context->info);
}
else
{
@ -53,6 +58,7 @@ void wf_peer_context_free(freerdp_peer* client, wfPeerContext* context)
{
if(win8)
{
wf_dxgi_cleanup(context->info);
}
else
{
@ -60,6 +66,7 @@ void wf_peer_context_free(freerdp_peer* client, wfPeerContext* context)
}
}
static DWORD WINAPI wf_peer_mirror_monitor(LPVOID lpParam)
{
DWORD fps;
@ -69,7 +76,7 @@ static DWORD WINAPI wf_peer_mirror_monitor(LPVOID lpParam)
freerdp_peer* client;
wfPeerContext* context;
fps = 24;
fps = 1;
rate = 1000 / fps;
client = (freerdp_peer*) lpParam;
context = (wfPeerContext*) client->context;
@ -87,6 +94,9 @@ static DWORD WINAPI wf_peer_mirror_monitor(LPVOID lpParam)
if (wf_info_have_updates(wfi))
{
//todo: changeme
if(win8)
wf_dxgi_encode(client);
wf_rfx_encode(client);
SetEvent(wfi->updateEvent);
}
@ -111,6 +121,189 @@ static DWORD WINAPI wf_peer_mirror_monitor(LPVOID lpParam)
return 0;
}
void wf_dxgi_encode(freerdp_peer* client)
{
STREAM* s;
wfInfo* wfi;
long offset;
RFX_RECT rect;
long height, width;
rdpUpdate* update;
wfPeerContext* wfp;
GETCHANGESBUF* buf;
SURFACE_BITS_COMMAND* cmd;
///
BYTE* MetaDataBuffer = NULL;
UINT MeinMetaDataSize = 0;
UINT BufSize;
UINT i;
HRESULT hr;
IDXGIResource* DesktopResource = NULL;
DXGI_OUTDUPL_FRAME_INFO FrameInfo;
BYTE* DirtyRects;
UINT dirty;
RECT* pRect;
///
wfp = (wfPeerContext*) client->context;
wfi = wfp->info;
if (client->activated == FALSE)
return;
if (wfp->activated == FALSE)
return;
//wf_info_find_invalid_region(wfi);
_tprintf(_T("\nTrying to acquire a frame...\n"));
hr = wfi->dxgi.DeskDupl->lpVtbl->AcquireNextFrame(wfi->dxgi.DeskDupl, 800, &FrameInfo, &DesktopResource);
_tprintf(_T("hr = %#0X\n"), hr);
if (hr == DXGI_ERROR_WAIT_TIMEOUT)
{
_tprintf(_T("Timeout\n"));
return;
}
if (FAILED(hr))
{
_tprintf(_T("Failed to acquire next frame\n"));
return;
}
_tprintf(_T("Gut!\n"));
///////////////////////////////////////////////
_tprintf(_T("Trying to QI for ID3D11Texture2D...\n"));
hr = DesktopResource->lpVtbl->QueryInterface(DesktopResource, &IID_ID3D11Texture2D, (void**) &wfi->dxgi.AcquiredDesktopImage);
DesktopResource->lpVtbl->Release(DesktopResource);
DesktopResource = NULL;
if (FAILED(hr))
{
_tprintf(_T("Failed to QI for ID3D11Texture2D from acquired IDXGIResource\n"));
return;
}
_tprintf(_T("Gut!\n"));
_tprintf(_T("FrameInfo\n"));
_tprintf(_T("\tAccumulated Frames: %d\n"), FrameInfo.AccumulatedFrames);
_tprintf(_T("\tCoalesced Rectangles: %d\n"), FrameInfo.RectsCoalesced);
_tprintf(_T("\tMetadata buffer size: %d\n"), FrameInfo.TotalMetadataBufferSize);
if(FrameInfo.TotalMetadataBufferSize)
{
if (FrameInfo.TotalMetadataBufferSize > MeinMetaDataSize)
{
if (MetaDataBuffer)
{
free(MetaDataBuffer);
MetaDataBuffer = NULL;
}
MetaDataBuffer = (BYTE*) malloc(FrameInfo.TotalMetadataBufferSize);
if (!MetaDataBuffer)
{
MeinMetaDataSize = 0;
_tprintf(_T("Failed to allocate memory for metadata\n"));
return;
}
MeinMetaDataSize = FrameInfo.TotalMetadataBufferSize;
}
BufSize = FrameInfo.TotalMetadataBufferSize;
// Get move rectangles
hr = wfi->dxgi.DeskDupl->lpVtbl->GetFrameMoveRects(wfi->dxgi.DeskDupl, BufSize, (DXGI_OUTDUPL_MOVE_RECT*) MetaDataBuffer, &BufSize);
if (FAILED(hr))
{
_tprintf(_T("Failed to get frame move rects\n"));
return;
}
_tprintf(_T("Move rects: %d\n"), BufSize / sizeof(DXGI_OUTDUPL_MOVE_RECT));
DirtyRects = MetaDataBuffer + BufSize;
BufSize = FrameInfo.TotalMetadataBufferSize - BufSize;
// Get dirty rectangles
hr = wfi->dxgi.DeskDupl->lpVtbl->GetFrameDirtyRects(wfi->dxgi.DeskDupl, BufSize, (RECT*) DirtyRects, &BufSize);
if (FAILED(hr))
{
_tprintf(_T("Failed to get frame dirty rects\n"));
return;
}
dirty = BufSize / sizeof(RECT);
_tprintf(_T("Dirty rects: %d\n"), dirty);
pRect = (RECT*) DirtyRects;
for(i = 0; i<dirty; ++i)
{
_tprintf(_T("\tRect: (%d, %d), (%d, %d)\n"),
pRect->left,
pRect->top,
pRect->right,
pRect->bottom);
++pRect;
}
}
hr = wfi->dxgi.DeskDupl->lpVtbl->ReleaseFrame(wfi->dxgi.DeskDupl);
if (FAILED(hr))
{
_tprintf(_T("Failed to release frame\n"));
return;
}
////////////////////////
////////////////////////
update = client->update;
cmd = &update->surface_bits_command;
buf = (GETCHANGESBUF*) wfi->changeBuffer;
width = (wfi->invalid.right - wfi->invalid.left) + 1;
height = (wfi->invalid.bottom - wfi->invalid.top) + 1;
stream_clear(wfi->s);
stream_set_pos(wfi->s, 0);
s = wfi->s;
rect.x = 0;
rect.y = 0;
rect.width = (uint16) width;
rect.height = (uint16) height;
offset = (4 * wfi->invalid.left) + (wfi->invalid.top * wfi->width * 4);
rfx_compose_message(wfi->rfx_context, s, &rect, 1,
((uint8*) (buf->Userbuffer)) + offset, width, height, wfi->width * 4);
cmd->destLeft = wfi->invalid.left;
cmd->destTop = wfi->invalid.top;
cmd->destRight = wfi->invalid.left + width;
cmd->destBottom = wfi->invalid.top + height;
cmd->bpp = 32;
cmd->codecID = client->settings->rfx_codec_id;
cmd->width = width;
cmd->height = height;
cmd->bitmapDataLength = stream_get_length(s);
cmd->bitmapData = stream_get_head(s);
wfi->updatePending = TRUE;
}
void wf_rfx_encode(freerdp_peer* client)
{
STREAM* s;

View File

@ -23,11 +23,14 @@
#include "wfreerdp.h"
#include "wf_info.h"
void wf_peer_context_new(freerdp_peer* client, wfPeerContext* context);
void wf_peer_context_free(freerdp_peer* client, wfPeerContext* context);
void wf_peer_init(freerdp_peer* client);
void wf_dxgi_encode(freerdp_peer* client);
void wf_rfx_encode(freerdp_peer* client);
boolean wf_peer_post_connect(freerdp_peer* client);