4
0
mirror of https://github.com/RT-Thread/rt-thread.git synced 2025-01-28 10:01:03 +08:00

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;
}