mirror of
https://github.com/Yours3lf/rpi-vk-driver.git
synced 2025-01-19 11:52:16 +01:00
initial vsync implementation done
This commit is contained in:
parent
f763dc1e6d
commit
5c4dc59395
@ -64,10 +64,35 @@ uint32_t fifoAdd(Fifo* f, void* data)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void fifoRemove(Fifo* f, void* data)
|
void* fifoGetLast(Fifo* f)
|
||||||
{
|
{
|
||||||
assert(f);
|
assert(f);
|
||||||
|
|
||||||
|
if(f->last)
|
||||||
|
{
|
||||||
|
return f->last->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* fifoGetFirst(Fifo* f)
|
||||||
|
{
|
||||||
|
assert(f);
|
||||||
|
|
||||||
|
if(f->first)
|
||||||
|
{
|
||||||
|
return f->first->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t fifoRemove(Fifo* f, void* data)
|
||||||
|
{
|
||||||
|
assert(f);
|
||||||
|
assert(data);
|
||||||
|
|
||||||
if(f->last)
|
if(f->last)
|
||||||
{
|
{
|
||||||
memcpy(data, f->last->data, f->dataSize);
|
memcpy(data, f->last->data, f->dataSize);
|
||||||
@ -87,7 +112,11 @@ void fifoRemove(Fifo* f, void* data)
|
|||||||
|
|
||||||
poolFree(&f->dataBuf, tmp->data);
|
poolFree(&f->dataBuf, tmp->data);
|
||||||
poolFree(&f->fifoElemBuf, tmp);
|
poolFree(&f->fifoElemBuf, tmp);
|
||||||
|
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void debugPrintFifo(Fifo* f)
|
void debugPrintFifo(Fifo* f)
|
||||||
|
@ -30,7 +30,9 @@ typedef struct Fifo
|
|||||||
Fifo createFifo(void* dataMem, void* fifoElemMem, uint32_t maxElems, uint32_t dataSize);
|
Fifo createFifo(void* dataMem, void* fifoElemMem, uint32_t maxElems, uint32_t dataSize);
|
||||||
void destroyFifo(Fifo* f);
|
void destroyFifo(Fifo* f);
|
||||||
uint32_t fifoAdd(Fifo* f, void* data);
|
uint32_t fifoAdd(Fifo* f, void* data);
|
||||||
void fifoRemove(Fifo* f, void* data);
|
uint32_t fifoRemove(Fifo* f, void* data);
|
||||||
|
void* fifoGetLast(Fifo* f);
|
||||||
|
void* fifoGetFirst(Fifo* f);
|
||||||
void debugPrintFifo(Fifo* f);
|
void debugPrintFifo(Fifo* f);
|
||||||
|
|
||||||
#if defined (__cplusplus)
|
#if defined (__cplusplus)
|
||||||
|
125
driver/modeset.c
125
driver/modeset.c
@ -1,8 +1,22 @@
|
|||||||
#include "modeset.h"
|
#include "modeset.h"
|
||||||
|
|
||||||
|
#include "fifo.h"
|
||||||
|
|
||||||
#include <stdatomic.h>
|
#include <stdatomic.h>
|
||||||
atomic_int saved_state_guard = 0;
|
atomic_int saved_state_guard = 0;
|
||||||
|
|
||||||
|
typedef struct vsyncData
|
||||||
|
{
|
||||||
|
_image* i;
|
||||||
|
modeset_display_surface* s;
|
||||||
|
uint32_t pending;
|
||||||
|
} vsyncData;
|
||||||
|
|
||||||
|
static Fifo flipQueueFifo = {};
|
||||||
|
static vsyncData dataMem[5];
|
||||||
|
static FifoElem fifoMem[5];
|
||||||
|
atomic_int flip_queue_guard = 0;
|
||||||
|
|
||||||
void modeset_enum_displays(int fd, uint32_t* numDisplays, modeset_display* displays)
|
void modeset_enum_displays(int fd, uint32_t* numDisplays, modeset_display* displays)
|
||||||
{
|
{
|
||||||
drmModeResPtr resPtr = drmModeGetResources(fd);
|
drmModeResPtr resPtr = drmModeGetResources(fd);
|
||||||
@ -166,6 +180,16 @@ void modeset_create_surface_for_mode(int fd, uint32_t display, uint32_t mode, mo
|
|||||||
{
|
{
|
||||||
// modeset_debug_print(fd);
|
// modeset_debug_print(fd);
|
||||||
|
|
||||||
|
while(flip_queue_guard);
|
||||||
|
flip_queue_guard = 1;
|
||||||
|
|
||||||
|
if(!flipQueueFifo.maxElems)
|
||||||
|
{
|
||||||
|
flipQueueFifo = createFifo(dataMem, fifoMem, 5, sizeof(vsyncData));
|
||||||
|
}
|
||||||
|
|
||||||
|
flip_queue_guard = 0;
|
||||||
|
|
||||||
surface->savedState = 0;
|
surface->savedState = 0;
|
||||||
|
|
||||||
drmModeResPtr resPtr = drmModeGetResources(fd);
|
drmModeResPtr resPtr = drmModeGetResources(fd);
|
||||||
@ -253,49 +277,85 @@ void modeset_destroy_fb(int fd, _image* buf)
|
|||||||
drmModeRmFB(fd, buf->fb);
|
drmModeRmFB(fd, buf->fb);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct vsyncData
|
|
||||||
{
|
|
||||||
_image* i;
|
|
||||||
modeset_display_surface* s;
|
|
||||||
uint32_t pending;
|
|
||||||
} vsyncData;
|
|
||||||
|
|
||||||
static vsyncData flipQueue[2] = {};
|
|
||||||
atomic_int flip_queue_guard = 0;
|
|
||||||
|
|
||||||
static void modeset_page_flip_event(int fd, unsigned int frame,
|
static void modeset_page_flip_event(int fd, unsigned int frame,
|
||||||
unsigned int sec, unsigned int usec,
|
unsigned int sec, unsigned int usec,
|
||||||
void *data)
|
void *data)
|
||||||
{
|
{
|
||||||
if(data)
|
if(data)
|
||||||
{
|
{
|
||||||
vsyncData* d = data;
|
|
||||||
|
|
||||||
while(flip_queue_guard);
|
while(flip_queue_guard);
|
||||||
flip_queue_guard = 1;
|
flip_queue_guard = 1;
|
||||||
|
|
||||||
flipQueue[0].pending = 0;
|
if(data)
|
||||||
|
{
|
||||||
|
vsyncData* d = data;
|
||||||
|
|
||||||
|
d->pending = 0;
|
||||||
|
}
|
||||||
|
|
||||||
flip_queue_guard = 0;
|
flip_queue_guard = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void modeset_acquire_image(int fd, _image* buf, modeset_display_surface* surface)
|
void modeset_acquire_image(int fd, _image** buf, modeset_display_surface** surface)
|
||||||
{
|
{
|
||||||
|
uint32_t pending = 1;
|
||||||
|
|
||||||
while(flip_queue_guard);
|
while(flip_queue_guard);
|
||||||
flip_queue_guard = 1;
|
flip_queue_guard = 1;
|
||||||
|
|
||||||
//TODO
|
vsyncData* last = fifoGetLast(&flipQueueFifo);
|
||||||
//try to find any image that's not pending
|
|
||||||
//call handle event until that happens
|
if(last)
|
||||||
//then find a non-pending image
|
{
|
||||||
drmEventContext ev;
|
pending = last->pending;
|
||||||
memset(&ev, 0, sizeof(ev));
|
}
|
||||||
ev.version = 2;
|
else
|
||||||
ev.page_flip_handler = modeset_page_flip_event;
|
{
|
||||||
drmHandleEvent(fd, &ev);
|
//fifo empty, just use any image
|
||||||
|
*buf = 0;
|
||||||
|
*surface = 0;
|
||||||
|
|
||||||
|
flip_queue_guard = 0;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
flip_queue_guard = 0;
|
flip_queue_guard = 0;
|
||||||
|
|
||||||
|
while(pending)
|
||||||
|
{
|
||||||
|
drmEventContext ev;
|
||||||
|
memset(&ev, 0, sizeof(ev));
|
||||||
|
ev.version = 2;
|
||||||
|
ev.page_flip_handler = modeset_page_flip_event;
|
||||||
|
drmHandleEvent(fd, &ev);
|
||||||
|
|
||||||
|
while(flip_queue_guard);
|
||||||
|
flip_queue_guard = 1;
|
||||||
|
|
||||||
|
vsyncData* d = fifoGetLast(&flipQueueFifo);
|
||||||
|
|
||||||
|
//a frame must be in flight
|
||||||
|
//so fifo must contain something
|
||||||
|
assert(d);
|
||||||
|
|
||||||
|
pending = d->pending;
|
||||||
|
|
||||||
|
flip_queue_guard = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
vsyncData d;
|
||||||
|
|
||||||
|
while(flip_queue_guard);
|
||||||
|
flip_queue_guard = 1;
|
||||||
|
|
||||||
|
fifoRemove(&flipQueueFifo, &d);
|
||||||
|
|
||||||
|
flip_queue_guard = 0;
|
||||||
|
|
||||||
|
*buf = d.i;
|
||||||
|
*surface = d.s;
|
||||||
}
|
}
|
||||||
|
|
||||||
void modeset_present(int fd, _image *buf, modeset_display_surface* surface)
|
void modeset_present(int fd, _image *buf, modeset_display_surface* surface)
|
||||||
@ -342,16 +402,29 @@ void modeset_present(int fd, _image *buf, modeset_display_surface* surface)
|
|||||||
d.s = surface;
|
d.s = surface;
|
||||||
d.pending = 1;
|
d.pending = 1;
|
||||||
|
|
||||||
while(flipQueue[0].pending);
|
uint32_t added = 0;
|
||||||
|
|
||||||
|
while(!added)
|
||||||
|
{
|
||||||
|
while(flip_queue_guard);
|
||||||
|
flip_queue_guard = 1;
|
||||||
|
|
||||||
|
//try to add request to queue
|
||||||
|
added = fifoAdd(&flipQueueFifo, &d);
|
||||||
|
|
||||||
|
flip_queue_guard = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* first = 0;
|
||||||
|
|
||||||
while(flip_queue_guard);
|
while(flip_queue_guard);
|
||||||
flip_queue_guard = 1;
|
flip_queue_guard = 1;
|
||||||
|
|
||||||
flipQueue[0] = d;
|
first = fifoGetFirst(&flipQueueFifo);
|
||||||
drmModePageFlip(fd, surface->crtc->crtc_id, buf->fb, DRM_MODE_PAGE_FLIP_EVENT, &flipQueue[0]);
|
|
||||||
|
|
||||||
flip_queue_guard = 0;
|
flip_queue_guard = 0;
|
||||||
|
|
||||||
|
drmModePageFlip(fd, surface->crtc->crtc_id, buf->fb, DRM_MODE_PAGE_FLIP_EVENT, first);
|
||||||
}
|
}
|
||||||
|
|
||||||
//modeset_debug_print(fd);
|
//modeset_debug_print(fd);
|
||||||
|
@ -62,7 +62,7 @@ void modeset_create_surface_for_mode(int fd, uint32_t display, uint32_t mode, mo
|
|||||||
void modeset_create_fb_for_surface(int fd, _image* buf, modeset_display_surface* surface);
|
void modeset_create_fb_for_surface(int fd, _image* buf, modeset_display_surface* surface);
|
||||||
void modeset_destroy_fb(int fd, _image* buf);
|
void modeset_destroy_fb(int fd, _image* buf);
|
||||||
void modeset_present(int fd, _image* buf, modeset_display_surface* surface);
|
void modeset_present(int fd, _image* buf, modeset_display_surface* surface);
|
||||||
void modeset_acquire_image(int fd, _image* buf, modeset_display_surface* surface);
|
void modeset_acquire_image(int fd, _image** buf, modeset_display_surface** surface);
|
||||||
void modeset_destroy_surface(int fd, modeset_display_surface* surface);
|
void modeset_destroy_surface(int fd, modeset_display_surface* surface);
|
||||||
void modeset_debug_print(int fd);
|
void modeset_debug_print(int fd);
|
||||||
|
|
||||||
|
30
driver/wsi.c
30
driver/wsi.c
@ -466,17 +466,38 @@ VKAPI_ATTR VkResult VKAPI_CALL RPIFUNC(vkAcquireNextImageKHR)(
|
|||||||
|
|
||||||
assert(semaphore != VK_NULL_HANDLE || fence != VK_NULL_HANDLE);
|
assert(semaphore != VK_NULL_HANDLE || fence != VK_NULL_HANDLE);
|
||||||
|
|
||||||
sem_t* s = semaphore;
|
sem_t* sem = semaphore;
|
||||||
|
_swapchain* sc = swapchain;
|
||||||
|
|
||||||
//TODO we need to keep track of currently acquired images?
|
//TODO we need to keep track of currently acquired images?
|
||||||
|
|
||||||
//TODO wait timeout?
|
//TODO wait timeout?
|
||||||
|
|
||||||
*pImageIndex = ((_swapchain*)swapchain)->backbufferIdx; //return back buffer index
|
_image* i;
|
||||||
|
modeset_display_surface* surf;
|
||||||
|
modeset_acquire_image(controlFd, &i, &surf);
|
||||||
|
|
||||||
|
if(i && surf)
|
||||||
|
{
|
||||||
|
for(uint32_t c = 0; c < sc->numImages; ++c)
|
||||||
|
{
|
||||||
|
if(&sc->images[c] == i && sc->surface == surf)
|
||||||
|
{
|
||||||
|
sc->backbufferIdx = c;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sc->backbufferIdx = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
*pImageIndex = sc->backbufferIdx; //return back buffer index
|
||||||
|
|
||||||
//signal semaphore
|
//signal semaphore
|
||||||
int semVal; sem_getvalue(s, &semVal); assert(semVal <= 0); //make sure semaphore is unsignalled
|
int semVal; sem_getvalue(sem, &semVal); assert(semVal <= 0); //make sure semaphore is unsignalled
|
||||||
sem_post(s);
|
sem_post(sem);
|
||||||
|
|
||||||
_fence* f = fence;
|
_fence* f = fence;
|
||||||
if(f)
|
if(f)
|
||||||
@ -526,7 +547,6 @@ VKAPI_ATTR VkResult VKAPI_CALL RPIFUNC(vkQueuePresentKHR)(
|
|||||||
{
|
{
|
||||||
_swapchain* s = pPresentInfo->pSwapchains[c];
|
_swapchain* s = pPresentInfo->pSwapchains[c];
|
||||||
modeset_present(controlFd, &s->images[pPresentInfo->pImageIndices[c]], s->surface);
|
modeset_present(controlFd, &s->images[pPresentInfo->pImageIndices[c]], s->surface);
|
||||||
s->backbufferIdx = (pPresentInfo->pImageIndices[c] + 1) % s->numImages;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PROFILEEND(RPIFUNC(vkQueuePresentKHR));
|
PROFILEEND(RPIFUNC(vkQueuePresentKHR));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user