mirror of
https://github.com/apache/nuttx.git
synced 2026-06-05 15:58:59 +08:00
VNC: Add some rectangle queuing logic
This commit is contained in:
@@ -71,6 +71,26 @@ config VNCSERVER_SCREENHEIGHT
|
|||||||
int "Framebuffer height (rows)"
|
int "Framebuffer height (rows)"
|
||||||
default 240
|
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
|
config VNCSERVER_KBDENCODE
|
||||||
bool "Encode keyboard input"
|
bool "Encode keyboard input"
|
||||||
default n
|
default n
|
||||||
@@ -79,8 +99,8 @@ config VNCSERVER_KBDENCODE
|
|||||||
Use a special encoding of keyboard characters as defined in
|
Use a special encoding of keyboard characters as defined in
|
||||||
include/nuttx/input/kbd_coded.h.
|
include/nuttx/input/kbd_coded.h.
|
||||||
|
|
||||||
config VNCSERVER_IOBUFFER_SIZE
|
config VNCSERVER_INBUFFER_SIZE
|
||||||
int "I/O buffer size
|
int "Input buffer size
|
||||||
default 80
|
default 80
|
||||||
|
|
||||||
endif # VNCSERVER
|
endif # VNCSERVER
|
||||||
|
|||||||
@@ -274,7 +274,7 @@ int vnc_negotiate(FAR struct vnc_session_s *session)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
(void)psock_recv(&session->connect, session->inbuf,
|
(void)psock_recv(&session->connect, session->inbuf,
|
||||||
CONFIG_VNCSERVER_IOBUFFER_SIZE, 0);
|
CONFIG_VNCSERVER_INBUFFER_SIZE, 0);
|
||||||
|
|
||||||
session->state = VNCSERVER_CONFIGURED;
|
session->state = VNCSERVER_CONFIGURED;
|
||||||
return OK;
|
return OK;
|
||||||
|
|||||||
@@ -41,7 +41,9 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <semaphore.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <queue.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
@@ -50,6 +52,7 @@
|
|||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
|
||||||
#include <nuttx/kmalloc.h>
|
#include <nuttx/kmalloc.h>
|
||||||
|
#include <nuttx/semaphore.h>
|
||||||
#include <nuttx/net/net.h>
|
#include <nuttx/net/net.h>
|
||||||
|
|
||||||
#include "vnc_server.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,
|
static void vnc_reset_session(FAR struct vnc_session_s *session,
|
||||||
FAR uint8_t *fb)
|
FAR uint8_t *fb)
|
||||||
{
|
{
|
||||||
|
FAR struct vnc_fbupdate_s *curr;
|
||||||
|
FAR struct vnc_fbupdate_s *next;
|
||||||
|
int i;
|
||||||
|
|
||||||
/* Close any open sockets */
|
/* Close any open sockets */
|
||||||
|
|
||||||
if (session->state >= VNCSERVER_CONNECTED)
|
if (session->state >= VNCSERVER_CONNECTED)
|
||||||
@@ -99,12 +106,29 @@ static void vnc_reset_session(FAR struct vnc_session_s *session,
|
|||||||
psock_close(&session->listen);
|
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->fb = fb;
|
||||||
session->state = VNCSERVER_INITIALIZED;
|
session->state = VNCSERVER_INITIALIZED;
|
||||||
}
|
}
|
||||||
@@ -242,6 +266,7 @@ int vnc_server(int argc, FAR char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
g_vnc_sessions[display] = session;
|
g_vnc_sessions[display] = session;
|
||||||
|
sem_init(&session->updsem, 0, CONFIG_VNCSERVER_NUPDATES);
|
||||||
|
|
||||||
/* Loop... handling each each VNC client connection to this display. Only
|
/* Loop... handling each each VNC client connection to this display. Only
|
||||||
* a single client is allowed for each display.
|
* a single client is allowed for each display.
|
||||||
|
|||||||
@@ -43,9 +43,12 @@
|
|||||||
#include <nuttx/config.h>
|
#include <nuttx/config.h>
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <semaphore.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
#include <queue.h>
|
||||||
|
|
||||||
#include <nuttx/video/fb.h>
|
#include <nuttx/video/fb.h>
|
||||||
|
#include <nuttx/video/rfb.h>
|
||||||
#include <nuttx/nx/nxglib.h>
|
#include <nuttx/nx/nxglib.h>
|
||||||
#include <nuttx/nx/nx.h>
|
#include <nuttx/nx/nx.h>
|
||||||
#include <nuttx/net/net.h>
|
#include <nuttx/net/net.h>
|
||||||
@@ -126,10 +129,21 @@
|
|||||||
# define CONFIG_VNCSERVER_UPDATER_STACKSIZE 2048
|
# define CONFIG_VNCSERVER_UPDATER_STACKSIZE 2048
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef CONFIG_VNCSERVER_IOBUFFER_SIZE
|
#ifndef CONFIG_VNCSERVER_INBUFFER_SIZE
|
||||||
# define CONFIG_VNCSERVER_IOBUFFER_SIZE 80
|
# define CONFIG_VNCSERVER_INBUFFER_SIZE 80
|
||||||
#endif
|
#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 */
|
/* Local framebuffer characteristics in bytes */
|
||||||
|
|
||||||
#define RFB_BYTESPERPIXEL ((RFB_BITSPERPIXEL + 7) >> 8)
|
#define RFB_BYTESPERPIXEL ((RFB_BITSPERPIXEL + 7) >> 8)
|
||||||
@@ -168,6 +182,16 @@ enum vnc_server_e
|
|||||||
VNCSERVER_STOPPING /* The server has been asked to stop */
|
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
|
struct vnc_session_s
|
||||||
{
|
{
|
||||||
/* NX graphics system */
|
/* NX graphics system */
|
||||||
@@ -190,10 +214,18 @@ struct vnc_session_s
|
|||||||
|
|
||||||
pthread_t updater; /* Updater thread ID */
|
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 */
|
/* I/O buffers for misc network send/receive */
|
||||||
|
|
||||||
uint8_t inbuf[CONFIG_VNCSERVER_IOBUFFER_SIZE];
|
uint8_t inbuf[CONFIG_VNCSERVER_INBUFFER_SIZE];
|
||||||
uint8_t outbuf[CONFIG_VNCSERVER_IOBUFFER_SIZE];
|
uint8_t outbuf[VNCSERVER_UPDATE_BUFSIZE];
|
||||||
};
|
};
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
|||||||
@@ -39,8 +39,11 @@
|
|||||||
|
|
||||||
#include <nuttx/config.h>
|
#include <nuttx/config.h>
|
||||||
|
|
||||||
|
#include <semaphore.h>
|
||||||
#include <sched.h>
|
#include <sched.h>
|
||||||
|
#include <string.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
#include <queue.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
@@ -50,6 +53,81 @@
|
|||||||
* Private Functions
|
* 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
|
* 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,
|
int vnc_update_rectangle(FAR struct vnc_session_s *session,
|
||||||
FAR const struct nxgl_rect_s *rect)
|
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))
|
/* Make sure that the rectangle has a area */
|
||||||
{
|
|
||||||
#warning Missing logic
|
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;
|
return -ENOSYS;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user