aboutsummaryrefslogtreecommitdiffstats
path: root/src/gqueue
diff options
context:
space:
mode:
authorinmarket <andrewh@inmarket.com.au>2014-03-20 23:33:32 +1000
committerinmarket <andrewh@inmarket.com.au>2014-03-20 23:33:32 +1000
commit8b9d31ef902b80c27065ab542c4783d6194f420f (patch)
treeb38673c199ba319d057ca6b17890ec8c2e4330e7 /src/gqueue
parente4d6884bca6ca422115765dab60039bd6296ccab (diff)
downloaduGFX-8b9d31ef902b80c27065ab542c4783d6194f420f.tar.gz
uGFX-8b9d31ef902b80c27065ab542c4783d6194f420f.tar.bz2
uGFX-8b9d31ef902b80c27065ab542c4783d6194f420f.zip
Move queued buffer code from gaudio into gqueue
Diffstat (limited to 'src/gqueue')
-rw-r--r--src/gqueue/gqueue.c56
-rw-r--r--src/gqueue/sys_defs.h122
-rw-r--r--src/gqueue/sys_options.h6
-rw-r--r--src/gqueue/sys_rules.h7
4 files changed, 167 insertions, 24 deletions
diff --git a/src/gqueue/gqueue.c b/src/gqueue/gqueue.c
index b7ecb032..1b2d4618 100644
--- a/src/gqueue/gqueue.c
+++ b/src/gqueue/gqueue.c
@@ -14,6 +14,21 @@
#if GFX_USE_GQUEUE
+#if GQUEUE_NEED_BUFFERS
+ static gfxQueueGSync bufferFreeList;
+#endif
+
+void _gqueueInit(void)
+{
+ #if GQUEUE_NEED_BUFFERS
+ gfxQueueGSyncInit(&bufferFreeList);
+ #endif
+}
+
+void _gqueueDeinit(void)
+{
+}
+
#if GQUEUE_NEED_ASYNC
void gfxQueueASyncInit(gfxQueueASync *pqueue) {
pqueue->head = pqueue->tail = 0;
@@ -123,6 +138,10 @@
pqueue->head = pqueue->tail = 0;
gfxSemInit(&pqueue->sem, 0, MAX_SEMAPHORE_COUNT);
}
+ void gfxQueueGSyncDeinit(gfxQueueGSync *pqueue) {
+ pqueue->head = pqueue->tail = 0;
+ gfxSemDestroy(&pqueue->sem);
+ }
gfxQueueGSyncItem *gfxQueueGSyncGet(gfxQueueGSync *pqueue, delaytime_t ms) {
gfxQueueGSyncItem *pi;
@@ -232,6 +251,11 @@
pqueue->head = pqueue->tail = 0;
gfxSemInit(&pqueue->sem, 0, MAX_SEMAPHORE_COUNT);
}
+ void gfxQueueFSyncDeinit(gfxQueueGSync *pqueue) {
+ while(gfxQueueFSyncGet(pqueue, TIME_IMMEDIATE));
+ pqueue->head = pqueue->tail = 0;
+ gfxSemDestroy(&pqueue->sem);
+ }
gfxQueueFSyncItem *gfxQueueFSyncGet(gfxQueueFSync *pqueue, delaytime_t ms) {
gfxQueueFSyncItem *pi;
@@ -333,4 +357,36 @@
}
#endif
+#if GQUEUE_NEED_BUFFERS
+ bool_t gfxBufferAlloc(unsigned num, size_t size) {
+ GDataBuffer *pd;
+
+ if (num < 1)
+ return FALSE;
+
+ // Round up to a multiple of 4 to prevent problems with structure alignment
+ size = (size + 3) & ~0x03;
+
+ // Allocate the memory
+ if (!(pd = gfxAlloc((size+sizeof(GDataBuffer)) * num)))
+ return FALSE;
+
+ // Add each of them to our free list
+ for(;num--; pd = (GDataBuffer *)((char *)(pd+1)+size)) {
+ pd->size = size;
+ gfxBufferRelease(pd);
+ }
+
+ return TRUE;
+ }
+
+ void gfxBufferRelease(GDataBuffer *pd) { gfxQueueGSyncPut(&bufferFreeList, (gfxQueueGSyncItem *)pd); }
+ void gfxBufferReleaseI(GDataBuffer *pd) { gfxQueueGSyncPutI(&bufferFreeList, (gfxQueueGSyncItem *)pd); }
+ GDataBuffer *gfxBufferGet(delaytime_t ms) { return (GDataBuffer *)gfxQueueGSyncGet(&bufferFreeList, ms); }
+ GDataBuffer *gfxBufferGetI(void) { return (GDataBuffer *)gfxQueueGSyncGetI(&bufferFreeList); }
+ bool_t gfxBufferIsAvailable(void) { return bufferFreeList.head != 0; }
+
+#endif
+
+
#endif /* GFX_USE_GQUEUE */
diff --git a/src/gqueue/sys_defs.h b/src/gqueue/sys_defs.h
index 4351d4ad..ea3f176e 100644
--- a/src/gqueue/sys_defs.h
+++ b/src/gqueue/sys_defs.h
@@ -23,6 +23,8 @@
* operations because fully synchronous queues have the highest storage requirements. The other queue types are
* optimizations. Efficiency IS important to use (particularly RAM efficiency).
* In practice we only implement ASync, GSync and FSync queues as PSync queues are of dubious value.
+ * <br>
+ * We also define GDataBuffer which is a data buffer that supports being queued.
* @{
*/
@@ -32,45 +34,52 @@
#if GFX_USE_GQUEUE || defined(__DOXYGEN__)
/**
+ * @brief A queue item
+ * @{
+ */
+typedef struct gfxQueueASyncItem {
+ struct gfxQueueASyncItem *next;
+} gfxQueueASyncItem, gfxQueueGSyncItem;
+
+typedef struct gfxQueueFSyncItem {
+ struct gfxQueueFSyncItem *next;
+ gfxSem sem;
+} gfxQueueFSyncItem;
+/* @} */
+
+/**
* @brief A queue
* @{
*/
typedef struct gfxQueueASync {
- struct gfxQueueASyncItem *head;
- struct gfxQueueASyncItem *tail;
+ gfxQueueASyncItem *head;
+ gfxQueueASyncItem *tail;
} gfxQueueASync;
typedef struct gfxQueueGSync {
- struct gfxQueueGSyncItem *head;
- struct gfxQueueGSyncItem *tail;
- gfxSem sem;
+ gfxQueueGSyncItem *head;
+ gfxQueueGSyncItem *tail;
+ gfxSem sem;
} gfxQueueGSync;
typedef struct gfxQueueFSync {
- struct gfxQueueFSyncItem *head;
- struct gfxQueueFSyncItem *tail;
- gfxSem sem;
+ gfxQueueFSyncItem *head;
+ gfxQueueFSyncItem *tail;
+ gfxSem sem;
} gfxQueueFSync;
/* @} */
/**
- * @brief A queue item
- * @{
+ * @brief A Data Buffer Queue
+ * @note This structure is followed immediately by the data itself.
+ * When allocating the buffers for the data put this structure
+ * at the beginning of the buffer.
*/
-typedef struct gfxQueueASyncItem {
- struct gfxQueueASyncItem *next;
-} gfxQueueASyncItem;
-
-typedef struct gfxQueueGSyncItem {
- struct gfxQueueGSyncItem *next;
-} gfxQueueGSyncItem;
-
-typedef struct gfxQueueFSyncItem {
- struct gfxQueueFSyncItem *next;
- gfxSem sem;
-} gfxQueueFSyncItem;
-/* @} */
-
+typedef struct GDataBuffer {
+ gfxQueueGSyncItem next; // @< Used for queueing the buffers
+ size_t size; // @< The size of the buffer area following this structure (in bytes)
+ size_t len; // @< The length of the data in the buffer area (in bytes)
+} GDataBuffer;
/*===========================================================================*/
/* Function declarations. */
@@ -98,6 +107,19 @@ void gfxQueueFSyncInit(gfxQueueFSync *pqueue);
/* @} */
/**
+ * @brief De-Initialise a queue.
+ *
+ * @param[in] pqueue A pointer to the queue
+ *
+ * @api
+ * @{
+ */
+#define gfxQueueASyncDeinit(pqueue)
+void gfxQueueGSyncDeinit(gfxQueueGSync *pqueue);
+void gfxQueueFSyncDeinit(gfxQueueFSync *pqueue);
+/* @} */
+
+/**
* @brief Get an item from the head of the queue (and remove it from the queue).
* @return NULL if the timeout expires before an item is available
*
@@ -286,6 +308,58 @@ bool_t gfxQueueFSyncIsInI(gfxQueueFSync *pqueue, const gfxQueueFSyncItem *pitem)
#define gfxQueueFSyncNextI(pitem) ((const gfxQueueFSyncItem *)((pitem)->next))
/* @} */
+/**
+ * @brief Allocate some buffers and put them on the free list
+ * @return TRUE is it succeeded. FALSE on allocation failure.
+ *
+ * @param[in] num The number of buffers to allocate
+ * @param[in] size The size (in bytes) of each buffer
+ *
+ * @api
+ */
+bool_t gfxBufferAlloc(unsigned num, size_t size);
+
+/**
+ * @brief Is there one or more buffers currently available on the free list
+ * @return TRUE if there are buffers in the free list
+ *
+ * @api
+ * @{
+ */
+bool_t gfxBufferIsAvailable(void);
+/* @} */
+
+/**
+ * @brief Get a buffer from the free list
+ * @return A GDataBuffer pointer or NULL if the timeout is exceeded
+ *
+ * @params[in] ms The maximum amount of time in milliseconds to wait for a buffer if one is not available.
+ *
+ * @api
+ * @{
+ */
+GDataBuffer *gfxBufferGet(delaytime_t ms);
+GDataBuffer *gfxBufferGetI(void);
+/* @} */
+
+/**
+ * @brief Release a buffer back to the free list
+ *
+ * @param[in] pd The buffer to put (back) on the free-list.
+ *
+ * @note This call should be used to return any buffers that were taken from
+ * the free-list once they have been finished with. It can also be used
+ * to put new buffers onto the free-list. Just make sure the "size" field
+ * of the GDataBuffer structure has been filled in first.
+ *
+ * @api
+ * @{
+ */
+void gfxBufferRelease(GDataBuffer *pd);
+void gfxBufferReleaseI(GDataBuffer *pd);
+/* @} */
+
+
#ifdef __cplusplus
}
#endif
diff --git a/src/gqueue/sys_options.h b/src/gqueue/sys_options.h
index 7c8627ce..169cf116 100644
--- a/src/gqueue/sys_options.h
+++ b/src/gqueue/sys_options.h
@@ -41,6 +41,12 @@
#ifndef GQUEUE_NEED_FSYNC
#define GQUEUE_NEED_FSYNC FALSE
#endif
+ /**
+ * @brief Enable Queue-able Data Buffers
+ */
+ #ifndef GQUEUE_NEED_BUFFERS
+ #define GQUEUE_NEED_BUFFERS FALSE
+ #endif
/**
* @}
*
diff --git a/src/gqueue/sys_rules.h b/src/gqueue/sys_rules.h
index baeb073d..831952d8 100644
--- a/src/gqueue/sys_rules.h
+++ b/src/gqueue/sys_rules.h
@@ -17,6 +17,13 @@
#define _GQUEUE_RULES_H
#if GFX_USE_GQUEUE
+ #if GQUEUE_NEED_BUFFERS && !GQUEUE_NEED_GSYNC
+ #if GFX_DISPLAY_RULE_WARNINGS
+ #warning "GQUEUE: GQUEUE_NEED_GSYNC is required if GQUEUE_NEED_BUFFERS is TRUE. It has been turned on for you."
+ #endif
+ #undef GQUEUE_NEED_GSYNC
+ #define GQUEUE_NEED_GSYNC TRUE
+ #endif
#endif
#endif /* _GQUEUE_RULES_H */