Compare commits

..

46 Commits
a3 ... a7

Author SHA1 Message Date
Geoffrey McRae
3784e9c06f [client] added support for new header format 2017-12-17 05:21:02 +11:00
Geoffrey McRae
24709ef186 [host] dxgi: set the pitch on new frames 2017-12-17 05:20:40 +11:00
Geoffrey McRae
db59e67ddb [host] update capture classes to return the pitch 2017-12-17 05:05:56 +11:00
Geoffrey McRae
1815387bbb [host] update to use the new header format 2017-12-17 05:03:47 +11:00
Geoffrey McRae
6595374a2c [common] cleanup header format and move resettable members 2017-12-17 05:03:16 +11:00
Geoffrey McRae
9d8f3a79b0 [host] detect switch user event and wait instead of terminating
Fixes #22
2017-12-17 04:50:04 +11:00
Geoffrey McRae
bf85358715 Revert "[host] simplify dll loading"
This reverts commit b89a8fee04.
2017-12-17 04:04:25 +11:00
Geoffrey McRae
b77a34b8b6 [host] DXGI: fix Secure Desktop wait logic
Fixes #20
2017-12-17 02:27:48 +11:00
Geoffrey McRae
287b983d27 [client] opengl: fixed broken mipmap logic
mipmapping is turned off for images that are scaled up a it degrades the
output quality.
2017-12-16 11:25:01 +11:00
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
23 changed files with 917 additions and 291 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**

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,7 +22,7 @@ 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 && \
@@ -41,6 +41,7 @@ typedef struct LG_RendererParams
TTF_Font * font;
bool showFPS;
bool resample;
bool vsync;
}
LG_RendererParams;

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 KVMFRFrame 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,25 +185,32 @@ 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)
{
// sainty check of the frame format
if (
header.frame.type >= FRAME_TYPE_MAX ||
header.frame.width == 0 ||
header.frame.height == 0 ||
header.frame.stride == 0 ||
header.frame.dataPos == 0 ||
header.frame.dataPos > state.shmSize
header.detail.frame.type >= FRAME_TYPE_MAX ||
header.detail.frame.width == 0 ||
header.detail.frame.height == 0 ||
header.detail.frame.stride == 0 ||
header.detail.frame.pitch == 0 ||
header.detail.frame.dataPos == 0 ||
header.detail.frame.dataPos > state.shmSize ||
header.detail.frame.pitch < header.detail.frame.width
){
usleep(1000);
continue;
@@ -195,19 +218,18 @@ int renderThread(void * unused)
// setup the renderer format with the frame format details
LG_RendererFormat lgrFormat;
lgrFormat.width = header.frame.width;
lgrFormat.height = header.frame.height;
lgrFormat.stride = header.frame.stride;
lgrFormat.width = header.detail.frame.width;
lgrFormat.height = header.detail.frame.height;
lgrFormat.stride = header.detail.frame.stride;
lgrFormat.pitch = header.detail.frame.pitch;
switch(header.frame.type)
switch(header.detail.frame.type)
{
case FRAME_TYPE_ARGB:
lgrFormat.pitch = header.frame.stride * 4;
lgrFormat.bpp = 32;
break;
case FRAME_TYPE_RGB:
lgrFormat.pitch = header.frame.stride * 3;
lgrFormat.bpp = 24;
break;
@@ -222,7 +244,7 @@ int renderThread(void * unused)
// check the header's dataPos is sane
const size_t dataSize = lgrFormat.height * lgrFormat.pitch;
if (header.frame.dataPos + dataSize > state.shmSize)
if (header.detail.frame.dataPos + dataSize > state.shmSize)
{
DEBUG_ERROR("The guest sent an invalid dataPos");
break;
@@ -241,14 +263,49 @@ int renderThread(void * unused)
break;
}
state.srcSize.x = header.frame.width;
state.srcSize.y = header.frame.height;
state.srcSize.x = header.detail.frame.width;
state.srcSize.y = header.detail.frame.height;
if (params.autoResize)
SDL_SetWindowSize(state.window, header.frame.width, header.frame.height);
SDL_SetWindowSize(state.window, header.detail.frame.width, header.detail.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.width,
cursor.height,
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;
const uint8_t * data = (const uint8_t *)state.shm + header.detail.frame.dataPos;
if (!state.lgr->on_frame_event(state.lgrData, data))
{
DEBUG_ERROR("Failed to render the frame");
@@ -259,36 +316,64 @@ int renderThread(void * unused)
// if we have cursor data
if (header.flags & KVMFR_HEADER_FLAG_CURSOR)
{
if (header.cursor.flags & KVMFR_CURSOR_FLAG_POS)
if (header.detail.cursor.flags & KVMFR_CURSOR_FLAG_POS)
{
state.cursor.x = header.cursor.x;
state.cursor.y = header.cursor.y;
state.cursor.x = header.detail.cursor.x;
state.cursor.y = header.detail.cursor.y;
state.cursorVisible = header.detail.cursor.flags & KVMFR_CURSOR_FLAG_VISIBLE;
state.haveCursorPos = true;
}
if (header.cursor.flags & KVMFR_CURSOR_FLAG_SHAPE)
if (header.detail.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)
{
bool bad = false;
switch(header.detail.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.detail.frame.height * header.detail.frame.pitch;
if (header.detail.frame.dataPos + dataSize > state.shmSize)
{
DEBUG_ERROR("The guest sent an invalid mouse dataPos");
break;
}
const uint8_t * data = (const uint8_t *)state.shm + header.detail.frame.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.detail.frame, sizeof(struct KVMFRFrame));
memcpy(cursorData, data, dataSize);
continue;
}
if (!state.lgr->on_mouse_shape(
state.lgrData,
c,
header.cursor.w,
header.cursor.h,
header.cursor.pitch,
header.cursor.shape
))
cursorType,
header.detail.frame.width,
header.detail.frame.height,
header.detail.frame.pitch,
data)
)
{
DEBUG_ERROR("Failed to update mouse shape");
break;
@@ -296,21 +381,24 @@ 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 (cursorData)
free(cursorData);
return 0;
}
@@ -613,6 +701,7 @@ int run()
lgrParams.font = state.font;
lgrParams.resample = params.useMipmap;
lgrParams.showFPS = params.showFPS;
lgrParams.vsync = params.vsync;
Uint32 sdlFlags;
// probe for a a suitable renderer
@@ -651,12 +740,18 @@ int run()
params.h,
(
SDL_WINDOW_SHOWN |
(params.fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0) |
(params.allowResize ? SDL_WINDOW_RESIZABLE : 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);
@@ -724,8 +819,7 @@ int run()
DEBUG_ERROR("Failed to map memory");
break;
}
state.shmSize = ivshmem_get_map_size();
state.shm->hostID = ivshmem_get_id();
state.shmSize = ivshmem_get_map_size();
if (params.useSpice)
{
@@ -822,13 +916,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"
@@ -875,7 +970,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 '?':
@@ -912,6 +1007,10 @@ int main(int argc, char * argv[])
params.useMipmap = false;
break;
case 'v':
params.vsync = false;
break;
case 'k':
params.showFPS = true;
break;
@@ -932,6 +1031,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

@@ -47,6 +47,7 @@ struct LGR_OpenGL
{
LG_RendererParams params;
bool configured;
SDL_Window * sdlWindow;
SDL_GLContext glContext;
bool doneInfo;
@@ -68,7 +69,6 @@ struct LGR_OpenGL
int fpsList;
int mouseList;
LG_RendererRect destRect;
bool mipmap;
bool hasTextures;
GLuint textures[TEXTURE_COUNT];
@@ -81,6 +81,7 @@ struct LGR_OpenGL
SDL_Rect fpsRect;
bool mouseUpdate;
bool newShape;
uint64_t lastMouseDraw;
LG_RendererCursor mouseType;
bool mouseVisible;
@@ -131,7 +132,7 @@ bool lgr_opengl_initialize(void ** opaque, const LG_RendererParams params, Uint3
}
*sdlFlags = SDL_WINDOW_OPENGL;
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 0);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
return true;
}
@@ -147,6 +148,7 @@ bool lgr_opengl_configure(void * opaque, SDL_Window *window, const LG_RendererFo
return false;
}
this->sdlWindow = window;
this->glContext = SDL_GL_CreateContext(window);
if (!this->glContext)
{
@@ -168,7 +170,7 @@ bool lgr_opengl_configure(void * opaque, SDL_Window *window, const LG_RendererFo
return false;
}
SDL_GL_SetSwapInterval(0);
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.
@@ -362,7 +364,7 @@ void lgr_opengl_on_resize(void * opaque, const int width, const int height, cons
if (!this || !this->configured)
return;
this->window.x = width;
this->window.x = width;
this->window.y = height;
memcpy(&this->destRect, &destRect, sizeof(LG_RendererRect));
@@ -391,7 +393,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
);
@@ -491,6 +493,7 @@ bool lgr_opengl_on_mouse_shape(void * opaque, const LG_RendererCursor cursor, co
}
this->mouseUpdate = true;
this->newShape = true;
return true;
}
@@ -630,15 +633,17 @@ bool lgr_opengl_on_frame_event(void * opaque, const uint8_t * data)
(this->format.width > this->destRect.w) ||
(this->format.height > this->destRect.h));
if (this->mipmap != mipmap)
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
mipmap ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR);
this->mipmap = mipmap;
}
if (mipmap)
{
glGenerateMipmap(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
}
else
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
}
glBindTexture(GL_TEXTURE_2D, 0);
@@ -700,15 +705,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);
@@ -718,7 +735,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();

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 4
typedef enum FrameType
{
@@ -50,9 +49,6 @@ typedef struct KVMFRCursor
uint8_t flags; // KVMFR_CURSOR_FLAGS
int16_t x, y; // cursor x & y position
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];
}
KVMFRCursor;
@@ -61,7 +57,8 @@ typedef struct KVMFRFrame
FrameType type; // the frame data type
uint32_t width; // the width
uint32_t height; // the height
uint32_t stride; // the row stride
uint32_t stride; // the row stride (zero if cursor data)
uint32_t pitch; // the row pitch (stride in bytes)
uint64_t dataPos; // offset to the frame
}
KVMFRFrame;
@@ -71,16 +68,19 @@ KVMFRFrame;
#define KVMFR_HEADER_FLAG_RESTART 4 // restart signal from client
#define KVMFR_HEADER_FLAG_READY 8 // ready signal from client
typedef struct KVMFRDetail
{
KVMFRFrame frame; // the frame information
KVMFRCursor cursor; // the cursor information
}
KVMFRDetail;
typedef struct KVMFRHeader
{
char magic[sizeof(KVMFR_HEADER_MAGIC)];
uint32_t version; // version of this structure
uint16_t hostID; // the host ivshmem client id
uint16_t guestID; // the guest ivshmem client id
uint32_t updateCount; // updated each change
uint8_t flags; // KVMFR_HEADER_FLAGS
KVMFRFrame frame; // the frame information
KVMFRCursor cursor; // the cursor information
KVMFRDetail detail; // details
}
KVMFRHeader;
KVMFRHeader;

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,23 @@ 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.pitch = m_rect.Pitch;
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 +292,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 +312,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;
}
@@ -321,36 +347,38 @@ GrabStatus DXGI::GrabFrame(FrameInfo & frame)
if (SUCCEEDED(status))
break;
HDESK desktop = NULL;
switch (status)
{
case DXGI_ERROR_ACCESS_LOST: // desktop switch, mode change or switch DWM on or off
return GRAB_STATUS_REINIT;
// desktop switch, mode change, switch DWM on or off or Secure Desktop
case DXGI_ERROR_ACCESS_LOST:
// see if we can open the desktop, if so request a reinit
// if not the secure desktop is active so just wait for it
// instead of aborting out
desktop = OpenInputDesktop(0, TRUE, GENERIC_READ);
if (desktop)
{
// open suceeded, not on the secure desktop, return to reinit
CloseDesktop(desktop);
return GRAB_STATUS_REINIT;
}
// fall through
case WAIT_ABANDONED: // this can happen also during desktop switches, not documented by MS though
{
// see if we can open the desktop, if not the secure desktop
// is active so just wait for it instead of aborting out
HDESK desktop = NULL;
while(!desktop)
// this can happen during desktop switches also, not documented by MS though
case WAIT_ABANDONED:
do
{
desktop = OpenInputDesktop(0, TRUE, GENERIC_READ);
if (desktop)
break;
Sleep(100);
}
} while (!desktop);
CloseDesktop(desktop);
if (!ReInitialize())
{
DEBUG_ERROR("Failed to ReInitialize after lost access to desktop");
return GRAB_STATUS_ERROR;
}
continue;
}
return GRAB_STATUS_REINIT;
default:
// unknown failure
DEBUG_INFO("AcquireNextFrame failed: %08x", status);
DEBUG_INFO("AcquireNextFrame failed: %08x", (int)status);
return GRAB_STATUS_ERROR;
}
}
@@ -363,7 +391,7 @@ GrabStatus DXGI::GrabFrame(FrameInfo & frame)
return GRAB_STATUS_ERROR;
}
CComQIPtr<ID3D11Texture2D> src = res;
ID3D11Texture2DPtr src(res);
if (!src)
{
m_dup->ReleaseFrame();
@@ -371,8 +399,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 +407,43 @@ 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;
m_width = m_desc.Width;
m_height = m_desc.Height;
frame.width = desc.Width;
frame.height = desc.Height;
frame.stride = rect.Pitch / 4;
memcpySSE(frame.buffer, rect.pBits, min(frame.bufferSize, m_height * rect.Pitch));
frame.width = m_desc.Width;
frame.height = m_desc.Height;
frame.pitch = m_rect.Pitch;
frame.stride = m_rect.Pitch / 4;
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
@@ -287,6 +289,7 @@ enum GrabStatus NvFBC::GrabFrame(struct FrameInfo & frame)
}
frame.stride = frame.width;
frame.pitch = dataWidth;
uint8_t *src = (uint8_t *)m_frameBuffer + dataOffset;
uint8_t *dst = (uint8_t *)frame.buffer;
for(unsigned int y = 0; y < frame.height; ++y, dst += dataWidth, src += m_grabInfo.dwBufferWidth * 4)
@@ -311,3 +314,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
{
@@ -41,6 +42,7 @@ struct FrameInfo
unsigned int width;
unsigned int height;
unsigned int stride;
unsigned int pitch;
void * buffer;
size_t bufferSize;
@@ -57,15 +59,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,9 +40,13 @@ 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_consoleSessionID = WTSGetActiveConsoleSessionId();
m_ivshmem = IVSHMEM::Get();
}
@@ -81,15 +93,13 @@ 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->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->detail, sizeof(KVMFRDetail));
m_initialized = true;
return true;
@@ -97,7 +107,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 +132,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 +170,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 +180,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 +189,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 +206,50 @@ 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(WTSGetActiveConsoleSessionId() != m_consoleSessionID)
{
DEBUG_INFO("User switch detected, waiting to regain control");
while (WTSGetActiveConsoleSessionId() != m_consoleSessionID)
Sleep(100);
}
if (!m_capture->ReInitialize() || !InitPointers())
{
DEBUG_ERROR("ReInitialize Failed");
return false;
}
continue;
}
if (ok)
break;
}
if (!ok)
{
@@ -225,76 +258,106 @@ bool Service::Process()
}
uint8_t updateFlags = 0;
m_header->cursor.flags = 0;
m_detail.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_detail.frame.type = m_capture->GetFrameType();
m_detail.frame.width = frame.width;
m_detail.frame.height = frame.height;
m_detail.frame.stride = frame.stride;
m_detail.frame.pitch = frame.pitch;
m_detail.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_detail.cursor.flags |= KVMFR_CURSOR_FLAG_POS;
if (m_cursor.visible)
m_detail.cursor.flags |= KVMFR_CURSOR_FLAG_VISIBLE;
m_detail.cursor.x = m_cursor.x;
m_detail.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_detail.cursor.flags |= KVMFR_CURSOR_FLAG_SHAPE;
if (m_cursor.visible)
m_detail.cursor.flags |= KVMFR_CURSOR_FLAG_VISIBLE;
// shapes are sent as frame data
m_detail.cursor.type = m_cursor.type;
m_detail.frame.width = m_cursor.w;
m_detail.frame.height = m_cursor.h;
m_detail.frame.stride = 0;
m_detail.frame.pitch = m_cursor.pitch;
m_detail.frame.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 details only
memcpy(&m_shmHeader->detail, &m_detail, sizeof(KVMFRDetail));
// 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"
@@ -49,17 +49,21 @@ private:
~Service();
bool m_initialized;
DWORD m_consoleSessionID;
uint8_t * m_memory;
IVSHMEM * m_ivshmem;
HANDLE m_timer;
ICapture * m_capture;
KVMFRHeader * m_header;
KVMFRDetail m_detail;
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

@@ -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>