mirror of
https://github.com/RT-Thread/rt-thread.git
synced 2025-01-28 10:01:03 +08:00
484 lines
15 KiB
C
484 lines
15 KiB
C
/****************************************************************************
|
|
*
|
|
* Copyright 2012 - 2020 Vivante Corporation, Santa Clara, California.
|
|
* All Rights Reserved.
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining
|
|
* a copy of this software and associated documentation files (the
|
|
* 'Software'), to deal in the Software without restriction, including
|
|
* without limitation the rights to use, copy, modify, merge, publish,
|
|
* distribute, sub license, and/or sell copies of the Software, and to
|
|
* permit persons to whom the Software is furnished to do so, subject
|
|
* to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice (including the
|
|
* next paragraph) shall be included in all copies or substantial
|
|
* portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
|
* IN NO EVENT SHALL VIVANTE AND/OR ITS SUPPLIERS BE LIABLE FOR ANY
|
|
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
#include "elm_precom.h"
|
|
|
|
#if (VG_RENDER_TEXT==1)
|
|
#include "elm_text.h"
|
|
#endif /* VG_RENDER_TEXT */
|
|
|
|
static void multiply(vg_lite_matrix_t * matrix, vg_lite_matrix_t * mult)
|
|
{
|
|
vg_lite_matrix_t temp;
|
|
int row, column;
|
|
|
|
/* Process all rows. */
|
|
for (row = 0; row < 3; row++) {
|
|
/* Process all columns. */
|
|
for (column = 0; column < 3; column++) {
|
|
/* Compute matrix entry. */
|
|
temp.m[row][column] = (matrix->m[row][0] * mult->m[0][column])
|
|
+ (matrix->m[row][1] * mult->m[1][column])
|
|
+ (matrix->m[row][2] * mult->m[2][column]);
|
|
}
|
|
}
|
|
|
|
memcpy(matrix, &temp, sizeof(temp));
|
|
|
|
}
|
|
|
|
static vg_lite_filter_t quality_to_filter(ELM_QUALITY quality)
|
|
{
|
|
switch (quality) {
|
|
case ELM_QULIATY_HI:
|
|
return VG_LITE_FILTER_BI_LINEAR;
|
|
break;
|
|
|
|
case ELM_QUALITY_MED:
|
|
return VG_LITE_FILTER_LINEAR;
|
|
break;
|
|
|
|
case ELM_QUALITY_LOW:
|
|
default:
|
|
return VG_LITE_FILTER_POINT;
|
|
break;
|
|
}
|
|
}
|
|
|
|
static vg_lite_pattern_mode_t pat_to_pad(ELM_PATTERN_MODE mode)
|
|
{
|
|
switch (mode) {
|
|
case ELM_PATTERN_MODE_PAD:
|
|
return VG_LITE_PATTERN_PAD;
|
|
break;
|
|
|
|
default:
|
|
return VG_LITE_PATTERN_COLOR;
|
|
break;
|
|
}
|
|
}
|
|
static vg_lite_error_t draw_evo_pattern(el_Obj_Buffer *buff, el_Obj_Group *ego,int * index)
|
|
{
|
|
el_Obj_EVO *evo;
|
|
vg_lite_error_t error = VG_LITE_INVALID_ARGUMENT;
|
|
vg_lite_color_t color;
|
|
vg_lite_filter_t filter;
|
|
vg_lite_blend_t blend;
|
|
vg_lite_fill_t rule;
|
|
vg_lite_buffer_t *buffer;
|
|
vg_lite_matrix_t mat;
|
|
vg_lite_pattern_mode_t pat_mode;
|
|
int width = 0;
|
|
int height = 0;
|
|
|
|
int start = *index;
|
|
int i = start;
|
|
evo = &ego->group.objects[i];
|
|
width = (int)(evo->data.path.bounding_box[2] - evo->data.path.bounding_box[0]);
|
|
height = (int)(evo->data.path.bounding_box[3] - evo->data.path.bounding_box[1]);
|
|
buffer = (vg_lite_buffer_t *)malloc(sizeof(vg_lite_buffer_t));
|
|
memset(buffer,0,sizeof(vg_lite_buffer_t));
|
|
buffer->width = width;
|
|
buffer->height = height;
|
|
buffer->format = VG_LITE_RGBA8888;
|
|
error = vg_lite_allocate(buffer);
|
|
vg_lite_clear(buffer,NULL,0xffffffff);
|
|
i++;
|
|
evo = &ego->group.objects[i];
|
|
while(evo->is_pattern)
|
|
{
|
|
blend = (vg_lite_blend_t)evo->attribute.blend;
|
|
rule = (vg_lite_fill_t)evo->attribute.fill_rule;
|
|
color = (vg_lite_color_t)evo->attribute.paint.color;
|
|
memcpy(&mat, &(evo->attribute.transform.matrix), sizeof(mat));
|
|
error = vg_lite_draw(buffer, &evo->data.path,
|
|
rule,
|
|
&mat,
|
|
blend,
|
|
color);
|
|
if(error)
|
|
return error;
|
|
i++;
|
|
evo = &ego->group.objects[i];
|
|
}
|
|
*index = i - 1;
|
|
evo = &ego->group.objects[start];
|
|
blend = (vg_lite_blend_t)evo->attribute.blend;
|
|
rule = (vg_lite_fill_t)evo->attribute.fill_rule;
|
|
color = (vg_lite_color_t)evo->attribute.paint.color;
|
|
memcpy(&mat, &(evo->attribute.transform.matrix), sizeof(mat));
|
|
filter = VG_LITE_FILTER_POINT;
|
|
pat_mode = VG_LITE_PATTERN_COLOR;
|
|
error = vg_lite_draw_pattern(&buff->buffer, &evo->data.path,
|
|
rule,
|
|
&mat,
|
|
buffer,
|
|
&mat,
|
|
blend,
|
|
pat_mode,
|
|
color,
|
|
filter);
|
|
vg_lite_finish();
|
|
vg_lite_free(buffer);
|
|
free(buffer);
|
|
return error;
|
|
}
|
|
|
|
static vg_lite_error_t draw_evo(el_Obj_Buffer *buff, el_Obj_EVO *evo, vg_lite_matrix_t *mat)
|
|
{
|
|
el_Obj_EBO *pattern;
|
|
vg_lite_error_t error = VG_LITE_INVALID_ARGUMENT;
|
|
vg_lite_color_t color;
|
|
vg_lite_filter_t filter;
|
|
vg_lite_matrix_t mat_pattern;
|
|
ELM_PAINT_TYPE paint_type = evo->attribute.paint.type;
|
|
vg_lite_blend_t blend = (vg_lite_blend_t)evo->attribute.blend;
|
|
vg_lite_fill_t rule = (vg_lite_fill_t)evo->attribute.fill_rule;
|
|
vg_lite_pattern_mode_t pat_mode = pat_to_pad(evo->attribute.paint.pattern.mode);
|
|
|
|
switch (paint_type) {
|
|
case ELM_PAINT_GRADIENT:
|
|
memcpy(&evo->attribute.paint.grad->data.grad.matrix,
|
|
&evo->attribute.paint.grad->data.transform.matrix,
|
|
sizeof(evo->attribute.paint.grad->data.transform.matrix));
|
|
#if !DDRLESS
|
|
error = vg_lite_draw_gradient(&buff->buffer, &evo->data.path,
|
|
rule,
|
|
mat,
|
|
&evo->attribute.paint.grad->data.grad,
|
|
blend);
|
|
#else
|
|
error = vg_lite_draw_gradient(NULL, &evo->data.path,
|
|
rule,
|
|
mat,
|
|
&evo->attribute.paint.grad->data.grad,
|
|
blend);
|
|
#endif
|
|
break;
|
|
case ELM_PAINT_RADIAL_GRADIENT:
|
|
memcpy(&evo->attribute.paint.radgrad->data.rad_grad.matrix,
|
|
&evo->attribute.paint.radgrad->data.transform.matrix,
|
|
sizeof(evo->attribute.paint.radgrad->data.transform.matrix));
|
|
|
|
error = vg_lite_draw_radial_gradient(&buff->buffer, &evo->data.path,
|
|
rule,
|
|
mat,
|
|
&evo->attribute.paint.radgrad->data.rad_grad,
|
|
0,
|
|
blend,
|
|
VG_LITE_FILTER_LINEAR);
|
|
break;
|
|
case ELM_PAINT_COLOR:
|
|
color = (vg_lite_color_t)evo->attribute.paint.color;
|
|
|
|
#if !DDRLESS
|
|
error = vg_lite_draw(&buff->buffer, &evo->data.path,
|
|
rule,
|
|
mat,
|
|
blend,
|
|
color);
|
|
#else
|
|
error = vg_lite_draw(NULL, &evo->data.path,
|
|
rule,
|
|
mat,
|
|
blend,
|
|
color);
|
|
#endif
|
|
break;
|
|
case ELM_PAINT_PATTERN:
|
|
pattern = (el_Obj_EBO *)(evo->attribute.paint.pattern.pattern);
|
|
blend = (vg_lite_blend_t)(pattern->attribute.blend);
|
|
filter = quality_to_filter(evo->attribute.quality);
|
|
color = (vg_lite_color_t)pattern->attribute.paint.color;
|
|
memcpy(&mat_pattern, &pattern->attribute.transform.matrix,
|
|
sizeof(pattern->attribute.transform.matrix));
|
|
|
|
#if !DDRLESS
|
|
error = vg_lite_draw_pattern(&buff->buffer, &evo->data.path, rule, mat,
|
|
&pattern->data.buffer, &mat_pattern, blend,
|
|
pat_mode, color, filter);
|
|
#else
|
|
error = vg_lite_draw_pattern(NULL, &evo->data.path, rule, mat,
|
|
&pattern->data.buffer, &mat_pattern, blend,
|
|
pat_mode, color, filter);
|
|
#endif
|
|
break;
|
|
case ELM_PAINT_TEXT:
|
|
#if (VG_RENDER_TEXT==1)
|
|
error = draw_text(buff, evo, mat);
|
|
#endif /* VG_RENDER_TEXT */
|
|
break;
|
|
}
|
|
|
|
return error;
|
|
}
|
|
|
|
static vg_lite_error_t draw_ebo(el_Obj_Buffer *buff, el_Obj_EBO *ebo, vg_lite_matrix_t *mat)
|
|
{
|
|
vg_lite_error_t error;
|
|
vg_lite_buffer_t *image_buffer = &ebo->data.buffer;
|
|
vg_lite_blend_t blend = (vg_lite_blend_t)ebo->attribute.blend;
|
|
vg_lite_color_t color = ebo->attribute.paint.color;
|
|
vg_lite_filter_t filter = quality_to_filter(ebo->attribute.quality);
|
|
|
|
if (image_buffer->format >= VG_LITE_INDEX_1 && image_buffer->format <= VG_LITE_INDEX_8)
|
|
{
|
|
vg_lite_set_CLUT(ebo->clut_count, ebo->clut);
|
|
}
|
|
|
|
image_buffer->image_mode = VG_LITE_NORMAL_IMAGE_MODE;
|
|
#if !DDRLESS
|
|
error = vg_lite_blit(&buff->buffer, image_buffer, mat, blend, color, filter);
|
|
#else
|
|
error = vg_lite_blit(NULL, image_buffer, mat, blend, color, filter);
|
|
#endif
|
|
return error;
|
|
}
|
|
/*!
|
|
@abstract Clear a render buffer with specified color and dimension.
|
|
|
|
@discussion
|
|
This function is called to clear full or partial of the buffer. If the rectangle is out of buffer space, the intersect portion will be cleared.
|
|
|
|
@param buffer
|
|
A render buffer handle.
|
|
|
|
@param color
|
|
Clear color value.
|
|
|
|
@param x
|
|
x origin of partical clear rectangle.
|
|
|
|
@param y
|
|
y origin of partial clear rectangle.
|
|
|
|
@param width
|
|
width of partical clear rectangle.
|
|
|
|
@param height
|
|
height of partical clear rectangle.
|
|
|
|
@param full
|
|
Flag to indicate a full buffer clear. If true, the dimension parameters will be ignored.
|
|
|
|
@return bool
|
|
Indicate the clear operation is set up correctly.
|
|
*/
|
|
BOOL ElmClear(ElmBuffer buffer, uint32_t color, uint32_t x, uint32_t y, uint32_t width, uint32_t height, BOOL full)
|
|
{
|
|
#if !DDRLESS
|
|
vg_lite_error_t error = VG_LITE_SUCCESS;
|
|
el_Obj_Buffer *buff = (el_Obj_Buffer *)get_object(buffer);
|
|
vg_lite_rectangle_t rectangle;
|
|
rectangle.x = x;
|
|
rectangle.y = y;
|
|
rectangle.width = width;
|
|
rectangle.height = height;
|
|
|
|
if (full == 1)
|
|
{
|
|
error = vg_lite_clear(&buff->buffer, NULL, color);
|
|
}
|
|
else
|
|
{
|
|
error = vg_lite_clear(&buff->buffer, &rectangle, color);
|
|
}
|
|
return ((error == VG_LITE_SUCCESS) ? TRUE : FALSE);
|
|
#else
|
|
return TRUE;
|
|
#endif
|
|
}
|
|
|
|
/*!
|
|
@abstract Finish all rendering on GPU issued before this call.
|
|
|
|
@discussion
|
|
This function tells the engine that it has finished the frame data and GPU can draw it now. It's blocked until GPU rendering done.
|
|
|
|
@return
|
|
If the opeartion is successfully done or not.
|
|
*/
|
|
BOOL ElmFinish()
|
|
{
|
|
vg_lite_finish();
|
|
return TRUE;
|
|
}
|
|
|
|
/*!
|
|
@abstract Flush all rendering command to GPU issued before this call.
|
|
|
|
@discussion
|
|
This function tells the engine to start kicking off command to GPU side, it will return immediately after firing off GPU.
|
|
|
|
@return
|
|
If the opeartion is successfully done or not.
|
|
*/
|
|
BOOL ElmFlush()
|
|
{
|
|
vg_lite_flush();
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
@abstract Draw a graphics object onto current render target
|
|
|
|
@discussion
|
|
This is an enssentail function to do the real job, it takes all current setting of the elementary object and
|
|
render into theb buffer target.
|
|
|
|
@param buffer
|
|
The render target that an elmentary object will be rendered into.
|
|
|
|
@param obj
|
|
The elmentary object will be draw into render target.
|
|
|
|
@return bool
|
|
The draw operation for this elmentary object is sucessful.
|
|
*/
|
|
BOOL ElmDraw(ElmBuffer buffer, ElmHandle object)
|
|
{
|
|
BOOL status = TRUE;
|
|
el_Object *elm;
|
|
el_Obj_Buffer *buff;
|
|
vg_lite_error_t error;
|
|
vg_lite_matrix_t mat;
|
|
elm = get_object(object);
|
|
|
|
if (!elm)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
#if !DDRLESS
|
|
buff = (el_Obj_Buffer *)get_object(buffer);
|
|
if (buff == NULL)
|
|
{
|
|
return FALSE;
|
|
}
|
|
#else
|
|
buff = NULL;
|
|
#endif
|
|
|
|
if (elm->type == ELM_OBJECT_TYPE_EGO)
|
|
{
|
|
el_Obj_EVO *evo;
|
|
el_Obj_Group *ego = (el_Obj_Group *)elm;
|
|
vg_lite_matrix_t mat_group, res_mat;
|
|
|
|
if (ego->group.count > 0)
|
|
{
|
|
int i;
|
|
memcpy(&mat_group, &(ego->transform.matrix), sizeof(ego->transform.matrix));
|
|
for (i = 0; i < ego->group.count; i++)
|
|
{
|
|
evo = &ego->group.objects[i];
|
|
|
|
/* Font objects may generate empty objects */
|
|
if (evo->object.handle == ELM_NULL_HANDLE)
|
|
continue;
|
|
|
|
if(evo->is_image)
|
|
{
|
|
ElmHandle ebo_handle;
|
|
el_Object *elm_ebo;
|
|
el_Obj_EBO *ebo;
|
|
ebo_handle = ElmCreateObjectFromFile(ELM_OBJECT_TYPE_EBO, evo->eboname);
|
|
elm_ebo = get_object(ebo_handle);
|
|
ebo = (el_Obj_EBO *)elm_ebo;
|
|
memcpy(&mat, &evo->defaultAttrib.transform.matrix, sizeof(mat));
|
|
|
|
error = draw_ebo(buff, ebo, &mat);
|
|
if (error)
|
|
{
|
|
status = FALSE;
|
|
}
|
|
continue;
|
|
}
|
|
memcpy(&mat, &(evo->attribute.transform.matrix), sizeof(mat));
|
|
memcpy(&res_mat, &mat_group, sizeof(mat_group));
|
|
multiply(&res_mat, &mat);
|
|
|
|
if(evo->has_pattern)
|
|
error = draw_evo_pattern(buff,ego,&i);
|
|
else
|
|
error = draw_evo(buff, evo, &res_mat);
|
|
if (error)
|
|
{
|
|
status = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (elm->type == ELM_OBJECT_TYPE_EVO)
|
|
{
|
|
el_Obj_EVO *evo = (el_Obj_EVO *)elm;
|
|
memcpy(&mat, &(evo->attribute.transform.matrix), sizeof(mat));
|
|
|
|
error = draw_evo(buff, evo, &mat);
|
|
if (error)
|
|
{
|
|
status = FALSE;
|
|
}
|
|
}
|
|
else if (elm->type == ELM_OBJECT_TYPE_EBO)
|
|
{
|
|
el_Obj_EBO *ebo = (el_Obj_EBO *)elm;
|
|
memcpy(&mat, &(ebo->attribute.transform.matrix), sizeof(mat));
|
|
|
|
error = draw_ebo(buff, ebo, &mat);
|
|
if (error)
|
|
{
|
|
status = FALSE;
|
|
}
|
|
|
|
}
|
|
else if (elm->type == ELM_OBJECT_TYPE_BUF)
|
|
{
|
|
el_Obj_Buffer *src = (el_Obj_Buffer *)elm;
|
|
vg_lite_identity(&mat);
|
|
|
|
#if !DDRLESS
|
|
if (VG_LITE_SUCCESS !=
|
|
vg_lite_blit(&buff->buffer, &src->buffer, &mat, VG_LITE_BLEND_NONE, 0,
|
|
VG_LITE_FILTER_BI_LINEAR)
|
|
)
|
|
#else
|
|
if (VG_LITE_SUCCESS !=
|
|
vg_lite_blit(NULL, &src->buffer, &mat, VG_LITE_BLEND_NONE, 0,
|
|
VG_LITE_FILTER_BI_LINEAR)
|
|
)
|
|
#endif
|
|
{
|
|
status = FALSE;
|
|
}
|
|
}
|
|
return status;
|
|
}
|