openmv/lib/imlib/framebuffer.h
iabdalkader 0458db2130 misc: Use updated mutex API.
Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2025-07-25 20:20:57 +02:00

182 lines
7.4 KiB
C

/*
* SPDX-License-Identifier: MIT
*
* Copyright (C) 2013-2024 OpenMV, LLC.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* Framebuffer functions.
*/
#ifndef __FRAMEBUFFER_H__
#define __FRAMEBUFFER_H__
#include <stdint.h>
#include "imlib.h"
#include "omv_common.h"
#include "common/queue.h"
#include "common/mutex.h"
#ifndef FRAMEBUFFER_ALIGNMENT
#define FRAMEBUFFER_ALIGNMENT OMV_CACHE_LINE_SIZE
#endif
// TODO these should just be removed.
#define framebuffer_get_width(fb) (fb->w)
#define framebuffer_get_height(fb) (fb->h)
#define framebuffer_get_depth(fb) (fb->bpp)
#define framebuffer_get_buffer_size(fb) (fb->buf_size)
// If FB_FLAG_CHECK_LAST is set and this is the last buffer in
// the free queue the release logic depends on the buffer mode:
//
// - Single/FIFO: The buffer is released.
// - Double buffer: The buffer is not released.
// - Triple buffer: The last used buffer is released first.
typedef enum {
FB_FLAG_NONE = (1 << 0), // No special flags.
FB_FLAG_USED = (1 << 1), // Acquire from used / Release to free.
FB_FLAG_FREE = (1 << 2), // Acquire from free / Release to used.
FB_FLAG_PEEK = (1 << 3), // Acquire a buffer and keep it in the queue.
FB_FLAG_CHECK_LAST = (1 << 6), // Check if last buffer before releasing.
FB_FLAG_INVALIDATE = (1 << 7), // Invalidate buffer when acquired/released.
} framebuffer_flags_t;
// The frame buffer memory is used for the following:
//
// - Buffer queues: If the number of video buffers exceeds 3.
// - Video buffers: Consisting of a header followed by the buffer.
// - Unused memory: Available for buffer expansion or fb_alloc.
// - fb_alloc memory: Only for statically allocated frame buffers.
//
// Dynamic Frame Buffer Memory Layout
// raw_base pool_start pool_end raw_end
// ▼ ▼ ▼ ▼
// ┌────────────────────────────────────────────────────────────┐
// │ Queues¹ | Frame Buffers Memory | Unused FB Memory² │
// └────────────────────────────────────────────────────────────┘
//
// For static frame buffers, fb_alloc uses a fixed end region and
// may use the free space for transient allocations if available.
//
// Static Frame Buffer Memory Layout
// fb_start pool_start pool_end fb_alloc_sp fb_alloc_end
// ▼ ▼ ▼ ▼ ▼
// ┌────────────────────────────────────────────────────────────┐
// │ Queues¹ | Buffers | Unused FB Memory² | Fixed FB Alloc │
// └────────────────────────────────────────────────────────────┘
// ¹ Queues use frame buffer memory only if count > 3, otherwise
// they're statically allocated to keep small buffers in SRAM.
//
// ² Unused frame buffer space can be used to expand buffers up
// to the maximum available size (raw size minus queue size).
typedef struct framebuffer {
int32_t x, y, w, h, u, v;
PIXFORMAT_STRUCT;
bool dynamic; // Dynamically allocated or not.
bool expanded; // True if buffers were expanded.
size_t raw_size; // Raw buffer size and address.
char *raw_base;
size_t buf_size; // Buffers size and count
size_t buf_count;
size_t frame_size; // Actual frame size
queue_t *used_queue;
queue_t *free_queue;
// Static memory for small queues.
char raw_static[queue_calc_size(3) * 2];
} framebuffer_t;
// Drivers can add more flags:
// VB_FLAG_EXAMPLE1 (VB_FLAG_LAST << 0)
// VB_FLAG_EXAMPLE2 (VB_FLAG_LAST << 1)
typedef enum {
VB_FLAG_NONE = (1 << 0),
VB_FLAG_USED = (1 << 1),
VB_FLAG_OVERFLOW = (1 << 2),
VB_FLAG_LAST = (1 << 3),
} vbuffer_flags_t;
typedef struct vbuffer {
int32_t offset; // Write offset into the buffer (used by some drivers).
uint32_t flags; // Flags, see above.
OMV_ATTR_ALIGNED(uint8_t data[], FRAMEBUFFER_ALIGNMENT); // Data.
} vbuffer_t;
typedef struct jpegbuffer {
int32_t w, h;
int32_t size;
int32_t enabled;
int32_t quality;
uint8_t *pixels;
mutex_t lock;
} jpegbuffer_t;
void framebuffer_init0();
// Initializes a frame buffer instance.
void framebuffer_init(framebuffer_t *fb, void *buff, size_t size, bool dynamic);
// Initializes an image from the frame buffer.
void framebuffer_init_image(framebuffer_t *fb, image_t *img);
// Sets the frame buffer from an image.
void framebuffer_init_from_image(framebuffer_t *fb, image_t *img);
// Return the static frame buffer instance.
framebuffer_t *framebuffer_get(size_t id);
// Returns a pointer to the end of the framebuffer(s).
char *framebuffer_pool_end(framebuffer_t *fb);
// Clear the framebuffer FIFO.
void framebuffer_flush(framebuffer_t *fb);
// Change the number of buffers in the frame buffer.
// If expand is true, the buffer size will expand to use all of the
// available memory, otherwise it will equal the current frame size.
int framebuffer_resize(framebuffer_t *fb, size_t count, bool expand);
// Return true if free queue is not empty.
bool framebuffer_writable(framebuffer_t *fb);
// Return true if used queue is not empty.
bool framebuffer_readable(framebuffer_t *fb);
// FB_FLAG_USED: acquire buffer from used queue.
// FB_FLAG_FREE: acquire buffer from free queue.
vbuffer_t *framebuffer_acquire(framebuffer_t *fb, uint32_t flags);
// FB_FLAG_USED: release buffer from used queue.
// FB_FLAG_FREE: release buffer from free queue.
// Note: Returns NULL if the buffer was Not released.
vbuffer_t *framebuffer_release(framebuffer_t *fb, uint32_t flags);
// Reset a vbuffer state.
static inline void framebuffer_reset(vbuffer_t *buffer) {
memset(buffer, 0, offsetof(vbuffer_t, data));
}
// Compress src image to the JPEG buffer if src is mutable,
// otherwise copy src to the JPEG buffer.
void framebuffer_update_jpeg_buffer(image_t *src);
// Use this macro to get a pointer to the JPEG buffer.
extern jpegbuffer_t jpegbuffer;
#define JPEG_FB() (&jpegbuffer)
#endif /* __FRAMEBUFFER_H__ */