1 /****************************************************************************
2 *
3 *    Copyright 2012 - 2020 Vivante Corporation, Santa Clara, California.
4 *    All Rights Reserved.
5 *
6 *    Permission is hereby granted, free of charge, to any person obtaining
7 *    a copy of this software and associated documentation files (the
8 *    'Software'), to deal in the Software without restriction, including
9 *    without limitation the rights to use, copy, modify, merge, publish,
10 *    distribute, sub license, and/or sell copies of the Software, and to
11 *    permit persons to whom the Software is furnished to do so, subject
12 *    to the following conditions:
13 *
14 *    The above copyright notice and this permission notice (including the
15 *    next paragraph) shall be included in all copies or substantial
16 *    portions of the Software.
17 *
18 *    THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
19 *    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 *    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 *    IN NO EVENT SHALL VIVANTE AND/OR ITS SUPPLIERS BE LIABLE FOR ANY
22 *    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 *    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 *    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 *****************************************************************************/
27 
28 #include "elm_precom.h"
29 
30 #if (VG_RENDER_TEXT==1)
31 #include "elm_text.h"
32 #endif /* VG_RENDER_TEXT */
33 
multiply(vg_lite_matrix_t * matrix,vg_lite_matrix_t * mult)34 static void multiply(vg_lite_matrix_t * matrix, vg_lite_matrix_t * mult)
35 {
36     vg_lite_matrix_t temp;
37     int row, column;
38 
39     /* Process all rows. */
40     for (row = 0; row < 3; row++) {
41         /* Process all columns. */
42         for (column = 0; column < 3; column++) {
43             /* Compute matrix entry. */
44             temp.m[row][column] =  (matrix->m[row][0] * mult->m[0][column])
45             + (matrix->m[row][1] * mult->m[1][column])
46             + (matrix->m[row][2] * mult->m[2][column]);
47         }
48     }
49 
50     memcpy(matrix, &temp, sizeof(temp));
51 
52 }
53 
quality_to_filter(ELM_QUALITY quality)54 static vg_lite_filter_t quality_to_filter(ELM_QUALITY quality)
55 {
56     switch (quality) {
57         case ELM_QULIATY_HI:
58             return VG_LITE_FILTER_BI_LINEAR;
59             break;
60 
61         case ELM_QUALITY_MED:
62             return VG_LITE_FILTER_LINEAR;
63             break;
64 
65         case ELM_QUALITY_LOW:
66         default:
67             return VG_LITE_FILTER_POINT;
68             break;
69     }
70 }
71 
pat_to_pad(ELM_PATTERN_MODE mode)72 static vg_lite_pattern_mode_t pat_to_pad(ELM_PATTERN_MODE mode)
73 {
74     switch (mode) {
75         case ELM_PATTERN_MODE_PAD:
76             return VG_LITE_PATTERN_PAD;
77             break;
78 
79         default:
80             return VG_LITE_PATTERN_COLOR;
81             break;
82     }
83 }
draw_evo_pattern(el_Obj_Buffer * buff,el_Obj_Group * ego,int * index)84 static vg_lite_error_t draw_evo_pattern(el_Obj_Buffer *buff, el_Obj_Group *ego,int * index)
85 {
86     el_Obj_EVO *evo;
87     vg_lite_error_t error = VG_LITE_INVALID_ARGUMENT;
88     vg_lite_color_t color;
89     vg_lite_filter_t filter;
90     vg_lite_blend_t blend;
91     vg_lite_fill_t rule;
92     vg_lite_buffer_t *buffer;
93     vg_lite_matrix_t mat;
94     vg_lite_pattern_mode_t pat_mode;
95     int width = 0;
96     int height = 0;
97 
98     int start = *index;
99     int i = start;
100     evo = &ego->group.objects[i];
101     width  = (int)(evo->data.path.bounding_box[2] - evo->data.path.bounding_box[0]);
102     height = (int)(evo->data.path.bounding_box[3] - evo->data.path.bounding_box[1]);
103     buffer = (vg_lite_buffer_t *)malloc(sizeof(vg_lite_buffer_t));
104     memset(buffer,0,sizeof(vg_lite_buffer_t));
105     buffer->width = width;
106     buffer->height = height;
107     buffer->format = VG_LITE_RGBA8888;
108     error = vg_lite_allocate(buffer);
109     vg_lite_clear(buffer,NULL,0xffffffff);
110     i++;
111     evo = &ego->group.objects[i];
112     while(evo->is_pattern)
113     {
114         blend = (vg_lite_blend_t)evo->attribute.blend;
115         rule = (vg_lite_fill_t)evo->attribute.fill_rule;
116         color = (vg_lite_color_t)evo->attribute.paint.color;
117         memcpy(&mat, &(evo->attribute.transform.matrix), sizeof(mat));
118         error = vg_lite_draw(buffer, &evo->data.path,
119                                 rule,
120                                 &mat,
121                                 blend,
122                                 color);
123         if(error)
124             return error;
125         i++;
126         evo = &ego->group.objects[i];
127     }
128     *index = i - 1;
129     evo = &ego->group.objects[start];
130     blend = (vg_lite_blend_t)evo->attribute.blend;
131     rule = (vg_lite_fill_t)evo->attribute.fill_rule;
132     color = (vg_lite_color_t)evo->attribute.paint.color;
133     memcpy(&mat, &(evo->attribute.transform.matrix), sizeof(mat));
134     filter = VG_LITE_FILTER_POINT;
135     pat_mode = VG_LITE_PATTERN_COLOR;
136     error = vg_lite_draw_pattern(&buff->buffer, &evo->data.path,
137                             rule,
138                             &mat,
139                             buffer,
140                             &mat,
141                             blend,
142                             pat_mode,
143                             color,
144                             filter);
145     vg_lite_finish();
146     vg_lite_free(buffer);
147     free(buffer);
148     return error;
149 }
150 
draw_evo(el_Obj_Buffer * buff,el_Obj_EVO * evo,vg_lite_matrix_t * mat)151 static vg_lite_error_t draw_evo(el_Obj_Buffer *buff, el_Obj_EVO *evo, vg_lite_matrix_t *mat)
152 {
153     el_Obj_EBO *pattern;
154     vg_lite_error_t error = VG_LITE_INVALID_ARGUMENT;
155     vg_lite_color_t color;
156     vg_lite_filter_t filter;
157     vg_lite_matrix_t mat_pattern;
158     ELM_PAINT_TYPE paint_type = evo->attribute.paint.type;
159     vg_lite_blend_t blend = (vg_lite_blend_t)evo->attribute.blend;
160     vg_lite_fill_t rule = (vg_lite_fill_t)evo->attribute.fill_rule;
161     vg_lite_pattern_mode_t pat_mode = pat_to_pad(evo->attribute.paint.pattern.mode);
162 
163     switch (paint_type) {
164     case ELM_PAINT_GRADIENT:
165         memcpy(&evo->attribute.paint.grad->data.grad.matrix,
166                &evo->attribute.paint.grad->data.transform.matrix,
167                sizeof(evo->attribute.paint.grad->data.transform.matrix));
168 #if !DDRLESS
169         error = vg_lite_draw_gradient(&buff->buffer, &evo->data.path,
170                                       rule,
171                                       mat,
172                                       &evo->attribute.paint.grad->data.grad,
173                                       blend);
174 #else
175         error = vg_lite_draw_gradient(NULL, &evo->data.path,
176                                       rule,
177                                       mat,
178                                       &evo->attribute.paint.grad->data.grad,
179                                       blend);
180 #endif
181         break;
182     case ELM_PAINT_RADIAL_GRADIENT:
183         memcpy(&evo->attribute.paint.radgrad->data.rad_grad.matrix,
184                &evo->attribute.paint.radgrad->data.transform.matrix,
185                sizeof(evo->attribute.paint.radgrad->data.transform.matrix));
186 
187         error = vg_lite_draw_radial_gradient(&buff->buffer, &evo->data.path,
188                                       rule,
189                                       mat,
190                                       &evo->attribute.paint.radgrad->data.rad_grad,
191                                       0,
192                                       blend,
193                                       VG_LITE_FILTER_LINEAR);
194         break;
195     case ELM_PAINT_COLOR:
196         color = (vg_lite_color_t)evo->attribute.paint.color;
197 
198 #if !DDRLESS
199         error = vg_lite_draw(&buff->buffer, &evo->data.path,
200                              rule,
201                              mat,
202                              blend,
203                              color);
204 #else
205         error = vg_lite_draw(NULL, &evo->data.path,
206                              rule,
207                              mat,
208                              blend,
209                              color);
210 #endif
211         break;
212     case ELM_PAINT_PATTERN:
213         pattern = (el_Obj_EBO *)(evo->attribute.paint.pattern.pattern);
214         blend = (vg_lite_blend_t)(pattern->attribute.blend);
215         filter = quality_to_filter(evo->attribute.quality);
216         color = (vg_lite_color_t)pattern->attribute.paint.color;
217         memcpy(&mat_pattern, &pattern->attribute.transform.matrix,
218                sizeof(pattern->attribute.transform.matrix));
219 
220 #if !DDRLESS
221         error = vg_lite_draw_pattern(&buff->buffer, &evo->data.path, rule, mat,
222                                      &pattern->data.buffer, &mat_pattern, blend,
223                                      pat_mode, color, filter);
224 #else
225         error = vg_lite_draw_pattern(NULL, &evo->data.path, rule, mat,
226                                      &pattern->data.buffer, &mat_pattern, blend,
227                                      pat_mode, color, filter);
228 #endif
229         break;
230     case ELM_PAINT_TEXT:
231 #if (VG_RENDER_TEXT==1)
232         error = draw_text(buff, evo, mat);
233 #endif /* VG_RENDER_TEXT */
234         break;
235     }
236 
237     return error;
238 }
239 
draw_ebo(el_Obj_Buffer * buff,el_Obj_EBO * ebo,vg_lite_matrix_t * mat)240 static vg_lite_error_t draw_ebo(el_Obj_Buffer *buff, el_Obj_EBO *ebo, vg_lite_matrix_t *mat)
241 {
242     vg_lite_error_t error;
243     vg_lite_buffer_t *image_buffer = &ebo->data.buffer;
244     vg_lite_blend_t   blend = (vg_lite_blend_t)ebo->attribute.blend;
245     vg_lite_color_t   color = ebo->attribute.paint.color;
246     vg_lite_filter_t filter = quality_to_filter(ebo->attribute.quality);
247 
248     if (image_buffer->format >= VG_LITE_INDEX_1 && image_buffer->format <= VG_LITE_INDEX_8)
249     {
250         vg_lite_set_CLUT(ebo->clut_count, ebo->clut);
251     }
252 
253     image_buffer->image_mode = VG_LITE_NORMAL_IMAGE_MODE;
254 #if !DDRLESS
255     error = vg_lite_blit(&buff->buffer, image_buffer, mat, blend, color, filter);
256 #else
257     error = vg_lite_blit(NULL, image_buffer, mat, blend, color, filter);
258 #endif
259     return error;
260 }
261 /*!
262  @abstract Clear a render buffer with specified color and dimension.
263 
264  @discussion
265  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.
266 
267  @param buffer
268  A render buffer handle.
269 
270  @param color
271  Clear color value.
272 
273  @param x
274  x origin of partical clear rectangle.
275 
276  @param y
277  y origin of partial clear rectangle.
278 
279  @param width
280  width of partical clear rectangle.
281 
282  @param height
283  height of partical clear rectangle.
284 
285  @param full
286  Flag to indicate a full buffer clear. If true, the dimension parameters will be ignored.
287 
288  @return bool
289  Indicate the clear operation is set up correctly.
290  */
ElmClear(ElmBuffer buffer,uint32_t color,uint32_t x,uint32_t y,uint32_t width,uint32_t height,BOOL full)291 BOOL ElmClear(ElmBuffer buffer, uint32_t color, uint32_t x, uint32_t y, uint32_t width, uint32_t height, BOOL full)
292 {
293 #if !DDRLESS
294     vg_lite_error_t error = VG_LITE_SUCCESS;
295     el_Obj_Buffer *buff = (el_Obj_Buffer *)get_object(buffer);
296     vg_lite_rectangle_t rectangle;
297     rectangle.x = x;
298     rectangle.y = y;
299     rectangle.width = width;
300     rectangle.height = height;
301 
302     if (full == 1)
303     {
304         error = vg_lite_clear(&buff->buffer, NULL, color);
305     }
306     else
307     {
308         error = vg_lite_clear(&buff->buffer, &rectangle, color);
309     }
310     return ((error == VG_LITE_SUCCESS) ? TRUE : FALSE);
311 #else
312     return TRUE;
313 #endif
314 }
315 
316 /*!
317  @abstract Finish all rendering on GPU issued before this call.
318 
319  @discussion
320  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.
321 
322  @return
323  If the opeartion is successfully done or not.
324  */
ElmFinish()325 BOOL ElmFinish()
326 {
327     vg_lite_finish();
328     return TRUE;
329 }
330 
331 /*!
332  @abstract Flush all rendering command to GPU issued before this call.
333 
334  @discussion
335  This function tells the engine to start kicking off command to GPU side, it will return immediately after firing off GPU.
336 
337  @return
338  If the opeartion is successfully done or not.
339  */
ElmFlush()340 BOOL ElmFlush()
341 {
342     vg_lite_flush();
343     return TRUE;
344 }
345 
346 
347 
348 /*!
349  @abstract Draw a graphics object onto current render target
350 
351  @discussion
352  This is an enssentail function to do the real job, it takes all current setting of the elementary object and
353  render into theb buffer target.
354 
355  @param buffer
356  The render target that an elmentary object will be rendered into.
357 
358  @param obj
359  The elmentary object will be draw into render target.
360 
361  @return bool
362  The draw operation for this elmentary object is sucessful.
363  */
ElmDraw(ElmBuffer buffer,ElmHandle object)364 BOOL ElmDraw(ElmBuffer buffer, ElmHandle object)
365 {
366     BOOL status = TRUE;
367     el_Object *elm;
368     el_Obj_Buffer *buff;
369     vg_lite_error_t error;
370     vg_lite_matrix_t mat;
371     elm = get_object(object);
372 
373     if (!elm)
374     {
375         return FALSE;
376     }
377 
378 #if !DDRLESS
379     buff = (el_Obj_Buffer *)get_object(buffer);
380     if (buff == NULL)
381     {
382         return FALSE;
383     }
384 #else
385     buff = NULL;
386 #endif
387 
388     if (elm->type == ELM_OBJECT_TYPE_EGO)
389     {
390         el_Obj_EVO *evo;
391         el_Obj_Group *ego = (el_Obj_Group *)elm;
392         vg_lite_matrix_t mat_group, res_mat;
393 
394         if (ego->group.count > 0)
395         {
396             int i;
397             memcpy(&mat_group, &(ego->transform.matrix), sizeof(ego->transform.matrix));
398             for (i = 0; i < ego->group.count; i++)
399             {
400                 evo = &ego->group.objects[i];
401 
402                 /* Font objects may generate empty objects */
403                 if (evo->object.handle == ELM_NULL_HANDLE)
404                     continue;
405 
406                 if(evo->is_image)
407                 {
408                     ElmHandle ebo_handle;
409                     el_Object *elm_ebo;
410                     el_Obj_EBO *ebo;
411                     ebo_handle = ElmCreateObjectFromFile(ELM_OBJECT_TYPE_EBO, evo->eboname);
412                     elm_ebo = get_object(ebo_handle);
413                     ebo = (el_Obj_EBO *)elm_ebo;
414                     memcpy(&mat, &evo->defaultAttrib.transform.matrix, sizeof(mat));
415 
416                     error = draw_ebo(buff, ebo, &mat);
417                     if (error)
418                     {
419                         status = FALSE;
420                     }
421                     continue;
422                 }
423                 memcpy(&mat, &(evo->attribute.transform.matrix), sizeof(mat));
424                 memcpy(&res_mat, &mat_group, sizeof(mat_group));
425                 multiply(&res_mat, &mat);
426 
427                 if(evo->has_pattern)
428                     error = draw_evo_pattern(buff,ego,&i);
429                 else
430                     error = draw_evo(buff, evo, &res_mat);
431                 if (error)
432                 {
433                     status = FALSE;
434                     break;
435                 }
436             }
437         }
438     }
439     else if (elm->type == ELM_OBJECT_TYPE_EVO)
440     {
441         el_Obj_EVO *evo = (el_Obj_EVO *)elm;
442         memcpy(&mat, &(evo->attribute.transform.matrix), sizeof(mat));
443 
444         error = draw_evo(buff, evo, &mat);
445         if (error)
446         {
447             status = FALSE;
448         }
449     }
450     else if (elm->type == ELM_OBJECT_TYPE_EBO)
451     {
452         el_Obj_EBO *ebo = (el_Obj_EBO *)elm;
453         memcpy(&mat, &(ebo->attribute.transform.matrix), sizeof(mat));
454 
455         error = draw_ebo(buff, ebo, &mat);
456         if (error)
457         {
458             status = FALSE;
459         }
460 
461     }
462     else if (elm->type == ELM_OBJECT_TYPE_BUF)
463     {
464         el_Obj_Buffer *src = (el_Obj_Buffer *)elm;
465         vg_lite_identity(&mat);
466 
467 #if !DDRLESS
468         if (VG_LITE_SUCCESS !=
469             vg_lite_blit(&buff->buffer, &src->buffer, &mat, VG_LITE_BLEND_NONE, 0,
470                          VG_LITE_FILTER_BI_LINEAR)
471             )
472 #else
473         if (VG_LITE_SUCCESS !=
474             vg_lite_blit(NULL, &src->buffer, &mat, VG_LITE_BLEND_NONE, 0,
475                          VG_LITE_FILTER_BI_LINEAR)
476             )
477 #endif
478         {
479             status = FALSE;
480         }
481     }
482     return status;
483 }
484