mirror of
https://github.com/gnif/LookingGlass.git
synced 2025-12-15 12:38:14 +00:00
Compare commits
18 Commits
B6-rc1
...
frame-timi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6ee30b2308 | ||
|
|
714b1bce70 | ||
|
|
3ec632dd3c | ||
|
|
f0cb9d1167 | ||
|
|
6cd88a70ad | ||
|
|
697bbcd6d4 | ||
|
|
ecca5720a9 | ||
|
|
50e856f823 | ||
|
|
6359bb9acd | ||
|
|
938011fce6 | ||
|
|
d09a10299e | ||
|
|
8e706636d3 | ||
|
|
352cd2fafe | ||
|
|
081a0a419d | ||
|
|
7e42e6cdce | ||
|
|
d857b2a36e | ||
|
|
ba64a2d400 | ||
|
|
9d8bc46812 |
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -10,3 +10,6 @@
|
||||
[submodule "repos/wayland-protocols"]
|
||||
path = repos/wayland-protocols
|
||||
url = https://gitlab.freedesktop.org/wayland/wayland-protocols.git
|
||||
[submodule "repos/nanosvg"]
|
||||
path = repos/nanosvg
|
||||
url = https://github.com/memononen/nanosvg.git
|
||||
|
||||
2
AUTHORS
2
AUTHORS
@@ -9,7 +9,7 @@ arcnmx <arcnmx@users.noreply.github.com> (arcnmx)
|
||||
TheCakeIsNaOH <TheCakeIsNaOH@gmail.com> (TheCakeIsNaOH)
|
||||
NamoDev <namodev@users.noreply.github.com> (NamoDev)
|
||||
feltcat <58396817+feltcat@users.noreply.github.com> (feltcat)
|
||||
Ali Abdel-Qader <abdelqaderali@protonmail.com>
|
||||
Ali Abdel-Qader <abdelqaderali@protonmail.com> (thrifty-txt)
|
||||
Jack Karamanian <karamanian.jack@gmail.com>
|
||||
Mikko Rasa <tdb@tdb.fi> (DataBeaver)
|
||||
Omar Pakker <Omar007@users.noreply.github.com> (Omar007)
|
||||
|
||||
@@ -103,7 +103,7 @@ bool x11CBEventThread(const XEvent xe)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool x11CBInit()
|
||||
bool x11CBInit(void)
|
||||
{
|
||||
x11cb.aCurSelection = BadValue;
|
||||
for(int i = 0; i < LG_CLIPBOARD_DATA_NONE; ++i)
|
||||
|
||||
@@ -458,7 +458,7 @@ void app_handleMouseRelative(double normx, double normy,
|
||||
// cursor warp support. Instead, we attempt a best-effort emulation which works
|
||||
// with a 1:1 mouse movement patch applied in the guest. For anything fancy, use
|
||||
// capture mode.
|
||||
void app_handleMouseBasic()
|
||||
void app_handleMouseBasic(void)
|
||||
{
|
||||
/* do not pass mouse events to the guest if we do not have focus */
|
||||
if (!g_cursor.guest.valid || !g_state.haveSrcSize || !g_state.focused ||
|
||||
@@ -495,7 +495,7 @@ void app_handleMouseBasic()
|
||||
DEBUG_ERROR("failed to send mouse motion message");
|
||||
}
|
||||
|
||||
void app_resyncMouseBasic()
|
||||
void app_resyncMouseBasic(void)
|
||||
{
|
||||
if (!g_cursor.guest.valid)
|
||||
return;
|
||||
|
||||
@@ -525,12 +525,15 @@ void audio_playbackData(uint8_t * data, size_t size)
|
||||
}
|
||||
|
||||
/* Determine the target latency. This is made up of the maximum audio device
|
||||
* period (plus a little extra to absorb timing jitter) and a configurable
|
||||
* period (or the current actual period, if larger than the expected maximum),
|
||||
* plus a little extra to absorb timing jitter, and a configurable
|
||||
* additional buffer period. The default is set high enough to absorb typical
|
||||
* timing jitter from qemu. */
|
||||
int configLatencyMs = max(g_params.audioBufferLatency, 0);
|
||||
int maxPeriodFrames =
|
||||
max(audio.playback.deviceMaxPeriodFrames, spiceData->devPeriodFrames);
|
||||
double targetLatencyFrames =
|
||||
audio.playback.deviceMaxPeriodFrames * 1.1 +
|
||||
maxPeriodFrames * 1.1 +
|
||||
configLatencyMs * audio.playback.sampleRate / 1000.0;
|
||||
|
||||
/* If the device is currently at a lower period size than its maximum (which
|
||||
|
||||
@@ -478,10 +478,11 @@ void core_handleMouseNormal(double ex, double ey)
|
||||
if (!g_state.stopVideo &&
|
||||
g_state.kvmfrFeatures & KVMFR_FEATURE_SETCURSORPOS)
|
||||
{
|
||||
const KVMFRSetCursorPos msg = {
|
||||
.msg.type = KVMFR_MESSAGE_SETCURSORPOS,
|
||||
.x = round(guest.x),
|
||||
.y = round(guest.y)
|
||||
const KVMFRMessage_SetCursorPos msg = {
|
||||
.msg.type = KVMFR_MESSAGE_SETCURSORPOS,
|
||||
.msg.clientID = g_state.clientID,
|
||||
.x = round(guest.x),
|
||||
.y = round(guest.y)
|
||||
};
|
||||
|
||||
uint32_t setPosSerial;
|
||||
|
||||
@@ -170,7 +170,7 @@ void keybind_spiceRegister(void)
|
||||
"Spice keyboard & mouse toggle");
|
||||
|
||||
app_registerKeybind(KEY_INSERT, 0, bind_mouseSens, (void *) true ,
|
||||
"Increase mouse sensitivity 0, in capture mode");
|
||||
"Increase mouse sensitivity in capture mode");
|
||||
app_registerKeybind(KEY_DELETE, 0, bind_mouseSens, (void *) false,
|
||||
"Descrease mouse sensitivity in capture mode");
|
||||
|
||||
|
||||
@@ -1433,7 +1433,8 @@ restart:
|
||||
initialSpiceEnable = 0;
|
||||
}
|
||||
|
||||
status = lgmpClientSessionInit(g_state.lgmp, &udataSize, (uint8_t **)&udata);
|
||||
status = lgmpClientSessionInit(g_state.lgmp, &udataSize, (uint8_t **)&udata,
|
||||
&g_state.clientID);
|
||||
switch(status)
|
||||
{
|
||||
case LGMP_OK:
|
||||
@@ -1442,21 +1443,19 @@ restart:
|
||||
|
||||
case LGMP_ERR_INVALID_VERSION:
|
||||
{
|
||||
reportBadVersion();
|
||||
msgs[msgsCount++] = app_msgBox(
|
||||
"Incompatible LGMP Version",
|
||||
"The host application is not compatible with this client.\n"
|
||||
"Please download and install the matching version."
|
||||
);
|
||||
if (waitCount++ == 0)
|
||||
{
|
||||
reportBadVersion();
|
||||
msgs[msgsCount++] = app_msgBox(
|
||||
"Incompatible LGMP Version",
|
||||
"The host application is not compatible with this client.\n"
|
||||
"Please download and install the matching version."
|
||||
);
|
||||
|
||||
DEBUG_INFO("Waiting for you to upgrade the host application");
|
||||
while (g_state.state == APP_STATE_RUNNING &&
|
||||
lgmpClientSessionInit(g_state.lgmp, &udataSize, (uint8_t **)&udata) != LGMP_OK)
|
||||
g_state.ds->wait(1000);
|
||||
|
||||
if (g_state.state != APP_STATE_RUNNING)
|
||||
return -1;
|
||||
DEBUG_INFO("Waiting for you to upgrade the host application");
|
||||
}
|
||||
|
||||
g_state.ds->wait(1000);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -121,6 +121,7 @@ struct AppState
|
||||
|
||||
struct IVSHMEM shm;
|
||||
PLGMPClient lgmp;
|
||||
uint32_t clientID;
|
||||
PLGMPClientQueue pointerQueue;
|
||||
LG_Lock pointerQueueLock;
|
||||
KVMFRFeatureFlags kvmfrFeatures;
|
||||
|
||||
@@ -3,7 +3,8 @@ if (EXISTS "${PROJECT_TOP}/.git" AND (
|
||||
(NOT EXISTS "${PROJECT_TOP}/repos/LGMP/.git") OR
|
||||
(NOT EXISTS "${PROJECT_TOP}/repos/PureSpice/.git") OR
|
||||
(NOT EXISTS "${PROJECT_TOP}/repos/cimgui/imgui/.git") OR
|
||||
(NOT EXISTS "${PROJECT_TOP}/repos/wayland-protocols/.git")
|
||||
(NOT EXISTS "${PROJECT_TOP}/repos/wayland-protocols/.git") OR
|
||||
(NOT EXISTS "${PROJECT_TOP}/repos/nanosvg/.git")
|
||||
))
|
||||
message(FATAL_ERROR "Submodules are not initialized. Run\n\tgit submodule update --init --recursive")
|
||||
endif()
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
#include "types.h"
|
||||
|
||||
#define KVMFR_MAGIC "KVMFR---"
|
||||
#define KVMFR_VERSION 19
|
||||
#define KVMFR_VERSION 20
|
||||
|
||||
#define KVMFR_MAX_DAMAGE_RECTS 64
|
||||
|
||||
@@ -56,7 +56,8 @@ typedef uint32_t KVMFRFeatureFlags;
|
||||
|
||||
enum
|
||||
{
|
||||
KVMFR_MESSAGE_SETCURSORPOS
|
||||
KVMFR_MESSAGE_SETCURSORPOS,
|
||||
KVMFR_MESSAGE_FRAME_TIME
|
||||
};
|
||||
|
||||
typedef uint32_t KVMFRMessageType;
|
||||
@@ -137,6 +138,8 @@ typedef struct KVMFRFrame
|
||||
{
|
||||
uint32_t formatVer; // the frame format version number
|
||||
uint32_t frameSerial; // the unique frame number
|
||||
uint64_t frameTimeUs; // when the capture was started
|
||||
uint64_t frameElapsedUs; // total time elapsed to capture the frame
|
||||
FrameType type; // the frame data type
|
||||
uint32_t screenWidth; // the client's screen width
|
||||
uint32_t screenHeight; // the client's screen height
|
||||
@@ -155,14 +158,28 @@ KVMFRFrame;
|
||||
typedef struct KVMFRMessage
|
||||
{
|
||||
KVMFRMessageType type;
|
||||
uint32_t clientID;
|
||||
}
|
||||
KVMFRMessage;
|
||||
|
||||
typedef struct KVMFRSetCursorPos
|
||||
typedef struct KVMFRMessage_SetCursorPos
|
||||
{
|
||||
KVMFRMessage msg;
|
||||
int32_t x, y;
|
||||
}
|
||||
KVMFRSetCursorPos;
|
||||
KVMFRMessage_SetCursorPos;
|
||||
|
||||
typedef struct KVMFRMessage_FrameTime
|
||||
{
|
||||
KVMFRMessage msg;
|
||||
/* this is the desired time to start the next capture operation where zero is
|
||||
* immediate. This is only a hint to the host application and may not be
|
||||
* honored. The value provided should be offset from the latest frame's
|
||||
* frameTimeUs. When multiple clients are sending this message, the one with
|
||||
* the lowest value will be used.
|
||||
*/
|
||||
uint64_t frameTimeUs;
|
||||
}
|
||||
KVMFRMessage_FrameTime;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -96,6 +96,7 @@ struct app
|
||||
unsigned int frameIndex;
|
||||
bool frameValid;
|
||||
uint32_t frameSerial;
|
||||
uint64_t frameTimeUs;
|
||||
|
||||
CaptureInterface * iface;
|
||||
|
||||
@@ -268,6 +269,7 @@ static bool sendFrame(void)
|
||||
}
|
||||
|
||||
fi->formatVer = frame.formatVer;
|
||||
fi->frameTimeUs = app.frameTimeUs;
|
||||
fi->frameSerial = app.frameSerial++;
|
||||
fi->screenWidth = frame.screenWidth;
|
||||
fi->screenHeight = frame.screenHeight;
|
||||
@@ -295,6 +297,11 @@ static bool sendFrame(void)
|
||||
FrameBuffer * fb = (FrameBuffer *)(((uint8_t*)fi) + fi->offset);
|
||||
framebuffer_prepare(fb);
|
||||
|
||||
// calculate the elapsed time as late as possible, note that this does not
|
||||
// take into account the memory copy time and the client's that care about
|
||||
// this value will need to take this into account
|
||||
fi->frameElapsedUs = microtime() - app.frameTimeUs;
|
||||
|
||||
/* we post and then get the frame, this is intentional! */
|
||||
if ((status = lgmpHostQueuePost(app.frameQueue, 0,
|
||||
app.frameMemory[app.frameIndex])) != LGMP_OK)
|
||||
@@ -719,6 +726,9 @@ int app_main(int argc, char * argv[])
|
||||
if (!installCrashHandler(os_getExecutable()))
|
||||
DEBUG_WARN("Failed to install the crash handler");
|
||||
|
||||
// make sure rng is actually seeded for LGMP
|
||||
srand((unsigned)time(NULL));
|
||||
|
||||
app.state = APP_STATE_RUNNING;
|
||||
ivshmemOptionsInit();
|
||||
|
||||
@@ -855,9 +865,9 @@ int app_main(int argc, char * argv[])
|
||||
{
|
||||
DEBUG_INFO("Performing LGMP reinitialization");
|
||||
lgmpShutdown();
|
||||
app.state = APP_STATE_RUNNING;
|
||||
if (!lgmpSetup(&shmDev))
|
||||
goto fail_lgmp;
|
||||
app.state = APP_STATE_RUNNING;
|
||||
}
|
||||
|
||||
if (app.state == APP_STATE_IDLE)
|
||||
@@ -908,6 +918,7 @@ int app_main(int argc, char * argv[])
|
||||
else
|
||||
previousFrameTime = now;
|
||||
|
||||
app.frameTimeUs = microtime();
|
||||
switch(iface->capture())
|
||||
{
|
||||
case CAPTURE_RESULT_OK:
|
||||
|
||||
@@ -124,7 +124,8 @@ err:
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
static void unmap_kvmfrbuf(struct dma_buf_attachment * at, struct sg_table * sg, enum dma_data_direction direction)
|
||||
static void unmap_kvmfrbuf(struct dma_buf_attachment * at, struct sg_table * sg,
|
||||
enum dma_data_direction direction)
|
||||
{
|
||||
dma_unmap_sg(at->dev, sg->sgl, sg->nents, direction);
|
||||
sg_free_table(sg);
|
||||
@@ -144,7 +145,8 @@ static int mmap_kvmfrbuf(struct dma_buf * buf, struct vm_area_struct * vma)
|
||||
unsigned long size = vma->vm_end - vma->vm_start;
|
||||
unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
|
||||
|
||||
if ((offset + size > (kbuf->pagecount << PAGE_SHIFT)) || (offset + size < offset))
|
||||
if ((offset + size > (kbuf->pagecount << PAGE_SHIFT))
|
||||
|| (offset + size < offset))
|
||||
return -EINVAL;
|
||||
|
||||
if ((vma->vm_flags & (VM_SHARED | VM_MAYSHARE)) == 0)
|
||||
@@ -158,7 +160,8 @@ static int mmap_kvmfrbuf(struct dma_buf * buf, struct vm_area_struct * vma)
|
||||
return 0;
|
||||
|
||||
case KVMFR_TYPE_STATIC:
|
||||
return remap_vmalloc_range(vma, kbuf->kdev->addr + kbuf->offset, vma->vm_pgoff);
|
||||
return remap_vmalloc_range(vma, kbuf->kdev->addr + kbuf->offset,
|
||||
vma->vm_pgoff);
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
@@ -173,7 +176,8 @@ static const struct dma_buf_ops kvmfrbuf_ops =
|
||||
.mmap = mmap_kvmfrbuf
|
||||
};
|
||||
|
||||
static long kvmfr_dmabuf_create(struct kvmfr_dev * kdev, struct file * filp, unsigned long arg)
|
||||
static long kvmfr_dmabuf_create(struct kvmfr_dev * kdev, struct file * filp,
|
||||
unsigned long arg)
|
||||
{
|
||||
struct kvmfr_dmabuf_create create;
|
||||
DEFINE_DMA_BUF_EXPORT_INFO(exp_kdev);
|
||||
@@ -194,7 +198,8 @@ static long kvmfr_dmabuf_create(struct kvmfr_dev * kdev, struct file * filp, uns
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((create.offset + create.size > kdev->size) || (create.offset + create.size < create.offset))
|
||||
if ((create.offset + create.size > kdev->size) ||
|
||||
(create.offset + create.size < create.offset))
|
||||
return -EINVAL;
|
||||
|
||||
kbuf = kzalloc(sizeof(struct kvmfrbuf), GFP_KERNEL);
|
||||
@@ -204,7 +209,8 @@ static long kvmfr_dmabuf_create(struct kvmfr_dev * kdev, struct file * filp, uns
|
||||
kbuf->kdev = kdev;
|
||||
kbuf->pagecount = create.size >> PAGE_SHIFT;
|
||||
kbuf->offset = create.offset;
|
||||
kbuf->pages = kmalloc_array(kbuf->pagecount, sizeof(*kbuf->pages), GFP_KERNEL);
|
||||
kbuf->pages = kmalloc_array(kbuf->pagecount, sizeof(*kbuf->pages),
|
||||
GFP_KERNEL);
|
||||
if (!kbuf->pages)
|
||||
{
|
||||
ret = -ENOMEM;
|
||||
@@ -244,7 +250,8 @@ static long kvmfr_dmabuf_create(struct kvmfr_dev * kdev, struct file * filp, uns
|
||||
goto err;
|
||||
}
|
||||
|
||||
printk("kvmfr_dmabuf_create: offset: %llu, size: %llu\n", create.offset, create.size);
|
||||
printk("kvmfr_dmabuf_create with size %llu offset: %llu",
|
||||
create.size, create.offset);
|
||||
return dma_buf_fd(buf, create.flags & KVMFR_DMABUF_FLAG_CLOEXEC ? O_CLOEXEC : 0);
|
||||
|
||||
err:
|
||||
@@ -253,7 +260,8 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static long device_ioctl(struct file * filp, unsigned int ioctl, unsigned long arg)
|
||||
static long device_ioctl(struct file * filp, unsigned int ioctl,
|
||||
unsigned long arg)
|
||||
{
|
||||
struct kvmfr_dev * kdev;
|
||||
long ret;
|
||||
@@ -359,7 +367,8 @@ static int kvmfr_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
|
||||
mutex_unlock(&minor_lock);
|
||||
|
||||
kdev->devNo = MKDEV(kvmfr->major, kdev->minor);
|
||||
kdev->pDev = device_create(kvmfr->pClass, NULL, kdev->devNo, NULL, KVMFR_DEV_NAME "%d", kdev->minor);
|
||||
kdev->pDev = device_create(kvmfr->pClass, NULL, kdev->devNo, NULL,
|
||||
KVMFR_DEV_NAME "%d", kdev->minor);
|
||||
if (IS_ERR(kdev->pDev))
|
||||
goto out_unminor;
|
||||
|
||||
@@ -451,7 +460,9 @@ static int create_static_device_unlocked(int size_mb)
|
||||
kdev->addr = vmalloc_user(kdev->size);
|
||||
if (!kdev->addr)
|
||||
{
|
||||
printk(KERN_ERR "kvmfr: failed to allocate memory for static device: %d MiB\n", size_mb);
|
||||
printk(
|
||||
KERN_ERR "kvmfr: failed to allocate memory for static device: %d MiB\n",
|
||||
size_mb);
|
||||
ret = -ENOMEM;
|
||||
goto out_free;
|
||||
}
|
||||
@@ -461,7 +472,8 @@ static int create_static_device_unlocked(int size_mb)
|
||||
goto out_release;
|
||||
|
||||
kdev->devNo = MKDEV(kvmfr->major, kdev->minor);
|
||||
kdev->pDev = device_create(kvmfr->pClass, NULL, kdev->devNo, NULL, KVMFR_DEV_NAME "%d", kdev->minor);
|
||||
kdev->pDev = device_create(kvmfr->pClass, NULL, kdev->devNo, NULL,
|
||||
KVMFR_DEV_NAME "%d", kdev->minor);
|
||||
if (IS_ERR(kdev->pDev))
|
||||
goto out_unminor;
|
||||
|
||||
|
||||
2
obs/lg.c
2
obs/lg.c
@@ -156,7 +156,7 @@ static void deinit(LGPlugin * this)
|
||||
case STATE_STOPPING:
|
||||
case STATE_RESTARTING:
|
||||
this->state = STATE_STOPPING;
|
||||
createThreads(this);
|
||||
waitThreads(this);
|
||||
this->state = STATE_STOPPED;
|
||||
/* fallthrough */
|
||||
|
||||
|
||||
Submodule repos/LGMP updated: bb3a212256...1b170ad8d7
1
repos/nanosvg
Submodule
1
repos/nanosvg
Submodule
Submodule repos/nanosvg added at 64d59e4d53
31
repos/nanosvg/.gitignore
vendored
31
repos/nanosvg/.gitignore
vendored
@@ -1,31 +0,0 @@
|
||||
## Compiled source #
|
||||
*.com
|
||||
*.class
|
||||
*.dll
|
||||
*.exe
|
||||
*.o
|
||||
*.so
|
||||
test
|
||||
|
||||
## Logs and databases #
|
||||
*.log
|
||||
*.sql
|
||||
*.sqlite
|
||||
|
||||
## OS generated files #
|
||||
.DS_Store
|
||||
.DS_Store?
|
||||
._*
|
||||
.Spotlight-V100
|
||||
.Trashes
|
||||
ehthumbs.db
|
||||
Thumbs.db
|
||||
|
||||
## Build dir
|
||||
build/*
|
||||
|
||||
## Stuff in example
|
||||
example/_*
|
||||
|
||||
## xcode specific
|
||||
*xcuserdata*
|
||||
@@ -1,18 +0,0 @@
|
||||
Copyright (c) 2013-14 Mikko Mononen memon@inside.org
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user