269 lines
5.7 KiB
C
269 lines
5.7 KiB
C
#include "basic_include.h"
|
|
#include "lib/multimedia/msi.h"
|
|
#ifdef MORE_SRAM
|
|
#define FBQ_MALLOC os_malloc_psram
|
|
#define FBQ_FREE os_free_psram
|
|
#define FBQ_ZALLOC os_zalloc_psram
|
|
#else
|
|
#define FBQ_MALLOC os_malloc
|
|
#define FBQ_FREE os_free
|
|
#define FBQ_ZALLOC os_zalloc
|
|
#endif
|
|
|
|
int32 fbq_init(struct fbqueue *q, uint8 *qbuff, int32 qsize)
|
|
{
|
|
if (qbuff == NULL && qsize) {
|
|
qbuff = (uint8 *)FBQ_MALLOC(sizeof(struct framebuff *) * (qsize + 1));
|
|
q->alloc = 1;
|
|
}
|
|
|
|
ASSERT(qbuff);
|
|
if (qbuff && qsize) {
|
|
RB_INIT_R(&q->rbQ, (qsize + 1), (struct framebuff **)qbuff);
|
|
os_sema_init(&q->sema, 0);
|
|
q->reader_max = 1;
|
|
q->readers = NULL;
|
|
q->init = 1;
|
|
return RET_OK;
|
|
}
|
|
return RET_ERR;
|
|
}
|
|
|
|
int32 fbq_destory(struct fbqueue *q)
|
|
{
|
|
if (q && q->init) {
|
|
while (RB_COUNT(&q->rbQ)) {
|
|
fb_put(fbq_dequeue(q, 0));
|
|
}
|
|
if (q->alloc) {
|
|
FBQ_FREE(q->rbQ.rbq);
|
|
}
|
|
if (q->readers) {
|
|
FBQ_FREE(q->readers);
|
|
}
|
|
os_sema_del(&q->sema);
|
|
q->init = 0;
|
|
}
|
|
return RET_OK;
|
|
}
|
|
|
|
int32 fbq_enqueue(struct fbqueue *q, struct framebuff *fb)
|
|
{
|
|
int32 ret;
|
|
uint32 i;
|
|
uint32 rpos;
|
|
uint32 flags;
|
|
struct framebuff *last = NULL;
|
|
|
|
if (!q || !q->init || !fb) {
|
|
return 0;
|
|
}
|
|
|
|
fb_get(fb);
|
|
|
|
if (q->reader_max > 1) {
|
|
flags = disable_irq();
|
|
if (RB_FULL(&q->rbQ)) { // FULL ! move rpos.
|
|
last = q->rbQ.rbq[q->rbQ.rpos];
|
|
rpos = RB_NPOS(&q->rbQ, rpos, 1);
|
|
for (i = 0; i < q->reader_max; i++) {
|
|
if (q->readers[i] == q->rbQ.rpos) {
|
|
q->readers[i] = rpos;
|
|
}
|
|
}
|
|
q->rbQ.rpos = rpos;
|
|
}
|
|
q->rbQ.rbq[q->rbQ.wpos] = fb;
|
|
q->rbQ.wpos = RB_NPOS(&q->rbQ, wpos, 1);
|
|
enable_irq(flags);
|
|
|
|
fb_put(last);
|
|
return 1;
|
|
} else {
|
|
ret = RB_INT_SET(&q->rbQ, fb);
|
|
if (ret) {
|
|
os_sema_up(&q->sema);
|
|
return 1;
|
|
} else {
|
|
fb_put(fb);
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
static int32 fbq_trace_pos(struct fbqueue *q, struct framebuff *fb, uint32 start, uint32 end, int8 discard)
|
|
{
|
|
uint32 pos;
|
|
for (pos = start; pos < end; pos++) {
|
|
if (q->rbQ.rbq[pos] == fb) {
|
|
if (discard) {
|
|
q->rbQ.rbq[pos] = NULL;
|
|
}
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int32 fbq_trace(struct fbqueue *q, struct framebuff *fb, int8 discard)
|
|
{
|
|
uint32 ret = 0;
|
|
uint32 flag;
|
|
|
|
if (!q || !q->init || !fb) {
|
|
return 0;
|
|
}
|
|
|
|
flag = disable_irq();
|
|
if (q->rbQ.rpos <= q->rbQ.wpos) {
|
|
ret = fbq_trace_pos(q, fb, q->rbQ.rpos, q->rbQ.wpos, discard);
|
|
} else {
|
|
ret = fbq_trace_pos(q, fb, 0, q->rbQ.wpos, discard);
|
|
if (!ret) {
|
|
ret = fbq_trace_pos(q, fb, q->rbQ.rpos, q->rbQ.qsize, discard);
|
|
}
|
|
}
|
|
enable_irq(flag);
|
|
|
|
if (ret && discard) {
|
|
fb_put(fb);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
struct framebuff *fbq_dequeue(struct fbqueue *q, uint32 tmo_ms)
|
|
{
|
|
uint64 jiff;
|
|
struct framebuff *fb;
|
|
|
|
if (!q || !q->init) {
|
|
return NULL;
|
|
}
|
|
|
|
do {
|
|
if (!RB_EMPTY(&q->rbQ)) {
|
|
RB_GET(&q->rbQ, fb);
|
|
return fb;
|
|
}
|
|
|
|
if(tmo_ms == 0){
|
|
return NULL;
|
|
}
|
|
|
|
jiff = os_jiffies();
|
|
os_sema_down(&q->sema, tmo_ms);
|
|
jiff = DIFF_JIFFIES(jiff, os_jiffies());
|
|
jiff = os_jiffies_to_msecs(jiff);
|
|
if (jiff >= tmo_ms) {
|
|
break;
|
|
}
|
|
|
|
tmo_ms -= jiff;
|
|
} while (tmo_ms);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
struct framebuff *fbq_dequeue_r(struct fbqueue *q, uint8 reader)
|
|
{
|
|
uint32 i = 0;
|
|
uint32 pos;
|
|
uint32 flags;
|
|
struct framebuff *fb = NULL;
|
|
struct framebuff *last = NULL;
|
|
|
|
if (!q || !q->init) {
|
|
return NULL;
|
|
}
|
|
|
|
ASSERT(reader > 0 && reader <= q->reader_max);
|
|
ASSERT(q->readers[reader - 1] != 0xffffffff);
|
|
|
|
reader -= 1;
|
|
flags = disable_irq();
|
|
pos = q->readers[reader];
|
|
|
|
if (pos == q->rbQ.wpos) { //no fb for this reader
|
|
enable_irq(flags);
|
|
return fb;
|
|
}
|
|
|
|
fb = q->rbQ.rbq[pos];
|
|
q->readers[reader] = NEXT_RPOS(pos, q->rbQ.qsize, 1);
|
|
|
|
//move rpos: find min pos.
|
|
pos = 0xffffffff;
|
|
for (i = 0; i < q->reader_max; i++) {
|
|
if (q->readers[i] < pos) {
|
|
pos = q->readers[i];
|
|
}
|
|
}
|
|
if (pos != 0xffffffff && q->rbQ.rpos != pos) {
|
|
last = q->rbQ.rbq[q->rbQ.rpos];
|
|
q->rbQ.rpos = pos;
|
|
}
|
|
|
|
fb_get(fb);
|
|
enable_irq(flags);
|
|
|
|
fb_put(last);
|
|
return fb;
|
|
}
|
|
|
|
int32 fbq_conf_readers(struct fbqueue *q, uint16 reader_max)
|
|
{
|
|
uint32 i;
|
|
uint32 *ptr;
|
|
|
|
if (!q || !q->init || reader_max <= 1 || q->readers) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
ptr = (uint32 *)FBQ_MALLOC(reader_max * sizeof(uint32));
|
|
if (ptr) {
|
|
for (i = 0; i < q->reader_max; i++) {
|
|
q->readers[i] = 0xffffffff;
|
|
}
|
|
q->readers = ptr;
|
|
q->reader_max = reader_max;
|
|
return RET_OK;
|
|
}
|
|
return -ENOMEM;
|
|
}
|
|
|
|
int32 fbq_open_reader(struct fbqueue *q)
|
|
{
|
|
uint32 i;
|
|
uint32 flags;
|
|
|
|
if (!q || !q->init || !q->readers) {
|
|
return 0;
|
|
}
|
|
|
|
flags = disable_irq();
|
|
for (i = 0; i < q->reader_max; i++) {
|
|
if (q->readers[i] == 0xffffffff) {
|
|
q->readers[i] = q->rbQ.rpos;
|
|
break;
|
|
}
|
|
}
|
|
enable_irq(flags);
|
|
return i < q->reader_max ? (i + 1) : 0;
|
|
}
|
|
|
|
int32 fbq_close_reader(struct fbqueue *q, uint8 reader)
|
|
{
|
|
uint32 flags;
|
|
|
|
if (!q || !q->init || !q->readers) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
ASSERT(reader > 0 && reader <= q->reader_max);
|
|
flags = disable_irq();
|
|
q->readers[reader - 1] = 0xffffffff;
|
|
enable_irq(flags);
|
|
return RET_OK;
|
|
}
|
|
|