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