wfreerdp-server: win8 dxgi initial support
This commit is contained in:
parent
a32636b877
commit
2a07ebec23
@ -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()
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user