Compare commits

..

44 Commits
a2 ... a6

Author SHA1 Message Date
Geoffrey McRae
7c5b2b5c1c [host] dxgi: re-send the last frame if capture times out
This change prevents the guest from stalling on startup if there are no
frames being captured
2017-12-16 10:24:37 +11:00
Geoffrey McRae
758b7af754 [host] use a local copy of the header and then update it all in one go
Writing to shared memory is much faster then reading as the shared
memory is not cached, this change ensures we are using a local copy
of the header performing the final update all in one go.
2017-12-16 10:06:55 +11:00
jmossman
b89a8fee04 [host] simplify dll loading 2017-12-16 07:01:41 +11:00
Geoffrey McRae
2bb8b0227c [client] don't send renderer mouse events until it's configured 2017-12-15 19:14:02 +11:00
Geoffrey McRae
ae4156d041 [client] don't update mouse scaling values until started 2017-12-15 19:14:02 +11:00
Patrick Steinhardt
fe337cf510 [client] ivshmem: fix missing <sys/select.h> include
While the function `ivshmem_wait_irq` makes use of the select(3)
function, it does not include <sys/select.h>. This happens to work on
glibc based systems, which include thet file transitively via other
header files. But on musl libc based systems, this breaks compilation.

Directly include <sys/select.h> to fix the problem.
2017-12-15 18:25:21 +11:00
Geoffrey McRae
7bfed41523 [client] opengl: update mouse draw time when doing decoupled draws 2017-12-15 17:03:51 +11:00
Geoffrey McRae
9bb66b7bd6 [client] opengl: decouple mouse updates from vsync 2017-12-15 16:58:21 +11:00
Geoffrey McRae
f7420317f1 [client] opengl: mouse shape updates bypass the draw timeout 2017-12-15 16:53:26 +11:00
Geoffrey McRae
c1379a45d2 [client] opengl: increase maximum mouse draw frequency 2017-12-15 16:34:29 +11:00
Geoffrey McRae
9c03327701 [client] opengl: added back double buffering and vsync support
This adds back in double buffering and vsync support. This has been
carefully implemented so that the render function blocks until the video
card reports that it has advanced a frame, this ensures that the OpenGL
pipeline never buffers frames.
2017-12-15 16:21:38 +11:00
Geoffrey McRae
0d8b2449cf [client] added back missing vsync disable option 2017-12-15 16:19:47 +11:00
Arti Zirk
d1bd5b3115 Do not minimize fullscreen window on focus loss 2017-12-15 15:59:28 +11:00
Jack Karamanian
e03621a622 [client] Add borderless fullscreen usage 2017-12-15 15:59:09 +11:00
Michał Zając
b93aca796c Add issue template 2017-12-15 13:00:10 +11:00
Jack Karamanian
606da0ae47 Add borderless fullscreen option 2017-12-15 12:59:34 +11:00
Geoffrey McRae
d08fba9cf9 [host] fix cursor not visible on client reconnect 2017-12-15 12:56:39 +11:00
Geoffrey McRae
df13340439 [host] reset the update count when the guest flags a restart 2017-12-15 12:08:41 +11:00
Geoffrey McRae
b6c8136565 [client] initialize the local header copy for proper startup 2017-12-15 12:02:37 +11:00
Geoffrey McRae
0948dda12f [host] implemented variable cursor buffer size 2017-12-15 11:30:25 +11:00
Geoffrey McRae
8ae9f8464b [client] updated client to support new KVMFR cursor dataPos field 2017-12-15 10:51:40 +11:00
Geoffrey McRae
110aced7d1 [common] changed KVMFR to allow for variable cursor buffer sizes 2017-12-15 10:51:10 +11:00
Geoffrey McRae
3c61814c56 [client] windows cursors are in BGRA format 2017-12-15 10:20:20 +11:00
Geoffrey McRae
133001b545 [host] added NvFBC build configurations to vcxproj 2017-12-15 09:58:51 +11:00
Geoffrey McRae
106136afd6 [host] corrections to build with VC++ 2017-12-15 09:51:23 +11:00
arcnmx
c72afff055 [host] Makefile to build host app with mingw 2017-12-14 15:40:07 -05:00
arcnmx
d052239721 [host] mingw interlocked intrinsics 2017-12-14 15:39:53 -05:00
arcnmx
fdfa3006b4 [host] ICapture portable interface definition 2017-12-14 15:39:33 -05:00
arcnmx
a01d755ab5 [host] configure/ifdef out nvfbc 2017-12-14 15:39:19 -05:00
arcnmx
9a9d84cd1f [host] remove ATL, mingw doesn't support it 2017-12-14 15:39:09 -05:00
arcnmx
892a3970ff [host] remove nonexistent ICapture function 2017-12-14 15:39:03 -05:00
arcnmx
d6fee6bf0b [host] inline the implementation of min() 2017-12-14 15:38:51 -05:00
arcnmx
7691093121 [host] DEBUG_* string format fixes 2017-12-14 15:38:43 -05:00
arcnmx
524183661d [host] fix include paths and casing 2017-12-14 15:38:25 -05:00
Geoffrey McRae
cd54cb179b [client] make gcc happy about the ignored read result
Fixes #5
2017-12-15 00:57:49 +11:00
Tyler Watson
973ad5e2b0 [meta] Add SELinux policy
This compiled policy file introduces support for reading of socket files
in the /tmp directory.  Used for communication with invshmem-server
without putting SELinux in permissive mode.
2017-12-14 22:22:44 +11:00
Geoffrey McRae
67bdf2ba97 [client] fix SDL_ttf.h include path. 2017-12-14 22:05:32 +11:00
Geoffrey McRae
ead48195db [client] opengl: use the stride rather then rect width for padded widths 2017-12-14 20:35:36 +11:00
Geoffrey McRae
c0b67e7cb2 [host] DXGI: copy based on the actual pitch 2017-12-14 20:34:32 +11:00
Geoffrey McRae
2ae9b479f6 [client] update window dimensions when the spice client is disabled 2017-12-14 20:09:48 +11:00
Geoffrey McRae
3fa9f371b4 [client] added license to opengl.c 2017-12-14 20:06:48 +11:00
Geoffrey McRae
8ec4abc544 [client] adjusted renderer interface to allow for APIs such as Vulkan 2017-12-14 17:42:59 +11:00
Geoffrey McRae
7280f305e0 Create README.md 2017-12-14 16:32:05 +11:00
Geoffrey McRae
7b64d35cd1 [client] corrected path to SDL2_ttf header 2017-12-14 16:09:39 +11:00
25 changed files with 1032 additions and 402 deletions

11
.github/issue_template.md vendored Normal file
View File

@@ -0,0 +1,11 @@
### Required information
Host CPU:
Host GPU:
Guest GPU:
Host Kernel version:
Host QEMU version:
Please describe what were you doing when the problem occured. If the Windows host application crashed please check for file named `looking-glass-host.dmp` and attach it to this bug report.
**Reports that do no include this information will be ignored and closed**

6
README.md Normal file
View File

@@ -0,0 +1,6 @@
# LookingGlass
An extremely low latency KVMFR (KVM FrameRelay) implementation for guests with VGA PCI Passthrough.
* Project Website: https://looking-glass.hostfission.com
* Support Forum: https://forum.level1techs.com/t/looking-glass-guides-help-and-support/122387
* Windows Builds of the host application: https://looking-glass.hostfission.com/downloads

View File

@@ -30,6 +30,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/select.h>
#include <sys/mman.h>
@@ -511,7 +512,8 @@ enum IVSHMEMWaitResult ivshmem_wait_irq(uint16_t vector, unsigned int timeout)
if (FD_ISSET(fd, &fds))
{
uint64_t kick;
read(fd, &kick, sizeof(kick));
int unused = read(fd, &kick, sizeof(kick));
(void)unused;
return IVSHMEM_WAIT_RESULT_OK;
}
}
@@ -543,4 +545,4 @@ bool ivshmem_kick_irq(uint16_t clientID, uint16_t vector)
DEBUG_ERROR("failed to send kick");
return false;
}
}

View File

@@ -22,11 +22,13 @@ Place, Suite 330, Boston, MA 02111-1307 USA
#include <stdbool.h>
#include <SDL2/SDL.h>
#include <SDL_ttf.h>
#include <SDL2/SDL_ttf.h>
#define IS_LG_RENDERER_VALID(x) \
((x)->get_name && \
(x)->initialize && \
(x)->configure && \
(x)->deconfigure && \
(x)->deinitialize && \
(x)->is_compatible && \
(x)->on_resize && \
@@ -36,12 +38,10 @@ Place, Suite 330, Boston, MA 02111-1307 USA
typedef struct LG_RendererParams
{
SDL_Window * window;
TTF_Font * font;
bool showFPS;
bool resample;
int width;
int height;
TTF_Font * font;
bool showFPS;
bool resample;
bool vsync;
}
LG_RendererParams;
@@ -73,7 +73,9 @@ typedef enum LG_RendererCursor
LG_RendererCursor;
typedef const char * (* LG_RendererGetName )();
typedef bool (* LG_RendererInitialize )(void ** opaque, const LG_RendererParams params, const LG_RendererFormat format);
typedef bool (* LG_RendererInitialize )(void ** opaque, const LG_RendererParams params, Uint32 * sdlFlags);
typedef bool (* LG_RendererConfigure )(void * opaque, SDL_Window *window, const LG_RendererFormat format);
typedef void (* LG_RendererDeConfigure )(void * opaque);
typedef void (* LG_RendererDeInitialize )(void * opaque);
typedef bool (* LG_RendererIsCompatible )(void * opaque, const LG_RendererFormat format);
typedef void (* LG_RendererOnResize )(void * opaque, const int width, const int height, const LG_RendererRect destRect);
@@ -86,6 +88,8 @@ typedef struct LG_Renderer
{
LG_RendererGetName get_name;
LG_RendererInitialize initialize;
LG_RendererConfigure configure;
LG_RendererDeConfigure deconfigure;
LG_RendererDeInitialize deinitialize;
LG_RendererIsCompatible is_compatible;
LG_RendererOnResize on_resize;

View File

@@ -50,6 +50,7 @@ struct AppState
SDL_Point srcSize;
LG_RendererRect dstRect;
SDL_Point cursor;
bool cursorVisible;
bool haveCursorPos;
float scaleX, scaleY;
@@ -63,10 +64,12 @@ struct AppState
struct AppParams
{
bool vsync;
bool autoResize;
bool allowResize;
bool keepAspect;
bool borderless;
bool fullscreen;
bool center;
int x, y;
unsigned int w, h;
@@ -83,10 +86,12 @@ struct AppParams
struct AppState state;
struct AppParams params =
{
.vsync = true,
.autoResize = false,
.allowResize = true,
.keepAspect = true,
.borderless = false,
.fullscreen = false,
.center = true,
.x = 0,
.y = 0,
@@ -134,8 +139,11 @@ inline void updatePositionInfo()
state.dstRect.h = h;
}
state.scaleX = (float)state.srcSize.y / (float)state.dstRect.h;
state.scaleY = (float)state.srcSize.x / (float)state.dstRect.w;
if (state.started)
{
state.scaleX = (float)state.srcSize.y / (float)state.dstRect.h;
state.scaleY = (float)state.srcSize.x / (float)state.dstRect.w;
}
if (state.lgr)
state.lgr->on_resize(state.lgrData, w, h, state.dstRect);
@@ -145,8 +153,16 @@ int renderThread(void * unused)
{
bool error = false;
struct KVMFRHeader header;
LG_RendererCursor cursorType = LG_CURSOR_COLOR;
struct KVMFRCursor cursor = {};
size_t cursorDataSize = 0;
uint8_t * cursorData = NULL;
volatile uint32_t * updateCount = &state.shm->updateCount;
memset(&header, 0, sizeof(struct KVMFRHeader));
while(state.running)
{
// poll until we have a new frame, or we time out
@@ -169,14 +185,19 @@ int renderThread(void * unused)
__sync_or_and_fetch(&state.shm->flags, KVMFR_HEADER_FLAG_READY);
// check the header's magic and version are valid
if (
memcmp(header.magic, KVMFR_HEADER_MAGIC, sizeof(KVMFR_HEADER_MAGIC)) != 0 ||
header.version != KVMFR_HEADER_VERSION
){
if (memcmp(header.magic, KVMFR_HEADER_MAGIC, sizeof(KVMFR_HEADER_MAGIC)) != 0)
{
usleep(1000);
continue;
}
if (header.version != KVMFR_HEADER_VERSION)
{
DEBUG_ERROR("KVMFR version missmatch, expected %u but got %u", KVMFR_HEADER_VERSION, header.version);
DEBUG_ERROR("This is not a bug, ensure you have the right version of looking-glass-host.exe on the guest");
break;
}
// if we have a frame
if (header.flags & KVMFR_HEADER_FLAG_FRAME)
{
@@ -228,74 +249,52 @@ int renderThread(void * unused)
break;
}
// check if we have a compatible renderer
if (!state.lgr || !state.lgr->is_compatible(state.lgrData, lgrFormat))
// check if the renderer needs reconfiguration
if (!state.lgr->is_compatible(state.lgrData, lgrFormat))
{
int width, height;
SDL_GetWindowSize(state.window, &width, &height);
LG_RendererParams lgrParams;
lgrParams.window = state.window;
lgrParams.font = state.font;
lgrParams.resample = params.useMipmap;
lgrParams.showFPS = params.showFPS;
lgrParams.width = width;
lgrParams.height = height;
DEBUG_INFO("Data Format: w=%u, h=%u, s=%u, p=%u, bpp=%u",
lgrFormat.width, lgrFormat.height, lgrFormat.stride, lgrFormat.pitch, lgrFormat.bpp);
// first try to reinitialize any existing renderer
if (state.lgr)
state.lgr->deconfigure(state.lgrData);
if (!state.lgr->configure(state.lgrData, state.window, lgrFormat))
{
state.lgr->deinitialize(state.lgrData);
if (state.lgr->initialize(&state.lgrData, lgrParams, lgrFormat))
{
DEBUG_INFO("Reinitialized %s", state.lgr->get_name());
}
else
{
DEBUG_ERROR("Failed to reinitialize %s, trying other renderers", state.lgr->get_name());
state.lgr->deinitialize(state.lgrData);
state.lgr = NULL;
}
}
if (!state.lgr)
{
// probe for a a suitable renderer
for(const LG_Renderer **r = &LG_Renderers[0]; *r; ++r)
{
if (!IS_LG_RENDERER_VALID(*r))
{
DEBUG_ERROR("FIXME: Renderer %d is invalid, skipping", (int)(r - &LG_Renderers[0]));
continue;
}
state.lgrData = NULL;
if (!(*r)->initialize(&state.lgrData, lgrParams, lgrFormat))
{
(*r)->deinitialize(state.lgrData);
continue;
}
state.lgr = *r;
DEBUG_INFO("Initialized %s", (*r)->get_name());
break;
}
if (!state.lgr)
{
DEBUG_INFO("Unable to find a suitable renderer");
return -1;
}
DEBUG_ERROR("Failed to reconfigure %s", state.lgr->get_name());
break;
}
state.srcSize.x = header.frame.width;
state.srcSize.y = header.frame.height;
if (params.autoResize)
SDL_SetWindowSize(state.window, header.frame.width, header.frame.height);
state.started = true;
updatePositionInfo();
// if we have saved shape info, send it now
if (cursorData)
{
if (!state.lgr->on_mouse_shape(state.lgrData, cursorType, cursor.w,
cursor.h, cursor.pitch, cursorData))
{
DEBUG_ERROR("Failed to update mouse shape");
break;
}
free(cursorData);
cursorData = NULL;
cursorDataSize = 0;
}
// if we have a cursor position, send it now
if (state.haveCursorPos)
{
state.lgr->on_mouse_event(
state.lgrData,
state.cursorVisible,
state.cursor.x,
state.cursor.y
);
}
}
const uint8_t * data = (const uint8_t *)state.shm + header.frame.dataPos;
@@ -313,32 +312,54 @@ int renderThread(void * unused)
{
state.cursor.x = header.cursor.x;
state.cursor.y = header.cursor.y;
state.cursorVisible = header.cursor.flags & KVMFR_CURSOR_FLAG_VISIBLE;
state.haveCursorPos = true;
}
if (header.cursor.flags & KVMFR_CURSOR_FLAG_SHAPE)
{
LG_RendererCursor c = LG_CURSOR_COLOR;
switch(header.cursor.type)
{
case CURSOR_TYPE_COLOR : c = LG_CURSOR_COLOR ; break;
case CURSOR_TYPE_MONOCHROME : c = LG_CURSOR_MONOCHROME ; break;
case CURSOR_TYPE_MASKED_COLOR: c = LG_CURSOR_MASKED_COLOR; break;
default:
DEBUG_ERROR("Invalid cursor type");
break;
}
if (state.lgr)
{
if (!state.lgr->on_mouse_shape(
state.lgrData,
c,
header.cursor.w,
header.cursor.h,
header.cursor.pitch,
header.cursor.shape
))
bool bad = false;
switch(header.cursor.type)
{
case CURSOR_TYPE_COLOR : cursorType = LG_CURSOR_COLOR ; break;
case CURSOR_TYPE_MONOCHROME : cursorType = LG_CURSOR_MONOCHROME ; break;
case CURSOR_TYPE_MASKED_COLOR: cursorType = LG_CURSOR_MASKED_COLOR; break;
default:
DEBUG_ERROR("Invalid cursor type");
bad = true;
break;
}
if (bad)
break;
// check the data position is sane
const uint64_t dataSize = header.cursor.h * header.cursor.pitch;
if (header.cursor.dataPos + dataSize > state.shmSize)
{
DEBUG_ERROR("The guest sent an invalid mouse dataPos");
break;
}
const uint8_t * data = (const uint8_t *)state.shm + header.cursor.dataPos;
if (!state.started)
{
// save off the cursor data so we can tell the renderer when it's ready
if (cursorDataSize < dataSize)
{
if (cursorData) free(cursorData);
cursorData = (uint8_t *)malloc(dataSize);
cursorDataSize = dataSize;
}
memcpy(&cursor, &header.cursor, sizeof(struct KVMFRCursor));
memcpy(cursorData, data, dataSize);
continue;
}
if (!state.lgr->on_mouse_shape(state.lgrData, cursorType, header.cursor.w,
header.cursor.h, header.cursor.pitch, data))
{
DEBUG_ERROR("Failed to update mouse shape");
break;
@@ -346,23 +367,23 @@ int renderThread(void * unused)
}
}
if (state.lgr)
if (state.lgr && state.started)
{
state.lgr->on_mouse_event(
state.lgrData,
(header.cursor.flags & KVMFR_CURSOR_FLAG_VISIBLE) != 0,
state.cursorVisible,
state.cursor.x,
state.cursor.y
);
}
}
if (state.lgr)
if (state.started && state.lgr)
state.lgr->render(state.lgrData);
}
if (state.lgr)
state.lgr->deinitialize(state.lgrData);
if (cursorData)
free(cursorData);
return 0;
}
@@ -431,10 +452,27 @@ int eventThread(void * arg)
continue;
}
if (event.type == SDL_QUIT)
switch(event.type)
{
case SDL_QUIT:
state.running = false;
break;
case SDL_WINDOWEVENT:
{
switch(event.window.event)
{
case SDL_WINDOWEVENT_ENTER:
realignGuest = true;
break;
case SDL_WINDOWEVENT_SIZE_CHANGED:
updatePositionInfo();
realignGuest = true;
break;
}
break;
}
}
if (!params.useSpice)
@@ -583,22 +621,6 @@ int eventThread(void * arg)
}
break;
case SDL_WINDOWEVENT:
{
switch(event.window.event)
{
case SDL_WINDOWEVENT_ENTER:
realignGuest = true;
break;
case SDL_WINDOWEVENT_SIZE_CHANGED:
updatePositionInfo();
realignGuest = true;
break;
}
break;
}
default:
break;
}
@@ -661,7 +683,40 @@ int run()
FcPatternDestroy(pat);
}
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 0);
LG_RendererParams lgrParams;
lgrParams.font = state.font;
lgrParams.resample = params.useMipmap;
lgrParams.showFPS = params.showFPS;
lgrParams.vsync = params.vsync;
Uint32 sdlFlags;
// probe for a a suitable renderer
for(const LG_Renderer **r = &LG_Renderers[0]; *r; ++r)
{
if (!IS_LG_RENDERER_VALID(*r))
{
DEBUG_ERROR("FIXME: Renderer %d is invalid, skipping", (int)(r - &LG_Renderers[0]));
continue;
}
state.lgrData = NULL;
sdlFlags = 0;
if (!(*r)->initialize(&state.lgrData, lgrParams, &sdlFlags))
{
(*r)->deinitialize(state.lgrData);
continue;
}
state.lgr = *r;
DEBUG_INFO("Initialized %s", (*r)->get_name());
break;
}
if (!state.lgr)
{
DEBUG_INFO("Unable to find a suitable renderer");
return -1;
}
state.window = SDL_CreateWindow(
"Looking Glass (Client)",
@@ -670,13 +725,19 @@ int run()
params.w,
params.h,
(
SDL_WINDOW_SHOWN |
SDL_WINDOW_OPENGL |
SDL_WINDOW_SHOWN |
(params.fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0) |
(params.allowResize ? SDL_WINDOW_RESIZABLE : 0) |
(params.borderless ? SDL_WINDOW_BORDERLESS : 0)
(params.borderless ? SDL_WINDOW_BORDERLESS : 0) |
sdlFlags
)
);
if (params.fullscreen)
{
SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0");
}
// set the compositor hint to bypass for low latency
SDL_SysWMinfo wminfo;
SDL_VERSION(&wminfo.version);
@@ -785,9 +846,7 @@ int run()
usleep(1000);
DEBUG_INFO("Host ready, starting session");
while(state.running)
renderThread(NULL);
renderThread(NULL);
break;
}
@@ -805,6 +864,9 @@ int run()
if (t_spice)
SDL_WaitThread(t_spice, NULL);
if (state.lgr)
state.lgr->deinitialize(state.lgrData);
if (state.window)
SDL_DestroyWindow(state.window);
@@ -841,13 +903,14 @@ void doHelp(char * app)
" -M Don't hide the host cursor\n"
"\n"
" -m Disable mipmapping\n"
" -v Disable VSync\n"
" -v Disable VSYNC\n"
" -k Enable FPS display\n"
"\n"
" -a Auto resize the window to the guest\n"
" -n Don't allow the window to be manually resized\n"
" -r Don't maintain the aspect ratio\n"
" -d Borderless mode\n"
" -F Borderless fullscreen mode\n"
" -x XPOS Initial window X position [current: %s]\n"
" -y YPOS Initial window Y position [current: %s]\n"
" -w WIDTH Initial window width [current: %u]\n"
@@ -894,7 +957,7 @@ void doLicense()
int main(int argc, char * argv[])
{
int c;
while((c = getopt(argc, argv, "hf:sc:p:jMmkanrdx:y:w:b:l")) != -1)
while((c = getopt(argc, argv, "hf:sc:p:jMmvkanrdFx:y:w:b:l")) != -1)
switch(c)
{
case '?':
@@ -931,6 +994,10 @@ int main(int argc, char * argv[])
params.useMipmap = false;
break;
case 'v':
params.vsync = false;
break;
case 'k':
params.showFPS = true;
break;
@@ -951,6 +1018,10 @@ int main(int argc, char * argv[])
params.borderless = true;
break;
case 'F':
params.fullscreen = true;
break;
case 'x':
params.center = false;
params.x = atoi(optarg);

View File

@@ -1,9 +1,28 @@
/*
Looking Glass - KVM FrameRelay (KVMFR) Client
Copyright (C) 2017 Geoffrey McRae <geoff@hostfission.com>
https://looking-glass.hostfission.com
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "lg-renderer.h"
#include <stdint.h>
#include <stdbool.h>
#include <unistd.h>
#include <SDL_ttf.h>
#include <SDL2/SDL_ttf.h>
#define GL_GLEXT_PROTOTYPES
#include <GL/gl.h>
@@ -27,8 +46,12 @@ static PFNGLXWAITVIDEOSYNCSGIPROC glXWaitVideoSyncSGI = NULL;
struct LGR_OpenGL
{
LG_RendererParams params;
bool initialized;
bool configured;
SDL_Window * sdlWindow;
SDL_GLContext glContext;
bool doneInfo;
SDL_Point window;
bool resizeWindow;
bool frameUpdate;
@@ -59,6 +82,7 @@ struct LGR_OpenGL
SDL_Rect fpsRect;
bool mouseUpdate;
bool newShape;
uint64_t lastMouseDraw;
LG_RendererCursor mouseType;
bool mouseVisible;
@@ -81,7 +105,7 @@ const char * lgr_opengl_get_name()
return "OpenGL";
}
bool lgr_opengl_initialize(void ** opaque, const LG_RendererParams params, const LG_RendererFormat format)
bool lgr_opengl_initialize(void ** opaque, const LG_RendererParams params, Uint32 * sdlFlags)
{
// create our local storage
*opaque = malloc(sizeof(struct LGR_OpenGL));
@@ -91,26 +115,10 @@ bool lgr_opengl_initialize(void ** opaque, const LG_RendererParams params, const
return false;
}
memset(*opaque, 0, sizeof(struct LGR_OpenGL));
struct LGR_OpenGL * this = (struct LGR_OpenGL *)*opaque;
memcpy(&this->params, &params, sizeof(LG_RendererParams));
this->glContext = SDL_GL_CreateContext(params.window);
if (!this->glContext)
{
DEBUG_ERROR("Failed to create the OpenGL context");
return false;
}
if (SDL_GL_MakeCurrent(params.window, this->glContext) != 0)
{
DEBUG_ERROR("Failed to make the GL context current");
return false;
}
DEBUG_INFO("Vendor : %s", glGetString(GL_VENDOR ));
DEBUG_INFO("Renderer: %s", glGetString(GL_RENDERER));
DEBUG_INFO("Version : %s", glGetString(GL_VERSION ));
if (!glXGetVideoSyncSGI)
{
glXGetVideoSyncSGI = (PFNGLXGETVIDEOSYNCSGIPROC )glXGetProcAddress((const GLubyte *)"glXGetVideoSyncSGI" );
@@ -124,7 +132,46 @@ bool lgr_opengl_initialize(void ** opaque, const LG_RendererParams params, const
}
}
SDL_GL_SetSwapInterval(0);
*sdlFlags = SDL_WINDOW_OPENGL;
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
return true;
}
bool lgr_opengl_configure(void * opaque, SDL_Window *window, const LG_RendererFormat format)
{
struct LGR_OpenGL * this = (struct LGR_OpenGL *)opaque;
if (!this)
return false;
if (this->configured)
{
DEBUG_ERROR("Renderer already configured, call deconfigure first");
return false;
}
this->sdlWindow = window;
this->glContext = SDL_GL_CreateContext(window);
if (!this->glContext)
{
DEBUG_ERROR("Failed to create the OpenGL context");
return false;
}
if (!this->doneInfo)
{
DEBUG_INFO("Vendor : %s", glGetString(GL_VENDOR ));
DEBUG_INFO("Renderer: %s", glGetString(GL_RENDERER));
DEBUG_INFO("Version : %s", glGetString(GL_VERSION ));
this->doneInfo = true;
}
if (SDL_GL_MakeCurrent(window, this->glContext) != 0)
{
DEBUG_ERROR("Failed to make the GL context current");
return false;
}
SDL_GL_SetSwapInterval(this->params.vsync ? 1 : 0);
// check if the GPU supports GL_ARB_buffer_storage first
// there is no advantage to this renderer if it is not present.
@@ -260,24 +307,45 @@ bool lgr_opengl_initialize(void ** opaque, const LG_RendererParams params, const
// copy the format into the local storage
memcpy(&this->format, &format, sizeof(LG_RendererFormat));
this->initialized = true;
this->configured = true;
return true;
}
void lgr_opengl_deconfigure(void * opaque)
{
struct LGR_OpenGL * this = (struct LGR_OpenGL *)opaque;
if (!this || !this->configured)
return;
if (this->hasTextures)
{
glDeleteTextures(TEXTURE_COUNT, this->textures);
this->hasTextures = false;
}
if (this->hasBuffers)
{
glDeleteBuffers(1, this->vboID);
this->hasBuffers = false;
}
if (this->glContext)
{
SDL_GL_DeleteContext(this->glContext);
this->glContext = NULL;
}
this->configured = false;
}
void lgr_opengl_deinitialize(void * opaque)
{
struct LGR_OpenGL * this = (struct LGR_OpenGL *)opaque;
if (!this)
return;
if (this->hasTextures)
glDeleteTextures(TEXTURE_COUNT, this->textures);
if (this->hasBuffers)
glDeleteBuffers(1, this->vboID);
if (this->glContext)
SDL_GL_DeleteContext(this->glContext);
if (this->configured)
lgr_opengl_deconfigure(opaque);
free(this);
}
@@ -285,7 +353,7 @@ void lgr_opengl_deinitialize(void * opaque)
bool lgr_opengl_is_compatible(void * opaque, const LG_RendererFormat format)
{
const struct LGR_OpenGL * this = (struct LGR_OpenGL *)opaque;
if (!this || !this->initialized)
if (!this || !this->configured)
return false;
return (memcmp(&this->format, &format, sizeof(LG_RendererFormat)) == 0);
@@ -294,11 +362,11 @@ bool lgr_opengl_is_compatible(void * opaque, const LG_RendererFormat format)
void lgr_opengl_on_resize(void * opaque, const int width, const int height, const LG_RendererRect destRect)
{
struct LGR_OpenGL * this = (struct LGR_OpenGL *)opaque;
if (!this || !this->initialized)
if (!this || !this->configured)
return;
this->params.width = width;
this->params.height = height;
this->window.x = width;
this->window.y = height;
memcpy(&this->destRect, &destRect, sizeof(LG_RendererRect));
this->resizeWindow = true;
@@ -307,7 +375,7 @@ void lgr_opengl_on_resize(void * opaque, const int width, const int height, cons
bool lgr_opengl_on_mouse_shape(void * opaque, const LG_RendererCursor cursor, const int width, const int height, const int pitch, const uint8_t * data)
{
struct LGR_OpenGL * this = (struct LGR_OpenGL *)opaque;
if (!this || !this->initialized)
if (!this || !this->configured)
return false;
this->mouseType = cursor;
@@ -326,7 +394,7 @@ bool lgr_opengl_on_mouse_shape(void * opaque, const LG_RendererCursor cursor, co
width ,
height ,
0 ,
GL_RGBA,
GL_BGRA, // windows cursors are in BGRA format
GL_UNSIGNED_BYTE,
data
);
@@ -426,13 +494,14 @@ bool lgr_opengl_on_mouse_shape(void * opaque, const LG_RendererCursor cursor, co
}
this->mouseUpdate = true;
this->newShape = true;
return true;
}
bool lgr_opengl_on_mouse_event(void * opaque, const bool visible, const int x, const int y)
{
struct LGR_OpenGL * this = (struct LGR_OpenGL *)opaque;
if (!this || !this->initialized)
if (!this || !this->configured)
return false;
if (this->mousePos.x == x && this->mousePos.y == y && this->mouseVisible == visible)
@@ -448,8 +517,17 @@ bool lgr_opengl_on_mouse_event(void * opaque, const bool visible, const int x, c
bool lgr_opengl_on_frame_event(void * opaque, const uint8_t * data)
{
struct LGR_OpenGL * this = (struct LGR_OpenGL *)opaque;
if (!this || !this->initialized)
if (!this)
{
DEBUG_ERROR("Invalid opaque pointer");
return false;
}
if (!this->configured)
{
DEBUG_ERROR("Not configured");
return false;
}
if (this->params.showFPS && this->renderTime > 1e9)
{
@@ -525,7 +603,7 @@ bool lgr_opengl_on_frame_event(void * opaque, const uint8_t * data)
glBindTexture(GL_TEXTURE_2D , this->textures[FRAME_TEXTURE]);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, this->vboID[0] );
glPixelStorei(GL_UNPACK_ALIGNMENT , 4 );
glPixelStorei(GL_UNPACK_ROW_LENGTH , this->format.width );
glPixelStorei(GL_UNPACK_ROW_LENGTH , this->format.stride );
// copy the buffer to the texture
memcpySSE(this->texPixels[this->texIndex], data, this->texSize);
@@ -589,16 +667,16 @@ static inline void lgr_opengl_draw_mouse(struct LGR_OpenGL * this)
bool lgr_opengl_render(void * opaque)
{
struct LGR_OpenGL * this = (struct LGR_OpenGL *)opaque;
if (!this || !this->initialized)
if (!this || !this->configured)
return false;
if (this->resizeWindow)
{
// setup the projection matrix
glViewport(0, 0, this->params.width, this->params.height);
glViewport(0, 0, this->window.x, this->window.y);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, this->params.width, this->params.height, 0);
gluOrtho2D(0, this->window.x, this->window.y, 0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
@@ -626,15 +704,27 @@ bool lgr_opengl_render(void * opaque)
if (!this->mouseUpdate)
return true;
// don't update the mouse too fast
const uint64_t delta = nanotime() - this->lastMouseDraw;
if (delta < 1e7)
return true;
}
if (!this->newShape)
{
// don't update the mouse too fast
const uint64_t delta = nanotime() - this->lastMouseDraw;
if (delta < 5e6)
return true;
}
this->newShape = false;
// wait for vsync
unsigned int count;
glXWaitVideoSyncSGI(1, 0, &count);
glDrawBuffer(GL_FRONT);
glCallList(this->texList + this->texIndex);
lgr_opengl_draw_mouse(this);
if (this->fpsTexture)
glCallList(this->fpsList);
glDrawBuffer(GL_BACK);
glFlush();
this->mouseUpdate = false;
this->lastMouseDraw = nanotime();
return true;
}
glDisable(GL_SCISSOR_TEST);
glClear(GL_COLOR_BUFFER_BIT);
@@ -644,7 +734,15 @@ bool lgr_opengl_render(void * opaque)
lgr_opengl_draw_mouse(this);
if (this->fpsTexture)
glCallList(this->fpsList);
glFlush();
unsigned int before, after;
glXGetVideoSyncSGI(&before);
SDL_GL_SwapWindow(this->sdlWindow);
// wait for the swap to happen to ensure we dont buffer frames
glXGetVideoSyncSGI(&after);
if (before == after)
glXWaitVideoSyncSGI(1, 0, &before);
++this->frameCount;
const uint64_t t = nanotime();
@@ -661,6 +759,8 @@ const LG_Renderer LGR_OpenGL =
{
.get_name = lgr_opengl_get_name,
.initialize = lgr_opengl_initialize,
.configure = lgr_opengl_configure,
.deconfigure = lgr_opengl_deconfigure,
.deinitialize = lgr_opengl_deinitialize,
.is_compatible = lgr_opengl_is_compatible,
.on_resize = lgr_opengl_on_resize,

View File

@@ -21,8 +21,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA
#include <stdint.h>
#define KVMFR_HEADER_MAGIC "[[KVMFR]]"
#define KVMFR_HEADER_VERSION 2
#define KVMFR_CURSOR_BUFFER (32*32*4)
#define KVMFR_HEADER_VERSION 3
typedef enum FrameType
{
@@ -52,7 +51,7 @@ typedef struct KVMFRCursor
CursorType type; // shape buffer data type
uint8_t w, h; // shape width and height
uint8_t pitch; // shape row length in bytes
uint8_t shape[KVMFR_CURSOR_BUFFER];
uint64_t dataPos; // offset to the cursor data
}
KVMFRCursor;

Binary file not shown.

View File

@@ -17,20 +17,21 @@ this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "DXGI.h"
#include "Capture/DXGI.h"
using namespace Capture;
#include "common\debug.h"
#include "common\memcpySSE.h"
#include "common/debug.h"
#include "common/memcpySSE.h"
DXGI::DXGI() :
m_options(NULL),
m_initialized(false),
m_dxgiFactory(NULL),
m_device(NULL),
m_deviceContext(NULL),
m_dup(NULL),
m_texture(NULL),
m_dxgiFactory(),
m_device(),
m_deviceContext(),
m_dup(),
m_texture(),
m_surface(),
m_pointer(NULL)
{
}
@@ -51,15 +52,15 @@ bool DXGI::Initialize(CaptureOptions * options)
status = CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void **)(&m_dxgiFactory));
if (FAILED(status))
{
DEBUG_ERROR("Failed to create DXGIFactory: %08x", status);
DEBUG_ERROR("Failed to create DXGIFactory: %08x", (int)status);
return false;
}
bool done = false;
CComPtr<IDXGIAdapter1> adapter;
IDXGIAdapter1Ptr adapter;
for (int i = 0; m_dxgiFactory->EnumAdapters1(i, &adapter) != DXGI_ERROR_NOT_FOUND; i++)
{
CComPtr<IDXGIOutput> output;
IDXGIOutputPtr output;
for (int i = 0; adapter->EnumOutputs(i, &output) != DXGI_ERROR_NOT_FOUND; i++)
{
DXGI_OUTPUT_DESC outputDesc;
@@ -150,7 +151,7 @@ bool DXGI::Initialize(CaptureOptions * options)
if (FAILED(status))
{
DEBUG_ERROR("DuplicateOutput Failed: %08x", status);
DEBUG_ERROR("DuplicateOutput Failed: %08x", (int)status);
DeInitialize();
return false;
}
@@ -172,7 +173,7 @@ bool DXGI::Initialize(CaptureOptions * options)
status = m_device->CreateTexture2D(&texDesc, NULL, &m_texture);
if (FAILED(status))
{
DEBUG_ERROR("Failed to create texture: %08x", status);
DEBUG_ERROR("Failed to create texture: %08x", (int)status);
DeInitialize();
return false;
}
@@ -190,6 +191,15 @@ void DXGI::DeInitialize()
m_pointerBufSize = 0;
}
if (m_surfaceMapped)
{
m_surface->Unmap();
m_surfaceMapped = false;
}
if (m_surface)
m_surface.Release();
if (m_texture)
m_texture.Release();
@@ -233,7 +243,7 @@ GrabStatus DXGI::GrabFrame(FrameInfo & frame)
return GRAB_STATUS_ERROR;
DXGI_OUTDUPL_FRAME_INFO frameInfo;
CComPtr<IDXGIResource> res;
IDXGIResourcePtr res;
HRESULT status;
bool cursorUpdate = false;
@@ -241,7 +251,22 @@ GrabStatus DXGI::GrabFrame(FrameInfo & frame)
{
while(true)
{
status = m_dup->AcquireNextFrame(INFINITE, &frameInfo, &res);
status = m_dup->AcquireNextFrame(1000, &frameInfo, &res);
if (status == DXGI_ERROR_WAIT_TIMEOUT)
{
if (!m_surfaceMapped)
break;
// send the last frame again if we timeout to prevent the client stalling on restart
frame.width = m_desc.Width;
frame.height = m_desc.Height;
frame.stride = m_rect.Pitch / 4;
unsigned int size = m_height * m_rect.Pitch;
memcpySSE(frame.buffer, m_rect.pBits, size < frame.bufferSize ? size : frame.bufferSize);
return GRAB_STATUS_OK;
}
if (!SUCCEEDED(status))
break;
@@ -266,7 +291,7 @@ GrabStatus DXGI::GrabFrame(FrameInfo & frame)
m_lastMouseVis = frameInfo.PointerPosition.Visible;
}
frame.cursor.visible = m_lastMouseVis;
frame.cursor.visible = m_lastMouseVis == TRUE;
}
// if the pointer shape has changed
@@ -286,7 +311,7 @@ GrabStatus DXGI::GrabFrame(FrameInfo & frame)
if (!SUCCEEDED(status))
{
m_dup->ReleaseFrame();
DEBUG_ERROR("Failed to get the new pointer shape: %08x", status);
DEBUG_ERROR("Failed to get the new pointer shape: %08x", (int)status);
return GRAB_STATUS_ERROR;
}
@@ -350,7 +375,7 @@ GrabStatus DXGI::GrabFrame(FrameInfo & frame)
default:
// unknown failure
DEBUG_INFO("AcquireNextFrame failed: %08x", status);
DEBUG_INFO("AcquireNextFrame failed: %08x", (int)status);
return GRAB_STATUS_ERROR;
}
}
@@ -363,7 +388,7 @@ GrabStatus DXGI::GrabFrame(FrameInfo & frame)
return GRAB_STATUS_ERROR;
}
CComQIPtr<ID3D11Texture2D> src = res;
ID3D11Texture2DPtr src(res);
if (!src)
{
m_dup->ReleaseFrame();
@@ -371,8 +396,7 @@ GrabStatus DXGI::GrabFrame(FrameInfo & frame)
return GRAB_STATUS_ERROR;
}
D3D11_TEXTURE2D_DESC desc;
src->GetDesc(&desc);
src->GetDesc(&m_desc);
m_deviceContext->CopyResource(m_texture, src);
@@ -380,37 +404,42 @@ GrabStatus DXGI::GrabFrame(FrameInfo & frame)
res.Release();
src.Release();
CComQIPtr<IDXGISurface1> surface = m_texture;
if (!surface)
if (m_surfaceMapped)
{
status = m_surface->Unmap();
if (FAILED(status))
{
DEBUG_ERROR("Failed to unmap surface: %08x", (int)status);
return GRAB_STATUS_ERROR;
}
m_surfaceMapped = false;
m_surface.Release();
}
m_surface = m_texture;
if (!m_surface)
{
DEBUG_ERROR("Failed to get IDXGISurface1");
return GRAB_STATUS_ERROR;
}
DXGI_MAPPED_RECT rect;
status = surface->Map(&rect, DXGI_MAP_READ);
status = m_surface->Map(&m_rect, DXGI_MAP_READ);
if (FAILED(status))
{
DEBUG_ERROR("Failed to map surface: %08x", status);
DEBUG_ERROR("Failed to map surface: %08x", (int)status);
return GRAB_STATUS_ERROR;
}
m_surfaceMapped = true;
m_width = desc.Width;
m_height = desc.Height;
const int pitch = m_width * 4;
m_width = m_desc.Width;
m_height = m_desc.Height;
frame.width = desc.Width;
frame.height = desc.Height;
frame.stride = desc.Width;
frame.width = m_desc.Width;
frame.height = m_desc.Height;
frame.stride = m_rect.Pitch / 4;
memcpySSE(frame.buffer, rect.pBits, min(frame.bufferSize, m_height * pitch));
status = surface->Unmap();
if (FAILED(status))
{
DEBUG_ERROR("Failed to unmap surface: %08x", status);
return GRAB_STATUS_ERROR;
}
unsigned int size = m_height * m_rect.Pitch;
memcpySSE(frame.buffer, m_rect.pBits, size < frame.bufferSize ? size : frame.bufferSize);
return GRAB_STATUS_OK;
}

View File

@@ -25,7 +25,19 @@ Place, Suite 330, Boston, MA 02111-1307 USA
#include <windows.h>
#include <dxgi1_2.h>
#include <d3d11.h>
#include <atlbase.h>
#include <stdio.h>
#include <comdef.h>
_COM_SMARTPTR_TYPEDEF(IDXGIFactory1 , __uuidof(IDXGIFactory1 ));
_COM_SMARTPTR_TYPEDEF(ID3D11Device , __uuidof(ID3D11Device ));
_COM_SMARTPTR_TYPEDEF(ID3D11DeviceContext , __uuidof(ID3D11DeviceContext ));
_COM_SMARTPTR_TYPEDEF(IDXGIOutput1 , __uuidof(IDXGIOutput1 ));
_COM_SMARTPTR_TYPEDEF(IDXGIOutput , __uuidof(IDXGIOutput ));
_COM_SMARTPTR_TYPEDEF(IDXGIAdapter1 , __uuidof(IDXGIAdapter1 ));
_COM_SMARTPTR_TYPEDEF(IDXGIOutputDuplication, __uuidof(IDXGIOutputDuplication));
_COM_SMARTPTR_TYPEDEF(ID3D11Texture2D , __uuidof(ID3D11Texture2D ));
_COM_SMARTPTR_TYPEDEF(IDXGIResource , __uuidof(IDXGIResource ));
_COM_SMARTPTR_TYPEDEF(IDXGISurface1 , __uuidof(IDXGISurface1 ));
namespace Capture
{
@@ -51,7 +63,6 @@ namespace Capture
}
enum FrameType GetFrameType();
enum FrameComp GetFrameCompression();
size_t GetMaxFrameSize();
enum GrabStatus GrabFrame(struct FrameInfo & frame);
@@ -62,13 +73,17 @@ namespace Capture
unsigned int m_width;
unsigned int m_height;
CComPtr<IDXGIFactory1> m_dxgiFactory;
CComPtr<ID3D11Device> m_device;
IDXGIFactory1Ptr m_dxgiFactory;
ID3D11DevicePtr m_device;
D3D_FEATURE_LEVEL m_featureLevel;
CComPtr<ID3D11DeviceContext> m_deviceContext;
CComQIPtr<IDXGIOutput1> m_output;
CComPtr<IDXGIOutputDuplication> m_dup;
CComPtr<ID3D11Texture2D> m_texture;
ID3D11DeviceContextPtr m_deviceContext;
IDXGIOutput1Ptr m_output;
IDXGIOutputDuplicationPtr m_dup;
ID3D11Texture2DPtr m_texture;
IDXGISurface1Ptr m_surface;
D3D11_TEXTURE2D_DESC m_desc;
DXGI_MAPPED_RECT m_rect;
bool m_surfaceMapped;
BYTE * m_pointer;
UINT m_pointerBufSize;
UINT m_pointerSize;

View File

@@ -17,13 +17,15 @@ this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA
*/
#if CONFIG_CAPTURE_NVFBC
#include "NvFBC.h"
using namespace Capture;
#include <string>
#include "common\debug.h"
#include "common\memcpySSE.h"
#include "common/debug.h"
#include "common/memcpySSE.h"
#include "Util.h"
#ifdef _WIN64
@@ -59,11 +61,10 @@ bool NvFBC::Initialize(CaptureOptions * options)
if (_strcmpi(*it, "nowait") == 0) { m_optNoWait = true ; continue; }
}
std::string nvfbc = Util::GetSystemRoot() + "\\" + NVFBC_LIBRARY_NAME;
m_hDLL = LoadLibraryA(nvfbc.c_str());
m_hDLL = LoadLibraryA(NVFBC_LIBRARY_NAME);
if (!m_hDLL)
{
DEBUG_ERROR("Failed to load the NvFBC library: %d - %s", GetLastError(), nvfbc.c_str());
DEBUG_ERROR("Failed to load the NvFBC library: %d - %s", GetLastError(), NVFBC_LIBRARY_NAME);
return false;
}
@@ -74,7 +75,7 @@ bool NvFBC::Initialize(CaptureOptions * options)
if (!m_fnCreateEx || !m_fnSetGlobalFlags || !m_fnGetStatusEx || !m_fnEnable)
{
DEBUG_ERROR("Unable to locate required entry points in %s", nvfbc.c_str());
DEBUG_ERROR("Unable to locate required entry points in %s", NVFBC_LIBRARY_NAME);
DeInitialize();
return false;
}
@@ -311,3 +312,5 @@ enum GrabStatus NvFBC::GrabFrame(struct FrameInfo & frame)
DEBUG_ERROR("Failed to grab frame");
return GRAB_STATUS_ERROR;
}
#endif// CONFIG_CAPTURE_NVFBC

View File

@@ -17,14 +17,16 @@ this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA
*/
#if CONFIG_CAPTURE_NVFBC
#pragma once
#include "ICapture.h"
#define W32_LEAN_AND_MEAN
#include <Windows.h>
#include <windows.h>
#include <NvFBC\nvFBC.h>
#include <NvFBC\nvFBCToSys.h>
#include <NvFBC/nvFBC.h>
#include <NvFBC/nvFBCToSys.h>
namespace Capture
{
@@ -44,7 +46,6 @@ namespace Capture
return Initialize(m_options);
}
enum FrameType GetFrameType();
enum FrameComp GetFrameCompression();
size_t GetMaxFrameSize();
enum GrabStatus GrabFrame(struct FrameInfo & frame);
@@ -68,4 +69,6 @@ namespace Capture
NvFBCFrameGrabInfo m_grabInfo;
NVFBC_TOSYS_GRAB_FRAME_PARAMS m_grabFrameParams;
};
};
};
#endif //CONFIG_CAPTURE_NVFBC

View File

@@ -20,13 +20,15 @@ Place, Suite 330, Boston, MA 02111-1307 USA
#pragma once
#define W32_LEAN_AND_MEAN
#include <Windows.h>
#include <windows.h>
#include <vector>
#include "common\debug.h"
#include "common/debug.h"
#include "ICapture.h"
#include "Capture\NvFBC.h"
#include "Capture\DXGI.h"
#if CONFIG_CAPTURE_NVFBC
#include "Capture/NvFBC.h"
#endif
#include "Capture/DXGI.h"
class CaptureFactory
{
@@ -39,7 +41,9 @@ public:
if (!devices.empty())
return devices;
#if CONFIG_CAPTURE_NVFBC
devices.push_back(new Capture::NvFBC());
#endif
devices.push_back(new Capture::DXGI ());
return devices;

View File

@@ -18,8 +18,8 @@ Place, Suite 330, Boston, MA 02111-1307 USA
*/
#pragma once
#include <Windows.h>
#include <DbgHelp.h>
#include <windows.h>
#include <dbghelp.h>
class CrashHandler
{

View File

@@ -21,6 +21,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA
#include "common/KVMFR.h"
#include <vector>
#include <windows.h>
struct CursorInfo
{
@@ -57,15 +58,15 @@ enum GrabStatus
typedef std::vector<const char *> CaptureOptions;
__interface ICapture
class ICapture
{
public:
const char * GetName();
bool Initialize(CaptureOptions * options);
void DeInitialize();
bool ReInitialize();
enum FrameType GetFrameType();
size_t GetMaxFrameSize();
enum GrabStatus GrabFrame(struct FrameInfo & frame);
};
virtual const char * GetName() = 0;
virtual bool Initialize(CaptureOptions * options) = 0;
virtual void DeInitialize() = 0;
virtual bool ReInitialize() = 0;
virtual enum FrameType GetFrameType() = 0;
virtual size_t GetMaxFrameSize() = 0;
virtual enum GrabStatus GrabFrame(struct FrameInfo & frame) = 0;
};

View File

@@ -17,12 +17,12 @@ this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "ivshmem.h"
#include "IVSHMEM.h"
#include <Windows.h>
#include <SetupAPI.h>
#include "vendor\kvm-guest-drivers-windows\ivshmem\Public.h"
#include "common\debug.h"
#include <windows.h>
#include <setupapi.h>
#include "vendor/kvm-guest-drivers-windows/ivshmem/Public.h"
#include "common/debug.h"
IVSHMEM * IVSHMEM::m_instance = NULL;
@@ -112,7 +112,7 @@ void IVSHMEM::DeInitialize()
if (m_gotMemory)
{
if (!DeviceIoControl(m_handle, IOCTL_IVSHMEM_RELEASE_MMAP, NULL, 0, NULL, 0, NULL, NULL))
DEBUG_ERROR("DeviceIoControl failed: %d", GetLastError());
DEBUG_ERROR("DeviceIoControl failed: %d", (int)GetLastError());
m_memory = NULL;
}
@@ -143,7 +143,7 @@ UINT64 IVSHMEM::GetSize()
IVSHMEM_SIZE size;
if (!DeviceIoControl(m_handle, IOCTL_IVSHMEM_REQUEST_SIZE, NULL, 0, &size, sizeof(IVSHMEM_SIZE), NULL, NULL))
{
DEBUG_ERROR("DeviceIoControl Failed: %d", GetLastError());
DEBUG_ERROR("DeviceIoControl Failed: %d", (int)GetLastError());
return 0;
}
@@ -163,7 +163,7 @@ UINT16 IVSHMEM::GetPeerID()
IVSHMEM_PEERID peerID;
if (!DeviceIoControl(m_handle, IOCTL_IVSHMEM_REQUEST_SIZE, NULL, 0, &peerID, sizeof(IVSHMEM_PEERID), NULL, NULL))
{
DEBUG_ERROR("DeviceIoControl Failed: %d", GetLastError());
DEBUG_ERROR("DeviceIoControl Failed: %d", (int)GetLastError());
return 0;
}
@@ -195,7 +195,7 @@ void * IVSHMEM::GetMemory()
ZeroMemory(&map, sizeof(IVSHMEM_MMAP));
if (!DeviceIoControl(m_handle, IOCTL_IVSHMEM_REQUEST_MMAP, NULL, 0, &map, sizeof(IVSHMEM_MMAP), NULL, NULL))
{
DEBUG_ERROR("DeviceIoControl Failed: %d", GetLastError());
DEBUG_ERROR("DeviceIoControl Failed: %d", (int)GetLastError());
return NULL;
}
@@ -219,7 +219,7 @@ HANDLE IVSHMEM::CreateVectorEvent(UINT16 vector)
HANDLE event = CreateEvent(NULL, TRUE, FALSE, NULL);
if (event == INVALID_HANDLE_VALUE)
{
DEBUG_ERROR("CreateEvent Failed: %d", GetLastError());
DEBUG_ERROR("CreateEvent Failed: %d", (int)GetLastError());
return INVALID_HANDLE_VALUE;
}
@@ -230,7 +230,7 @@ HANDLE IVSHMEM::CreateVectorEvent(UINT16 vector)
if (!DeviceIoControl(m_handle, IOCTL_IVSHMEM_REGISTER_EVENT, &msg, sizeof(IVSHMEM_EVENT), NULL, 0, NULL, NULL))
{
DEBUG_ERROR("DeviceIoControl Failed: %d", GetLastError());
DEBUG_ERROR("DeviceIoControl Failed: %d", (int)GetLastError());
CloseHandle(event);
return INVALID_HANDLE_VALUE;
}
@@ -249,7 +249,7 @@ bool IVSHMEM::RingDoorbell(UINT16 peerID, UINT16 door)
if (!DeviceIoControl(m_handle, IOCTL_IVSHMEM_RING_DOORBELL, &msg, sizeof(IVSHMEM_RING), NULL, 0, NULL, NULL))
{
DEBUG_ERROR("DeviceIoControl Failed: %d", GetLastError());
DEBUG_ERROR("DeviceIoControl Failed: %d", (int)GetLastError());
return false;
}

View File

@@ -20,7 +20,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA
#pragma once
#define W32_LEAN_AND_MEAN
#include <Windows.h>
#include <windows.h>
#include <stdbool.h>
class IVSHMEM

View File

@@ -9,24 +9,44 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sync-test", "sync-test\sync
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug - NvFBC|x64 = Debug - NvFBC|x64
Debug - NvFBC|x86 = Debug - NvFBC|x86
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release - NvFBC|x64 = Release - NvFBC|x64
Release - NvFBC|x86 = Release - NvFBC|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{D439DE3E-32FB-4599-8B5D-C92674D400D4}.Debug - NvFBC|x64.ActiveCfg = Debug - NvFBC|x64
{D439DE3E-32FB-4599-8B5D-C92674D400D4}.Debug - NvFBC|x64.Build.0 = Debug - NvFBC|x64
{D439DE3E-32FB-4599-8B5D-C92674D400D4}.Debug - NvFBC|x86.ActiveCfg = Debug - NvFBC|Win32
{D439DE3E-32FB-4599-8B5D-C92674D400D4}.Debug - NvFBC|x86.Build.0 = Debug - NvFBC|Win32
{D439DE3E-32FB-4599-8B5D-C92674D400D4}.Debug|x64.ActiveCfg = Debug|x64
{D439DE3E-32FB-4599-8B5D-C92674D400D4}.Debug|x64.Build.0 = Debug|x64
{D439DE3E-32FB-4599-8B5D-C92674D400D4}.Debug|x86.ActiveCfg = Debug|Win32
{D439DE3E-32FB-4599-8B5D-C92674D400D4}.Debug|x86.Build.0 = Debug|Win32
{D439DE3E-32FB-4599-8B5D-C92674D400D4}.Release - NvFBC|x64.ActiveCfg = Release - NvFBC|x64
{D439DE3E-32FB-4599-8B5D-C92674D400D4}.Release - NvFBC|x64.Build.0 = Release - NvFBC|x64
{D439DE3E-32FB-4599-8B5D-C92674D400D4}.Release - NvFBC|x86.ActiveCfg = Release - NvFBC|Win32
{D439DE3E-32FB-4599-8B5D-C92674D400D4}.Release - NvFBC|x86.Build.0 = Release - NvFBC|Win32
{D439DE3E-32FB-4599-8B5D-C92674D400D4}.Release|x64.ActiveCfg = Release|x64
{D439DE3E-32FB-4599-8B5D-C92674D400D4}.Release|x64.Build.0 = Release|x64
{D439DE3E-32FB-4599-8B5D-C92674D400D4}.Release|x86.ActiveCfg = Release|Win32
{D439DE3E-32FB-4599-8B5D-C92674D400D4}.Release|x86.Build.0 = Release|Win32
{6CC4DA30-6FBD-4ACA-9BA6-2DE731032800}.Debug - NvFBC|x64.ActiveCfg = Debug - NvFBC|x64
{6CC4DA30-6FBD-4ACA-9BA6-2DE731032800}.Debug - NvFBC|x64.Build.0 = Debug - NvFBC|x64
{6CC4DA30-6FBD-4ACA-9BA6-2DE731032800}.Debug - NvFBC|x86.ActiveCfg = Debug - NvFBC|Win32
{6CC4DA30-6FBD-4ACA-9BA6-2DE731032800}.Debug - NvFBC|x86.Build.0 = Debug - NvFBC|Win32
{6CC4DA30-6FBD-4ACA-9BA6-2DE731032800}.Debug|x64.ActiveCfg = Debug|x64
{6CC4DA30-6FBD-4ACA-9BA6-2DE731032800}.Debug|x64.Build.0 = Debug|x64
{6CC4DA30-6FBD-4ACA-9BA6-2DE731032800}.Debug|x86.ActiveCfg = Debug|Win32
{6CC4DA30-6FBD-4ACA-9BA6-2DE731032800}.Debug|x86.Build.0 = Debug|Win32
{6CC4DA30-6FBD-4ACA-9BA6-2DE731032800}.Release - NvFBC|x64.ActiveCfg = Release - NvFBC|x64
{6CC4DA30-6FBD-4ACA-9BA6-2DE731032800}.Release - NvFBC|x64.Build.0 = Release - NvFBC|x64
{6CC4DA30-6FBD-4ACA-9BA6-2DE731032800}.Release - NvFBC|x86.ActiveCfg = Release - NvFBC|Win32
{6CC4DA30-6FBD-4ACA-9BA6-2DE731032800}.Release - NvFBC|x86.Build.0 = Release - NvFBC|Win32
{6CC4DA30-6FBD-4ACA-9BA6-2DE731032800}.Release|x64.ActiveCfg = Release|x64
{6CC4DA30-6FBD-4ACA-9BA6-2DE731032800}.Release|x64.Build.0 = Release|x64
{6CC4DA30-6FBD-4ACA-9BA6-2DE731032800}.Release|x86.ActiveCfg = Release|Win32

49
host/Makefile Normal file
View File

@@ -0,0 +1,49 @@
BINARY = looking-glass-host.exe
CFLAGS = -g -O3 -march=native -Wall -Werror -I./ -I../common # -DDEBUG
LDFLAGS = -lshlwapi -ldxgi -ld3d11 -lsetupapi -luuid
CFLAGS += -ffast-math
CFLAGS += -fdata-sections -ffunction-sections
CFLAGS += -I../ -I.
LDFLAGS += -Wl,--gc-sections -mwindows
PREFIX ?= x86_64-w64-mingw32-
STRIP = $(PREFIX)strip
CC = $(PREFIX)cc
CXX = $(PREFIX)c++
LD = $(CXX)
BUILD ?= .build
BIN ?= bin
#CFLAGS += -DCONFIG_CAPTURE_NVFBC=1
CFLAGS += -DBUILD_VERSION='"$(shell git describe --always --long --dirty --abbrev=10 --tags)"'
OBJS = main.o \
CrashHandler.o \
IVSHMEM.o \
Service.o \
Capture/DXGI.o
BUILD_OBJS = $(foreach obj,$(OBJS),$(BUILD)/$(obj))
all: $(BIN)/$(BINARY)
$(BUILD)/%.o: %.c
@mkdir -p $(dir $@)
$(CC) -c $(CFLAGS) -o $@ $<
$(BUILD)/%.o: %.cpp
@mkdir -p $(dir $@)
$(CXX) -c $(CFLAGS) -o $@ $<
$(BIN)/$(BINARY): $(BUILD_OBJS)
@mkdir -p $(dir $@)
$(LD) -o $@ $^ $(LDFLAGS)
$(STRIP) -s $@
clean:
rm -rf $(BUILD) $(BIN)
.PHONY: clean

View File

@@ -20,11 +20,19 @@ Place, Suite 330, Boston, MA 02111-1307 USA
#include "Service.h"
#include "IVSHMEM.h"
#include "common\debug.h"
#include "common\KVMFR.h"
#include "common/debug.h"
#include "common/KVMFR.h"
#include "CaptureFactory.h"
#if __MINGW32__
#define INTERLOCKED_AND8 __sync_and_and_fetch
#define INTERLOCKED_OR8 __sync_or_and_fetch
#else
#define INTERLOCKED_OR8 InterlockedOr8
#define INTERLOCKED_AND8 InterlockedAnd8
#endif
Service * Service::m_instance = NULL;
Service::Service() :
@@ -32,8 +40,11 @@ Service::Service() :
m_memory(NULL),
m_timer(NULL),
m_capture(NULL),
m_header(NULL),
m_frameIndex(0)
m_shmHeader(NULL),
m_frameIndex(0),
m_cursorDataSize(0),
m_cursorData(NULL),
m_shapePending(false)
{
m_ivshmem = IVSHMEM::Get();
}
@@ -81,15 +92,15 @@ bool Service::Initialize(ICapture * captureDevice)
}
// update everything except for the hostID
memcpy(m_header->magic, KVMFR_HEADER_MAGIC, sizeof(KVMFR_HEADER_MAGIC));
m_header->version = KVMFR_HEADER_VERSION;
m_header->guestID = m_ivshmem->GetPeerID();
m_header->updateCount = 0;
memcpy(m_shmHeader->magic, KVMFR_HEADER_MAGIC, sizeof(KVMFR_HEADER_MAGIC));
m_shmHeader->version = KVMFR_HEADER_VERSION;
m_shmHeader->guestID = m_ivshmem->GetPeerID();
m_shmHeader->updateCount = 0;
// clear but retain the restart flag if it was set by the client
InterlockedAnd8((char *)&m_header->flags, KVMFR_HEADER_FLAG_RESTART);
ZeroMemory(&m_header->frame , sizeof(KVMFRFrame ));
ZeroMemory(&m_header->cursor, sizeof(KVMFRCursor));
INTERLOCKED_AND8((char *)&m_shmHeader->flags, KVMFR_HEADER_FLAG_RESTART);
ZeroMemory(&m_shmHeader->frame , sizeof(KVMFRFrame ));
ZeroMemory(&m_shmHeader->cursor, sizeof(KVMFRCursor));
m_initialized = true;
return true;
@@ -97,7 +108,7 @@ bool Service::Initialize(ICapture * captureDevice)
bool Service::InitPointers()
{
m_header = reinterpret_cast<KVMFRHeader *>(m_memory);
m_shmHeader = reinterpret_cast<KVMFRHeader *>(m_memory);
m_frame[0] = (uint8_t *)(((uintptr_t)m_memory + sizeof(KVMFRHeader *) + 0x7F) & ~0x7F);
m_frameSize = ((m_ivshmem->GetSize() - (m_frame[0] - m_memory)) & ~0x7F) >> 1;
m_frame[1] = m_frame[0] + m_frameSize;
@@ -122,7 +133,16 @@ void Service::DeInitialize()
m_timer = NULL;
}
m_header = NULL;
m_shapePending = false;
if (m_cursorData)
{
delete[] m_cursorData;
m_cursorDataSize = 0;
m_cursorData = NULL;
}
m_shmHeader = NULL;
m_frame[0] = NULL;
m_frame[1] = NULL;
m_dataOffset[0] = 0;
@@ -151,7 +171,7 @@ bool Service::Process()
frame.buffer = m_frame[m_frameIndex];
frame.bufferSize = m_frameSize;
volatile uint8_t *flags = &m_header->flags;
volatile uint8_t *flags = &m_shmHeader->flags;
// wait for the host to notify that is it is ready to proceed
while (true)
@@ -161,7 +181,8 @@ bool Service::Process()
// check if the client has flagged a restart
if (f & KVMFR_HEADER_FLAG_RESTART)
{
InterlockedAnd8((volatile char *)flags, ~(KVMFR_HEADER_FLAG_RESTART));
m_shmHeader->updateCount = 0;
INTERLOCKED_AND8((volatile char *)flags, ~(KVMFR_HEADER_FLAG_RESTART));
restart = true;
break;
}
@@ -169,7 +190,7 @@ bool Service::Process()
// check if the client has flagged it's ready
if (f & KVMFR_HEADER_FLAG_READY)
{
InterlockedAnd8((volatile char *)flags, ~(KVMFR_HEADER_FLAG_READY));
INTERLOCKED_AND8((volatile char *)flags, ~(KVMFR_HEADER_FLAG_READY));
break;
}
@@ -186,37 +207,43 @@ bool Service::Process()
bool ok = false;
bool cursorOnly = false;
for(int i = 0; i < 2; ++i)
if (m_shapePending)
{
// capture a frame of data
switch (m_capture->GrabFrame(frame))
{
case GRAB_STATUS_OK:
ok = true;
break;
case GRAB_STATUS_CURSOR:
ok = true;
cursorOnly = true;
break;
case GRAB_STATUS_ERROR:
DEBUG_ERROR("Capture failed");
return false;
case GRAB_STATUS_REINIT:
DEBUG_INFO("ReInitialize Requested");
if (!m_capture->ReInitialize() || !InitPointers())
{
DEBUG_ERROR("ReInitialize Failed");
return false;
}
continue;
}
if (ok)
break;
ok = true;
cursorOnly = true;
}
else
for(int i = 0; i < 2; ++i)
{
// capture a frame of data
switch (m_capture->GrabFrame(frame))
{
case GRAB_STATUS_OK:
ok = true;
break;
case GRAB_STATUS_CURSOR:
ok = true;
cursorOnly = true;
break;
case GRAB_STATUS_ERROR:
DEBUG_ERROR("Capture failed");
return false;
case GRAB_STATUS_REINIT:
DEBUG_INFO("ReInitialize Requested");
if (!m_capture->ReInitialize() || !InitPointers())
{
DEBUG_ERROR("ReInitialize Failed");
return false;
}
continue;
}
if (ok)
break;
}
if (!ok)
{
@@ -225,76 +252,108 @@ bool Service::Process()
}
uint8_t updateFlags = 0;
m_header->cursor.flags = 0;
m_header.cursor.flags = 0;
if (!cursorOnly)
{
// signal a frame update
updateFlags |= KVMFR_HEADER_FLAG_FRAME;
m_header->frame.type = m_capture->GetFrameType();
m_header->frame.width = frame.width;
m_header->frame.height = frame.height;
m_header->frame.stride = frame.stride;
m_header->frame.dataPos = m_dataOffset[m_frameIndex];
m_header.frame.type = m_capture->GetFrameType();
m_header.frame.width = frame.width;
m_header.frame.height = frame.height;
m_header.frame.stride = frame.stride;
m_header.frame.dataPos = m_dataOffset[m_frameIndex];
if (++m_frameIndex == 2)
m_frameIndex = 0;
}
if (frame.cursor.hasPos)
if (frame.cursor.hasPos || (m_cursor.hasPos && restart))
{
// remember the last state for client restart
if (frame.cursor.hasPos)
{
m_cursor.hasPos = true;
m_cursor.visible = frame.cursor.visible;
m_cursor.x = frame.cursor.x;
m_cursor.y = frame.cursor.y;
}
// tell the host where the cursor is
updateFlags |= KVMFR_HEADER_FLAG_CURSOR;
m_header->cursor.flags |= KVMFR_CURSOR_FLAG_POS;
if (frame.cursor.visible)
m_header->cursor.flags |= KVMFR_CURSOR_FLAG_VISIBLE;
m_header->cursor.x = frame.cursor.x;
m_header->cursor.y = frame.cursor.y;
// update our local copy for client restarts
m_cursor.flags = m_header->cursor.flags;
m_cursor.x = frame.cursor.x;
m_cursor.y = frame.cursor.y;
m_header.cursor.flags |= KVMFR_CURSOR_FLAG_POS;
if (m_cursor.visible)
m_header.cursor.flags |= KVMFR_CURSOR_FLAG_VISIBLE;
m_header.cursor.x = m_cursor.x;
m_header.cursor.y = m_cursor.y;
}
if (frame.cursor.hasShape)
if (frame.cursor.hasShape || m_shapePending || (m_cursor.hasShape && restart))
{
// give the host the new cursor shape
updateFlags |= KVMFR_HEADER_FLAG_CURSOR;
m_header->cursor.flags |= KVMFR_CURSOR_FLAG_SHAPE;
m_header->cursor.type = frame.cursor.type;
m_header->cursor.w = frame.cursor.w;
m_header->cursor.h = frame.cursor.h;
m_header->cursor.pitch = frame.cursor.pitch;
if (frame.cursor.dataSize > KVMFR_CURSOR_BUFFER)
if (!m_shapePending && !restart)
{
DEBUG_ERROR("Cursor shape size exceeds buffer size");
return false;
if (frame.cursor.dataSize > m_frameSize)
{
DEBUG_ERROR("Cursor size exceeds frame size! This should never happen unless your shared memory is WAY too small");
return false;
}
// take a copy of the shape information for client restarts or pending shape changes
m_cursor.hasShape = frame.cursor.hasShape;
m_cursor.type = frame.cursor.type;
m_cursor.w = frame.cursor.w;
m_cursor.h = frame.cursor.h;
m_cursor.pitch = frame.cursor.pitch;
m_cursor.dataSize = frame.cursor.dataSize;
memcpy(&m_cursor, &frame.cursor, sizeof(CursorInfo));
if (m_cursorDataSize < frame.cursor.dataSize)
{
delete[] m_cursorData;
m_cursorData = new uint8_t[frame.cursor.dataSize];
m_cursorDataSize = frame.cursor.dataSize;
}
memcpy(m_cursorData, frame.cursor.shape, frame.cursor.dataSize);
}
memcpy(m_header->cursor.shape, frame.cursor.shape, frame.cursor.dataSize);
// take a copy of the information for client restarts
uint8_t f = m_cursor.flags;
memcpy(&m_cursor, &m_header->cursor, sizeof(KVMFRCursor));
m_cursor.flags = f | m_header->cursor.flags;
m_haveShape = true;
}
else
{
// if we already have a shape and the client restarted send it to them
if (restart && m_haveShape)
// we can't send a frame with the cursor shape as we need the buffer location
// flag it to send on the next packet
if (updateFlags & KVMFR_HEADER_FLAG_FRAME)
m_shapePending = true;
else
{
updateFlags |= KVMFR_HEADER_FLAG_CURSOR;
m_cursor.flags |= KVMFR_CURSOR_FLAG_SHAPE;
memcpy(&m_header->cursor, &m_cursor, sizeof(KVMFRCursor));
// give the host the new cursor shape
updateFlags |= KVMFR_HEADER_FLAG_CURSOR;
m_header.cursor.flags |= KVMFR_CURSOR_FLAG_SHAPE;
if (m_cursor.visible)
m_header.cursor.flags |= KVMFR_CURSOR_FLAG_VISIBLE;
m_header.cursor.type = m_cursor.type;
m_header.cursor.w = m_cursor.w;
m_header.cursor.h = m_cursor.h;
m_header.cursor.pitch = m_cursor.pitch;
m_header.cursor.dataPos = m_dataOffset[m_frameIndex];
memcpy(m_frame[m_frameIndex], m_cursorData, m_cursor.dataSize);
m_shapePending = false;
if (++m_frameIndex == 2)
m_frameIndex = 0;
}
}
// update the flags
InterlockedAnd8((volatile char *)flags, KVMFR_HEADER_FLAG_RESTART);
InterlockedOr8 ((volatile char *)flags, updateFlags);
INTERLOCKED_AND8((volatile char *)flags, KVMFR_HEADER_FLAG_RESTART);
INTERLOCKED_OR8 ((volatile char *)flags, updateFlags);
// increment the update count to resume the host
++m_header->updateCount;
// update the shared header but don't touch the setup fields
const size_t offset = (uintptr_t)&m_header.frame - (uintptr_t)&m_header;
memcpy(
(uint8_t *)m_shmHeader + offset,
(uint8_t *)&m_header + offset,
sizeof(KVMFRHeader) - offset
);
// increment the update count so the guest stops waiting
++m_shmHeader->updateCount;
return true;
}

View File

@@ -20,7 +20,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA
#pragma once
#define W32_LEAN_AND_MEAN
#include <Windows.h>
#include <windows.h>
#include <stdbool.h>
#include "IVSHMEM.h"
@@ -54,12 +54,15 @@ private:
HANDLE m_timer;
ICapture * m_capture;
KVMFRHeader * m_header;
KVMFRHeader m_header;
KVMFRHeader * m_shmHeader;
uint8_t * m_frame[2];
size_t m_frameSize;
uint64_t m_dataOffset[2];
int m_frameIndex;
KVMFRCursor m_cursor;
bool m_haveShape;
CursorInfo m_cursor;
size_t m_cursorDataSize;
uint8_t * m_cursorData;
bool m_shapePending;
};

View File

@@ -23,45 +23,10 @@ Place, Suite 330, Boston, MA 02111-1307 USA
#include <inttypes.h>
#include <tmmintrin.h>
#include "common\debug.h"
class Util
{
public:
static std::string GetSystemRoot()
{
std::string defaultPath;
size_t pathSize;
char *libPath;
if (_dupenv_s(&libPath, &pathSize, "SystemRoot") != 0)
{
DEBUG_ERROR("Unable to get the SystemRoot environment variable");
return defaultPath;
}
if (!pathSize)
{
DEBUG_ERROR("The SystemRoot environment variable is not set");
return defaultPath;
}
#ifdef _WIN64
defaultPath = std::string(libPath) + "\\System32";
#else
if (IsWow64())
{
defaultPath = std::string(libPath) + "\\Syswow64";
}
else
{
defaultPath = std::string(libPath) + "\\System32";
}
#endif
return defaultPath;
}
static inline void BGRAtoRGB(uint8_t * orig, size_t imagesize, uint8_t * dest)
{
assert((uintptr_t)orig % 16 == 0);

View File

@@ -1,10 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug - NvFBC|Win32">
<Configuration>Debug - NvFBC</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug - NvFBC|x64">
<Configuration>Debug - NvFBC</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release - NvFBC|Win32">
<Configuration>Release - NvFBC</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release - NvFBC|x64">
<Configuration>Release - NvFBC</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
@@ -31,6 +47,11 @@
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug - NvFBC|Win32'" Label="Configuration">
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
@@ -38,11 +59,23 @@
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release - NvFBC|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug - NvFBC|x64'" Label="Configuration">
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
@@ -50,6 +83,13 @@
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release - NvFBC|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
@@ -58,32 +98,60 @@
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug - NvFBC|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release - NvFBC|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug - NvFBC|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release - NvFBC|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);;C:\Program Files %28x86%29\NVIDIA Corporation\NVIDIA Capture SDK\inc</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug - NvFBC|Win32'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);;C:\Program Files %28x86%29\NVIDIA Corporation\NVIDIA Capture SDK\inc</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);;C:\Program Files %28x86%29\NVIDIA Corporation\NVIDIA Capture SDK\inc</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug - NvFBC|x64'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);;C:\Program Files %28x86%29\NVIDIA Corporation\NVIDIA Capture SDK\inc</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);;C:\Program Files %28x86%29\NVIDIA Corporation\NVIDIA Capture SDK\inc</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release - NvFBC|Win32'">
<LinkIncremental>false</LinkIncremental>
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);;C:\Program Files %28x86%29\NVIDIA Corporation\NVIDIA Capture SDK\inc</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);;C:\Program Files %28x86%29\NVIDIA Corporation\NVIDIA Capture SDK\inc</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release - NvFBC|x64'">
<LinkIncremental>false</LinkIncremental>
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);;C:\Program Files %28x86%29\NVIDIA Corporation\NVIDIA Capture SDK\inc</IncludePath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
@@ -97,7 +165,27 @@
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;setupapi.lib;d3d11.lib;dxgi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>kernel32.lib;shlwapi.lib;dxgi.lib;d3d11.lib;setupapi.lib;uuid.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
<Manifest>
<EnableDpiAwareness>PerMonitorHighDPIAware</EnableDpiAwareness>
</Manifest>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug - NvFBC|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>CONFIG_CAPTURE_NVFBC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>..\;.\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>kernel32.lib;shlwapi.lib;dxgi.lib;d3d11.lib;setupapi.lib;uuid.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
<Manifest>
@@ -117,7 +205,27 @@
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;setupapi.lib;d3d11.lib;dxgi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>kernel32.lib;shlwapi.lib;dxgi.lib;d3d11.lib;setupapi.lib;uuid.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
<Manifest>
<EnableDpiAwareness>PerMonitorHighDPIAware</EnableDpiAwareness>
</Manifest>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug - NvFBC|x64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>CONFIG_CAPTURE_NVFBC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>..\;.\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>kernel32.lib;shlwapi.lib;dxgi.lib;d3d11.lib;setupapi.lib;uuid.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
<Manifest>
@@ -141,7 +249,31 @@
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;setupapi.lib;d3d11.lib;dxgi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>kernel32.lib;shlwapi.lib;dxgi.lib;d3d11.lib;setupapi.lib;uuid.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
<Manifest>
<EnableDpiAwareness>PerMonitorHighDPIAware</EnableDpiAwareness>
</Manifest>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release - NvFBC|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>CONFIG_CAPTURE_NVFBC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>..\;.\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>kernel32.lib;shlwapi.lib;dxgi.lib;d3d11.lib;setupapi.lib;uuid.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
<Manifest>
@@ -165,7 +297,31 @@
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;setupapi.lib;d3d11.lib;dxgi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>kernel32.lib;shlwapi.lib;dxgi.lib;d3d11.lib;setupapi.lib;uuid.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
<Manifest>
<EnableDpiAwareness>PerMonitorHighDPIAware</EnableDpiAwareness>
</Manifest>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release - NvFBC|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>CONFIG_CAPTURE_NVFBC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>..\;.\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>kernel32.lib;shlwapi.lib;dxgi.lib;d3d11.lib;setupapi.lib;uuid.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
<Manifest>

View File

@@ -17,11 +17,11 @@ this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <Windows.h>
#include <Shlwapi.h>
#include <windows.h>
#include <shlwapi.h>
#include "common\debug.h"
#include "vendor\getopt\getopt.h"
#include "common/debug.h"
#include "vendor/getopt/getopt.h"
#include "CrashHandler.h"
#include "CaptureFactory.h"

View File

@@ -1,10 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug - NvFBC|Win32">
<Configuration>Debug - NvFBC</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug - NvFBC|x64">
<Configuration>Debug - NvFBC</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release - NvFBC|Win32">
<Configuration>Release - NvFBC</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release - NvFBC|x64">
<Configuration>Release - NvFBC</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
@@ -31,6 +47,12 @@
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug - NvFBC|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
@@ -38,12 +60,25 @@
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release - NvFBC|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug - NvFBC|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
@@ -51,6 +86,13 @@
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release - NvFBC|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
@@ -59,28 +101,52 @@
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug - NvFBC|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release - NvFBC|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug - NvFBC|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release - NvFBC|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug - NvFBC|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug - NvFBC|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release - NvFBC|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release - NvFBC|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
@@ -95,6 +161,20 @@
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug - NvFBC|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>
@@ -109,6 +189,20 @@
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug - NvFBC|x64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
@@ -127,6 +221,24 @@
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release - NvFBC|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
@@ -145,6 +257,24 @@
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release - NvFBC|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="main.c" />
</ItemGroup>