doc: renamed project
This commit is contained in:
committed by
Sylvan Arnold
parent
244e516bd8
commit
32618389d1
28
pico-sensor/McuLib/LittlevGL/lvgl/src/draw/sdl/README.md
Normal file
28
pico-sensor/McuLib/LittlevGL/lvgl/src/draw/sdl/README.md
Normal file
@@ -0,0 +1,28 @@
|
||||
# SDL_Renderer Based Drawing Functions
|
||||
|
||||
In LVGL, drawing was performed by CPU. To improve drawing performance on platforms with GPU,
|
||||
we should perform drawing operations on GPU if possible.
|
||||
|
||||
This implementation has moved most bitmap blending and drawing procedures to utilize SDL_Renderer,
|
||||
which takes advantages of hardware acceleration APIs like DirectX or OpenGL.
|
||||
|
||||
This implementation can be also considered as a reference implementation, for contributors wants to
|
||||
develop accelerated drawing functions with other APIs such as OpenGL/OpenGL ES.
|
||||
|
||||
## Caveats
|
||||
`lv_draw_arc`, `lv_draw_line` is not enabled, due to incomplete implementation. So lines and arcs will
|
||||
have significant impact to drawing performances.
|
||||
|
||||
Performance of this implementation still has room to improve. Or we should use more powerful APIs
|
||||
such as OpenGL.
|
||||
|
||||
## Notices for files
|
||||
|
||||
### `lv_draw_sdl_stack_blur.c`
|
||||
|
||||
Contains modified code from [android-stackblur](https://github.com/kikoso/android-stackblur) project.
|
||||
Apache License 2.0
|
||||
|
||||
### `lv_draw_sdl_lru.c`/`lv_draw_sdl_lru.h`
|
||||
|
||||
Contains modified code from [C-LRU-Cache](https://github.com/willcannings/C-LRU-Cache) project. No license defined.
|
||||
103
pico-sensor/McuLib/LittlevGL/lvgl/src/draw/sdl/lv_draw_sdl.c
Normal file
103
pico-sensor/McuLib/LittlevGL/lvgl/src/draw/sdl/lv_draw_sdl.c
Normal file
@@ -0,0 +1,103 @@
|
||||
/**
|
||||
* @file lv_draw_sdl.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
|
||||
#include "../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_GPU_SDL
|
||||
|
||||
#include "lv_draw_sdl.h"
|
||||
#include "lv_draw_sdl_utils.h"
|
||||
#include "lv_draw_sdl_texture_cache.h"
|
||||
#include "lv_draw_sdl_layer.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
void lv_draw_sdl_draw_rect(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords);
|
||||
|
||||
lv_res_t lv_draw_sdl_img_core(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * draw_dsc,
|
||||
const lv_area_t * coords, const void * src);
|
||||
|
||||
void lv_draw_sdl_draw_letter(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc, const lv_point_t * pos_p,
|
||||
uint32_t letter);
|
||||
|
||||
void lv_draw_sdl_draw_line(lv_draw_ctx_t * draw_ctx, const lv_draw_line_dsc_t * dsc, const lv_point_t * point1,
|
||||
const lv_point_t * point2);
|
||||
|
||||
void lv_draw_sdl_draw_arc(lv_draw_ctx_t * draw_ctx, const lv_draw_arc_dsc_t * dsc, const lv_point_t * center,
|
||||
uint16_t radius, uint16_t start_angle, uint16_t end_angle);
|
||||
|
||||
void lv_draw_sdl_polygon(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * draw_dsc, const lv_point_t * points,
|
||||
uint16_t point_cnt);
|
||||
|
||||
void lv_draw_sdl_draw_bg(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords);
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_draw_sdl_init_ctx(lv_disp_drv_t * disp_drv, lv_draw_ctx_t * draw_ctx)
|
||||
{
|
||||
_lv_draw_sdl_utils_init();
|
||||
lv_memset_00(draw_ctx, sizeof(lv_draw_sdl_ctx_t));
|
||||
draw_ctx->draw_rect = lv_draw_sdl_draw_rect;
|
||||
draw_ctx->draw_img = lv_draw_sdl_img_core;
|
||||
draw_ctx->draw_letter = lv_draw_sdl_draw_letter;
|
||||
draw_ctx->draw_line = lv_draw_sdl_draw_line;
|
||||
draw_ctx->draw_arc = lv_draw_sdl_draw_arc;
|
||||
draw_ctx->draw_polygon = lv_draw_sdl_polygon;
|
||||
draw_ctx->draw_bg = lv_draw_sdl_draw_bg;
|
||||
draw_ctx->layer_init = lv_draw_sdl_layer_init;
|
||||
draw_ctx->layer_blend = lv_draw_sdl_layer_blend;
|
||||
draw_ctx->layer_destroy = lv_draw_sdl_layer_destroy;
|
||||
draw_ctx->layer_instance_size = sizeof(lv_draw_sdl_layer_ctx_t);
|
||||
lv_draw_sdl_ctx_t * draw_ctx_sdl = (lv_draw_sdl_ctx_t *) draw_ctx;
|
||||
draw_ctx_sdl->renderer = ((lv_draw_sdl_drv_param_t *) disp_drv->user_data)->renderer;
|
||||
draw_ctx_sdl->internals = lv_mem_alloc(sizeof(lv_draw_sdl_context_internals_t));
|
||||
lv_memset_00(draw_ctx_sdl->internals, sizeof(lv_draw_sdl_context_internals_t));
|
||||
lv_draw_sdl_texture_cache_init(draw_ctx_sdl);
|
||||
}
|
||||
|
||||
void lv_draw_sdl_deinit_ctx(lv_disp_drv_t * disp_drv, lv_draw_ctx_t * draw_ctx)
|
||||
{
|
||||
lv_draw_sdl_ctx_t * draw_ctx_sdl = (lv_draw_sdl_ctx_t *) draw_ctx;
|
||||
lv_draw_sdl_texture_cache_deinit(draw_ctx_sdl);
|
||||
lv_mem_free(draw_ctx_sdl->internals);
|
||||
_lv_draw_sdl_utils_deinit();
|
||||
}
|
||||
|
||||
SDL_Texture * lv_draw_sdl_create_screen_texture(SDL_Renderer * renderer, lv_coord_t hor, lv_coord_t ver)
|
||||
{
|
||||
SDL_Texture * texture = SDL_CreateTexture(renderer, LV_DRAW_SDL_TEXTURE_FORMAT, SDL_TEXTUREACCESS_TARGET, hor, ver);
|
||||
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
|
||||
return texture;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_GPU_SDL*/
|
||||
96
pico-sensor/McuLib/LittlevGL/lvgl/src/draw/sdl/lv_draw_sdl.h
Normal file
96
pico-sensor/McuLib/LittlevGL/lvgl/src/draw/sdl/lv_draw_sdl.h
Normal file
@@ -0,0 +1,96 @@
|
||||
/**
|
||||
* @file lv_draw_sdl.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_DRAW_SDL_H
|
||||
#define LV_DRAW_SDL_H
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_GPU_SDL
|
||||
|
||||
#include LV_GPU_SDL_INCLUDE_PATH
|
||||
|
||||
#include "../lv_draw.h"
|
||||
#include "../../core/lv_disp.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
|
||||
#define LV_DRAW_SDL_TEXTURE_FORMAT SDL_PIXELFORMAT_ARGB8888
|
||||
#else
|
||||
#define LV_DRAW_SDL_TEXTURE_FORMAT SDL_PIXELFORMAT_RGBA8888
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
struct lv_draw_sdl_context_internals_t;
|
||||
|
||||
typedef struct {
|
||||
/**
|
||||
* Render for display driver
|
||||
*/
|
||||
SDL_Renderer * renderer;
|
||||
void * user_data;
|
||||
} lv_draw_sdl_drv_param_t;
|
||||
|
||||
typedef struct {
|
||||
lv_draw_ctx_t base_draw;
|
||||
SDL_Renderer * renderer;
|
||||
struct lv_draw_sdl_context_internals_t * internals;
|
||||
} lv_draw_sdl_ctx_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
void lv_draw_sdl_init_ctx(lv_disp_drv_t * disp_drv, lv_draw_ctx_t * draw_ctx);
|
||||
|
||||
/**
|
||||
* @brief Free caches
|
||||
*
|
||||
*/
|
||||
void lv_draw_sdl_deinit_ctx(lv_disp_drv_t * disp_drv, lv_draw_ctx_t * draw_ctx);
|
||||
|
||||
SDL_Texture * lv_draw_sdl_create_screen_texture(SDL_Renderer * renderer, lv_coord_t hor, lv_coord_t ver);
|
||||
|
||||
/*======================
|
||||
* Add/remove functions
|
||||
*=====================*/
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/*=====================
|
||||
* Other functions
|
||||
*====================*/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_GPU_SDL*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_DRAW_SDL_H*/
|
||||
@@ -0,0 +1,19 @@
|
||||
CSRCS += lv_draw_sdl.c
|
||||
CSRCS += lv_draw_sdl_arc.c
|
||||
CSRCS += lv_draw_sdl_bg.c
|
||||
CSRCS += lv_draw_sdl_composite.c
|
||||
CSRCS += lv_draw_sdl_img.c
|
||||
CSRCS += lv_draw_sdl_label.c
|
||||
CSRCS += lv_draw_sdl_line.c
|
||||
CSRCS += lv_draw_sdl_mask.c
|
||||
CSRCS += lv_draw_sdl_polygon.c
|
||||
CSRCS += lv_draw_sdl_rect.c
|
||||
CSRCS += lv_draw_sdl_stack_blur.c
|
||||
CSRCS += lv_draw_sdl_texture_cache.c
|
||||
CSRCS += lv_draw_sdl_utils.c
|
||||
CSRCS += lv_draw_sdl_layer.c
|
||||
|
||||
DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/sdl
|
||||
VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/sdl
|
||||
|
||||
CFLAGS += "-I$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/sdl"
|
||||
238
pico-sensor/McuLib/LittlevGL/lvgl/src/draw/sdl/lv_draw_sdl_arc.c
Normal file
238
pico-sensor/McuLib/LittlevGL/lvgl/src/draw/sdl/lv_draw_sdl_arc.c
Normal file
@@ -0,0 +1,238 @@
|
||||
/**
|
||||
* @file lv_draw_sdl_arc.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_GPU_SDL
|
||||
|
||||
#include "lv_draw_sdl.h"
|
||||
#include "lv_draw_sdl_utils.h"
|
||||
#include "lv_draw_sdl_texture_cache.h"
|
||||
#include "lv_draw_sdl_composite.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
static void dump_masks(SDL_Texture * texture, const lv_area_t * coords, const int16_t * ids, int16_t ids_count,
|
||||
const int16_t * caps);
|
||||
|
||||
static void get_cap_area(int16_t angle, lv_coord_t thickness, uint16_t radius, const lv_point_t * center,
|
||||
lv_area_t * out);
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
void lv_draw_sdl_draw_arc(lv_draw_ctx_t * draw_ctx, const lv_draw_arc_dsc_t * dsc, const lv_point_t * center,
|
||||
uint16_t radius, uint16_t start_angle, uint16_t end_angle)
|
||||
{
|
||||
lv_draw_sdl_ctx_t * ctx = (lv_draw_sdl_ctx_t *) draw_ctx;
|
||||
|
||||
lv_area_t area_out;
|
||||
area_out.x1 = center->x - radius;
|
||||
area_out.y1 = center->y - radius;
|
||||
area_out.x2 = center->x + radius - 1; /*-1 because the center already belongs to the left/bottom part*/
|
||||
area_out.y2 = center->y + radius - 1;
|
||||
|
||||
lv_area_t draw_area;
|
||||
if(!_lv_area_intersect(&draw_area, &area_out, draw_ctx->clip_area)) {
|
||||
return;
|
||||
}
|
||||
|
||||
lv_area_t area_in;
|
||||
lv_area_copy(&area_in, &area_out);
|
||||
area_in.x1 += dsc->width;
|
||||
area_in.y1 += dsc->width;
|
||||
area_in.x2 -= dsc->width;
|
||||
area_in.y2 -= dsc->width;
|
||||
|
||||
|
||||
while(start_angle >= 360) start_angle -= 360;
|
||||
while(end_angle >= 360) end_angle -= 360;
|
||||
|
||||
int16_t mask_ids[3] = {LV_MASK_ID_INV, LV_MASK_ID_INV, LV_MASK_ID_INV}, mask_ids_count = 1;
|
||||
int16_t cap_ids[2] = {LV_MASK_ID_INV, LV_MASK_ID_INV};
|
||||
|
||||
lv_draw_mask_radius_param_t mask_out_param;
|
||||
lv_draw_mask_radius_init(&mask_out_param, &area_out, LV_RADIUS_CIRCLE, false);
|
||||
mask_ids[0] = lv_draw_mask_add(&mask_out_param, NULL);
|
||||
|
||||
lv_draw_mask_radius_param_t mask_in_param;
|
||||
if(lv_area_get_width(&area_in) > 0 && lv_area_get_height(&area_in) > 0) {
|
||||
lv_draw_mask_radius_init(&mask_in_param, &area_in, LV_RADIUS_CIRCLE, true);
|
||||
mask_ids[1] = lv_draw_mask_add(&mask_in_param, NULL);
|
||||
mask_ids_count++;
|
||||
}
|
||||
|
||||
lv_draw_mask_angle_param_t mask_angle_param;
|
||||
if((start_angle - end_angle) % 360) {
|
||||
lv_draw_mask_angle_init(&mask_angle_param, center->x, center->y, start_angle, end_angle);
|
||||
mask_ids[2] = lv_draw_mask_add(&mask_angle_param, NULL);
|
||||
mask_ids_count++;
|
||||
}
|
||||
|
||||
lv_draw_mask_radius_param_t cap_start_param, cap_end_param;
|
||||
if(mask_ids_count == 3 && dsc->rounded) {
|
||||
lv_area_t start_area, end_area;
|
||||
get_cap_area((int16_t) start_angle, dsc->width, radius, center, &start_area);
|
||||
get_cap_area((int16_t) end_angle, dsc->width, radius, center, &end_area);
|
||||
lv_draw_mask_radius_init(&cap_start_param, &start_area, dsc->width / 2, false);
|
||||
cap_ids[0] = lv_draw_mask_add(&cap_start_param, NULL);
|
||||
lv_draw_mask_radius_init(&cap_end_param, &end_area, dsc->width / 2, false);
|
||||
cap_ids[1] = lv_draw_mask_add(&cap_end_param, NULL);
|
||||
}
|
||||
|
||||
lv_coord_t w = lv_area_get_width(&draw_area), h = lv_area_get_height(&draw_area);
|
||||
SDL_Texture * texture = lv_draw_sdl_composite_texture_obtain(ctx, LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_STREAM1, w, h);
|
||||
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
|
||||
dump_masks(texture, &draw_area, mask_ids, mask_ids_count, cap_ids[0] != LV_MASK_ID_INV ? cap_ids : NULL);
|
||||
|
||||
lv_draw_mask_remove_id(mask_ids[0]);
|
||||
lv_draw_mask_free_param(&mask_out_param);
|
||||
|
||||
if(mask_ids_count > 1) {
|
||||
lv_draw_mask_remove_id(mask_ids[1]);
|
||||
lv_draw_mask_free_param(&mask_in_param);
|
||||
}
|
||||
|
||||
if(mask_ids_count > 2) {
|
||||
lv_draw_mask_remove_id(mask_ids[2]);
|
||||
lv_draw_mask_free_param(&mask_angle_param);
|
||||
}
|
||||
|
||||
if(cap_ids[0] != LV_MASK_ID_INV) {
|
||||
lv_draw_mask_remove_id(cap_ids[0]);
|
||||
lv_draw_mask_remove_id(cap_ids[1]);
|
||||
lv_draw_mask_free_param(&cap_start_param);
|
||||
lv_draw_mask_free_param(&cap_end_param);
|
||||
}
|
||||
|
||||
SDL_Rect srcrect = {0, 0, w, h}, dstrect;
|
||||
lv_area_to_sdl_rect(&draw_area, &dstrect);
|
||||
SDL_Color color;
|
||||
lv_color_to_sdl_color(&dsc->color, &color);
|
||||
SDL_SetTextureColorMod(texture, color.r, color.g, color.b);
|
||||
SDL_SetTextureAlphaMod(texture, dsc->opa);
|
||||
SDL_RenderCopy(ctx->renderer, texture, &srcrect, &dstrect);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void dump_masks(SDL_Texture * texture, const lv_area_t * coords, const int16_t * ids, int16_t ids_count,
|
||||
const int16_t * caps)
|
||||
{
|
||||
lv_coord_t w = lv_area_get_width(coords), h = lv_area_get_height(coords);
|
||||
SDL_assert(w > 0 && h > 0);
|
||||
SDL_Rect rect = {0, 0, w, h};
|
||||
uint8_t * pixels;
|
||||
int pitch;
|
||||
if(SDL_LockTexture(texture, &rect, (void **) &pixels, &pitch) != 0) return;
|
||||
|
||||
lv_opa_t * line_buf = lv_mem_buf_get(rect.w);
|
||||
for(lv_coord_t y = 0; y < rect.h; y++) {
|
||||
lv_memset_ff(line_buf, rect.w);
|
||||
lv_coord_t abs_x = (lv_coord_t) coords->x1, abs_y = (lv_coord_t)(y + coords->y1), len = (lv_coord_t) rect.w;
|
||||
lv_draw_mask_res_t res;
|
||||
res = lv_draw_mask_apply_ids(line_buf, abs_x, abs_y, len, ids, ids_count);
|
||||
if(res == LV_DRAW_MASK_RES_TRANSP) {
|
||||
lv_memset_00(&pixels[y * pitch], 4 * rect.w);
|
||||
}
|
||||
else if(res == LV_DRAW_MASK_RES_FULL_COVER) {
|
||||
lv_memset_ff(&pixels[y * pitch], 4 * rect.w);
|
||||
}
|
||||
else {
|
||||
for(int x = 0; x < rect.w; x++) {
|
||||
uint8_t * pixel = &pixels[y * pitch + x * 4];
|
||||
*pixel = line_buf[x];
|
||||
pixel[1] = pixel[2] = pixel[3] = 0xFF;
|
||||
}
|
||||
}
|
||||
if(caps) {
|
||||
for(int i = 0; i < 2; i++) {
|
||||
lv_memset_ff(line_buf, rect.w);
|
||||
res = lv_draw_mask_apply_ids(line_buf, abs_x, abs_y, len, &caps[i], 1);
|
||||
if(res == LV_DRAW_MASK_RES_TRANSP) {
|
||||
/* Ignore */
|
||||
}
|
||||
else if(res == LV_DRAW_MASK_RES_FULL_COVER) {
|
||||
lv_memset_ff(&pixels[y * pitch], 4 * rect.w);
|
||||
}
|
||||
else {
|
||||
for(int x = 0; x < rect.w; x++) {
|
||||
uint8_t * pixel = &pixels[y * pitch + x * 4];
|
||||
uint16_t old_opa = line_buf[x] + *pixel;
|
||||
*pixel = LV_MIN(old_opa, 0xFF);
|
||||
pixel[1] = pixel[2] = pixel[3] = 0xFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
lv_mem_buf_release(line_buf);
|
||||
SDL_UnlockTexture(texture);
|
||||
}
|
||||
|
||||
static void get_cap_area(int16_t angle, lv_coord_t thickness, uint16_t radius, const lv_point_t * center,
|
||||
lv_area_t * out)
|
||||
{
|
||||
const uint8_t ps = 8;
|
||||
const uint8_t pa = 127;
|
||||
|
||||
int32_t thick_half = thickness / 2;
|
||||
uint8_t thick_corr = (thickness & 0x01) ? 0 : 1;
|
||||
|
||||
int32_t cir_x;
|
||||
int32_t cir_y;
|
||||
|
||||
cir_x = ((radius - thick_half) * lv_trigo_sin((int16_t)(90 - angle))) >> (LV_TRIGO_SHIFT - ps);
|
||||
cir_y = ((radius - thick_half) * lv_trigo_sin(angle)) >> (LV_TRIGO_SHIFT - ps);
|
||||
|
||||
/*Actually the center of the pixel need to be calculated so apply 1/2 px offset*/
|
||||
if(cir_x > 0) {
|
||||
cir_x = (cir_x - pa) >> ps;
|
||||
out->x1 = cir_x - thick_half + thick_corr;
|
||||
out->x2 = cir_x + thick_half;
|
||||
}
|
||||
else {
|
||||
cir_x = (cir_x + pa) >> ps;
|
||||
out->x1 = cir_x - thick_half;
|
||||
out->x2 = cir_x + thick_half - thick_corr;
|
||||
}
|
||||
|
||||
if(cir_y > 0) {
|
||||
cir_y = (cir_y - pa) >> ps;
|
||||
out->y1 = cir_y - thick_half + thick_corr;
|
||||
out->y2 = cir_y + thick_half;
|
||||
}
|
||||
else {
|
||||
cir_y = (cir_y + pa) >> ps;
|
||||
out->y1 = cir_y - thick_half;
|
||||
out->y2 = cir_y + thick_half - thick_corr;
|
||||
}
|
||||
lv_area_move(out, center->x, center->y);
|
||||
}
|
||||
|
||||
#endif /*LV_USE_GPU_SDL*/
|
||||
106
pico-sensor/McuLib/LittlevGL/lvgl/src/draw/sdl/lv_draw_sdl_bg.c
Normal file
106
pico-sensor/McuLib/LittlevGL/lvgl/src/draw/sdl/lv_draw_sdl_bg.c
Normal file
@@ -0,0 +1,106 @@
|
||||
/**
|
||||
* @file lv_draw_sdl_bg.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_GPU_SDL
|
||||
|
||||
#include "../lv_draw_rect.h"
|
||||
#include "../lv_draw_img.h"
|
||||
#include "../lv_draw_label.h"
|
||||
#include "../lv_draw_mask.h"
|
||||
#include "../../core/lv_refr.h"
|
||||
#include "lv_draw_sdl_utils.h"
|
||||
#include "lv_draw_sdl_texture_cache.h"
|
||||
#include "lv_draw_sdl_composite.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static void draw_bg_color(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords, const lv_area_t * draw_area,
|
||||
const lv_draw_rect_dsc_t * dsc);
|
||||
|
||||
static void draw_bg_img(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords, const lv_area_t * draw_area,
|
||||
const lv_draw_rect_dsc_t * dsc);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_draw_sdl_draw_bg(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords)
|
||||
{
|
||||
const lv_area_t * clip = draw_ctx->clip_area;
|
||||
lv_draw_sdl_ctx_t * ctx = (lv_draw_sdl_ctx_t *) draw_ctx;
|
||||
/* Coords will be translated so coords will start at (0,0) */
|
||||
lv_area_t t_area;
|
||||
bool has_content = _lv_area_intersect(&t_area, coords, clip);
|
||||
|
||||
/* Shadows and outlines will also draw in extended area */
|
||||
if(has_content) {
|
||||
if(dsc->bg_img_src) {
|
||||
draw_bg_img(ctx, coords, &t_area, dsc);
|
||||
}
|
||||
else {
|
||||
draw_bg_color(ctx, coords, &t_area, dsc);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void draw_bg_color(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords, const lv_area_t * draw_area,
|
||||
const lv_draw_rect_dsc_t * dsc)
|
||||
{
|
||||
SDL_Color bg_color;
|
||||
lv_color_to_sdl_color(&dsc->bg_color, &bg_color);
|
||||
SDL_SetRenderDrawBlendMode(ctx->renderer, SDL_BLENDMODE_NONE);
|
||||
SDL_SetRenderDrawColor(ctx->renderer, bg_color.r, bg_color.g, bg_color.b, dsc->bg_opa);
|
||||
|
||||
SDL_Rect rect;
|
||||
lv_area_to_sdl_rect(draw_area, &rect);
|
||||
SDL_RenderFillRect(ctx->renderer, &rect);
|
||||
|
||||
SDL_SetRenderDrawBlendMode(ctx->renderer, SDL_BLENDMODE_BLEND);
|
||||
}
|
||||
|
||||
static void draw_bg_img(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords, const lv_area_t * draw_area,
|
||||
const lv_draw_rect_dsc_t * dsc)
|
||||
{
|
||||
SDL_SetRenderDrawBlendMode(ctx->renderer, SDL_BLENDMODE_NONE);
|
||||
SDL_SetRenderDrawColor(ctx->renderer, 0, 0, 0, 0);
|
||||
|
||||
SDL_Rect rect;
|
||||
lv_area_to_sdl_rect(draw_area, &rect);
|
||||
SDL_RenderFillRect(ctx->renderer, &rect);
|
||||
|
||||
SDL_SetRenderDrawBlendMode(ctx->renderer, SDL_BLENDMODE_BLEND);
|
||||
lv_draw_rect((lv_draw_ctx_t *) ctx, dsc, coords);
|
||||
}
|
||||
|
||||
#endif /*LV_USE_GPU_SDL*/
|
||||
@@ -0,0 +1,262 @@
|
||||
/**
|
||||
* @file lv_draw_sdl_composite.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_GPU_SDL
|
||||
|
||||
#include "../../misc/lv_gc.h"
|
||||
#include "../../core/lv_refr.h"
|
||||
#include "lv_draw_sdl_composite.h"
|
||||
#include "lv_draw_sdl_utils.h"
|
||||
#include "lv_draw_sdl_priv.h"
|
||||
#include "lv_draw_sdl_texture_cache.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct {
|
||||
lv_sdl_cache_key_magic_t magic;
|
||||
lv_draw_sdl_composite_texture_id_t type;
|
||||
} composite_key_t;
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static composite_key_t mask_key_create(lv_draw_sdl_composite_texture_id_t type);
|
||||
|
||||
static lv_coord_t next_pow_of_2(lv_coord_t num);
|
||||
|
||||
static void dump_masks(SDL_Texture * texture, const lv_area_t * coords);
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
bool lv_draw_sdl_composite_begin(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords_in, const lv_area_t * clip_in,
|
||||
const lv_area_t * extension, lv_blend_mode_t blend_mode, lv_area_t * coords_out,
|
||||
lv_area_t * clip_out, lv_area_t * apply_area)
|
||||
{
|
||||
lv_area_t full_coords = *coords_in;
|
||||
|
||||
/* Normalize full_coords */
|
||||
if(full_coords.x1 > full_coords.x2) {
|
||||
lv_coord_t x2 = full_coords.x2;
|
||||
full_coords.x2 = full_coords.x1;
|
||||
full_coords.x1 = x2;
|
||||
}
|
||||
if(full_coords.y1 > full_coords.y2) {
|
||||
lv_coord_t y2 = full_coords.y2;
|
||||
full_coords.y2 = full_coords.y1;
|
||||
full_coords.y1 = y2;
|
||||
}
|
||||
|
||||
if(extension) {
|
||||
full_coords.x1 -= extension->x1;
|
||||
full_coords.x2 += extension->x2;
|
||||
full_coords.y1 -= extension->y1;
|
||||
full_coords.y2 += extension->y2;
|
||||
}
|
||||
|
||||
if(!_lv_area_intersect(apply_area, &full_coords, clip_in)) return false;
|
||||
bool has_mask = lv_draw_mask_is_any(apply_area);
|
||||
|
||||
const bool draw_mask = has_mask && LV_GPU_SDL_CUSTOM_BLEND_MODE;
|
||||
const bool draw_blend = blend_mode != LV_BLEND_MODE_NORMAL;
|
||||
if(draw_mask || draw_blend) {
|
||||
lv_draw_sdl_context_internals_t * internals = ctx->internals;
|
||||
LV_ASSERT(internals->mask == NULL && internals->composition == NULL && internals->target_backup == NULL);
|
||||
|
||||
lv_coord_t w = lv_area_get_width(apply_area), h = lv_area_get_height(apply_area);
|
||||
internals->composition = lv_draw_sdl_composite_texture_obtain(ctx, LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_TARGET0, w, h);
|
||||
/* Don't need to worry about integral overflow */
|
||||
lv_coord_t ofs_x = (lv_coord_t) - apply_area->x1, ofs_y = (lv_coord_t) - apply_area->y1;
|
||||
/* Offset draw area to start with (0,0) of coords */
|
||||
lv_area_move(coords_out, ofs_x, ofs_y);
|
||||
lv_area_move(clip_out, ofs_x, ofs_y);
|
||||
internals->target_backup = SDL_GetRenderTarget(ctx->renderer);
|
||||
SDL_SetRenderTarget(ctx->renderer, internals->composition);
|
||||
SDL_SetRenderDrawColor(ctx->renderer, 255, 255, 255, 0);
|
||||
/* SDL_RenderClear is not working properly, so we overwrite the target with solid color */
|
||||
SDL_SetRenderDrawBlendMode(ctx->renderer, SDL_BLENDMODE_NONE);
|
||||
SDL_RenderFillRect(ctx->renderer, NULL);
|
||||
SDL_SetRenderDrawBlendMode(ctx->renderer, SDL_BLENDMODE_BLEND);
|
||||
#if LV_GPU_SDL_CUSTOM_BLEND_MODE
|
||||
internals->mask = lv_draw_sdl_composite_texture_obtain(ctx, LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_STREAM0, w, h);
|
||||
dump_masks(internals->mask, apply_area);
|
||||
#endif
|
||||
}
|
||||
else if(has_mask) {
|
||||
/* Fallback mask handling. This will at least make bars looks less bad */
|
||||
for(uint8_t i = 0; i < _LV_MASK_MAX_NUM; i++) {
|
||||
_lv_draw_mask_common_dsc_t * comm_param = LV_GC_ROOT(_lv_draw_mask_list[i]).param;
|
||||
if(comm_param == NULL) continue;
|
||||
switch(comm_param->type) {
|
||||
case LV_DRAW_MASK_TYPE_RADIUS: {
|
||||
const lv_draw_mask_radius_param_t * param = (const lv_draw_mask_radius_param_t *) comm_param;
|
||||
if(param->cfg.outer) break;
|
||||
_lv_area_intersect(clip_out, apply_area, ¶m->cfg.rect);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return has_mask;
|
||||
}
|
||||
|
||||
void lv_draw_sdl_composite_end(lv_draw_sdl_ctx_t * ctx, const lv_area_t * apply_area, lv_blend_mode_t blend_mode)
|
||||
{
|
||||
lv_draw_sdl_context_internals_t * internals = ctx->internals;
|
||||
SDL_Rect src_rect = {0, 0, lv_area_get_width(apply_area), lv_area_get_height(apply_area)};
|
||||
#if LV_GPU_SDL_CUSTOM_BLEND_MODE
|
||||
if(internals->mask) {
|
||||
SDL_BlendMode mode = SDL_ComposeCustomBlendMode(SDL_BLENDFACTOR_ZERO, SDL_BLENDFACTOR_ONE,
|
||||
SDL_BLENDOPERATION_ADD, SDL_BLENDFACTOR_ZERO,
|
||||
SDL_BLENDFACTOR_SRC_ALPHA, SDL_BLENDOPERATION_ADD);
|
||||
SDL_SetTextureBlendMode(internals->mask, mode);
|
||||
SDL_RenderCopy(ctx->renderer, internals->mask, &src_rect, &src_rect);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Shapes are drawn on composite layer when mask or blend mode is present */
|
||||
if(internals->composition) {
|
||||
SDL_Rect dst_rect;
|
||||
lv_area_to_sdl_rect(apply_area, &dst_rect);
|
||||
|
||||
SDL_SetRenderTarget(ctx->renderer, internals->target_backup);
|
||||
switch(blend_mode) {
|
||||
case LV_BLEND_MODE_NORMAL:
|
||||
SDL_SetTextureBlendMode(internals->composition, SDL_BLENDMODE_BLEND);
|
||||
break;
|
||||
case LV_BLEND_MODE_ADDITIVE:
|
||||
SDL_SetTextureBlendMode(internals->composition, SDL_BLENDMODE_ADD);
|
||||
break;
|
||||
#if LV_GPU_SDL_CUSTOM_BLEND_MODE
|
||||
case LV_BLEND_MODE_SUBTRACTIVE: {
|
||||
SDL_BlendMode mode = SDL_ComposeCustomBlendMode(SDL_BLENDFACTOR_ONE, SDL_BLENDFACTOR_ONE,
|
||||
SDL_BLENDOPERATION_SUBTRACT, SDL_BLENDFACTOR_ONE,
|
||||
SDL_BLENDFACTOR_ONE, SDL_BLENDOPERATION_SUBTRACT);
|
||||
SDL_SetTextureBlendMode(internals->composition, mode);
|
||||
break;
|
||||
}
|
||||
case LV_BLEND_MODE_MULTIPLY: {
|
||||
SDL_BlendMode mode = SDL_ComposeCustomBlendMode(SDL_BLENDFACTOR_ZERO, SDL_BLENDFACTOR_SRC_COLOR,
|
||||
SDL_BLENDOPERATION_ADD, SDL_BLENDFACTOR_ZERO,
|
||||
SDL_BLENDFACTOR_DST_ALPHA, SDL_BLENDOPERATION_ADD);
|
||||
SDL_SetTextureBlendMode(internals->composition, mode);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
LV_LOG_WARN("Doesn't support blend mode %d", blend_mode);
|
||||
SDL_SetTextureBlendMode(internals->composition, SDL_BLENDMODE_BLEND);
|
||||
/* Unsupported yet */
|
||||
break;
|
||||
}
|
||||
SDL_RenderCopy(ctx->renderer, internals->composition, &src_rect, &dst_rect);
|
||||
}
|
||||
|
||||
internals->mask = internals->composition = internals->target_backup = NULL;
|
||||
}
|
||||
|
||||
SDL_Texture * lv_draw_sdl_composite_texture_obtain(lv_draw_sdl_ctx_t * ctx, lv_draw_sdl_composite_texture_id_t id,
|
||||
lv_coord_t w, lv_coord_t h)
|
||||
{
|
||||
lv_point_t * tex_size = NULL;
|
||||
composite_key_t mask_key = mask_key_create(id);
|
||||
SDL_Texture * result = lv_draw_sdl_texture_cache_get_with_userdata(ctx, &mask_key, sizeof(composite_key_t), NULL,
|
||||
(void **) &tex_size);
|
||||
if(!result || tex_size->x < w || tex_size->y < h) {
|
||||
lv_coord_t size = next_pow_of_2(LV_MAX(w, h));
|
||||
int access = SDL_TEXTUREACCESS_STREAMING;
|
||||
if(id >= LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_TRANSFORM0) {
|
||||
access = SDL_TEXTUREACCESS_TARGET;
|
||||
}
|
||||
else if(id >= LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_TARGET0) {
|
||||
access = SDL_TEXTUREACCESS_TARGET;
|
||||
}
|
||||
result = SDL_CreateTexture(ctx->renderer, LV_DRAW_SDL_TEXTURE_FORMAT, access, size, size);
|
||||
tex_size = lv_mem_alloc(sizeof(lv_point_t));
|
||||
tex_size->x = tex_size->y = size;
|
||||
lv_draw_sdl_texture_cache_put_advanced(ctx, &mask_key, sizeof(composite_key_t), result, tex_size, lv_mem_free, 0);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static composite_key_t mask_key_create(lv_draw_sdl_composite_texture_id_t type)
|
||||
{
|
||||
composite_key_t key;
|
||||
/* VERY IMPORTANT! Padding between members is uninitialized, so we have to wipe them manually */
|
||||
SDL_memset(&key, 0, sizeof(key));
|
||||
key.magic = LV_GPU_CACHE_KEY_MAGIC_MASK;
|
||||
key.type = type;
|
||||
return key;
|
||||
}
|
||||
|
||||
static lv_coord_t next_pow_of_2(lv_coord_t num)
|
||||
{
|
||||
lv_coord_t n = 128;
|
||||
while(n < num && n < 16384) {
|
||||
n = n << 1;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
static void dump_masks(SDL_Texture * texture, const lv_area_t * coords)
|
||||
{
|
||||
lv_coord_t w = lv_area_get_width(coords), h = lv_area_get_height(coords);
|
||||
SDL_assert(w > 0 && h > 0);
|
||||
SDL_Rect rect = {0, 0, w, h};
|
||||
uint8_t * pixels;
|
||||
int pitch;
|
||||
if(SDL_LockTexture(texture, &rect, (void **) &pixels, &pitch) != 0) return;
|
||||
|
||||
lv_opa_t * line_buf = lv_mem_buf_get(rect.w);
|
||||
for(lv_coord_t y = 0; y < rect.h; y++) {
|
||||
lv_memset_ff(line_buf, rect.w);
|
||||
lv_coord_t abs_x = (lv_coord_t) coords->x1, abs_y = (lv_coord_t)(y + coords->y1), len = (lv_coord_t) rect.w;
|
||||
lv_draw_mask_res_t res;
|
||||
res = lv_draw_mask_apply(line_buf, abs_x, abs_y, len);
|
||||
if(res == LV_DRAW_MASK_RES_TRANSP) {
|
||||
lv_memset_00(&pixels[y * pitch], 4 * rect.w);
|
||||
}
|
||||
else if(res == LV_DRAW_MASK_RES_FULL_COVER) {
|
||||
lv_memset_ff(&pixels[y * pitch], 4 * rect.w);
|
||||
}
|
||||
else {
|
||||
for(int x = 0; x < rect.w; x++) {
|
||||
const size_t idx = y * pitch + x * 4;
|
||||
pixels[idx] = line_buf[x];
|
||||
pixels[idx + 1] = pixels[idx + 2] = pixels[idx + 3] = 0xFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
lv_mem_buf_release(line_buf);
|
||||
SDL_UnlockTexture(texture);
|
||||
}
|
||||
|
||||
#endif /*LV_USE_GPU_SDL*/
|
||||
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* @file lv_draw_sdl_composite.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_DRAW_SDL_COMPOSITE_H
|
||||
#define LV_DRAW_SDL_COMPOSITE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "../../lv_conf_internal.h"
|
||||
|
||||
#include LV_GPU_SDL_INCLUDE_PATH
|
||||
|
||||
#include "lv_draw_sdl.h"
|
||||
#include "../../misc/lv_area.h"
|
||||
#include "../../misc/lv_color.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef enum lv_draw_sdl_composite_texture_id_t {
|
||||
LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_STREAM0,
|
||||
LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_STREAM1,
|
||||
LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_TARGET0,
|
||||
LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_TARGET1,
|
||||
LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_TRANSFORM0,
|
||||
} lv_draw_sdl_composite_texture_id_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Begin drawing with mask. Render target will be switched to a temporary texture,
|
||||
* and drawing coordinates may get clipped or translated
|
||||
* @param coords_in Original coordinates
|
||||
* @param clip_in Original clip area
|
||||
* @param extension Useful for shadows or outlines, can be NULL
|
||||
* @param coords_out Translated coords
|
||||
* @param clip_out Translated clip area
|
||||
* @param apply_area Area of actual composited texture will be drawn
|
||||
* @return true if there are any mask needs to be drawn, false otherwise
|
||||
*/
|
||||
bool lv_draw_sdl_composite_begin(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords_in, const lv_area_t * clip_in,
|
||||
const lv_area_t * extension, lv_blend_mode_t blend_mode, lv_area_t * coords_out,
|
||||
lv_area_t * clip_out, lv_area_t * apply_area);
|
||||
|
||||
void lv_draw_sdl_composite_end(lv_draw_sdl_ctx_t * ctx, const lv_area_t * apply_area, lv_blend_mode_t blend_mode);
|
||||
|
||||
SDL_Texture * lv_draw_sdl_composite_texture_obtain(lv_draw_sdl_ctx_t * ctx, lv_draw_sdl_composite_texture_id_t id,
|
||||
lv_coord_t w, lv_coord_t h);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_DRAW_SDL_COMPOSITE_H*/
|
||||
467
pico-sensor/McuLib/LittlevGL/lvgl/src/draw/sdl/lv_draw_sdl_img.c
Normal file
467
pico-sensor/McuLib/LittlevGL/lvgl/src/draw/sdl/lv_draw_sdl_img.c
Normal file
@@ -0,0 +1,467 @@
|
||||
/**
|
||||
* @file lv_draw_sdl_img.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_GPU_SDL
|
||||
|
||||
#include "../lv_draw_img.h"
|
||||
#include "../lv_img_cache.h"
|
||||
#include "../lv_draw_mask.h"
|
||||
#include "../../misc/lv_lru.h"
|
||||
#include "../../misc/lv_gc.h"
|
||||
|
||||
#include "lv_draw_sdl_img.h"
|
||||
#include "lv_draw_sdl_utils.h"
|
||||
#include "lv_draw_sdl_texture_cache.h"
|
||||
#include "lv_draw_sdl_composite.h"
|
||||
#include "lv_draw_sdl_rect.h"
|
||||
#include "lv_draw_sdl_layer.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct {
|
||||
lv_sdl_cache_key_magic_t magic;
|
||||
const SDL_Texture * texture;
|
||||
lv_coord_t w, h, radius;
|
||||
} lv_draw_img_rounded_key_t;
|
||||
|
||||
enum {
|
||||
ROUNDED_IMG_PART_LEFT = 0,
|
||||
ROUNDED_IMG_PART_HCENTER = 1,
|
||||
ROUNDED_IMG_PART_RIGHT = 2,
|
||||
ROUNDED_IMG_PART_TOP = 3,
|
||||
ROUNDED_IMG_PART_VCENTER = 4,
|
||||
ROUNDED_IMG_PART_BOTTOM = 5,
|
||||
};
|
||||
|
||||
enum {
|
||||
ROUNDED_IMG_CORNER_TOP_LEFT = 0,
|
||||
ROUNDED_IMG_CORNER_TOP_RIGHT = 1,
|
||||
ROUNDED_IMG_CORNER_BOTTOM_RIGHT = 2,
|
||||
ROUNDED_IMG_CORNER_BOTTOM_LEFT = 3,
|
||||
};
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static SDL_Texture * upload_img_texture(SDL_Renderer * renderer, lv_img_decoder_dsc_t * dsc);
|
||||
|
||||
static SDL_Texture * upload_img_texture_fallback(SDL_Renderer * renderer, lv_img_decoder_dsc_t * dsc);
|
||||
|
||||
static bool check_mask_simple_radius(const lv_area_t * coords, lv_coord_t * radius);
|
||||
|
||||
static void draw_img_simple(lv_draw_sdl_ctx_t * ctx, SDL_Texture * texture, const lv_draw_sdl_img_header_t * header,
|
||||
const lv_draw_img_dsc_t * draw_dsc, const lv_area_t * coords, const lv_area_t * clip);
|
||||
|
||||
static void draw_img_rounded(lv_draw_sdl_ctx_t * ctx, SDL_Texture * texture, const lv_draw_sdl_img_header_t * header,
|
||||
const lv_draw_img_dsc_t * draw_dsc, const lv_area_t * coords, const lv_area_t * clip,
|
||||
lv_coord_t radius);
|
||||
|
||||
static SDL_Texture * img_rounded_frag_obtain(lv_draw_sdl_ctx_t * ctx, SDL_Texture * texture,
|
||||
const lv_draw_sdl_img_header_t * header, int w, int h, lv_coord_t radius);
|
||||
|
||||
static lv_draw_img_rounded_key_t rounded_key_create(const SDL_Texture * texture, lv_coord_t w, lv_coord_t h,
|
||||
lv_coord_t radius);
|
||||
|
||||
static void calc_draw_part(SDL_Texture * texture, const lv_draw_sdl_img_header_t * header, const lv_area_t * coords,
|
||||
const lv_area_t * clip, SDL_Rect * clipped_src, SDL_Rect * clipped_dst);
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
|
||||
static void apply_recolor_opa(SDL_Texture * texture, const lv_draw_img_dsc_t * draw_dsc);
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
lv_res_t lv_draw_sdl_img_core(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * draw_dsc,
|
||||
const lv_area_t * coords, const void * src)
|
||||
{
|
||||
const lv_area_t * clip = draw_ctx->clip_area;
|
||||
lv_draw_sdl_ctx_t * ctx = (lv_draw_sdl_ctx_t *) draw_ctx;
|
||||
|
||||
size_t key_size;
|
||||
lv_draw_sdl_cache_key_head_img_t * key = lv_draw_sdl_texture_img_key_create(src, draw_dsc->frame_id, &key_size);
|
||||
bool texture_found = false;
|
||||
lv_draw_sdl_img_header_t * header = NULL;
|
||||
SDL_Texture * texture = lv_draw_sdl_texture_cache_get_with_userdata(ctx, key, key_size, &texture_found,
|
||||
(void **) &header);
|
||||
if(!texture_found) {
|
||||
lv_draw_sdl_img_load_texture(ctx, key, key_size, src, draw_dsc->frame_id, &texture, &header);
|
||||
}
|
||||
SDL_free(key);
|
||||
if(!texture) {
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
lv_area_t zoomed_cords;
|
||||
_lv_img_buf_get_transformed_area(&zoomed_cords, lv_area_get_width(coords), lv_area_get_height(coords), 0,
|
||||
draw_dsc->zoom, &draw_dsc->pivot);
|
||||
lv_area_move(&zoomed_cords, coords->x1, coords->y1);
|
||||
|
||||
/* When in > 0, draw simple radius */
|
||||
lv_coord_t radius = 0;
|
||||
/* Coords will be translated so coords will start at (0,0) */
|
||||
lv_area_t t_coords = zoomed_cords, t_clip = *clip, apply_area;
|
||||
|
||||
bool has_composite = false;
|
||||
|
||||
if(!check_mask_simple_radius(&t_coords, &radius)) {
|
||||
has_composite = lv_draw_sdl_composite_begin(ctx, &zoomed_cords, clip, NULL, draw_dsc->blend_mode,
|
||||
&t_coords, &t_clip, &apply_area);
|
||||
}
|
||||
|
||||
lv_draw_sdl_transform_areas_offset(ctx, has_composite, &apply_area, &t_coords, &t_clip);
|
||||
|
||||
SDL_Rect clip_rect, coords_rect;
|
||||
lv_area_to_sdl_rect(&t_clip, &clip_rect);
|
||||
lv_area_to_sdl_rect(&t_coords, &coords_rect);
|
||||
|
||||
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
|
||||
|
||||
if(radius > 0) {
|
||||
draw_img_rounded(ctx, texture, header, draw_dsc, &t_coords, &t_clip, radius);
|
||||
}
|
||||
else {
|
||||
draw_img_simple(ctx, texture, header, draw_dsc, &t_coords, &t_clip);
|
||||
}
|
||||
|
||||
lv_draw_sdl_composite_end(ctx, &apply_area, draw_dsc->blend_mode);
|
||||
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
static void calc_draw_part(SDL_Texture * texture, const lv_draw_sdl_img_header_t * header, const lv_area_t * coords,
|
||||
const lv_area_t * clip, SDL_Rect * clipped_src, SDL_Rect * clipped_dst)
|
||||
{
|
||||
double x = 0, y = 0, w, h;
|
||||
if(SDL_RectEmpty(&header->rect)) {
|
||||
Uint32 format = 0;
|
||||
int access = 0, tw, th;
|
||||
SDL_QueryTexture(texture, &format, &access, &tw, &th);
|
||||
w = tw;
|
||||
h = th;
|
||||
}
|
||||
else {
|
||||
x = header->rect.x;
|
||||
y = header->rect.y;
|
||||
w = header->rect.w;
|
||||
h = header->rect.h;
|
||||
}
|
||||
if(clip) {
|
||||
lv_area_t clipped_area;
|
||||
_lv_area_intersect(&clipped_area, coords, clip);
|
||||
lv_area_to_sdl_rect(&clipped_area, clipped_dst);
|
||||
}
|
||||
else {
|
||||
lv_area_to_sdl_rect(coords, clipped_dst);
|
||||
}
|
||||
lv_coord_t coords_w = lv_area_get_width(coords), coords_h = lv_area_get_height(coords);
|
||||
clipped_src->x = (int)(x + (clipped_dst->x - coords->x1) * w / coords_w);
|
||||
clipped_src->y = (int)(y + (clipped_dst->y - coords->y1) * h / coords_h);
|
||||
clipped_src->w = (int)(w - (coords_w - clipped_dst->w) * w / coords_w);
|
||||
clipped_src->h = (int)(h - (coords_h - clipped_dst->h) * h / coords_h);
|
||||
}
|
||||
|
||||
bool lv_draw_sdl_img_load_texture(lv_draw_sdl_ctx_t * ctx, lv_draw_sdl_cache_key_head_img_t * key, size_t key_size,
|
||||
const void * src, int32_t frame_id, SDL_Texture ** texture,
|
||||
lv_draw_sdl_img_header_t ** header)
|
||||
{
|
||||
_lv_img_cache_entry_t * cdsc = _lv_img_cache_open(src, lv_color_white(), frame_id);
|
||||
lv_draw_sdl_cache_flag_t tex_flags = 0;
|
||||
SDL_Rect rect;
|
||||
SDL_memset(&rect, 0, sizeof(SDL_Rect));
|
||||
if(cdsc) {
|
||||
lv_img_decoder_dsc_t * dsc = &cdsc->dec_dsc;
|
||||
if(dsc->user_data && SDL_memcmp(dsc->user_data, LV_DRAW_SDL_DEC_DSC_TEXTURE_HEAD, 8) == 0) {
|
||||
lv_draw_sdl_dec_dsc_userdata_t * ptr = (lv_draw_sdl_dec_dsc_userdata_t *) dsc->user_data;
|
||||
*texture = ptr->texture;
|
||||
rect = ptr->rect;
|
||||
if(ptr->texture_managed) {
|
||||
tex_flags |= LV_DRAW_SDL_CACHE_FLAG_MANAGED;
|
||||
}
|
||||
ptr->texture_referenced = true;
|
||||
}
|
||||
else {
|
||||
*texture = upload_img_texture(ctx->renderer, dsc);
|
||||
}
|
||||
#if LV_IMG_CACHE_DEF_SIZE == 0
|
||||
lv_img_decoder_close(dsc);
|
||||
#endif
|
||||
}
|
||||
if(texture && cdsc) {
|
||||
*header = SDL_malloc(sizeof(lv_draw_sdl_img_header_t));
|
||||
SDL_memcpy(&(*header)->base, &cdsc->dec_dsc.header, sizeof(lv_img_header_t));
|
||||
(*header)->rect = rect;
|
||||
lv_draw_sdl_texture_cache_put_advanced(ctx, key, key_size, *texture, *header, SDL_free, tex_flags);
|
||||
}
|
||||
else {
|
||||
lv_draw_sdl_texture_cache_put(ctx, key, key_size, NULL);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static SDL_Texture * upload_img_texture(SDL_Renderer * renderer, lv_img_decoder_dsc_t * dsc)
|
||||
{
|
||||
if(!dsc->img_data) {
|
||||
return upload_img_texture_fallback(renderer, dsc);
|
||||
}
|
||||
bool chroma_keyed = dsc->header.cf == (uint32_t) LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED;
|
||||
int h = (int) dsc->header.h;
|
||||
int w = (int) dsc->header.w;
|
||||
void * data = (void *) dsc->img_data;
|
||||
Uint32 rmask = 0x00FF0000;
|
||||
Uint32 gmask = 0x0000FF00;
|
||||
Uint32 bmask = 0x000000FF;
|
||||
Uint32 amask = 0xFF000000;
|
||||
if(chroma_keyed) {
|
||||
amask = 0x00;
|
||||
}
|
||||
SDL_Surface * surface = SDL_CreateRGBSurfaceFrom(data, w, h, LV_COLOR_DEPTH, w * LV_COLOR_DEPTH / 8,
|
||||
rmask, gmask, bmask, amask);
|
||||
SDL_SetColorKey(surface, chroma_keyed, lv_color_to32(LV_COLOR_CHROMA_KEY));
|
||||
SDL_Texture * texture = SDL_CreateTextureFromSurface(renderer, surface);
|
||||
SDL_FreeSurface(surface);
|
||||
return texture;
|
||||
}
|
||||
|
||||
static SDL_Texture * upload_img_texture_fallback(SDL_Renderer * renderer, lv_img_decoder_dsc_t * dsc)
|
||||
{
|
||||
lv_coord_t h = (lv_coord_t) dsc->header.h;
|
||||
lv_coord_t w = (lv_coord_t) dsc->header.w;
|
||||
uint8_t * data = lv_mem_buf_get(w * h * sizeof(lv_color_t));
|
||||
for(lv_coord_t y = 0; y < h; y++) {
|
||||
lv_img_decoder_read_line(dsc, 0, y, w, &data[y * w * sizeof(lv_color_t)]);
|
||||
}
|
||||
Uint32 rmask = 0x00FF0000;
|
||||
Uint32 gmask = 0x0000FF00;
|
||||
Uint32 bmask = 0x000000FF;
|
||||
Uint32 amask = 0xFF000000;
|
||||
SDL_Surface * surface = SDL_CreateRGBSurfaceFrom(data, w, h, LV_COLOR_DEPTH, w * LV_COLOR_DEPTH / 8,
|
||||
rmask, gmask, bmask, amask);
|
||||
SDL_SetColorKey(surface, SDL_TRUE, lv_color_to32(LV_COLOR_CHROMA_KEY));
|
||||
SDL_Texture * texture = SDL_CreateTextureFromSurface(renderer, surface);
|
||||
SDL_FreeSurface(surface);
|
||||
lv_mem_buf_release(data);
|
||||
return texture;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if there is only one radius mask
|
||||
* @param radius Set to radius value if the only mask is a radius mask
|
||||
* @return true if the only mask is a radius mask
|
||||
*/
|
||||
static bool check_mask_simple_radius(const lv_area_t * coords, lv_coord_t * radius)
|
||||
{
|
||||
if(lv_draw_mask_get_cnt() != 1) return false;
|
||||
for(uint8_t i = 0; i < _LV_MASK_MAX_NUM; i++) {
|
||||
_lv_draw_mask_common_dsc_t * param = LV_GC_ROOT(_lv_draw_mask_list[i]).param;
|
||||
if(param->type == LV_DRAW_MASK_TYPE_RADIUS) {
|
||||
lv_draw_mask_radius_param_t * rparam = (lv_draw_mask_radius_param_t *) param;
|
||||
if(rparam->cfg.outer) return false;
|
||||
if(!_lv_area_is_equal(&rparam->cfg.rect, coords)) return false;
|
||||
*radius = rparam->cfg.radius;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void draw_img_simple(lv_draw_sdl_ctx_t * ctx, SDL_Texture * texture, const lv_draw_sdl_img_header_t * header,
|
||||
const lv_draw_img_dsc_t * draw_dsc, const lv_area_t * coords, const lv_area_t * clip)
|
||||
{
|
||||
apply_recolor_opa(texture, draw_dsc);
|
||||
SDL_Point pivot = {.x = draw_dsc->pivot.x, .y = draw_dsc->pivot.y};
|
||||
|
||||
/*Image needs to be rotated, so we have to use clip rect which is slower*/
|
||||
if(draw_dsc->angle != 0) {
|
||||
/* No radius, set clip here */
|
||||
SDL_Rect clip_rect;
|
||||
lv_area_to_sdl_rect(clip, &clip_rect);
|
||||
SDL_RenderSetClipRect(ctx->renderer, &clip_rect);
|
||||
}
|
||||
SDL_Rect src_rect, dst_rect;
|
||||
calc_draw_part(texture, header, coords, clip, &src_rect, &dst_rect);
|
||||
SDL_RenderCopyEx(ctx->renderer, texture, &src_rect, &dst_rect, draw_dsc->angle, &pivot, SDL_FLIP_NONE);
|
||||
if(draw_dsc->angle != 0) {
|
||||
SDL_RenderSetClipRect(ctx->renderer, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void draw_img_rounded(lv_draw_sdl_ctx_t * ctx, SDL_Texture * texture, const lv_draw_sdl_img_header_t * header,
|
||||
const lv_draw_img_dsc_t * draw_dsc, const lv_area_t * coords, const lv_area_t * clip,
|
||||
lv_coord_t radius)
|
||||
{
|
||||
const int w = lv_area_get_width(coords), h = lv_area_get_height(coords);
|
||||
lv_coord_t real_radius = LV_MIN3(radius, w, h);
|
||||
SDL_Texture * frag = img_rounded_frag_obtain(ctx, texture, header, w, h, real_radius);
|
||||
apply_recolor_opa(frag, draw_dsc);
|
||||
lv_draw_sdl_rect_bg_frag_draw_corners(ctx, frag, real_radius, coords, clip, true);
|
||||
|
||||
apply_recolor_opa(texture, draw_dsc);
|
||||
|
||||
SDL_Rect src_rect, dst_rect;
|
||||
/* Draw 3 parts */
|
||||
lv_area_t clip_tmp, part;
|
||||
calc_draw_part(texture, header, coords, NULL, &src_rect, &dst_rect);
|
||||
for(int i = w > h ? ROUNDED_IMG_PART_LEFT : ROUNDED_IMG_PART_TOP, j = i + 3; i <= j; i++) {
|
||||
switch(i) {
|
||||
case ROUNDED_IMG_PART_LEFT:
|
||||
lv_area_set(&part, coords->x1, coords->y1 + radius, coords->x1 + radius - 1, coords->y2 - radius);
|
||||
break;
|
||||
case ROUNDED_IMG_PART_HCENTER:
|
||||
lv_area_set(&part, coords->x1 + radius, coords->y1, coords->x2 - radius, coords->y2);
|
||||
break;
|
||||
case ROUNDED_IMG_PART_RIGHT:
|
||||
lv_area_set(&part, coords->x2 - radius + 1, coords->y1 + radius, coords->x2, coords->y2 - radius);
|
||||
break;
|
||||
case ROUNDED_IMG_PART_TOP:
|
||||
lv_area_set(&part, coords->x1 + radius, coords->y1, coords->x2 - radius, coords->y1 + radius - 1);
|
||||
break;
|
||||
case ROUNDED_IMG_PART_VCENTER:
|
||||
lv_area_set(&part, coords->x1 + radius, coords->y2 - radius + 1, coords->x2 - radius, coords->y2);
|
||||
break;
|
||||
case ROUNDED_IMG_PART_BOTTOM:
|
||||
lv_area_set(&part, coords->x1, coords->y1 + radius, coords->x2, coords->y2 - radius);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if(!_lv_area_intersect(&clip_tmp, &part, clip)) continue;
|
||||
SDL_Rect clip_rect;
|
||||
lv_area_to_sdl_rect(&clip_tmp, &clip_rect);
|
||||
SDL_RenderSetClipRect(ctx->renderer, &clip_rect);
|
||||
SDL_RenderCopy(ctx->renderer, texture, &src_rect, &dst_rect);
|
||||
}
|
||||
SDL_RenderSetClipRect(ctx->renderer, NULL);
|
||||
}
|
||||
|
||||
static void apply_recolor_opa(SDL_Texture * texture, const lv_draw_img_dsc_t * draw_dsc)
|
||||
{
|
||||
if(draw_dsc->recolor_opa > LV_OPA_TRANSP) {
|
||||
/* Draw with mixed recolor */
|
||||
lv_color_t recolor = lv_color_mix(draw_dsc->recolor, lv_color_white(), draw_dsc->recolor_opa);
|
||||
SDL_SetTextureColorMod(texture, recolor.ch.red, recolor.ch.green, recolor.ch.blue);
|
||||
}
|
||||
else {
|
||||
/* Draw with no recolor */
|
||||
SDL_SetTextureColorMod(texture, 0xFF, 0xFF, 0xFF);
|
||||
}
|
||||
SDL_SetTextureAlphaMod(texture, draw_dsc->opa);
|
||||
}
|
||||
|
||||
static SDL_Texture * img_rounded_frag_obtain(lv_draw_sdl_ctx_t * ctx, SDL_Texture * texture,
|
||||
const lv_draw_sdl_img_header_t * header, int w, int h, lv_coord_t radius)
|
||||
{
|
||||
lv_draw_img_rounded_key_t key = rounded_key_create(texture, w, h, radius);
|
||||
SDL_Texture * mask_frag = lv_draw_sdl_rect_bg_frag_obtain(ctx, radius);
|
||||
SDL_Texture * img_frag = lv_draw_sdl_texture_cache_get(ctx, &key, sizeof(key), NULL);
|
||||
if(img_frag == NULL) {
|
||||
const lv_coord_t full_frag_size = radius * 2 + 3;
|
||||
img_frag = SDL_CreateTexture(ctx->renderer, LV_DRAW_SDL_TEXTURE_FORMAT, SDL_TEXTUREACCESS_TARGET,
|
||||
full_frag_size, full_frag_size);
|
||||
SDL_SetTextureBlendMode(img_frag, SDL_BLENDMODE_BLEND);
|
||||
SDL_Texture * old_target = SDL_GetRenderTarget(ctx->renderer);
|
||||
SDL_SetRenderTarget(ctx->renderer, img_frag);
|
||||
SDL_SetRenderDrawColor(ctx->renderer, 0, 0, 0, 0);
|
||||
/* SDL_RenderClear is not working properly, so we overwrite the target with solid color */
|
||||
SDL_SetRenderDrawBlendMode(ctx->renderer, SDL_BLENDMODE_NONE);
|
||||
SDL_RenderFillRect(ctx->renderer, NULL);
|
||||
SDL_SetRenderDrawBlendMode(ctx->renderer, SDL_BLENDMODE_BLEND);
|
||||
|
||||
lv_area_t coords = {0, 0, w - 1, h - 1}, clip;
|
||||
lv_area_t frag_coords = {0, 0, full_frag_size - 1, full_frag_size - 1};
|
||||
lv_draw_sdl_rect_bg_frag_draw_corners(ctx, mask_frag, radius, &frag_coords, NULL, false);
|
||||
|
||||
SDL_SetTextureAlphaMod(texture, 0xFF);
|
||||
SDL_SetTextureColorMod(texture, 0xFF, 0xFF, 0xFF);
|
||||
#if LV_GPU_SDL_CUSTOM_BLEND_MODE
|
||||
SDL_BlendMode blend_mode = SDL_ComposeCustomBlendMode(SDL_BLENDFACTOR_ONE, SDL_BLENDFACTOR_ZERO,
|
||||
SDL_BLENDOPERATION_ADD, SDL_BLENDFACTOR_DST_ALPHA,
|
||||
SDL_BLENDFACTOR_ZERO, SDL_BLENDOPERATION_ADD);
|
||||
SDL_SetTextureBlendMode(texture, blend_mode);
|
||||
#else
|
||||
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_MOD);
|
||||
#endif
|
||||
SDL_Rect srcrect, cliprect, dstrect = {0, 0, radius, radius};
|
||||
|
||||
cliprect.w = cliprect.h = radius;
|
||||
for(int i = 0; i <= ROUNDED_IMG_CORNER_BOTTOM_LEFT; i++) {
|
||||
switch(i) {
|
||||
case ROUNDED_IMG_CORNER_TOP_LEFT:
|
||||
cliprect.x = 0;
|
||||
cliprect.y = 0;
|
||||
lv_area_align(&frag_coords, &coords, LV_ALIGN_TOP_LEFT, 0, 0);
|
||||
break;
|
||||
case ROUNDED_IMG_CORNER_TOP_RIGHT:
|
||||
cliprect.x = full_frag_size - radius;
|
||||
cliprect.y = 0;
|
||||
lv_area_align(&frag_coords, &coords, LV_ALIGN_TOP_RIGHT, 0, 0);
|
||||
break;
|
||||
case ROUNDED_IMG_CORNER_BOTTOM_RIGHT:
|
||||
cliprect.x = full_frag_size - radius;
|
||||
cliprect.y = full_frag_size - radius;
|
||||
lv_area_align(&frag_coords, &coords, LV_ALIGN_BOTTOM_RIGHT, 0, 0);
|
||||
break;
|
||||
case ROUNDED_IMG_CORNER_BOTTOM_LEFT:
|
||||
cliprect.x = 0;
|
||||
cliprect.y = full_frag_size - radius;
|
||||
lv_area_align(&frag_coords, &coords, LV_ALIGN_BOTTOM_LEFT, 0, 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
calc_draw_part(texture, header, &coords, NULL, &srcrect, &dstrect);
|
||||
SDL_RenderSetClipRect(ctx->renderer, &cliprect);
|
||||
SDL_RenderCopy(ctx->renderer, texture, &srcrect, &dstrect);
|
||||
}
|
||||
SDL_RenderSetClipRect(ctx->renderer, NULL);
|
||||
|
||||
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
|
||||
|
||||
SDL_SetRenderTarget(ctx->renderer, old_target);
|
||||
lv_draw_sdl_texture_cache_put(ctx, &key, sizeof(key), img_frag);
|
||||
}
|
||||
return img_frag;
|
||||
}
|
||||
|
||||
static lv_draw_img_rounded_key_t rounded_key_create(const SDL_Texture * texture, lv_coord_t w, lv_coord_t h,
|
||||
lv_coord_t radius)
|
||||
{
|
||||
lv_draw_img_rounded_key_t key;
|
||||
SDL_memset(&key, 0, sizeof(key));
|
||||
key.magic = LV_GPU_CACHE_KEY_MAGIC_IMG_ROUNDED_CORNERS;
|
||||
key.texture = texture;
|
||||
key.w = w;
|
||||
key.h = h;
|
||||
key.radius = radius;
|
||||
return key;
|
||||
}
|
||||
|
||||
#endif /*LV_USE_GPU_SDL*/
|
||||
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
* @file lv_draw_sdl_img.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_DRAW_SDL_IMG_H
|
||||
#define LV_DRAW_SDL_IMG_H
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_GPU_SDL
|
||||
|
||||
#include LV_GPU_SDL_INCLUDE_PATH
|
||||
|
||||
#include "../lv_draw.h"
|
||||
|
||||
#include "lv_draw_sdl_texture_cache.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct lv_draw_sdl_img_header_t {
|
||||
lv_img_header_t base;
|
||||
SDL_Rect rect;
|
||||
} lv_draw_sdl_img_header_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/*======================
|
||||
* Add/remove functions
|
||||
*=====================*/
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/*=====================
|
||||
* Other functions
|
||||
*====================*/
|
||||
bool lv_draw_sdl_img_load_texture(lv_draw_sdl_ctx_t * ctx, lv_draw_sdl_cache_key_head_img_t * key, size_t key_size,
|
||||
const void * src, int32_t frame_id, SDL_Texture ** texture,
|
||||
lv_draw_sdl_img_header_t ** header);
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_GPU_SDL*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_DRAW_SDL_IMG_H*/
|
||||
@@ -0,0 +1,176 @@
|
||||
/**
|
||||
* @file lv_draw_sdl_label.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_GPU_SDL
|
||||
|
||||
#include LV_GPU_SDL_INCLUDE_PATH
|
||||
|
||||
#include "../lv_draw_label.h"
|
||||
#include "../../misc/lv_utils.h"
|
||||
|
||||
#include "lv_draw_sdl_utils.h"
|
||||
#include "lv_draw_sdl_texture_cache.h"
|
||||
#include "lv_draw_sdl_composite.h"
|
||||
#include "lv_draw_sdl_layer.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct {
|
||||
lv_sdl_cache_key_magic_t magic;
|
||||
const lv_font_t * font_p;
|
||||
uint32_t letter;
|
||||
} lv_font_glyph_key_t;
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static lv_font_glyph_key_t font_key_glyph_create(const lv_font_t * font_p, uint32_t letter);
|
||||
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_draw_sdl_draw_letter(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc, const lv_point_t * pos_p,
|
||||
uint32_t letter)
|
||||
{
|
||||
const lv_area_t * clip_area = draw_ctx->clip_area;
|
||||
const lv_font_t * font_p = dsc->font;
|
||||
lv_opa_t opa = dsc->opa;
|
||||
lv_color_t color = dsc->color;
|
||||
if(opa < LV_OPA_MIN) return;
|
||||
if(opa > LV_OPA_MAX) opa = LV_OPA_COVER;
|
||||
|
||||
if(font_p == NULL) {
|
||||
LV_LOG_WARN("lv_draw_letter: font is NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
lv_font_glyph_dsc_t g;
|
||||
bool g_ret = lv_font_get_glyph_dsc(font_p, &g, letter, '\0');
|
||||
if(g_ret == false) {
|
||||
/*Add warning if the dsc is not found
|
||||
*but do not print warning for non printable ASCII chars (e.g. '\n')*/
|
||||
if(letter >= 0x20 &&
|
||||
letter != 0xf8ff && /*LV_SYMBOL_DUMMY*/
|
||||
letter != 0x200c) { /*ZERO WIDTH NON-JOINER*/
|
||||
LV_LOG_WARN("lv_draw_letter: glyph dsc. not found for U+%X", letter);
|
||||
|
||||
/* draw placeholder */
|
||||
lv_area_t glyph_coords;
|
||||
lv_draw_rect_dsc_t glyph_dsc;
|
||||
lv_coord_t begin_x = pos_p->x + g.ofs_x;
|
||||
lv_coord_t begin_y = pos_p->y + g.ofs_y;
|
||||
lv_area_set(&glyph_coords, begin_x, begin_y, begin_x + g.box_w, begin_y + g.box_h);
|
||||
lv_draw_rect_dsc_init(&glyph_dsc);
|
||||
glyph_dsc.bg_opa = LV_OPA_MIN;
|
||||
glyph_dsc.outline_opa = LV_OPA_MIN;
|
||||
glyph_dsc.shadow_opa = LV_OPA_MIN;
|
||||
glyph_dsc.bg_img_opa = LV_OPA_MIN;
|
||||
glyph_dsc.border_color = dsc->color;
|
||||
glyph_dsc.border_width = 1;
|
||||
draw_ctx->draw_rect(draw_ctx, &glyph_dsc, &glyph_coords);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*Don't draw anything if the character is empty. E.g. space*/
|
||||
if((g.box_h == 0) || (g.box_w == 0)) return;
|
||||
|
||||
int32_t pos_x = pos_p->x + g.ofs_x;
|
||||
int32_t pos_y = pos_p->y + (font_p->line_height - font_p->base_line) - g.box_h - g.ofs_y;
|
||||
|
||||
const lv_area_t letter_area = {pos_x, pos_y, pos_x + g.box_w - 1, pos_y + g.box_h - 1};
|
||||
lv_area_t draw_area;
|
||||
|
||||
/*If the letter is completely out of mask don't draw it*/
|
||||
if(!_lv_area_intersect(&draw_area, &letter_area, clip_area)) {
|
||||
return;
|
||||
}
|
||||
|
||||
lv_draw_sdl_ctx_t * ctx = (lv_draw_sdl_ctx_t *) draw_ctx;
|
||||
SDL_Renderer * renderer = ctx->renderer;
|
||||
|
||||
lv_font_glyph_key_t glyph_key = font_key_glyph_create(font_p, letter);
|
||||
bool glyph_found = false;
|
||||
SDL_Texture * texture = lv_draw_sdl_texture_cache_get(ctx, &glyph_key, sizeof(glyph_key), &glyph_found);
|
||||
if(!glyph_found) {
|
||||
if(g.resolved_font) {
|
||||
font_p = g.resolved_font;
|
||||
}
|
||||
const uint8_t * bmp = lv_font_get_glyph_bitmap(font_p, letter);
|
||||
uint8_t * buf = lv_mem_alloc(g.box_w * g.box_h);
|
||||
lv_sdl_to_8bpp(buf, bmp, g.box_w, g.box_h, g.box_w, g.bpp);
|
||||
SDL_Surface * mask = lv_sdl_create_opa_surface(buf, g.box_w, g.box_h, g.box_w);
|
||||
texture = SDL_CreateTextureFromSurface(renderer, mask);
|
||||
SDL_FreeSurface(mask);
|
||||
lv_mem_free(buf);
|
||||
lv_draw_sdl_texture_cache_put(ctx, &glyph_key, sizeof(glyph_key), texture);
|
||||
}
|
||||
if(!texture) {
|
||||
return;
|
||||
}
|
||||
|
||||
lv_area_t t_letter = letter_area, t_clip = *clip_area, apply_area;
|
||||
bool has_composite = lv_draw_sdl_composite_begin(ctx, &letter_area, clip_area, NULL, dsc->blend_mode, &t_letter,
|
||||
&t_clip, &apply_area);
|
||||
|
||||
lv_draw_sdl_transform_areas_offset(ctx, has_composite, &apply_area, &t_letter, &t_clip);
|
||||
|
||||
/*If the letter is completely out of mask don't draw it*/
|
||||
if(!_lv_area_intersect(&draw_area, &t_letter, &t_clip)) {
|
||||
return;
|
||||
}
|
||||
SDL_Rect srcrect, dstrect;
|
||||
lv_area_to_sdl_rect(&draw_area, &dstrect);
|
||||
srcrect.x = draw_area.x1 - t_letter.x1;
|
||||
srcrect.y = draw_area.y1 - t_letter.y1;
|
||||
srcrect.w = dstrect.w;
|
||||
srcrect.h = dstrect.h;
|
||||
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
|
||||
SDL_SetTextureAlphaMod(texture, opa);
|
||||
SDL_SetTextureColorMod(texture, color.ch.red, color.ch.green, color.ch.blue);
|
||||
SDL_RenderCopy(renderer, texture, &srcrect, &dstrect);
|
||||
|
||||
lv_draw_sdl_composite_end(ctx, &apply_area, dsc->blend_mode);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static lv_font_glyph_key_t font_key_glyph_create(const lv_font_t * font_p, uint32_t letter)
|
||||
{
|
||||
lv_font_glyph_key_t key;
|
||||
/* VERY IMPORTANT! Padding between members is uninitialized, so we have to wipe them manually */
|
||||
SDL_memset(&key, 0, sizeof(key));
|
||||
key.magic = LV_GPU_CACHE_KEY_MAGIC_FONT_GLYPH;
|
||||
key.font_p = font_p;
|
||||
key.letter = letter;
|
||||
return key;
|
||||
}
|
||||
|
||||
#endif /*LV_USE_GPU_SDL*/
|
||||
@@ -0,0 +1,141 @@
|
||||
/**
|
||||
* @file lv_draw_sdl_refr.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_GPU_SDL
|
||||
|
||||
#include "../../core/lv_refr.h"
|
||||
|
||||
#include "lv_draw_sdl.h"
|
||||
#include "lv_draw_sdl_priv.h"
|
||||
#include "lv_draw_sdl_composite.h"
|
||||
#include "lv_draw_sdl_utils.h"
|
||||
#include "lv_draw_sdl_layer.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
lv_draw_layer_ctx_t * lv_draw_sdl_layer_init(lv_draw_ctx_t * draw_ctx, lv_draw_layer_ctx_t * layer_ctx,
|
||||
lv_draw_layer_flags_t flags)
|
||||
{
|
||||
lv_draw_sdl_ctx_t * ctx = (lv_draw_sdl_ctx_t *) draw_ctx;
|
||||
SDL_Renderer * renderer = ctx->renderer;
|
||||
|
||||
lv_draw_sdl_layer_ctx_t * transform_ctx = (lv_draw_sdl_layer_ctx_t *) layer_ctx;
|
||||
|
||||
transform_ctx->flags = flags;
|
||||
transform_ctx->orig_target = SDL_GetRenderTarget(renderer);
|
||||
|
||||
lv_coord_t target_w = lv_area_get_width(&layer_ctx->area_full);
|
||||
lv_coord_t target_h = lv_area_get_height(&layer_ctx->area_full);
|
||||
|
||||
enum lv_draw_sdl_composite_texture_id_t texture_id = LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_TRANSFORM0 +
|
||||
ctx->internals->transform_count;
|
||||
transform_ctx->target = lv_draw_sdl_composite_texture_obtain(ctx, texture_id, target_w, target_h);
|
||||
transform_ctx->target_rect.x = 0;
|
||||
transform_ctx->target_rect.y = 0;
|
||||
transform_ctx->target_rect.w = target_w;
|
||||
transform_ctx->target_rect.h = target_h;
|
||||
|
||||
layer_ctx->max_row_with_alpha = target_h;
|
||||
layer_ctx->max_row_with_no_alpha = target_h;
|
||||
|
||||
SDL_SetTextureBlendMode(transform_ctx->target, SDL_BLENDMODE_BLEND);
|
||||
SDL_SetRenderTarget(renderer, transform_ctx->target);
|
||||
|
||||
/* SDL_RenderClear is not working properly, so we overwrite the target with solid color */
|
||||
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_NONE);
|
||||
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
|
||||
SDL_RenderFillRect(renderer, NULL);
|
||||
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
|
||||
|
||||
/* Set proper drawing context for transform layer */
|
||||
ctx->internals->transform_count += 1;
|
||||
draw_ctx->buf_area = &layer_ctx->area_full;
|
||||
draw_ctx->clip_area = &layer_ctx->area_full;
|
||||
|
||||
return layer_ctx;
|
||||
}
|
||||
|
||||
void lv_draw_sdl_layer_blend(lv_draw_ctx_t * draw_ctx, lv_draw_layer_ctx_t * layer_ctx,
|
||||
const lv_draw_img_dsc_t * draw_dsc)
|
||||
{
|
||||
lv_draw_sdl_ctx_t * ctx = (lv_draw_sdl_ctx_t *) draw_ctx;
|
||||
lv_draw_sdl_layer_ctx_t * transform_ctx = (lv_draw_sdl_layer_ctx_t *) layer_ctx;
|
||||
|
||||
SDL_Renderer * renderer = ctx->renderer;
|
||||
|
||||
SDL_Rect trans_rect;
|
||||
|
||||
if(transform_ctx->flags & LV_DRAW_LAYER_FLAG_CAN_SUBDIVIDE) {
|
||||
lv_area_zoom_to_sdl_rect(&layer_ctx->area_act, &trans_rect, draw_dsc->zoom, &draw_dsc->pivot);
|
||||
}
|
||||
else {
|
||||
lv_area_zoom_to_sdl_rect(&layer_ctx->area_full, &trans_rect, draw_dsc->zoom, &draw_dsc->pivot);
|
||||
}
|
||||
|
||||
SDL_SetRenderTarget(renderer, transform_ctx->orig_target);
|
||||
|
||||
/*Render off-screen texture, transformed*/
|
||||
SDL_Rect clip_rect;
|
||||
lv_area_to_sdl_rect(layer_ctx->original.clip_area, &clip_rect);
|
||||
SDL_Point center = {.x = draw_dsc->pivot.x, .y = draw_dsc->pivot.y};
|
||||
SDL_RenderSetClipRect(renderer, &clip_rect);
|
||||
SDL_SetTextureAlphaMod(transform_ctx->target, draw_dsc->opa);
|
||||
SDL_RenderCopyEx(renderer, transform_ctx->target, &transform_ctx->target_rect, &trans_rect,
|
||||
draw_dsc->angle, ¢er, SDL_FLIP_NONE);
|
||||
SDL_RenderSetClipRect(renderer, NULL);
|
||||
}
|
||||
|
||||
void lv_draw_sdl_layer_destroy(lv_draw_ctx_t * draw_ctx, lv_draw_layer_ctx_t * layer_ctx)
|
||||
{
|
||||
lv_draw_sdl_ctx_t * ctx = (lv_draw_sdl_ctx_t *) draw_ctx;
|
||||
ctx->internals->transform_count -= 1;
|
||||
}
|
||||
|
||||
void lv_draw_sdl_transform_areas_offset(lv_draw_sdl_ctx_t * ctx, bool has_composite, lv_area_t * apply_area,
|
||||
lv_area_t * coords, lv_area_t * clip)
|
||||
{
|
||||
if(ctx->internals->transform_count == 0) {
|
||||
return;
|
||||
}
|
||||
lv_area_t * area = ctx->base_draw.buf_area;
|
||||
lv_area_move(coords, -area->x1, -area->y1);
|
||||
lv_area_move(clip, -area->x1, -area->y1);
|
||||
if(has_composite) {
|
||||
lv_area_move(apply_area, -area->x1, -area->y1);
|
||||
}
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_GPU_SDL*/
|
||||
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* @file lv_draw_sdl_refr.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_TEMPL_H
|
||||
#define LV_TEMPL_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_draw_sdl.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
typedef struct _lv_draw_sdl_layer_ctx_t {
|
||||
lv_draw_layer_ctx_t base;
|
||||
|
||||
SDL_Texture * orig_target;
|
||||
SDL_Texture * target;
|
||||
SDL_Rect target_rect;
|
||||
lv_draw_layer_flags_t flags;
|
||||
} lv_draw_sdl_layer_ctx_t;
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
lv_draw_layer_ctx_t * lv_draw_sdl_layer_init(lv_draw_ctx_t * draw_ctx, lv_draw_layer_ctx_t * layer_ctx,
|
||||
lv_draw_layer_flags_t flags);
|
||||
|
||||
void lv_draw_sdl_layer_blend(lv_draw_ctx_t * draw_ctx, lv_draw_layer_ctx_t * transform_ctx,
|
||||
const lv_draw_img_dsc_t * draw_dsc);
|
||||
|
||||
void lv_draw_sdl_layer_destroy(lv_draw_ctx_t * draw_ctx, lv_draw_layer_ctx_t * layer_ctx);
|
||||
|
||||
void lv_draw_sdl_transform_areas_offset(lv_draw_sdl_ctx_t * ctx, bool has_composite, lv_area_t * apply_area,
|
||||
lv_area_t * coords, lv_area_t * clip);
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_TEMPL_H*/
|
||||
@@ -0,0 +1,157 @@
|
||||
/**
|
||||
* @file lv_draw_sdl_line.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_GPU_SDL
|
||||
|
||||
#include "lv_draw_sdl.h"
|
||||
#include "lv_draw_sdl_utils.h"
|
||||
#include "lv_draw_sdl_texture_cache.h"
|
||||
#include "lv_draw_sdl_composite.h"
|
||||
#include "lv_draw_sdl_mask.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define ROUND_START 0x01
|
||||
#define ROUND_END 0x02
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct {
|
||||
lv_sdl_cache_key_magic_t magic;
|
||||
lv_coord_t length;
|
||||
lv_coord_t width;
|
||||
uint8_t round;
|
||||
} lv_draw_line_key_t;
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
static lv_draw_line_key_t line_key_create(const lv_draw_line_dsc_t * dsc, lv_coord_t length);
|
||||
|
||||
static SDL_Texture * line_texture_create(lv_draw_sdl_ctx_t * sdl_ctx, const lv_draw_line_dsc_t * dsc,
|
||||
lv_coord_t length);
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
void lv_draw_sdl_draw_line(lv_draw_ctx_t * draw_ctx, const lv_draw_line_dsc_t * dsc, const lv_point_t * point1,
|
||||
const lv_point_t * point2)
|
||||
{
|
||||
lv_draw_sdl_ctx_t * sdl_ctx = (lv_draw_sdl_ctx_t *) draw_ctx;
|
||||
SDL_Renderer * renderer = sdl_ctx->renderer;
|
||||
lv_coord_t x1 = point1->x, x2 = point2->x, y1 = point1->y, y2 = point2->y;
|
||||
double length = SDL_sqrt(SDL_pow(x2 - x1, 2) + SDL_pow(y2 - y1, 2));
|
||||
if(length - (long) length > 0.5) {
|
||||
length = (long) length + 1;
|
||||
}
|
||||
|
||||
double angle = SDL_atan2(y2 - y1, x2 - x1) * 180 / M_PI;
|
||||
lv_draw_line_key_t key = line_key_create(dsc, (lv_coord_t) length);
|
||||
SDL_Texture * texture = lv_draw_sdl_texture_cache_get(sdl_ctx, &key, sizeof(key), NULL);
|
||||
if(!texture) {
|
||||
texture = line_texture_create(sdl_ctx, dsc, (lv_coord_t) length);
|
||||
lv_draw_sdl_texture_cache_put(sdl_ctx, &key, sizeof(key), texture);
|
||||
}
|
||||
|
||||
lv_area_t coords = {x1, y1, x2, y2};
|
||||
const lv_area_t * clip = draw_ctx->clip_area;
|
||||
|
||||
SDL_Rect coords_r, clip_r;
|
||||
lv_area_to_sdl_rect(&coords, &coords_r);
|
||||
lv_area_to_sdl_rect(clip, &clip_r);
|
||||
|
||||
lv_area_t t_coords = coords, t_clip = *clip, apply_area;
|
||||
lv_area_t extension = {dsc->width / 2, dsc->width / 2, dsc->width / 2, dsc->width / 2};
|
||||
lv_draw_sdl_composite_begin(sdl_ctx, &coords, clip, &extension, dsc->blend_mode, &t_coords, &t_clip,
|
||||
&apply_area);
|
||||
|
||||
SDL_Color color;
|
||||
lv_color_to_sdl_color(&dsc->color, &color);
|
||||
|
||||
SDL_SetTextureColorMod(texture, color.r, color.g, color.b);
|
||||
SDL_SetTextureAlphaMod(texture, dsc->opa);
|
||||
SDL_Rect srcrect = {0, 0, (int) length + dsc->width + 2, dsc->width + 2},
|
||||
dstrect = {t_coords.x1 - 1 - dsc->width / 2, t_coords.y1 - 1, srcrect.w, srcrect.h};
|
||||
SDL_Point center = {1 + dsc->width / 2, 1 + dsc->width / 2};
|
||||
|
||||
SDL_Rect clip_rect;
|
||||
lv_area_to_sdl_rect(&t_clip, &clip_rect);
|
||||
if(!SDL_RectEquals(&clip_rect, &dstrect) || angle != 0) {
|
||||
SDL_RenderSetClipRect(renderer, &clip_rect);
|
||||
}
|
||||
SDL_RenderCopyEx(renderer, texture, &srcrect, &dstrect, angle, ¢er, 0);
|
||||
SDL_RenderSetClipRect(renderer, NULL);
|
||||
|
||||
lv_draw_sdl_composite_end(sdl_ctx, &apply_area, dsc->blend_mode);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static lv_draw_line_key_t line_key_create(const lv_draw_line_dsc_t * dsc, lv_coord_t length)
|
||||
{
|
||||
lv_draw_line_key_t key;
|
||||
lv_memset_00(&key, sizeof(lv_draw_line_key_t));
|
||||
key.magic = LV_GPU_CACHE_KEY_MAGIC_LINE;
|
||||
key.length = length;
|
||||
key.width = dsc->width;
|
||||
key.round = (dsc->round_start ? ROUND_START : 0) | (dsc->round_end ? ROUND_END : 0);
|
||||
return key;
|
||||
}
|
||||
|
||||
static SDL_Texture * line_texture_create(lv_draw_sdl_ctx_t * sdl_ctx, const lv_draw_line_dsc_t * dsc, lv_coord_t length)
|
||||
{
|
||||
SDL_Texture * texture = SDL_CreateTexture(sdl_ctx->renderer, LV_DRAW_SDL_TEXTURE_FORMAT, SDL_TEXTUREACCESS_TARGET,
|
||||
length + dsc->width + 2, dsc->width + 2);
|
||||
SDL_Texture * target = SDL_GetRenderTarget(sdl_ctx->renderer);
|
||||
SDL_SetRenderTarget(sdl_ctx->renderer, texture);
|
||||
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
|
||||
SDL_SetRenderDrawColor(sdl_ctx->renderer, 0xFF, 0xFF, 0xFF, 0x0);
|
||||
/* SDL_RenderClear is not working properly, so we overwrite the target with solid color */
|
||||
SDL_SetRenderDrawBlendMode(sdl_ctx->renderer, SDL_BLENDMODE_NONE);
|
||||
SDL_RenderFillRect(sdl_ctx->renderer, NULL);
|
||||
SDL_SetRenderDrawBlendMode(sdl_ctx->renderer, SDL_BLENDMODE_BLEND);
|
||||
SDL_SetRenderDrawColor(sdl_ctx->renderer, 0xFF, 0xFF, 0xFF, 0xFF);
|
||||
SDL_Rect line_rect = {1 + dsc->width / 2, 1, length, dsc->width};
|
||||
SDL_RenderFillRect(sdl_ctx->renderer, &line_rect);
|
||||
if(dsc->round_start || dsc->round_end) {
|
||||
lv_draw_mask_radius_param_t param;
|
||||
lv_area_t round_area = {0, 0, dsc->width - 1, dsc->width - 1};
|
||||
lv_draw_mask_radius_init(¶m, &round_area, LV_RADIUS_CIRCLE, false);
|
||||
|
||||
int16_t mask_id = lv_draw_mask_add(¶m, NULL);
|
||||
SDL_Texture * round_texture = lv_draw_sdl_mask_dump_texture(sdl_ctx->renderer, &round_area, &mask_id, 1);
|
||||
lv_draw_mask_remove_id(mask_id);
|
||||
|
||||
SDL_Rect round_src = {0, 0, dsc->width, dsc->width};
|
||||
SDL_Rect round_dst = {line_rect.x - dsc->width / 2, 1, dsc->width, dsc->width};
|
||||
SDL_RenderCopy(sdl_ctx->renderer, round_texture, &round_src, &round_dst);
|
||||
round_dst.x = line_rect.w + dsc->width / 2;
|
||||
SDL_RenderCopy(sdl_ctx->renderer, round_texture, &round_src, &round_dst);
|
||||
SDL_DestroyTexture(round_texture);
|
||||
}
|
||||
|
||||
SDL_SetRenderTarget(sdl_ctx->renderer, target);
|
||||
return texture;
|
||||
}
|
||||
|
||||
#endif /*LV_USE_GPU_SDL*/
|
||||
@@ -0,0 +1,84 @@
|
||||
/**
|
||||
* @file lv_draw_sdl_mask.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_GPU_SDL
|
||||
|
||||
#include "../../misc/lv_gc.h"
|
||||
#include "lv_draw_sdl_mask.h"
|
||||
#include "lv_draw_sdl_utils.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#ifndef HAVE_SDL_CUSTOM_BLEND_MODE
|
||||
#define HAVE_SDL_CUSTOM_BLEND_MODE (SDL_VERSION_ATLEAST(2, 0, 6))
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
lv_opa_t * lv_draw_sdl_mask_dump_opa(const lv_area_t * coords, const int16_t * ids, int16_t ids_count)
|
||||
{
|
||||
SDL_assert(coords->x2 >= coords->x1);
|
||||
SDL_assert(coords->y2 >= coords->y1);
|
||||
lv_coord_t w = lv_area_get_width(coords), h = lv_area_get_height(coords);
|
||||
lv_opa_t * mask_buf = lv_mem_buf_get(w * h);
|
||||
for(lv_coord_t y = 0; y < h; y++) {
|
||||
lv_opa_t * line_buf = &mask_buf[y * w];
|
||||
lv_memset_ff(line_buf, w);
|
||||
lv_coord_t abs_x = (lv_coord_t) coords->x1, abs_y = (lv_coord_t)(y + coords->y1), len = (lv_coord_t) w;
|
||||
lv_draw_mask_res_t res;
|
||||
if(ids) {
|
||||
res = lv_draw_mask_apply_ids(line_buf, abs_x, abs_y, len, ids, ids_count);
|
||||
}
|
||||
else {
|
||||
res = lv_draw_mask_apply(line_buf, abs_x, abs_y, len);
|
||||
}
|
||||
if(res == LV_DRAW_MASK_RES_TRANSP) {
|
||||
lv_memset_00(line_buf, w);
|
||||
}
|
||||
}
|
||||
return mask_buf;
|
||||
}
|
||||
|
||||
SDL_Texture * lv_draw_sdl_mask_dump_texture(SDL_Renderer * renderer, const lv_area_t * coords, const int16_t * ids,
|
||||
int16_t ids_count)
|
||||
{
|
||||
lv_coord_t w = lv_area_get_width(coords), h = lv_area_get_height(coords);
|
||||
lv_opa_t * mask_buf = lv_draw_sdl_mask_dump_opa(coords, ids, ids_count);
|
||||
SDL_Surface * surface = lv_sdl_create_opa_surface(mask_buf, w, h, w);
|
||||
lv_mem_buf_release(mask_buf);
|
||||
SDL_Texture * texture = SDL_CreateTextureFromSurface(renderer, surface);
|
||||
SDL_FreeSurface(surface);
|
||||
return texture;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_GPU_SDL*/
|
||||
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* @file lv_draw_sdl_mask.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_DRAW_SDL_MASK_H
|
||||
#define LV_DRAW_SDL_MASK_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "../../lv_conf_internal.h"
|
||||
|
||||
#include LV_GPU_SDL_INCLUDE_PATH
|
||||
|
||||
#include "lv_draw_sdl.h"
|
||||
#include "../../misc/lv_area.h"
|
||||
#include "../../misc/lv_color.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
lv_opa_t * lv_draw_sdl_mask_dump_opa(const lv_area_t * coords, const int16_t * ids, int16_t ids_count);
|
||||
|
||||
SDL_Texture * lv_draw_sdl_mask_dump_texture(SDL_Renderer * renderer, const lv_area_t * coords, const int16_t * ids,
|
||||
int16_t ids_count);
|
||||
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_DRAW_SDL_MASK_H*/
|
||||
@@ -0,0 +1,133 @@
|
||||
/**
|
||||
* @file lv_draw_sdl_polygon.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_GPU_SDL
|
||||
|
||||
#include "lv_draw_sdl.h"
|
||||
#include "lv_draw_sdl_utils.h"
|
||||
#include "lv_draw_sdl_texture_cache.h"
|
||||
#include "lv_draw_sdl_composite.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
static void dump_masks(SDL_Texture * texture, const lv_area_t * coords);
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
void lv_draw_sdl_polygon(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * draw_dsc, const lv_point_t * points,
|
||||
uint16_t point_cnt)
|
||||
{
|
||||
if(point_cnt < 3) return;
|
||||
if(points == NULL) return;
|
||||
|
||||
lv_draw_mask_polygon_param_t polygon_param;
|
||||
lv_draw_mask_polygon_init(&polygon_param, points, point_cnt);
|
||||
|
||||
if(polygon_param.cfg.point_cnt < 3) {
|
||||
lv_draw_mask_free_param(&polygon_param);
|
||||
return;
|
||||
}
|
||||
|
||||
lv_area_t poly_coords = {.x1 = LV_COORD_MAX, .y1 = LV_COORD_MAX, .x2 = LV_COORD_MIN, .y2 = LV_COORD_MIN};
|
||||
|
||||
uint16_t i;
|
||||
for(i = 0; i < point_cnt; i++) {
|
||||
poly_coords.x1 = LV_MIN(poly_coords.x1, polygon_param.cfg.points[i].x);
|
||||
poly_coords.y1 = LV_MIN(poly_coords.y1, polygon_param.cfg.points[i].y);
|
||||
poly_coords.x2 = LV_MAX(poly_coords.x2, polygon_param.cfg.points[i].x);
|
||||
poly_coords.y2 = LV_MAX(poly_coords.y2, polygon_param.cfg.points[i].y);
|
||||
}
|
||||
|
||||
bool is_common;
|
||||
lv_area_t draw_area;
|
||||
is_common = _lv_area_intersect(&draw_area, &poly_coords, draw_ctx->clip_area);
|
||||
if(!is_common) {
|
||||
lv_draw_mask_free_param(&polygon_param);
|
||||
return;
|
||||
}
|
||||
|
||||
lv_draw_sdl_ctx_t * ctx = (lv_draw_sdl_ctx_t *) draw_ctx;
|
||||
|
||||
int16_t mask_id = lv_draw_mask_add(&polygon_param, NULL);
|
||||
|
||||
lv_coord_t w = lv_area_get_width(&draw_area), h = lv_area_get_height(&draw_area);
|
||||
SDL_Texture * texture = lv_draw_sdl_composite_texture_obtain(ctx, LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_STREAM1, w, h);
|
||||
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
|
||||
dump_masks(texture, &draw_area);
|
||||
|
||||
lv_draw_mask_remove_id(mask_id);
|
||||
lv_draw_mask_free_param(&polygon_param);
|
||||
|
||||
SDL_Rect srcrect = {0, 0, w, h}, dstrect;
|
||||
lv_area_to_sdl_rect(&draw_area, &dstrect);
|
||||
SDL_Color color;
|
||||
lv_color_to_sdl_color(&draw_dsc->bg_color, &color);
|
||||
SDL_SetTextureColorMod(texture, color.r, color.g, color.b);
|
||||
SDL_SetTextureAlphaMod(texture, draw_dsc->bg_opa);
|
||||
SDL_RenderCopy(ctx->renderer, texture, &srcrect, &dstrect);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void dump_masks(SDL_Texture * texture, const lv_area_t * coords)
|
||||
{
|
||||
lv_coord_t w = lv_area_get_width(coords), h = lv_area_get_height(coords);
|
||||
SDL_assert(w > 0 && h > 0);
|
||||
SDL_Rect rect = {0, 0, w, h};
|
||||
uint8_t * pixels;
|
||||
int pitch;
|
||||
if(SDL_LockTexture(texture, &rect, (void **) &pixels, &pitch) != 0) return;
|
||||
|
||||
lv_opa_t * line_buf = lv_mem_buf_get(rect.w);
|
||||
for(lv_coord_t y = 0; y < rect.h; y++) {
|
||||
lv_memset_ff(line_buf, rect.w);
|
||||
lv_coord_t abs_x = (lv_coord_t) coords->x1, abs_y = (lv_coord_t)(y + coords->y1), len = (lv_coord_t) rect.w;
|
||||
lv_draw_mask_res_t res;
|
||||
res = lv_draw_mask_apply(line_buf, abs_x, abs_y, len);
|
||||
if(res == LV_DRAW_MASK_RES_TRANSP) {
|
||||
lv_memset_00(&pixels[y * pitch], 4 * rect.w);
|
||||
}
|
||||
else if(res == LV_DRAW_MASK_RES_FULL_COVER) {
|
||||
lv_memset_ff(&pixels[y * pitch], 4 * rect.w);
|
||||
}
|
||||
else {
|
||||
for(int x = 0; x < rect.w; x++) {
|
||||
uint8_t * pixel = &pixels[y * pitch + x * 4];
|
||||
*pixel = line_buf[x];
|
||||
pixel[1] = pixel[2] = pixel[3] = 0xFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
lv_mem_buf_release(line_buf);
|
||||
SDL_UnlockTexture(texture);
|
||||
}
|
||||
|
||||
#endif /*LV_USE_GPU_SDL*/
|
||||
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
* @file lv_draw_sdl_priv.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_DRAW_SDL_PRIV_H
|
||||
#define LV_DRAW_SDL_PRIV_H
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_GPU_SDL
|
||||
|
||||
#include LV_GPU_SDL_INCLUDE_PATH
|
||||
|
||||
#include "../lv_draw.h"
|
||||
#include "../../misc/lv_lru.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct lv_draw_sdl_context_internals_t {
|
||||
lv_lru_t * texture_cache;
|
||||
SDL_Texture * mask;
|
||||
SDL_Texture * composition;
|
||||
SDL_Texture * target_backup;
|
||||
uint8_t transform_count;
|
||||
} lv_draw_sdl_context_internals_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/*======================
|
||||
* Add/remove functions
|
||||
*=====================*/
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/*=====================
|
||||
* Other functions
|
||||
*====================*/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_GPU_SDL*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_DRAW_SDL_PRIV_H*/
|
||||
@@ -0,0 +1,712 @@
|
||||
/**
|
||||
* @file lv_draw_sdl_rect.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_GPU_SDL
|
||||
|
||||
#include "../lv_draw_rect.h"
|
||||
#include "../lv_draw_img.h"
|
||||
#include "../lv_draw_label.h"
|
||||
#include "../lv_draw_mask.h"
|
||||
#include "../../core/lv_refr.h"
|
||||
#include "lv_draw_sdl_utils.h"
|
||||
#include "lv_draw_sdl_texture_cache.h"
|
||||
#include "lv_draw_sdl_composite.h"
|
||||
#include "lv_draw_sdl_mask.h"
|
||||
#include "lv_draw_sdl_stack_blur.h"
|
||||
#include "lv_draw_sdl_layer.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct {
|
||||
lv_sdl_cache_key_magic_t magic;
|
||||
lv_coord_t radius;
|
||||
lv_coord_t size;
|
||||
} lv_draw_rect_bg_key_t;
|
||||
|
||||
typedef struct {
|
||||
lv_sdl_cache_key_magic_t magic;
|
||||
lv_coord_t radius;
|
||||
lv_coord_t size;
|
||||
lv_coord_t blur;
|
||||
} lv_draw_rect_shadow_key_t;
|
||||
|
||||
typedef struct {
|
||||
lv_sdl_cache_key_magic_t magic;
|
||||
lv_coord_t rout, rin;
|
||||
lv_area_t offsets;
|
||||
} lv_draw_rect_border_key_t;
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static void draw_bg_color(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords, const lv_area_t * draw_area,
|
||||
const lv_draw_rect_dsc_t * dsc);
|
||||
|
||||
static void draw_bg_img(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords, const lv_area_t * draw_area,
|
||||
const lv_draw_rect_dsc_t * dsc);
|
||||
|
||||
static void draw_border(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords, const lv_area_t * draw_area,
|
||||
const lv_draw_rect_dsc_t * dsc);
|
||||
|
||||
static void draw_shadow(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords, const lv_area_t * clip,
|
||||
const lv_draw_rect_dsc_t * dsc);
|
||||
|
||||
static void draw_outline(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords, const lv_area_t * clip,
|
||||
const lv_draw_rect_dsc_t * dsc);
|
||||
|
||||
static void draw_border_generic(lv_draw_sdl_ctx_t * ctx, const lv_area_t * outer_area, const lv_area_t * inner_area,
|
||||
const lv_area_t * clip, lv_coord_t rout, lv_coord_t rin, lv_color_t color, lv_opa_t opa,
|
||||
lv_blend_mode_t blend_mode);
|
||||
|
||||
static void frag_render_borders(SDL_Renderer * renderer, SDL_Texture * frag, lv_coord_t frag_size,
|
||||
const lv_area_t * coords, const lv_area_t * clipped, bool full);
|
||||
|
||||
static void frag_render_center(SDL_Renderer * renderer, SDL_Texture * frag, lv_coord_t frag_size,
|
||||
const lv_area_t * coords, const lv_area_t * clipped, bool full);
|
||||
|
||||
static lv_draw_rect_bg_key_t rect_bg_key_create(lv_coord_t radius, lv_coord_t size);
|
||||
|
||||
static lv_draw_rect_shadow_key_t rect_shadow_key_create(lv_coord_t radius, lv_coord_t size, lv_coord_t blur);
|
||||
|
||||
static lv_draw_rect_border_key_t rect_border_key_create(lv_coord_t rout, lv_coord_t rin, const lv_area_t * outer_area,
|
||||
const lv_area_t * inner_area);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
#define SKIP_BORDER(dsc) ((dsc)->border_opa <= LV_OPA_MIN || (dsc)->border_width == 0 || (dsc)->border_side == LV_BORDER_SIDE_NONE || (dsc)->border_post)
|
||||
#define SKIP_SHADOW(dsc) ((dsc)->shadow_width == 0 || (dsc)->shadow_opa <= LV_OPA_MIN || ((dsc)->shadow_width == 1 && (dsc)->shadow_spread <= 0 && (dsc)->shadow_ofs_x == 0 && (dsc)->shadow_ofs_y == 0))
|
||||
#define SKIP_IMAGE(dsc) ((dsc)->bg_img_src == NULL || (dsc)->bg_img_opa <= LV_OPA_MIN)
|
||||
#define SKIP_OUTLINE(dsc) ((dsc)->outline_opa <= LV_OPA_MIN || (dsc)->outline_width == 0)
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_draw_sdl_draw_rect(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords)
|
||||
{
|
||||
const lv_area_t * clip = draw_ctx->clip_area;
|
||||
lv_draw_sdl_ctx_t * ctx = (lv_draw_sdl_ctx_t *) draw_ctx;
|
||||
|
||||
lv_area_t extension = {0, 0, 0, 0};
|
||||
if(!SKIP_SHADOW(dsc)) {
|
||||
lv_coord_t ext = (lv_coord_t)(dsc->shadow_spread - dsc->shadow_width / 2 + 1);
|
||||
extension.x1 = LV_MAX(extension.x1, -dsc->shadow_ofs_x + ext);
|
||||
extension.x2 = LV_MAX(extension.x2, dsc->shadow_ofs_x + ext);
|
||||
extension.y1 = LV_MAX(extension.y1, -dsc->shadow_ofs_y + ext);
|
||||
extension.y2 = LV_MAX(extension.y2, dsc->shadow_ofs_y + ext);
|
||||
}
|
||||
if(!SKIP_OUTLINE(dsc)) {
|
||||
lv_coord_t ext = (lv_coord_t)(dsc->outline_pad - 1 + dsc->outline_width);
|
||||
extension.x1 = LV_MAX(extension.x1, ext);
|
||||
extension.x2 = LV_MAX(extension.x2, ext);
|
||||
extension.y1 = LV_MAX(extension.y1, ext);
|
||||
extension.y2 = LV_MAX(extension.y2, ext);
|
||||
}
|
||||
/* Coords will be translated so coords will start at (0,0) */
|
||||
lv_area_t t_coords = *coords, t_clip = *clip, apply_area, t_area;
|
||||
bool has_composite = lv_draw_sdl_composite_begin(ctx, coords, clip, &extension, dsc->blend_mode, &t_coords, &t_clip,
|
||||
&apply_area);
|
||||
|
||||
lv_draw_sdl_transform_areas_offset(ctx, has_composite, &apply_area, &t_coords, &t_clip);
|
||||
|
||||
bool has_content = _lv_area_intersect(&t_area, &t_coords, &t_clip);
|
||||
|
||||
SDL_Rect clip_rect;
|
||||
lv_area_to_sdl_rect(&t_clip, &clip_rect);
|
||||
draw_shadow(ctx, &t_coords, &t_clip, dsc);
|
||||
/* Shadows and outlines will also draw in extended area */
|
||||
if(has_content) {
|
||||
draw_bg_color(ctx, &t_coords, &t_area, dsc);
|
||||
draw_bg_img(ctx, &t_coords, &t_area, dsc);
|
||||
draw_border(ctx, &t_coords, &t_area, dsc);
|
||||
}
|
||||
draw_outline(ctx, &t_coords, &t_clip, dsc);
|
||||
|
||||
lv_draw_sdl_composite_end(ctx, &apply_area, dsc->blend_mode);
|
||||
}
|
||||
|
||||
SDL_Texture * lv_draw_sdl_rect_bg_frag_obtain(lv_draw_sdl_ctx_t * ctx, lv_coord_t radius)
|
||||
{
|
||||
lv_draw_rect_bg_key_t key = rect_bg_key_create(radius, radius);
|
||||
lv_area_t coords = {0, 0, radius * 2 - 1, radius * 2 - 1};
|
||||
lv_area_t coords_frag = {0, 0, radius - 1, radius - 1};
|
||||
SDL_Texture * texture = lv_draw_sdl_texture_cache_get(ctx, &key, sizeof(key), NULL);
|
||||
if(texture == NULL) {
|
||||
lv_draw_mask_radius_param_t mask_rout_param;
|
||||
lv_draw_mask_radius_init(&mask_rout_param, &coords, radius, false);
|
||||
int16_t mask_id = lv_draw_mask_add(&mask_rout_param, NULL);
|
||||
texture = lv_draw_sdl_mask_dump_texture(ctx->renderer, &coords_frag, &mask_id, 1);
|
||||
lv_draw_mask_remove_id(mask_id);
|
||||
SDL_assert(texture);
|
||||
lv_draw_sdl_texture_cache_put(ctx, &key, sizeof(key), texture);
|
||||
}
|
||||
return texture;
|
||||
}
|
||||
|
||||
void lv_draw_sdl_rect_bg_frag_draw_corners(lv_draw_sdl_ctx_t * ctx, SDL_Texture * frag, lv_coord_t frag_size,
|
||||
const lv_area_t * coords, const lv_area_t * clip, bool full)
|
||||
{
|
||||
if(!clip) clip = coords;
|
||||
lv_area_t corner_area, dst_area;
|
||||
/* Upper left */
|
||||
corner_area.x1 = coords->x1;
|
||||
corner_area.y1 = coords->y1;
|
||||
corner_area.x2 = coords->x1 + frag_size - 1;
|
||||
corner_area.y2 = coords->y1 + frag_size - 1;
|
||||
if(_lv_area_intersect(&dst_area, &corner_area, clip)) {
|
||||
SDL_Rect dst_rect;
|
||||
lv_area_to_sdl_rect(&dst_area, &dst_rect);
|
||||
|
||||
lv_coord_t dw = lv_area_get_width(&dst_area), dh = lv_area_get_height(&dst_area);
|
||||
lv_coord_t sx = (lv_coord_t)(dst_area.x1 - corner_area.x1), sy = (lv_coord_t)(dst_area.y1 - corner_area.y1);
|
||||
SDL_Rect src_rect = {sx, sy, dw, dh};
|
||||
SDL_RenderCopy(ctx->renderer, frag, &src_rect, &dst_rect);
|
||||
}
|
||||
/* Upper right, clip right edge if too big */
|
||||
corner_area.x1 = LV_MAX(coords->x2 - frag_size + 1, coords->x1 + frag_size);
|
||||
corner_area.x2 = coords->x2;
|
||||
if(_lv_area_intersect(&dst_area, &corner_area, clip)) {
|
||||
SDL_Rect dst_rect;
|
||||
lv_area_to_sdl_rect(&dst_area, &dst_rect);
|
||||
|
||||
lv_coord_t dw = lv_area_get_width(&dst_area), dh = lv_area_get_height(&dst_area);
|
||||
if(full) {
|
||||
lv_coord_t sx = (lv_coord_t)(dst_area.x1 - corner_area.x1),
|
||||
sy = (lv_coord_t)(dst_area.y1 - corner_area.y1);
|
||||
SDL_Rect src_rect = {frag_size + 3 + sx, sy, dw, dh};
|
||||
SDL_RenderCopy(ctx->renderer, frag, &src_rect, &dst_rect);
|
||||
}
|
||||
else {
|
||||
SDL_Rect src_rect = {corner_area.x2 - dst_area.x2, dst_area.y1 - corner_area.y1, dw, dh};
|
||||
SDL_RenderCopyEx(ctx->renderer, frag, &src_rect, &dst_rect, 0, NULL, SDL_FLIP_HORIZONTAL);
|
||||
}
|
||||
}
|
||||
/* Lower right, clip bottom edge if too big */
|
||||
corner_area.y1 = LV_MAX(coords->y2 - frag_size + 1, coords->y1 + frag_size);
|
||||
corner_area.y2 = coords->y2;
|
||||
if(_lv_area_intersect(&dst_area, &corner_area, clip)) {
|
||||
SDL_Rect dst_rect;
|
||||
lv_area_to_sdl_rect(&dst_area, &dst_rect);
|
||||
|
||||
lv_coord_t dw = lv_area_get_width(&dst_area), dh = lv_area_get_height(&dst_area);
|
||||
if(full) {
|
||||
lv_coord_t sx = (lv_coord_t)(dst_area.x1 - corner_area.x1),
|
||||
sy = (lv_coord_t)(dst_area.y1 - corner_area.y1);
|
||||
SDL_Rect src_rect = {frag_size + 3 + sx, frag_size + 3 + sy, dw, dh};
|
||||
SDL_RenderCopy(ctx->renderer, frag, &src_rect, &dst_rect);
|
||||
}
|
||||
else {
|
||||
SDL_Rect src_rect = {corner_area.x2 - dst_area.x2, corner_area.y2 - dst_area.y2, dw, dh};
|
||||
SDL_RenderCopyEx(ctx->renderer, frag, &src_rect, &dst_rect, 0, NULL, SDL_FLIP_HORIZONTAL | SDL_FLIP_VERTICAL);
|
||||
}
|
||||
}
|
||||
/* Lower left, right edge should not be clip */
|
||||
corner_area.x1 = coords->x1;
|
||||
corner_area.x2 = coords->x1 + frag_size - 1;
|
||||
if(_lv_area_intersect(&dst_area, &corner_area, clip)) {
|
||||
SDL_Rect dst_rect;
|
||||
lv_area_to_sdl_rect(&dst_area, &dst_rect);
|
||||
|
||||
lv_coord_t dw = lv_area_get_width(&dst_area), dh = lv_area_get_height(&dst_area);
|
||||
if(full) {
|
||||
lv_coord_t sx = (lv_coord_t)(dst_area.x1 - corner_area.x1),
|
||||
sy = (lv_coord_t)(dst_area.y1 - corner_area.y1);
|
||||
SDL_Rect src_rect = {sx, frag_size + 3 + sy, dw, dh};
|
||||
SDL_RenderCopy(ctx->renderer, frag, &src_rect, &dst_rect);
|
||||
}
|
||||
else {
|
||||
SDL_Rect src_rect = {dst_area.x1 - corner_area.x1, corner_area.y2 - dst_area.y2, dw, dh};
|
||||
SDL_RenderCopyEx(ctx->renderer, frag, &src_rect, &dst_rect, 0, NULL, SDL_FLIP_VERTICAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void draw_bg_color(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords, const lv_area_t * draw_area,
|
||||
const lv_draw_rect_dsc_t * dsc)
|
||||
{
|
||||
if(dsc->bg_opa == 0) {
|
||||
return;
|
||||
}
|
||||
SDL_Color bg_color;
|
||||
lv_color_to_sdl_color(&dsc->bg_color, &bg_color);
|
||||
lv_coord_t radius = dsc->radius;
|
||||
if(radius <= 0) {
|
||||
SDL_Rect rect;
|
||||
lv_area_to_sdl_rect(draw_area, &rect);
|
||||
SDL_SetRenderDrawColor(ctx->renderer, bg_color.r, bg_color.g, bg_color.b, dsc->bg_opa);
|
||||
SDL_SetRenderDrawBlendMode(ctx->renderer, SDL_BLENDMODE_BLEND);
|
||||
SDL_RenderFillRect(ctx->renderer, &rect);
|
||||
return;
|
||||
}
|
||||
|
||||
/*A small texture with a quarter of the rect is enough*/
|
||||
lv_coord_t bg_w = lv_area_get_width(coords), bg_h = lv_area_get_height(coords);
|
||||
lv_coord_t real_radius = LV_MIN3(bg_w / 2, bg_h / 2, radius);
|
||||
SDL_Texture * texture = lv_draw_sdl_rect_bg_frag_obtain(ctx, real_radius);
|
||||
|
||||
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
|
||||
SDL_SetTextureAlphaMod(texture, dsc->bg_opa);
|
||||
SDL_SetTextureColorMod(texture, bg_color.r, bg_color.g, bg_color.b);
|
||||
lv_draw_sdl_rect_bg_frag_draw_corners(ctx, texture, real_radius, coords, draw_area, false);
|
||||
frag_render_borders(ctx->renderer, texture, real_radius, coords, draw_area, false);
|
||||
frag_render_center(ctx->renderer, texture, real_radius, coords, draw_area, false);
|
||||
}
|
||||
|
||||
static void draw_bg_img(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords, const lv_area_t * draw_area,
|
||||
const lv_draw_rect_dsc_t * dsc)
|
||||
{
|
||||
if(SKIP_IMAGE(dsc)) return;
|
||||
|
||||
lv_img_src_t src_type = lv_img_src_get_type(dsc->bg_img_src);
|
||||
if(src_type == LV_IMG_SRC_SYMBOL) {
|
||||
lv_point_t size;
|
||||
lv_txt_get_size(&size, dsc->bg_img_src, dsc->bg_img_symbol_font, 0, 0, LV_COORD_MAX, LV_TEXT_FLAG_NONE);
|
||||
lv_area_t a;
|
||||
a.x1 = coords->x1 + lv_area_get_width(coords) / 2 - size.x / 2;
|
||||
a.x2 = a.x1 + size.x - 1;
|
||||
a.y1 = coords->y1 + lv_area_get_height(coords) / 2 - size.y / 2;
|
||||
a.y2 = a.y1 + size.y - 1;
|
||||
|
||||
lv_draw_label_dsc_t label_draw_dsc;
|
||||
lv_draw_label_dsc_init(&label_draw_dsc);
|
||||
label_draw_dsc.font = dsc->bg_img_symbol_font;
|
||||
label_draw_dsc.color = dsc->bg_img_recolor;
|
||||
label_draw_dsc.opa = dsc->bg_img_opa;
|
||||
lv_draw_label((lv_draw_ctx_t *) ctx, &label_draw_dsc, &a, dsc->bg_img_src, NULL);
|
||||
}
|
||||
else {
|
||||
lv_img_header_t header;
|
||||
size_t key_size;
|
||||
lv_draw_sdl_cache_key_head_img_t * key = lv_draw_sdl_texture_img_key_create(dsc->bg_img_src, 0, &key_size);
|
||||
bool key_found;
|
||||
lv_img_header_t * cache_header = NULL;
|
||||
SDL_Texture * texture = lv_draw_sdl_texture_cache_get_with_userdata(ctx, key, key_size, &key_found,
|
||||
(void **) &cache_header);
|
||||
SDL_free(key);
|
||||
if(texture) {
|
||||
header = *cache_header;
|
||||
}
|
||||
else if(key_found || lv_img_decoder_get_info(dsc->bg_img_src, &header) != LV_RES_OK) {
|
||||
/* When cache hit but with negative result, use default decoder. If still fail, return.*/
|
||||
LV_LOG_WARN("Couldn't read the background image");
|
||||
return;
|
||||
}
|
||||
|
||||
lv_draw_img_dsc_t img_dsc;
|
||||
lv_draw_img_dsc_init(&img_dsc);
|
||||
img_dsc.blend_mode = dsc->blend_mode;
|
||||
img_dsc.recolor = dsc->bg_img_recolor;
|
||||
img_dsc.recolor_opa = dsc->bg_img_recolor_opa;
|
||||
img_dsc.opa = dsc->bg_img_opa;
|
||||
img_dsc.frame_id = 0;
|
||||
|
||||
int16_t radius_mask_id = LV_MASK_ID_INV;
|
||||
lv_draw_mask_radius_param_t radius_param;
|
||||
if(dsc->radius > 0) {
|
||||
lv_draw_mask_radius_init(&radius_param, coords, dsc->radius, false);
|
||||
radius_mask_id = lv_draw_mask_add(&radius_param, NULL);
|
||||
}
|
||||
|
||||
/*Center align*/
|
||||
if(dsc->bg_img_tiled == false) {
|
||||
lv_area_t area;
|
||||
area.x1 = coords->x1 + lv_area_get_width(coords) / 2 - header.w / 2;
|
||||
area.y1 = coords->y1 + lv_area_get_height(coords) / 2 - header.h / 2;
|
||||
area.x2 = area.x1 + header.w - 1;
|
||||
area.y2 = area.y1 + header.h - 1;
|
||||
|
||||
lv_draw_img((lv_draw_ctx_t *) ctx, &img_dsc, &area, dsc->bg_img_src);
|
||||
}
|
||||
else {
|
||||
lv_area_t area;
|
||||
area.y1 = coords->y1;
|
||||
area.y2 = area.y1 + header.h - 1;
|
||||
|
||||
for(; area.y1 <= coords->y2; area.y1 += header.h, area.y2 += header.h) {
|
||||
|
||||
area.x1 = coords->x1;
|
||||
area.x2 = area.x1 + header.w - 1;
|
||||
for(; area.x1 <= coords->x2; area.x1 += header.w, area.x2 += header.w) {
|
||||
lv_draw_img((lv_draw_ctx_t *) ctx, &img_dsc, &area, dsc->bg_img_src);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(radius_mask_id != LV_MASK_ID_INV) {
|
||||
lv_draw_mask_remove_id(radius_mask_id);
|
||||
lv_draw_mask_free_param(&radius_param);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void draw_shadow(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords, const lv_area_t * clip,
|
||||
const lv_draw_rect_dsc_t * dsc)
|
||||
{
|
||||
/*Check whether the shadow is visible*/
|
||||
if(SKIP_SHADOW(dsc)) return;
|
||||
|
||||
lv_coord_t sw = dsc->shadow_width;
|
||||
|
||||
lv_area_t core_area;
|
||||
core_area.x1 = coords->x1 + dsc->shadow_ofs_x - dsc->shadow_spread;
|
||||
core_area.x2 = coords->x2 + dsc->shadow_ofs_x + dsc->shadow_spread;
|
||||
core_area.y1 = coords->y1 + dsc->shadow_ofs_y - dsc->shadow_spread;
|
||||
core_area.y2 = coords->y2 + dsc->shadow_ofs_y + dsc->shadow_spread;
|
||||
|
||||
lv_area_t shadow_area;
|
||||
shadow_area.x1 = core_area.x1 - sw / 2 - 1;
|
||||
shadow_area.x2 = core_area.x2 + sw / 2 + 1;
|
||||
shadow_area.y1 = core_area.y1 - sw / 2 - 1;
|
||||
shadow_area.y2 = core_area.y2 + sw / 2 + 1;
|
||||
|
||||
lv_opa_t opa = dsc->shadow_opa;
|
||||
|
||||
if(opa > LV_OPA_MAX) opa = LV_OPA_COVER;
|
||||
|
||||
/*Get clipped draw area which is the real draw area.
|
||||
*It is always the same or inside `shadow_area`*/
|
||||
lv_area_t draw_area;
|
||||
if(!_lv_area_intersect(&draw_area, &shadow_area, clip)) return;
|
||||
|
||||
SDL_Rect core_area_rect;
|
||||
lv_area_to_sdl_rect(&shadow_area, &core_area_rect);
|
||||
|
||||
lv_coord_t radius = dsc->radius;
|
||||
/* No matter how big the shadow is, what we need is just a corner */
|
||||
lv_coord_t frag_size = LV_MIN3(lv_area_get_width(&core_area) / 2, lv_area_get_height(&core_area) / 2,
|
||||
LV_MAX(sw / 2, radius));
|
||||
|
||||
/* This is how big the corner is after blurring */
|
||||
lv_coord_t blur_growth = (lv_coord_t)(sw / 2 + 1);
|
||||
|
||||
lv_coord_t blur_frag_size = (lv_coord_t)(frag_size + blur_growth);
|
||||
|
||||
lv_draw_rect_shadow_key_t key = rect_shadow_key_create(radius, frag_size, sw);
|
||||
|
||||
SDL_Texture * texture = lv_draw_sdl_texture_cache_get(ctx, &key, sizeof(key), NULL);
|
||||
if(texture == NULL) {
|
||||
lv_area_t mask_area = {blur_growth, blur_growth}, mask_area_blurred = {0, 0};
|
||||
lv_area_set_width(&mask_area, frag_size * 2);
|
||||
lv_area_set_height(&mask_area, frag_size * 2);
|
||||
lv_area_set_width(&mask_area_blurred, blur_frag_size * 2);
|
||||
lv_area_set_height(&mask_area_blurred, blur_frag_size * 2);
|
||||
|
||||
lv_draw_mask_radius_param_t mask_rout_param;
|
||||
lv_draw_mask_radius_init(&mask_rout_param, &mask_area, radius, false);
|
||||
int16_t mask_id = lv_draw_mask_add(&mask_rout_param, NULL);
|
||||
lv_opa_t * mask_buf = lv_draw_sdl_mask_dump_opa(&mask_area_blurred, &mask_id, 1);
|
||||
lv_stack_blur_grayscale(mask_buf, lv_area_get_width(&mask_area_blurred), lv_area_get_height(&mask_area_blurred),
|
||||
sw / 2 + sw % 2);
|
||||
texture = lv_sdl_create_opa_texture(ctx->renderer, mask_buf, blur_frag_size, blur_frag_size,
|
||||
lv_area_get_width(&mask_area_blurred));
|
||||
lv_mem_buf_release(mask_buf);
|
||||
lv_draw_mask_remove_id(mask_id);
|
||||
SDL_assert(texture);
|
||||
lv_draw_sdl_texture_cache_put(ctx, &key, sizeof(key), texture);
|
||||
}
|
||||
|
||||
SDL_Color shadow_color;
|
||||
lv_color_to_sdl_color(&dsc->shadow_color, &shadow_color);
|
||||
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
|
||||
SDL_SetTextureAlphaMod(texture, opa);
|
||||
SDL_SetTextureColorMod(texture, shadow_color.r, shadow_color.g, shadow_color.b);
|
||||
|
||||
lv_draw_sdl_rect_bg_frag_draw_corners(ctx, texture, blur_frag_size, &shadow_area, clip, false);
|
||||
frag_render_borders(ctx->renderer, texture, blur_frag_size, &shadow_area, clip, false);
|
||||
frag_render_center(ctx->renderer, texture, blur_frag_size, &shadow_area, clip, false);
|
||||
}
|
||||
|
||||
|
||||
static void draw_border(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords, const lv_area_t * draw_area,
|
||||
const lv_draw_rect_dsc_t * dsc)
|
||||
{
|
||||
if(SKIP_BORDER(dsc)) return;
|
||||
|
||||
SDL_Color border_color;
|
||||
lv_color_to_sdl_color(&dsc->border_color, &border_color);
|
||||
|
||||
lv_coord_t coords_w = lv_area_get_width(coords), coords_h = lv_area_get_height(coords);
|
||||
lv_coord_t short_side = LV_MIN(coords_w, coords_h);
|
||||
lv_coord_t rout = LV_MIN(dsc->radius, short_side / 2);/*Get the inner area*/
|
||||
lv_area_t area_inner;
|
||||
lv_area_copy(&area_inner, coords);// lv_area_increase(&area_inner, 1, 1);
|
||||
area_inner.x1 += ((dsc->border_side & LV_BORDER_SIDE_LEFT) ? dsc->border_width : -(dsc->border_width + rout));
|
||||
area_inner.x2 -= ((dsc->border_side & LV_BORDER_SIDE_RIGHT) ? dsc->border_width : -(dsc->border_width + rout));
|
||||
area_inner.y1 += ((dsc->border_side & LV_BORDER_SIDE_TOP) ? dsc->border_width : -(dsc->border_width + rout));
|
||||
area_inner.y2 -= ((dsc->border_side & LV_BORDER_SIDE_BOTTOM) ? dsc->border_width : -(dsc->border_width + rout));
|
||||
lv_coord_t rin = LV_MAX(rout - dsc->border_width, 0);
|
||||
draw_border_generic(ctx, coords, &area_inner, draw_area, rout, rin, dsc->border_color, dsc->border_opa,
|
||||
dsc->blend_mode);
|
||||
}
|
||||
|
||||
static void draw_outline(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords, const lv_area_t * clip,
|
||||
const lv_draw_rect_dsc_t * dsc)
|
||||
{
|
||||
if(SKIP_OUTLINE(dsc)) return;
|
||||
|
||||
lv_opa_t opa = dsc->outline_opa;
|
||||
|
||||
if(opa > LV_OPA_MAX) opa = LV_OPA_COVER;
|
||||
|
||||
/*Get the inner radius*/
|
||||
lv_area_t area_inner;
|
||||
lv_area_copy(&area_inner, coords);
|
||||
|
||||
/*Bring the outline closer to make sure there is no color bleeding with pad=0*/
|
||||
lv_coord_t pad = dsc->outline_pad - 1;
|
||||
area_inner.x1 -= pad;
|
||||
area_inner.y1 -= pad;
|
||||
area_inner.x2 += pad;
|
||||
area_inner.y2 += pad;
|
||||
|
||||
lv_area_t area_outer;
|
||||
lv_area_copy(&area_outer, &area_inner);
|
||||
|
||||
area_outer.x1 -= dsc->outline_width;
|
||||
area_outer.x2 += dsc->outline_width;
|
||||
area_outer.y1 -= dsc->outline_width;
|
||||
area_outer.y2 += dsc->outline_width;
|
||||
|
||||
lv_area_t draw_area;
|
||||
if(!_lv_area_intersect(&draw_area, &area_outer, clip)) return;
|
||||
|
||||
int32_t inner_w = lv_area_get_width(&area_inner);
|
||||
int32_t inner_h = lv_area_get_height(&area_inner);
|
||||
lv_coord_t rin = dsc->radius;
|
||||
int32_t short_side = LV_MIN(inner_w, inner_h);
|
||||
if(rin > short_side >> 1) rin = short_side >> 1;
|
||||
|
||||
lv_coord_t rout = rin + dsc->outline_width;
|
||||
|
||||
draw_border_generic(ctx, &area_outer, &area_inner, clip, rout, rin, dsc->outline_color, dsc->outline_opa,
|
||||
dsc->blend_mode);
|
||||
}
|
||||
|
||||
static void draw_border_generic(lv_draw_sdl_ctx_t * ctx, const lv_area_t * outer_area, const lv_area_t * inner_area,
|
||||
const lv_area_t * clip, lv_coord_t rout, lv_coord_t rin, lv_color_t color, lv_opa_t opa,
|
||||
lv_blend_mode_t blend_mode)
|
||||
{
|
||||
opa = opa >= LV_OPA_COVER ? LV_OPA_COVER : opa;
|
||||
|
||||
SDL_Renderer * renderer = ctx->renderer;
|
||||
|
||||
lv_draw_rect_border_key_t key = rect_border_key_create(rout, rin, outer_area, inner_area);
|
||||
lv_coord_t radius = LV_MIN3(rout, lv_area_get_width(outer_area) / 2, lv_area_get_height(outer_area) / 2);
|
||||
lv_coord_t max_side = LV_MAX4(key.offsets.x1, key.offsets.y1, -key.offsets.x2, -key.offsets.y2);
|
||||
lv_coord_t frag_size = LV_MAX(radius, max_side);
|
||||
SDL_Texture * texture = lv_draw_sdl_texture_cache_get(ctx, &key, sizeof(key), NULL);
|
||||
if(texture == NULL) {
|
||||
/* Create a mask texture with size of (frag_size * 2 + 3) */
|
||||
const lv_area_t frag_area = {0, 0, frag_size * 2 + 2, frag_size * 2 + 2};
|
||||
|
||||
/*Create mask for the outer area*/
|
||||
int16_t mask_ids[2] = {LV_MASK_ID_INV, LV_MASK_ID_INV};
|
||||
lv_draw_mask_radius_param_t mask_rout_param;
|
||||
if(rout > 0) {
|
||||
lv_draw_mask_radius_init(&mask_rout_param, &frag_area, rout, false);
|
||||
mask_ids[0] = lv_draw_mask_add(&mask_rout_param, NULL);
|
||||
}
|
||||
|
||||
/*Create mask for the inner mask*/
|
||||
if(rin < 0) rin = 0;
|
||||
const lv_area_t frag_inner_area = {frag_area.x1 + key.offsets.x1, frag_area.y1 + key.offsets.y1,
|
||||
frag_area.x2 + key.offsets.x2, frag_area.y2 + key.offsets.y2
|
||||
};
|
||||
lv_draw_mask_radius_param_t mask_rin_param;
|
||||
lv_draw_mask_radius_init(&mask_rin_param, &frag_inner_area, rin, true);
|
||||
mask_ids[1] = lv_draw_mask_add(&mask_rin_param, NULL);
|
||||
|
||||
texture = lv_draw_sdl_mask_dump_texture(renderer, &frag_area, mask_ids, 2);
|
||||
|
||||
lv_draw_mask_remove_id(mask_ids[1]);
|
||||
lv_draw_mask_remove_id(mask_ids[0]);
|
||||
SDL_assert(texture);
|
||||
lv_draw_sdl_texture_cache_put(ctx, &key, sizeof(key), texture);
|
||||
}
|
||||
|
||||
SDL_Rect outer_rect;
|
||||
lv_area_to_sdl_rect(outer_area, &outer_rect);
|
||||
SDL_Color color_sdl;
|
||||
lv_color_to_sdl_color(&color, &color_sdl);
|
||||
|
||||
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
|
||||
SDL_SetTextureAlphaMod(texture, opa);
|
||||
SDL_SetTextureColorMod(texture, color_sdl.r, color_sdl.g, color_sdl.b);
|
||||
|
||||
lv_draw_sdl_rect_bg_frag_draw_corners(ctx, texture, frag_size, outer_area, clip, true);
|
||||
frag_render_borders(renderer, texture, frag_size, outer_area, clip, true);
|
||||
}
|
||||
|
||||
static void frag_render_borders(SDL_Renderer * renderer, SDL_Texture * frag, lv_coord_t frag_size,
|
||||
const lv_area_t * coords, const lv_area_t * clipped, bool full)
|
||||
{
|
||||
lv_area_t border_area, dst_area;
|
||||
/* Top border */
|
||||
border_area.x1 = coords->x1 + frag_size;
|
||||
border_area.y1 = coords->y1;
|
||||
border_area.x2 = coords->x2 - frag_size;
|
||||
border_area.y2 = coords->y1 + frag_size - 1;
|
||||
if(_lv_area_intersect(&dst_area, &border_area, clipped)) {
|
||||
SDL_Rect dst_rect;
|
||||
lv_area_to_sdl_rect(&dst_area, &dst_rect);
|
||||
|
||||
lv_coord_t sy = (lv_coord_t)(dst_area.y1 - border_area.y1);
|
||||
if(full) {
|
||||
SDL_Rect src_rect = {frag_size + 1, sy, 1, lv_area_get_height(&dst_area)};
|
||||
SDL_RenderCopy(renderer, frag, &src_rect, &dst_rect);
|
||||
}
|
||||
else {
|
||||
SDL_Rect src_rect = {frag_size - 1, sy, 1, lv_area_get_height(&dst_area)};
|
||||
SDL_RenderCopy(renderer, frag, &src_rect, &dst_rect);
|
||||
}
|
||||
}
|
||||
/* Bottom border */
|
||||
border_area.y1 = LV_MAX(coords->y2 - frag_size + 1, coords->y1 + frag_size);
|
||||
border_area.y2 = coords->y2;
|
||||
if(_lv_area_intersect(&dst_area, &border_area, clipped)) {
|
||||
SDL_Rect dst_rect;
|
||||
lv_area_to_sdl_rect(&dst_area, &dst_rect);
|
||||
|
||||
lv_coord_t dh = lv_area_get_height(&dst_area);
|
||||
if(full) {
|
||||
lv_coord_t sy = (lv_coord_t)(dst_area.y1 - border_area.y1);
|
||||
SDL_Rect src_rect = {frag_size + 1, frag_size + 3 + sy, 1, dh};
|
||||
SDL_RenderCopy(renderer, frag, &src_rect, &dst_rect);
|
||||
}
|
||||
else {
|
||||
lv_coord_t sy = (lv_coord_t)(border_area.y2 - dst_area.y2);
|
||||
SDL_Rect src_rect = {frag_size - 1, sy, 1, dh};
|
||||
SDL_RenderCopyEx(renderer, frag, &src_rect, &dst_rect, 0, NULL, SDL_FLIP_VERTICAL);
|
||||
}
|
||||
}
|
||||
/* Left border */
|
||||
border_area.x1 = coords->x1;
|
||||
border_area.y1 = coords->y1 + frag_size;
|
||||
border_area.x2 = coords->x1 + frag_size - 1;
|
||||
border_area.y2 = coords->y2 - frag_size;
|
||||
if(_lv_area_intersect(&dst_area, &border_area, clipped)) {
|
||||
SDL_Rect dst_rect;
|
||||
lv_area_to_sdl_rect(&dst_area, &dst_rect);
|
||||
|
||||
lv_coord_t dw = lv_area_get_width(&dst_area);
|
||||
lv_coord_t sx = (lv_coord_t)(dst_area.x1 - border_area.x1);
|
||||
if(full) {
|
||||
SDL_Rect src_rect = {sx, frag_size + 1, dw, 1};
|
||||
SDL_RenderCopy(renderer, frag, &src_rect, &dst_rect);
|
||||
}
|
||||
else {
|
||||
SDL_Rect src_rect = {sx, frag_size - 1, dw, 1};
|
||||
SDL_RenderCopy(renderer, frag, &src_rect, &dst_rect);
|
||||
}
|
||||
}
|
||||
/* Right border */
|
||||
border_area.x1 = LV_MAX(coords->x2 - frag_size + 1, coords->x1 + frag_size);
|
||||
border_area.x2 = coords->x2;
|
||||
if(_lv_area_intersect(&dst_area, &border_area, clipped)) {
|
||||
SDL_Rect dst_rect;
|
||||
lv_area_to_sdl_rect(&dst_area, &dst_rect);
|
||||
|
||||
lv_coord_t dw = lv_area_get_width(&dst_area);
|
||||
if(full) {
|
||||
lv_coord_t sx = (lv_coord_t)(dst_area.x1 - border_area.x1);
|
||||
SDL_Rect src_rect = {frag_size + 3 + sx, frag_size + 1, dw, 1};
|
||||
SDL_RenderCopy(renderer, frag, &src_rect, &dst_rect);
|
||||
}
|
||||
else {
|
||||
lv_coord_t sx = (lv_coord_t)(border_area.x2 - dst_area.x2);
|
||||
SDL_Rect src_rect = {sx, frag_size - 1, dw, 1};
|
||||
SDL_RenderCopyEx(renderer, frag, &src_rect, &dst_rect, 0, NULL, SDL_FLIP_HORIZONTAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void frag_render_center(SDL_Renderer * renderer, SDL_Texture * frag, lv_coord_t frag_size,
|
||||
const lv_area_t * coords,
|
||||
const lv_area_t * clipped, bool full)
|
||||
{
|
||||
lv_area_t center_area = {
|
||||
coords->x1 + frag_size,
|
||||
coords->y1 + frag_size,
|
||||
coords->x2 - frag_size,
|
||||
coords->y2 - frag_size,
|
||||
};
|
||||
if(center_area.x2 < center_area.x1 || center_area.y2 < center_area.y1) return;
|
||||
lv_area_t draw_area;
|
||||
if(!_lv_area_intersect(&draw_area, ¢er_area, clipped)) {
|
||||
return;
|
||||
}
|
||||
SDL_Rect dst_rect;
|
||||
lv_area_to_sdl_rect(&draw_area, &dst_rect);
|
||||
if(full) {
|
||||
SDL_Rect src_rect = {frag_size, frag_size, 1, 1};
|
||||
SDL_RenderCopy(renderer, frag, &src_rect, &dst_rect);
|
||||
}
|
||||
else {
|
||||
SDL_Rect src_rect = {frag_size - 1, frag_size - 1, 1, 1};
|
||||
SDL_RenderCopy(renderer, frag, &src_rect, &dst_rect);
|
||||
}
|
||||
}
|
||||
|
||||
static lv_draw_rect_bg_key_t rect_bg_key_create(lv_coord_t radius, lv_coord_t size)
|
||||
{
|
||||
lv_draw_rect_bg_key_t key;
|
||||
SDL_memset(&key, 0, sizeof(key));
|
||||
key.magic = LV_GPU_CACHE_KEY_MAGIC_RECT_BG;
|
||||
key.radius = radius;
|
||||
key.size = size;
|
||||
return key;
|
||||
}
|
||||
|
||||
static lv_draw_rect_shadow_key_t rect_shadow_key_create(lv_coord_t radius, lv_coord_t size, lv_coord_t blur)
|
||||
{
|
||||
lv_draw_rect_shadow_key_t key;
|
||||
SDL_memset(&key, 0, sizeof(key));
|
||||
key.magic = LV_GPU_CACHE_KEY_MAGIC_RECT_SHADOW;
|
||||
key.radius = radius;
|
||||
key.size = size;
|
||||
key.blur = blur;
|
||||
return key;
|
||||
}
|
||||
|
||||
static lv_draw_rect_border_key_t rect_border_key_create(lv_coord_t rout, lv_coord_t rin, const lv_area_t * outer_area,
|
||||
const lv_area_t * inner_area)
|
||||
{
|
||||
lv_draw_rect_border_key_t key;
|
||||
/* VERY IMPORTANT! Padding between members is uninitialized, so we have to wipe them manually */
|
||||
SDL_memset(&key, 0, sizeof(key));
|
||||
key.magic = LV_GPU_CACHE_KEY_MAGIC_RECT_BORDER;
|
||||
key.rout = rout;
|
||||
key.rin = rin;
|
||||
key.offsets.x1 = inner_area->x1 - outer_area->x1;
|
||||
key.offsets.x2 = inner_area->x2 - outer_area->x2;
|
||||
key.offsets.y1 = inner_area->y1 - outer_area->y1;
|
||||
key.offsets.y2 = inner_area->y2 - outer_area->y2;
|
||||
return key;
|
||||
}
|
||||
|
||||
#endif /*LV_USE_GPU_SDL*/
|
||||
@@ -0,0 +1,75 @@
|
||||
/**
|
||||
* @file lv_draw_sdl_rect.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_DRAW_SDL_RECT_H
|
||||
#define LV_DRAW_SDL_RECT_H
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_GPU_SDL
|
||||
|
||||
#include LV_GPU_SDL_INCLUDE_PATH
|
||||
|
||||
#include "../lv_draw.h"
|
||||
|
||||
#include "lv_draw_sdl_texture_cache.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct lv_draw_sdl_rect_header_t {
|
||||
lv_img_header_t base;
|
||||
SDL_Rect rect;
|
||||
} lv_draw_sdl_rect_header_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/*======================
|
||||
* Add/remove functions
|
||||
*=====================*/
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/*=====================
|
||||
* Other functions
|
||||
*====================*/
|
||||
|
||||
SDL_Texture * lv_draw_sdl_rect_bg_frag_obtain(lv_draw_sdl_ctx_t * ctx, lv_coord_t radius);
|
||||
|
||||
void lv_draw_sdl_rect_bg_frag_draw_corners(lv_draw_sdl_ctx_t * ctx, SDL_Texture * frag, lv_coord_t frag_size,
|
||||
const lv_area_t * coords, const lv_area_t * clip, bool full);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_GPU_SDL*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_DRAW_SDL_RECT_H*/
|
||||
@@ -0,0 +1,249 @@
|
||||
/**
|
||||
* @file lv_draw_sdl_stack_blur.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_draw_sdl_stack_blur.h"
|
||||
|
||||
#if LV_USE_GPU_SDL
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static void
|
||||
stack_blur_job(lv_opa_t * src, unsigned int w, unsigned int h, unsigned int radius, int cores, int core, int step);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
// Based heavily on http://vitiy.info/Code/stackblur.cpp
|
||||
// See http://vitiy.info/stackblur-algorithm-multi-threaded-blur-for-cpp/
|
||||
// Stack Blur Algorithm by Mario Klingemann <mario@quasimondo.com>
|
||||
|
||||
static unsigned short const stackblur_mul[255] = {
|
||||
512, 512, 456, 512, 328, 456, 335, 512, 405, 328, 271, 456, 388, 335, 292, 512,
|
||||
454, 405, 364, 328, 298, 271, 496, 456, 420, 388, 360, 335, 312, 292, 273, 512,
|
||||
482, 454, 428, 405, 383, 364, 345, 328, 312, 298, 284, 271, 259, 496, 475, 456,
|
||||
437, 420, 404, 388, 374, 360, 347, 335, 323, 312, 302, 292, 282, 273, 265, 512,
|
||||
497, 482, 468, 454, 441, 428, 417, 405, 394, 383, 373, 364, 354, 345, 337, 328,
|
||||
320, 312, 305, 298, 291, 284, 278, 271, 265, 259, 507, 496, 485, 475, 465, 456,
|
||||
446, 437, 428, 420, 412, 404, 396, 388, 381, 374, 367, 360, 354, 347, 341, 335,
|
||||
329, 323, 318, 312, 307, 302, 297, 292, 287, 282, 278, 273, 269, 265, 261, 512,
|
||||
505, 497, 489, 482, 475, 468, 461, 454, 447, 441, 435, 428, 422, 417, 411, 405,
|
||||
399, 394, 389, 383, 378, 373, 368, 364, 359, 354, 350, 345, 341, 337, 332, 328,
|
||||
324, 320, 316, 312, 309, 305, 301, 298, 294, 291, 287, 284, 281, 278, 274, 271,
|
||||
268, 265, 262, 259, 257, 507, 501, 496, 491, 485, 480, 475, 470, 465, 460, 456,
|
||||
451, 446, 442, 437, 433, 428, 424, 420, 416, 412, 408, 404, 400, 396, 392, 388,
|
||||
385, 381, 377, 374, 370, 367, 363, 360, 357, 354, 350, 347, 344, 341, 338, 335,
|
||||
332, 329, 326, 323, 320, 318, 315, 312, 310, 307, 304, 302, 299, 297, 294, 292,
|
||||
289, 287, 285, 282, 280, 278, 275, 273, 271, 269, 267, 265, 263, 261, 259
|
||||
};
|
||||
|
||||
static unsigned char const stackblur_shr[255] = {
|
||||
9, 11, 12, 13, 13, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 17,
|
||||
17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20,
|
||||
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21,
|
||||
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
|
||||
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22,
|
||||
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
|
||||
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23,
|
||||
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
|
||||
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
|
||||
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
|
||||
23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
|
||||
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
|
||||
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
|
||||
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
|
||||
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24
|
||||
};
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_stack_blur_grayscale(lv_opa_t * buf, uint16_t w, uint16_t h, uint16_t r)
|
||||
{
|
||||
stack_blur_job(buf, w, h, r, 1, 0, 1);
|
||||
stack_blur_job(buf, w, h, r, 1, 0, 2);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void stack_blur_job(lv_opa_t * src, unsigned int w, unsigned int h, unsigned int radius, int cores, int core,
|
||||
int step)
|
||||
{
|
||||
if(radius < 2 || radius > 254) {
|
||||
/* Silently ignore bad radius */
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int x, y, xp, yp, i;
|
||||
unsigned int sp;
|
||||
unsigned int stack_start;
|
||||
unsigned char * stack_ptr;
|
||||
|
||||
lv_opa_t * src_ptr;
|
||||
lv_opa_t * dst_ptr;
|
||||
|
||||
unsigned long sum_r;
|
||||
unsigned long sum_in_r;
|
||||
unsigned long sum_out_r;
|
||||
|
||||
unsigned int wm = w - 1;
|
||||
unsigned int hm = h - 1;
|
||||
unsigned int stride = w;
|
||||
unsigned int div = (radius * 2) + 1;
|
||||
unsigned int mul_sum = stackblur_mul[radius];
|
||||
unsigned char shr_sum = stackblur_shr[radius];
|
||||
unsigned char stack[254 * 2 + 1];
|
||||
|
||||
if(step == 1) {
|
||||
unsigned int minY = core * h / cores;
|
||||
unsigned int maxY = (core + 1) * h / cores;
|
||||
|
||||
for(y = minY; y < maxY; y++) {
|
||||
sum_r =
|
||||
sum_in_r =
|
||||
sum_out_r = 0;
|
||||
|
||||
src_ptr = src + stride * y; // start of line (0,y)
|
||||
|
||||
for(i = 0; i <= radius; i++) {
|
||||
stack_ptr = &stack[i];
|
||||
stack_ptr[0] = src_ptr[0];
|
||||
sum_r += src_ptr[0] * (i + 1);
|
||||
sum_out_r += src_ptr[0];
|
||||
}
|
||||
|
||||
|
||||
for(i = 1; i <= radius; i++) {
|
||||
if(i <= wm) src_ptr += 1;
|
||||
stack_ptr = &stack[i + radius];
|
||||
stack_ptr[0] = src_ptr[0];
|
||||
sum_r += src_ptr[0] * (radius + 1 - i);
|
||||
sum_in_r += src_ptr[0];
|
||||
}
|
||||
|
||||
|
||||
sp = radius;
|
||||
xp = radius;
|
||||
if(xp > wm) xp = wm;
|
||||
src_ptr = src + (xp + y * w); // img.pix_ptr(xp, y);
|
||||
dst_ptr = src + y * stride; // img.pix_ptr(0, y);
|
||||
for(x = 0; x < w; x++) {
|
||||
dst_ptr[0] = LV_CLAMP((sum_r * mul_sum) >> shr_sum, 0, 255);
|
||||
dst_ptr += 1;
|
||||
|
||||
sum_r -= sum_out_r;
|
||||
|
||||
stack_start = sp + div - radius;
|
||||
if(stack_start >= div) stack_start -= div;
|
||||
stack_ptr = &stack[stack_start];
|
||||
|
||||
sum_out_r -= stack_ptr[0];
|
||||
|
||||
if(xp < wm) {
|
||||
src_ptr += 1;
|
||||
++xp;
|
||||
}
|
||||
|
||||
stack_ptr[0] = src_ptr[0];
|
||||
|
||||
sum_in_r += src_ptr[0];
|
||||
sum_r += sum_in_r;
|
||||
|
||||
++sp;
|
||||
if(sp >= div) sp = 0;
|
||||
stack_ptr = &stack[sp];
|
||||
|
||||
sum_out_r += stack_ptr[0];
|
||||
sum_in_r -= stack_ptr[0];
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// step 2
|
||||
if(step == 2) {
|
||||
unsigned int minX = core * w / cores;
|
||||
unsigned int maxX = (core + 1) * w / cores;
|
||||
|
||||
for(x = minX; x < maxX; x++) {
|
||||
sum_r =
|
||||
sum_in_r =
|
||||
sum_out_r = 0;
|
||||
|
||||
src_ptr = src + x; // x,0
|
||||
for(i = 0; i <= radius; i++) {
|
||||
stack_ptr = &stack[i];
|
||||
stack_ptr[0] = src_ptr[0];
|
||||
sum_r += src_ptr[0] * (i + 1);
|
||||
sum_out_r += src_ptr[0];
|
||||
}
|
||||
for(i = 1; i <= radius; i++) {
|
||||
if(i <= hm) src_ptr += stride; // +stride
|
||||
|
||||
stack_ptr = &stack[i + radius];
|
||||
stack_ptr[0] = src_ptr[0];
|
||||
sum_r += src_ptr[0] * (radius + 1 - i);
|
||||
sum_in_r += src_ptr[0];
|
||||
}
|
||||
|
||||
sp = radius;
|
||||
yp = radius;
|
||||
if(yp > hm) yp = hm;
|
||||
src_ptr = src + (x + yp * w); // img.pix_ptr(x, yp);
|
||||
dst_ptr = src + x; // img.pix_ptr(x, 0);
|
||||
for(y = 0; y < h; y++) {
|
||||
dst_ptr[0] = LV_CLAMP((sum_r * mul_sum) >> shr_sum, 0, 255);
|
||||
dst_ptr += stride;
|
||||
|
||||
sum_r -= sum_out_r;
|
||||
|
||||
stack_start = sp + div - radius;
|
||||
if(stack_start >= div) stack_start -= div;
|
||||
stack_ptr = &stack[stack_start];
|
||||
|
||||
sum_out_r -= stack_ptr[0];
|
||||
|
||||
if(yp < hm) {
|
||||
src_ptr += stride; // stride
|
||||
++yp;
|
||||
}
|
||||
|
||||
stack_ptr[0] = src_ptr[0];
|
||||
|
||||
sum_in_r += src_ptr[0];
|
||||
sum_r += sum_in_r;
|
||||
|
||||
++sp;
|
||||
if(sp >= div) sp = 0;
|
||||
stack_ptr = &stack[sp];
|
||||
|
||||
sum_out_r += stack_ptr[0];
|
||||
sum_in_r -= stack_ptr[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /*LV_USE_GPU_SDL*/
|
||||
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* @file lv_draw_sdl_stack_blur.h
|
||||
*
|
||||
*/
|
||||
#ifndef LV_DRAW_SDL_STACK_BLUR_H
|
||||
#define LV_DRAW_SDL_STACK_BLUR_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_GPU_SDL
|
||||
|
||||
#include "../../misc/lv_color.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
void lv_stack_blur_grayscale(lv_opa_t * buf, uint16_t w, uint16_t h, uint16_t r);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_GPU_SDL*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_DRAW_SDL_STACK_BLUR_H*/
|
||||
@@ -0,0 +1,178 @@
|
||||
/**
|
||||
* @file lv_draw_sdl_texture_cache.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_GPU_SDL
|
||||
|
||||
#include "lv_draw_sdl_texture_cache.h"
|
||||
|
||||
#include "lv_draw_sdl_utils.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct {
|
||||
SDL_Texture * texture;
|
||||
void * userdata;
|
||||
lv_lru_free_t * userdata_free;
|
||||
lv_draw_sdl_cache_flag_t flags;
|
||||
} draw_cache_value_t;
|
||||
|
||||
typedef struct {
|
||||
lv_sdl_cache_key_magic_t magic;
|
||||
} temp_texture_key_t;
|
||||
|
||||
typedef struct {
|
||||
lv_coord_t width, height;
|
||||
} temp_texture_userdata_t;
|
||||
|
||||
static void draw_cache_free_value(draw_cache_value_t *);
|
||||
|
||||
static draw_cache_value_t * draw_cache_get_entry(lv_draw_sdl_ctx_t * ctx, const void * key, size_t key_length,
|
||||
bool * found);
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_draw_sdl_texture_cache_init(lv_draw_sdl_ctx_t * ctx)
|
||||
{
|
||||
ctx->internals->texture_cache = lv_lru_create(LV_GPU_SDL_LRU_SIZE, 65536,
|
||||
(lv_lru_free_t *) draw_cache_free_value, NULL);
|
||||
}
|
||||
|
||||
void lv_draw_sdl_texture_cache_deinit(lv_draw_sdl_ctx_t * ctx)
|
||||
{
|
||||
lv_lru_del(ctx->internals->texture_cache);
|
||||
}
|
||||
|
||||
SDL_Texture * lv_draw_sdl_texture_cache_get(lv_draw_sdl_ctx_t * ctx, const void * key, size_t key_length, bool * found)
|
||||
{
|
||||
return lv_draw_sdl_texture_cache_get_with_userdata(ctx, key, key_length, found, NULL);
|
||||
}
|
||||
|
||||
SDL_Texture * lv_draw_sdl_texture_cache_get_with_userdata(lv_draw_sdl_ctx_t * ctx, const void * key, size_t key_length,
|
||||
bool * found, void ** userdata)
|
||||
{
|
||||
draw_cache_value_t * value = draw_cache_get_entry(ctx, key, key_length, found);
|
||||
if(!value) return NULL;
|
||||
if(userdata) {
|
||||
*userdata = value->userdata;
|
||||
}
|
||||
return value->texture;
|
||||
}
|
||||
|
||||
void lv_draw_sdl_texture_cache_put(lv_draw_sdl_ctx_t * ctx, const void * key, size_t key_length, SDL_Texture * texture)
|
||||
{
|
||||
lv_draw_sdl_texture_cache_put_advanced(ctx, key, key_length, texture, NULL, NULL, 0);
|
||||
}
|
||||
|
||||
void lv_draw_sdl_texture_cache_put_advanced(lv_draw_sdl_ctx_t * ctx, const void * key, size_t key_length,
|
||||
SDL_Texture * texture, void * userdata, void userdata_free(void *),
|
||||
lv_draw_sdl_cache_flag_t flags)
|
||||
{
|
||||
lv_lru_t * lru = ctx->internals->texture_cache;
|
||||
draw_cache_value_t * value = SDL_malloc(sizeof(draw_cache_value_t));
|
||||
value->texture = texture;
|
||||
value->userdata = userdata;
|
||||
value->userdata_free = userdata_free;
|
||||
value->flags = flags;
|
||||
if(!texture) {
|
||||
lv_lru_set(lru, key, key_length, value, 1);
|
||||
return;
|
||||
}
|
||||
if(flags & LV_DRAW_SDL_CACHE_FLAG_MANAGED) {
|
||||
/* Managed texture doesn't count into cache size */
|
||||
LV_LOG_INFO("cache texture %p", texture);
|
||||
lv_lru_set(lru, key, key_length, value, 1);
|
||||
return;
|
||||
}
|
||||
Uint32 format;
|
||||
int access, width, height;
|
||||
if(SDL_QueryTexture(texture, &format, &access, &width, &height) != 0) {
|
||||
return;
|
||||
}
|
||||
LV_LOG_INFO("cache texture %p, %d*%d@%dbpp", texture, width, height, SDL_BITSPERPIXEL(format));
|
||||
lv_lru_set(lru, key, key_length, value, width * height * SDL_BITSPERPIXEL(format) / 8);
|
||||
}
|
||||
|
||||
lv_draw_sdl_cache_key_head_img_t * lv_draw_sdl_texture_img_key_create(const void * src, int32_t frame_id, size_t * size)
|
||||
{
|
||||
lv_draw_sdl_cache_key_head_img_t header;
|
||||
/* VERY IMPORTANT! Padding between members is uninitialized, so we have to wipe them manually */
|
||||
SDL_memset(&header, 0, sizeof(header));
|
||||
header.magic = LV_GPU_CACHE_KEY_MAGIC_IMG;
|
||||
header.type = lv_img_src_get_type(src);
|
||||
header.frame_id = frame_id;
|
||||
void * key;
|
||||
size_t key_size;
|
||||
if(header.type == LV_IMG_SRC_FILE || header.type == LV_IMG_SRC_SYMBOL) {
|
||||
size_t srclen = SDL_strlen(src);
|
||||
key_size = sizeof(header) + srclen;
|
||||
key = SDL_malloc(key_size);
|
||||
SDL_memcpy(key, &header, sizeof(header));
|
||||
/*Copy string content as key value*/
|
||||
SDL_memcpy(key + sizeof(header), src, srclen);
|
||||
}
|
||||
else {
|
||||
key_size = sizeof(header) + sizeof(void *);
|
||||
key = SDL_malloc(key_size);
|
||||
SDL_memcpy(key, &header, sizeof(header));
|
||||
/*Copy address number as key value*/
|
||||
SDL_memcpy(key + sizeof(header), &src, sizeof(void *));
|
||||
}
|
||||
*size = key_size;
|
||||
return (lv_draw_sdl_cache_key_head_img_t *) key;
|
||||
}
|
||||
|
||||
static void draw_cache_free_value(draw_cache_value_t * value)
|
||||
{
|
||||
if(value->texture && !(value->flags & LV_DRAW_SDL_CACHE_FLAG_MANAGED)) {
|
||||
LV_LOG_INFO("destroy texture %p", value->texture);
|
||||
SDL_DestroyTexture(value->texture);
|
||||
}
|
||||
if(value->userdata_free) {
|
||||
value->userdata_free(value->userdata);
|
||||
}
|
||||
SDL_free(value);
|
||||
}
|
||||
|
||||
static draw_cache_value_t * draw_cache_get_entry(lv_draw_sdl_ctx_t * ctx, const void * key, size_t key_length,
|
||||
bool * found)
|
||||
{
|
||||
lv_lru_t * lru = ctx->internals->texture_cache;
|
||||
draw_cache_value_t * value = NULL;
|
||||
lv_lru_get(lru, key, key_length, (void **) &value);
|
||||
if(!value) {
|
||||
if(found) {
|
||||
*found = false;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
if(found) {
|
||||
*found = true;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
#endif /*LV_USE_GPU_SDL*/
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
/**
|
||||
* @file lv_draw_sdl_texture_cache.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_DRAW_SDL_TEXTURE_CACHE_H
|
||||
#define LV_DRAW_SDL_TEXTURE_CACHE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_GPU_SDL
|
||||
|
||||
#include LV_GPU_SDL_INCLUDE_PATH
|
||||
#include "lv_draw_sdl.h"
|
||||
#include "lv_draw_sdl_priv.h"
|
||||
#include "../../draw/lv_img_decoder.h"
|
||||
#include "../../misc/lv_area.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
#define LV_DRAW_SDL_DEC_DSC_TEXTURE_HEAD "@LVSDLTex"
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct {
|
||||
char head[8];
|
||||
SDL_Texture * texture;
|
||||
SDL_Rect rect;
|
||||
bool texture_managed;
|
||||
bool texture_referenced;
|
||||
} lv_draw_sdl_dec_dsc_userdata_t;
|
||||
|
||||
typedef enum {
|
||||
LV_GPU_CACHE_KEY_MAGIC_ARC = 0x01,
|
||||
LV_GPU_CACHE_KEY_MAGIC_IMG = 0x11,
|
||||
LV_GPU_CACHE_KEY_MAGIC_IMG_ROUNDED_CORNERS = 0x12,
|
||||
LV_GPU_CACHE_KEY_MAGIC_LINE = 0x21,
|
||||
LV_GPU_CACHE_KEY_MAGIC_RECT_BG = 0x31,
|
||||
LV_GPU_CACHE_KEY_MAGIC_RECT_SHADOW = 0x32,
|
||||
LV_GPU_CACHE_KEY_MAGIC_RECT_BORDER = 0x33,
|
||||
LV_GPU_CACHE_KEY_MAGIC_FONT_GLYPH = 0x41,
|
||||
LV_GPU_CACHE_KEY_MAGIC_MASK = 0x51,
|
||||
} lv_sdl_cache_key_magic_t;
|
||||
|
||||
typedef enum {
|
||||
LV_DRAW_SDL_CACHE_FLAG_NONE = 0,
|
||||
LV_DRAW_SDL_CACHE_FLAG_MANAGED = 1,
|
||||
} lv_draw_sdl_cache_flag_t;
|
||||
|
||||
typedef struct {
|
||||
lv_sdl_cache_key_magic_t magic;
|
||||
lv_img_src_t type;
|
||||
int32_t frame_id;
|
||||
} lv_draw_sdl_cache_key_head_img_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
void lv_draw_sdl_texture_cache_init(lv_draw_sdl_ctx_t * ctx);
|
||||
|
||||
void lv_draw_sdl_texture_cache_deinit(lv_draw_sdl_ctx_t * ctx);
|
||||
|
||||
/**
|
||||
* Find cached texture by key. The texture can be destroyed during usage.
|
||||
*/
|
||||
SDL_Texture * lv_draw_sdl_texture_cache_get(lv_draw_sdl_ctx_t * ctx, const void * key, size_t key_length, bool * found);
|
||||
|
||||
SDL_Texture * lv_draw_sdl_texture_cache_get_with_userdata(lv_draw_sdl_ctx_t * ctx, const void * key, size_t key_length,
|
||||
bool * found, void ** userdata);
|
||||
|
||||
void lv_draw_sdl_texture_cache_put(lv_draw_sdl_ctx_t * ctx, const void * key, size_t key_length, SDL_Texture * texture);
|
||||
|
||||
void lv_draw_sdl_texture_cache_put_advanced(lv_draw_sdl_ctx_t * ctx, const void * key, size_t key_length,
|
||||
SDL_Texture * texture, void * userdata, void userdata_free(void *),
|
||||
lv_draw_sdl_cache_flag_t flags);
|
||||
|
||||
lv_draw_sdl_cache_key_head_img_t * lv_draw_sdl_texture_img_key_create(const void * src, int32_t frame_id,
|
||||
size_t * size);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
#endif /*LV_USE_GPU_SDL*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_DRAW_SDL_TEXTURE_CACHE_H*/
|
||||
@@ -0,0 +1,183 @@
|
||||
/**
|
||||
* @file lv_draw_sdl_utils.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_GPU_SDL
|
||||
|
||||
#include "lv_draw_sdl_utils.h"
|
||||
|
||||
#include "../lv_draw.h"
|
||||
#include "../lv_draw_label.h"
|
||||
#include "../../core/lv_refr.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
extern const uint8_t _lv_bpp1_opa_table[2];
|
||||
extern const uint8_t _lv_bpp2_opa_table[4];
|
||||
extern const uint8_t _lv_bpp4_opa_table[16];
|
||||
extern const uint8_t _lv_bpp8_opa_table[256];
|
||||
|
||||
static int utils_init_count = 0;
|
||||
static SDL_Palette * lv_sdl_palette_grayscale8 = NULL;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void _lv_draw_sdl_utils_init()
|
||||
{
|
||||
utils_init_count++;
|
||||
if(utils_init_count > 1) {
|
||||
return;
|
||||
}
|
||||
lv_sdl_palette_grayscale8 = lv_sdl_alloc_palette_for_bpp(_lv_bpp8_opa_table, 8);
|
||||
}
|
||||
|
||||
void _lv_draw_sdl_utils_deinit()
|
||||
{
|
||||
if(utils_init_count == 0) {
|
||||
return;
|
||||
}
|
||||
utils_init_count--;
|
||||
if(utils_init_count == 0) {
|
||||
SDL_FreePalette(lv_sdl_palette_grayscale8);
|
||||
lv_sdl_palette_grayscale8 = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void lv_area_to_sdl_rect(const lv_area_t * in, SDL_Rect * out)
|
||||
{
|
||||
out->x = in->x1;
|
||||
out->y = in->y1;
|
||||
out->w = in->x2 - in->x1 + 1;
|
||||
out->h = in->y2 - in->y1 + 1;
|
||||
}
|
||||
|
||||
void lv_color_to_sdl_color(const lv_color_t * in, SDL_Color * out)
|
||||
{
|
||||
#if LV_COLOR_DEPTH == 32
|
||||
out->a = in->ch.alpha;
|
||||
out->r = in->ch.red;
|
||||
out->g = in->ch.green;
|
||||
out->b = in->ch.blue;
|
||||
#else
|
||||
uint32_t color32 = lv_color_to32(*in);
|
||||
lv_color32_t * color32_t = (lv_color32_t *) &color32;
|
||||
out->a = color32_t->ch.alpha;
|
||||
out->r = color32_t->ch.red;
|
||||
out->g = color32_t->ch.green;
|
||||
out->b = color32_t->ch.blue;
|
||||
#endif
|
||||
}
|
||||
|
||||
void lv_area_zoom_to_sdl_rect(const lv_area_t * in, SDL_Rect * out, uint16_t zoom, const lv_point_t * pivot)
|
||||
{
|
||||
if(zoom == LV_IMG_ZOOM_NONE) {
|
||||
lv_area_to_sdl_rect(in, out);
|
||||
return;
|
||||
}
|
||||
lv_area_t tmp;
|
||||
_lv_img_buf_get_transformed_area(&tmp, lv_area_get_width(in), lv_area_get_height(in), 0, zoom, pivot);
|
||||
lv_area_move(&tmp, in->x1, in->y1);
|
||||
lv_area_to_sdl_rect(&tmp, out);
|
||||
}
|
||||
|
||||
SDL_Palette * lv_sdl_alloc_palette_for_bpp(const uint8_t * mapping, uint8_t bpp)
|
||||
{
|
||||
SDL_assert(bpp >= 1 && bpp <= 8);
|
||||
int color_cnt = 1 << bpp;
|
||||
SDL_Palette * result = SDL_AllocPalette(color_cnt);
|
||||
SDL_Color palette[256];
|
||||
for(int i = 0; i < color_cnt; i++) {
|
||||
palette[i].r = palette[i].g = palette[i].b = 0xFF;
|
||||
palette[i].a = mapping ? mapping[i] : i;
|
||||
}
|
||||
SDL_SetPaletteColors(result, palette, 0, color_cnt);
|
||||
return result;
|
||||
}
|
||||
|
||||
SDL_Surface * lv_sdl_create_opa_surface(lv_opa_t * opa, lv_coord_t width, lv_coord_t height, lv_coord_t stride)
|
||||
{
|
||||
SDL_Surface * indexed = SDL_CreateRGBSurfaceFrom(opa, width, height, 8, stride, 0, 0, 0, 0);
|
||||
SDL_SetSurfacePalette(indexed, lv_sdl_palette_grayscale8);
|
||||
SDL_Surface * converted = SDL_ConvertSurfaceFormat(indexed, LV_DRAW_SDL_TEXTURE_FORMAT, 0);
|
||||
SDL_FreeSurface(indexed);
|
||||
return converted;
|
||||
}
|
||||
|
||||
SDL_Texture * lv_sdl_create_opa_texture(SDL_Renderer * renderer, lv_opa_t * pixels, lv_coord_t width,
|
||||
lv_coord_t height, lv_coord_t stride)
|
||||
{
|
||||
SDL_Surface * indexed = lv_sdl_create_opa_surface(pixels, width, height, stride);
|
||||
SDL_Texture * texture = SDL_CreateTextureFromSurface(renderer, indexed);
|
||||
SDL_FreeSurface(indexed);
|
||||
return texture;
|
||||
}
|
||||
|
||||
void lv_sdl_to_8bpp(uint8_t * dest, const uint8_t * src, int width, int height, int stride, uint8_t bpp)
|
||||
{
|
||||
int src_len = width * height;
|
||||
int cur = 0;
|
||||
int curbit;
|
||||
uint8_t opa_mask;
|
||||
const uint8_t * opa_table;
|
||||
switch(bpp) {
|
||||
case 1:
|
||||
opa_mask = 0x1;
|
||||
opa_table = _lv_bpp1_opa_table;
|
||||
break;
|
||||
case 2:
|
||||
opa_mask = 0x4;
|
||||
opa_table = _lv_bpp2_opa_table;
|
||||
break;
|
||||
case 4:
|
||||
opa_mask = 0xF;
|
||||
opa_table = _lv_bpp4_opa_table;
|
||||
break;
|
||||
case 8:
|
||||
opa_mask = 0xFF;
|
||||
opa_table = _lv_bpp8_opa_table;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
/* Does this work well on big endian systems? */
|
||||
while(cur < src_len) {
|
||||
curbit = 8 - bpp;
|
||||
uint8_t src_byte = src[cur * bpp / 8];
|
||||
while(curbit >= 0 && cur < src_len) {
|
||||
uint8_t src_bits = opa_mask & (src_byte >> curbit);
|
||||
dest[(cur / width * stride) + (cur % width)] = opa_table[src_bits];
|
||||
curbit -= bpp;
|
||||
cur++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_GPU_SDL*/
|
||||
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* @file lv_draw_sdl_utils.h
|
||||
*
|
||||
*/
|
||||
#ifndef LV_DRAW_SDL_UTILS_H
|
||||
#define LV_DRAW_SDL_UTILS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "../../lv_conf_internal.h"
|
||||
#if LV_USE_GPU_SDL
|
||||
|
||||
#include "lv_draw_sdl.h"
|
||||
#include "../../misc/lv_color.h"
|
||||
#include "../../misc/lv_area.h"
|
||||
|
||||
#include LV_GPU_SDL_INCLUDE_PATH
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
void _lv_draw_sdl_utils_init();
|
||||
|
||||
void _lv_draw_sdl_utils_deinit();
|
||||
|
||||
void lv_area_to_sdl_rect(const lv_area_t * in, SDL_Rect * out);
|
||||
|
||||
void lv_color_to_sdl_color(const lv_color_t * in, SDL_Color * out);
|
||||
|
||||
void lv_area_zoom_to_sdl_rect(const lv_area_t * in, SDL_Rect * out, uint16_t zoom, const lv_point_t * pivot);
|
||||
|
||||
SDL_Palette * lv_sdl_alloc_palette_for_bpp(const uint8_t * mapping, uint8_t bpp);
|
||||
|
||||
SDL_Surface * lv_sdl_create_opa_surface(lv_opa_t * opa, lv_coord_t width, lv_coord_t height, lv_coord_t stride);
|
||||
|
||||
SDL_Texture * lv_sdl_create_opa_texture(SDL_Renderer * renderer, lv_opa_t * pixels, lv_coord_t width,
|
||||
lv_coord_t height, lv_coord_t stride);
|
||||
|
||||
void lv_sdl_to_8bpp(uint8_t * dest, const uint8_t * src, int width, int height, int stride, uint8_t bpp);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_GPU_SDL*/
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_DRAW_SDL_UTILS_H*/
|
||||
Reference in New Issue
Block a user