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 #include "vg_lite.h"
30 #if !DDRLESS
_buffer_format_to_vglite(ELM_BUFFER_FORMAT format)31 static vg_lite_buffer_format_t _buffer_format_to_vglite(ELM_BUFFER_FORMAT format)
32 {
33     vg_lite_buffer_format_t fmt;
34     switch (format) {
35         case ELM_BUFFER_FORMAT_RGBA8888:
36             fmt = VG_LITE_RGBA8888;
37             break;
38 
39         case ELM_BUFFER_FORMAT_RGBX8888:
40             fmt = VG_LITE_RGBX8888;
41             break;
42 
43         case ELM_BUFFER_FORMAT_BGRA8888:
44             fmt = VG_LITE_BGRA8888;
45             break;
46 
47         case ELM_BUFFER_FORMAT_BGRX8888:
48             fmt = VG_LITE_BGRX8888;
49             break;
50 
51         case ELM_BUFFER_FORMAT_RGB565:
52             fmt = VG_LITE_RGB565;
53             break;
54 
55         case ELM_BUFFER_FORMAT_BGR565:
56             fmt = VG_LITE_BGR565;
57             break;
58 
59         case ELM_BUFFER_FORMAT_RGBA4444:
60             fmt = VG_LITE_RGBA4444;
61             break;
62 
63         case ELM_BUFFER_FORMAT_BGRA4444:
64             fmt = VG_LITE_BGRA4444;
65             break;
66 
67         default:
68             fmt = VG_LITE_RGBA8888;
69             break;
70     }
71 
72     return fmt;
73 }
74 #endif
75 /*!
76  @abstract Create internal render buffer.
77 
78  @discussion
79  This functiois is to create an internal render buffer for Elementary rendering, ussually it's not for direct display.
80  The buffer which is displayed on pannel is wrapped up by another API, whose address is managed by display controller side.
81 
82  @param width
83  The buffer's width.
84 
85  @param height
86  The buffer's height.
87 
88  @param format
89  The buffer's format, check enumeration of ELM_BUFFER_FORMAT.
90 
91  @return
92  The buffer handle.
93  */
ElmCreateBuffer(unsigned int width,unsigned int height,ELM_BUFFER_FORMAT format)94 ElmBuffer ElmCreateBuffer(unsigned int width, unsigned int height, ELM_BUFFER_FORMAT format)
95 {
96 #if !DDRLESS
97     el_Obj_Buffer *buffer_obj;
98     vg_lite_buffer_t *buffer;
99     vg_lite_error_t error;
100     ElmHandle handle = ELM_NULL_HANDLE;
101 
102     do {
103         /* Allocate ebo object. */
104         buffer_obj = (el_Obj_Buffer *)calloc(1,sizeof(el_Obj_Buffer));
105         if (buffer_obj != NULL) {
106             buffer_obj->object.type = ELM_OBJECT_TYPE_BUF;
107 
108             /* Allocate the buffer. */
109             buffer = &buffer_obj->buffer;
110             memset(buffer, 0, sizeof(vg_lite_buffer_t));
111             buffer->width  = width;
112             buffer->height = height;
113             buffer->format = (vg_lite_buffer_format_t)format;
114             error = vg_lite_allocate(buffer);
115             if (error)
116                 goto error_exit;
117 
118             JUMP_IF_NON_ZERO_VALUE(add_object((el_Object *)buffer_obj), error_exit);
119             handle = buffer_obj->object.handle;
120         }
121     } while(0);
122 
123     return handle;
124 error_exit:
125     vg_lite_free(buffer);
126     free(buffer_obj);
127     return ELM_NULL_HANDLE;
128 #else
129     return ELM_NULL_HANDLE;
130 #endif
131 }
132 
133 /*!
134  @abstract Wrap a customized buffer.
135 
136  @discussion
137  The application may wrap a user created buffer by giving the information of
138  the buffer including the size, the memory addresses and format. E.g., the
139  application can wrap a system framebuffer thus ELM can directly render onto
140  the screen.
141 
142  @return
143  The buffer handle.
144  */
ElmWrapBuffer(int width,int height,int stride,void * logical,uint32_t physical,ELM_BUFFER_FORMAT format)145 ElmBuffer ElmWrapBuffer(int width, int height, int stride,
146                         void *logical, uint32_t physical,
147                         ELM_BUFFER_FORMAT format)
148 {
149 #if !DDRLESS
150     el_Obj_Buffer *buffer_obj;
151     vg_lite_buffer_t *buffer;
152     ElmHandle handle = ELM_NULL_HANDLE;
153 
154     do {
155         /* open framebuffer. */
156         buffer_obj = (el_Obj_Buffer *)elm_alloc(1, sizeof(el_Obj_Buffer));
157         if (buffer_obj != NULL) {
158             buffer_obj->object.type = ELM_OBJECT_TYPE_BUF;
159             buffer = &buffer_obj->buffer;
160 
161             buffer->width = width;
162             buffer->height = height;
163             buffer->stride = stride;
164             buffer->memory = logical;
165             buffer->handle = NULL;
166             buffer->address = physical;
167             buffer->format = _buffer_format_to_vglite(format);
168             buffer->tiled  = VG_LITE_LINEAR;
169             JUMP_IF_NON_ZERO_VALUE(add_object((el_Object *)buffer_obj), error_exit);
170             handle = buffer_obj->object.handle;
171         }
172     } while(0);
173 
174     return handle;
175 
176 error_exit:
177     free(buffer_obj);
178     return ELM_NULL_HANDLE;
179 #else
180     return ELM_NULL_HANDLE;
181 #endif
182 
183 }
184 
185 /*!
186  @abstract Get buffer address.
187 
188 @discussion
189 The function is to get the address of ElmBuffer.
190 
191 @return
192 The buffer address.
193 */
194 
ElmGetBufferAddress(ElmBuffer buffer)195 uint32_t ElmGetBufferAddress(ElmBuffer buffer)
196 {
197 #if !DDRLESS
198     el_Obj_Buffer *buff_obj;
199     buff_obj = (el_Obj_Buffer *)get_object(buffer);
200 
201     if (buff_obj == NULL)
202     {
203         return 0;
204     }
205     else
206     {
207         return buff_obj->buffer.address;
208     }
209 #else
210     return 0;
211 #endif
212 }
213 
214 /*!
215  @abstract Destroy a render buffer.
216 
217  @discussion
218  This function is to release all internal resource inside Elementary libary belonging to this buffer.
219  Applicatoin need make sure the buffer is not being used by elmentary library any more when calling this function.
220 
221  @param buffer
222  The render buffer handle
223 
224  @return
225  If destroying is completed successfully.
226  */
ElmDestroyBuffer(ElmBuffer buffer)227 BOOL ElmDestroyBuffer(ElmBuffer buffer)
228 {
229 #if !DDRLESS
230     /* Find the object. */
231     el_Obj_Buffer *buff = (el_Obj_Buffer *)get_object(buffer);
232 
233     /* If found, delete the vg_lite_buffer object. Otherwise, return FALSE. */
234     if (buff != NULL) {
235         if (buff->buffer.handle != NULL) {
236             /* Free the buffer memory. */
237             vg_lite_free(&buff->buffer);
238         }
239 
240         remove_object((el_Object*)buff);
241         elm_free(buff);
242 
243         return TRUE;
244     }
245     else {
246         return FALSE;
247     }
248 #else
249     return TRUE;
250 #endif
251 }
252 
ElmSaveBuffer(ElmBuffer buffer,const char * name)253 BOOL ElmSaveBuffer(ElmBuffer buffer, const char *name)
254 {
255 #if !DDRLESS
256     el_Obj_Buffer *buff = (el_Obj_Buffer *)get_object(buffer);
257 
258     /* If found, delete the vg_lite_buffer object. Otherwise, return FALSE. */
259     if (buff != NULL) {
260 #if !RTOS
261         /*
262             "vg_lite_save_png" function does not exist (anymore). Probably a left
263             over from an older driver.
264         */
265             if (buff->buffer.memory != NULL) {
266                 vg_lite_save_png(name, &buff->buffer);
267             }
268 #endif
269         return TRUE;
270     }
271     else {
272         return FALSE;
273     }
274 #else
275     return TRUE;
276 #endif
277 }
278 
279  /*!
280  @abstract Convert vglite format to elm format.
281  */
_buffer_format_to_Elm(vg_lite_buffer_format_t format)282 ELM_BUFFER_FORMAT _buffer_format_to_Elm(vg_lite_buffer_format_t format)
283 {
284     switch (format)
285     {
286         case VG_LITE_RGB565:
287             return ELM_BUFFER_FORMAT_RGB565;
288             break;
289         case VG_LITE_BGR565:
290             return ELM_BUFFER_FORMAT_BGR565;
291             break;
292         default:
293             return ELM_BUFFER_FORMAT_RGBA8888;
294             break;
295     }
296 }
297 
298  /*!
299  @abstract Get handle of the framebuffer.
300  */
ElmGetBuffer(vg_lite_buffer_t * buffer)301 ElmBuffer ElmGetBuffer(vg_lite_buffer_t *buffer)
302 {
303     elm_tls_t* elm_tls;
304 
305     elm_tls = (elm_tls_t *) elm_os_get_tls();
306     if (elm_tls == NULL)
307         return ELM_NULL_HANDLE;
308 
309     for (int i = 0; i < APP_BUFFER_COUNT; i++) {
310         if (elm_tls->gContext.elmFB[i].buffer == NULL) {
311             elm_tls->gContext.elmFB[i].buffer = buffer;
312             elm_tls->gContext.elmFB[i].handle = ElmWrapBuffer(buffer->width, buffer->height, buffer->stride, buffer->memory,
313                                                 buffer->address, _buffer_format_to_Elm(buffer->format));
314             vg_lite_clear(buffer, NULL, 0x0);
315             return elm_tls->gContext.elmFB[i].handle;
316         }
317         if (elm_tls->gContext.elmFB[i].buffer == buffer)
318             return elm_tls->gContext.elmFB[i].handle;
319     }
320     return 0;
321 }
322