VNC: Add some rectangle queuing logic
This commit is contained in:
parent
e7f4a02e45
commit
df297ec8fc
@ -71,6 +71,26 @@ config VNCSERVER_SCREENHEIGHT
|
||||
int "Framebuffer height (rows)"
|
||||
default 240
|
||||
|
||||
config VNCSERVER_NUPDATES
|
||||
int "Number of pre-allocate update structures"
|
||||
default 48
|
||||
---help---
|
||||
This setting provides the number of pre-allocated update structures
|
||||
that will be used. Dynamic memory allocations are never made. In
|
||||
the likely event that we run out of update structures, the graphics
|
||||
subsystem will pause and wait for the next structures to be released.
|
||||
|
||||
Overhead is 12-bytes per update structure.
|
||||
|
||||
config VNCSERVER_UPDATE_BUFSIZE
|
||||
int "Max update buffer size (bytes)"
|
||||
default 4096
|
||||
---help---
|
||||
A single buffer is pre-allocated for rendering updates. This
|
||||
setting specifies the maximum in bytes of that update buffer. For
|
||||
example, an update buffers of 32 pixels at 32-bits per pixel and
|
||||
32-rows would yield a buffer size of 4096.
|
||||
|
||||
config VNCSERVER_KBDENCODE
|
||||
bool "Encode keyboard input"
|
||||
default n
|
||||
@ -79,8 +99,8 @@ config VNCSERVER_KBDENCODE
|
||||
Use a special encoding of keyboard characters as defined in
|
||||
include/nuttx/input/kbd_coded.h.
|
||||
|
||||
config VNCSERVER_IOBUFFER_SIZE
|
||||
int "I/O buffer size
|
||||
config VNCSERVER_INBUFFER_SIZE
|
||||
int "Input buffer size
|
||||
default 80
|
||||
|
||||
endif # VNCSERVER
|
||||
|
@ -274,7 +274,7 @@ int vnc_negotiate(FAR struct vnc_session_s *session)
|
||||
*/
|
||||
|
||||
(void)psock_recv(&session->connect, session->inbuf,
|
||||
CONFIG_VNCSERVER_IOBUFFER_SIZE, 0);
|
||||
CONFIG_VNCSERVER_INBUFFER_SIZE, 0);
|
||||
|
||||
session->state = VNCSERVER_CONFIGURED;
|
||||
return OK;
|
||||
|
@ -41,7 +41,9 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <semaphore.h>
|
||||
#include <string.h>
|
||||
#include <queue.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
@ -50,6 +52,7 @@
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <nuttx/kmalloc.h>
|
||||
#include <nuttx/semaphore.h>
|
||||
#include <nuttx/net/net.h>
|
||||
|
||||
#include "vnc_server.h"
|
||||
@ -91,6 +94,10 @@ static FAR struct vnc_session_s *g_vnc_sessions[RFB_MAX_DISPLAYS];
|
||||
static void vnc_reset_session(FAR struct vnc_session_s *session,
|
||||
FAR uint8_t *fb)
|
||||
{
|
||||
FAR struct vnc_fbupdate_s *curr;
|
||||
FAR struct vnc_fbupdate_s *next;
|
||||
int i;
|
||||
|
||||
/* Close any open sockets */
|
||||
|
||||
if (session->state >= VNCSERVER_CONNECTED)
|
||||
@ -99,12 +106,29 @@ static void vnc_reset_session(FAR struct vnc_session_s *session,
|
||||
psock_close(&session->listen);
|
||||
}
|
||||
|
||||
/* [Re-]nitialize the session. Set all values to 0 == NULL == false. */
|
||||
/* [Re-]initialize the session. */
|
||||
/* Put all of the pre-allocated update structures into the freelist */
|
||||
|
||||
memset(session, 0, sizeof(struct vnc_session_s));
|
||||
sq_init(&session->updqueue);
|
||||
|
||||
/* Then initialize only non-zero values */
|
||||
session->updfree.head =
|
||||
(FAR sq_entry_t *)&session->updpool[0];
|
||||
session->updfree.tail =
|
||||
(FAR sq_entry_t *)&session->updpool[CONFIG_VNCSERVER_NUPDATES-1];
|
||||
|
||||
next = &session->updpool[0];
|
||||
for (i = 1; i < CONFIG_VNCSERVER_NUPDATES-1; i++)
|
||||
{
|
||||
curr = next;
|
||||
next = &session->updpool[i];
|
||||
curr->flink = next;
|
||||
}
|
||||
|
||||
next->flink = NULL;
|
||||
|
||||
/* Set the INITIALIZED state */
|
||||
|
||||
sem_reset(&session->updsem, CONFIG_VNCSERVER_NUPDATES);
|
||||
session->fb = fb;
|
||||
session->state = VNCSERVER_INITIALIZED;
|
||||
}
|
||||
@ -242,6 +266,7 @@ int vnc_server(int argc, FAR char *argv[])
|
||||
}
|
||||
|
||||
g_vnc_sessions[display] = session;
|
||||
sem_init(&session->updsem, 0, CONFIG_VNCSERVER_NUPDATES);
|
||||
|
||||
/* Loop... handling each each VNC client connection to this display. Only
|
||||
* a single client is allowed for each display.
|
||||
|
@ -43,9 +43,12 @@
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <semaphore.h>
|
||||
#include <pthread.h>
|
||||
#include <queue.h>
|
||||
|
||||
#include <nuttx/video/fb.h>
|
||||
#include <nuttx/video/rfb.h>
|
||||
#include <nuttx/nx/nxglib.h>
|
||||
#include <nuttx/nx/nx.h>
|
||||
#include <nuttx/net/net.h>
|
||||
@ -126,10 +129,21 @@
|
||||
# define CONFIG_VNCSERVER_UPDATER_STACKSIZE 2048
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_VNCSERVER_IOBUFFER_SIZE
|
||||
# define CONFIG_VNCSERVER_IOBUFFER_SIZE 80
|
||||
#ifndef CONFIG_VNCSERVER_INBUFFER_SIZE
|
||||
# define CONFIG_VNCSERVER_INBUFFER_SIZE 80
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_VNCSERVER_NUPDATES
|
||||
# define CONFIG_VNCSERVER_NUPDATES 48
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_VNCSERVER_UPDATE_BUFSIZE
|
||||
# define CONFIG_VNCSERVER_UPDATE_BUFSIZE 4096
|
||||
#endif
|
||||
|
||||
#define VNCSERVER_UPDATE_BUFSIZE \
|
||||
(CONFIG_VNCSERVER_UPDATE_BUFSIZE + SIZEOF_RFB_FRAMEBUFFERUPDATE_S(0))
|
||||
|
||||
/* Local framebuffer characteristics in bytes */
|
||||
|
||||
#define RFB_BYTESPERPIXEL ((RFB_BITSPERPIXEL + 7) >> 8)
|
||||
@ -168,6 +182,16 @@ enum vnc_server_e
|
||||
VNCSERVER_STOPPING /* The server has been asked to stop */
|
||||
};
|
||||
|
||||
/* This structure is used to queue FrameBufferUpdate event. It includes a
|
||||
* pointer to support singly linked list.
|
||||
*/
|
||||
|
||||
struct vnc_fbupdate_s
|
||||
{
|
||||
FAR struct vnc_fbupdate_s *flink;
|
||||
struct nxgl_rect_s rect; /* The enqueued update rectangle */
|
||||
};
|
||||
|
||||
struct vnc_session_s
|
||||
{
|
||||
/* NX graphics system */
|
||||
@ -185,15 +209,23 @@ struct vnc_session_s
|
||||
uint8_t colorfmt; /* Remote color format (See include/nuttx/fb.h) */
|
||||
uint8_t bpp; /* Remote bits per pixel */
|
||||
FAR uint8_t *fb; /* Allocated local frame buffer */
|
||||
|
||||
|
||||
/* Updater information */
|
||||
|
||||
pthread_t updater; /* Updater thread ID */
|
||||
|
||||
/* Update list information */
|
||||
|
||||
struct vnc_fbupdate_s updpool[CONFIG_VNCSERVER_NUPDATES];
|
||||
sq_queue_t updfree;
|
||||
sq_queue_t updqueue;
|
||||
sem_t exclsem;
|
||||
sem_t updsem;
|
||||
|
||||
/* I/O buffers for misc network send/receive */
|
||||
|
||||
uint8_t inbuf[CONFIG_VNCSERVER_IOBUFFER_SIZE];
|
||||
uint8_t outbuf[CONFIG_VNCSERVER_IOBUFFER_SIZE];
|
||||
uint8_t inbuf[CONFIG_VNCSERVER_INBUFFER_SIZE];
|
||||
uint8_t outbuf[VNCSERVER_UPDATE_BUFSIZE];
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -39,8 +39,11 @@
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <semaphore.h>
|
||||
#include <sched.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
#include <queue.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
@ -50,6 +53,81 @@
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: vnc_alloc_update
|
||||
*
|
||||
* Description:
|
||||
* Allocate one update structure by taking it from the freelist.
|
||||
*
|
||||
* Input Parameters:
|
||||
* session - A reference to the VNC session structure.
|
||||
*
|
||||
* Returned Value:
|
||||
* A non-NULL structure pointer should always be returned. This function
|
||||
* will wait if no structure is available.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static FAR struct vnc_fbupdate_s *
|
||||
vnc_alloc_update(FAR struct vnc_session_s *session)
|
||||
{
|
||||
FAR struct vnc_fbupdate_s *update;
|
||||
|
||||
/* Reserve one element from the free list. Lock the scheduler to assure
|
||||
* that the sq_remfirst() and the successful return for sem_wait are
|
||||
* atomic. Of course, the scheduler will be unlocked while we wait.
|
||||
*/
|
||||
|
||||
sched_lock();
|
||||
while (sem_wait(&session->updsem) < 0)
|
||||
{
|
||||
DEBUGASSERT(get_errno() == EINTR);
|
||||
}
|
||||
|
||||
/* It is reserved.. go get it */
|
||||
|
||||
update = (FAR struct vnc_fbupdate_s *)sq_remfirst(&session->updfree);
|
||||
sched_unlock();
|
||||
|
||||
DEBUGASSERT(update != NULL);
|
||||
return update;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: vnc_free_update
|
||||
*
|
||||
* Description:
|
||||
* Free one update structure by returning it from the freelist.
|
||||
*
|
||||
* Input Parameters:
|
||||
* Standard pthread arguments.
|
||||
*
|
||||
* Returned Value:
|
||||
* NULL is always returned.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void vnc_free_update(FAR struct vnc_session_s *session,
|
||||
FAR struct vnc_fbupdate_s *update)
|
||||
{
|
||||
/* Reserve one element from the free list. Lock the scheduler to assure
|
||||
* that the sq_addlast() and the sem_post() are atomic.
|
||||
*/
|
||||
|
||||
sched_lock();
|
||||
|
||||
/* Put the entry into the free list */
|
||||
|
||||
sq_addlast((FAR sq_entry_t *)update, &session->updfree);
|
||||
|
||||
/* Post the semaphore to indicate the availability of one more update */
|
||||
|
||||
sem_post(&session->updsem);
|
||||
DEBUGASSERT(session->updsem.semcount <= CONFIG_VNCSERVER_NUPDATES);
|
||||
|
||||
sched_unlock();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: vnc_updater
|
||||
*
|
||||
@ -189,12 +267,29 @@ int vnc_stop_updater(FAR struct vnc_session_s *session)
|
||||
int vnc_update_rectangle(FAR struct vnc_session_s *session,
|
||||
FAR const struct nxgl_rect_s *rect)
|
||||
{
|
||||
/* Make sure that the rectangle has a area */
|
||||
FAR struct vnc_fbupdate_s *update;
|
||||
|
||||
if (!nxgl_nullrect(rect))
|
||||
{
|
||||
#warning Missing logic
|
||||
}
|
||||
/* Make sure that the rectangle has a area */
|
||||
|
||||
if (!nxgl_nullrect(rect))
|
||||
{
|
||||
/* Allocate an update structure... waiting if necessary */
|
||||
|
||||
update = vnc_alloc_update(session);
|
||||
DEBUGASSERT(update != NULL);
|
||||
|
||||
/* Copy the rectangle into the update structure */
|
||||
|
||||
memcpy(&update->rect, rect, sizeof(struct nxgl_rect_s));
|
||||
|
||||
/* Add the upate to the end of the update queue. Lock the scheduler
|
||||
* to assure that the sq_addlast() is atomic.
|
||||
*/
|
||||
|
||||
sched_lock();
|
||||
sq_addlast((FAR sq_entry_t *)update, &session->updqueue);
|
||||
sched_unlock();
|
||||
}
|
||||
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user