Fix various build warnings
[platform/framework/web/web-provider.git] / src / Core / Buffer / RenderBuffer.cpp
1 /*
2  * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *    Licensed under the Flora License, Version 1.1 (the "License");
5  *    you may not use this file except in compliance with the License.
6  *    You may obtain a copy of the License at
7  *
8  *        http://floralicense.org/license/
9  *
10  *    Unless required by applicable law or agreed to in writing, software
11  *    distributed under the License is distributed on an "AS IS" BASIS,
12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *    See the License for the specific language governing permissions and
14  *    limitations under the License.
15  */
16 /**
17  * @file    RenderBuffer.cpp
18  * @author  Yunchan Cho (yunchan.cho@samsung.com)
19  */
20 #include <string>
21 #include <Evas.h>
22 #include <Ecore.h>
23 #include <Ecore_Evas.h>
24 #include <provider.h>
25 #include <provider_buffer.h>
26 #include <Core/Util/Log.h>
27 #include <Core/Util/Util.h>
28 #include "IRenderBuffer.h"
29 #include "RenderBuffer.h"
30
31 RenderBuffer::RenderBuffer()
32     : m_bufferAddr(NULL)
33     , m_bufferInfo(NULL)
34 {
35     LogD("enter");
36 }
37
38 RenderBuffer::~RenderBuffer()
39 {
40     LogD("enter");
41 }
42
43 bool RenderBuffer::allocate()
44 {
45     LogD("enter");
46     if (m_bufferAddr) {
47         free();
48         m_bufferAddr = NULL;
49     }
50
51     Ecore_Evas* ee =
52         ecore_evas_buffer_allocfunc_new(
53                 getWidth(), getHeight(),
54                 allocateCallback, freeCallback,
55                 this);
56     LogD("Using %s engine!", ecore_evas_engine_name_get(ee));
57
58     if (!ee) {
59         LogD("invalid ecore evas object");
60         return false;
61     }
62
63     LogD("evas ecore setting");
64
65     // alpha_set function access the canvas buffer directly,
66     //  without pre/post render callback.
67     provider_buffer_pre_render(m_bufferInfo);
68     ecore_evas_alpha_set(ee, EINA_TRUE);
69     provider_buffer_post_render(m_bufferInfo);
70     ecore_evas_manual_render_set(ee, EINA_FALSE);
71
72     // resize function will invoke the freeCallback and allocateCallback again. (internally)
73     ecore_evas_resize(ee, getWidth(), getHeight());
74     ecore_evas_show(ee);
75     ecore_evas_activate(ee);
76
77     LogD("Using %s engine!", ecore_evas_engine_name_get(ee));
78
79     Evas* e = ecore_evas_get(ee);
80     evas_image_cache_flush(e);
81     Evas_Object *eo = evas_object_rectangle_add(e);
82     evas_object_size_hint_weight_set(eo, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
83     evas_object_color_set(eo, 0, 0, 0, 1);
84     evas_object_resize(eo, getWidth(), getHeight());
85
86     m_canvas = e;
87     m_win = eo;
88
89     startCanvasUpdate();
90     return true;
91 }
92
93 bool RenderBuffer::reallocate(int width, int height)
94 {
95     LogD("enter");
96     stopCanvasUpdate();
97
98     // TODO This function should be implemented due to box resize operation
99     setWidth(width);
100     setHeight(height);
101
102     Ecore_Evas* ee = ecore_evas_ecore_evas_get(m_canvas);
103     // resize function will invoke the freeCallback and allocateCallback again. (internally)
104     ecore_evas_resize(ee, getWidth(), getHeight());
105     evas_object_resize(m_win, getWidth(), getHeight());
106     startCanvasUpdate();
107     return true;
108 }
109
110 bool RenderBuffer::free()
111 {
112     if (!m_canvas) {
113         return false;
114     }
115
116     stopCanvasUpdate();
117     ecore_evas_free(ecore_evas_ecore_evas_get(m_canvas));
118     m_canvas = NULL;
119     m_win = NULL;
120
121     return true;
122 }
123
124 void RenderBuffer::startCanvasUpdate()
125 {
126     LogD("enter");
127     evas_event_callback_del(
128             m_canvas,
129             EVAS_CALLBACK_RENDER_PRE,
130             preRenderCallback);
131
132     evas_event_callback_del(
133             m_canvas,
134             EVAS_CALLBACK_RENDER_POST,
135             postRenderCallback);
136
137     evas_event_callback_add(
138             m_canvas,
139             EVAS_CALLBACK_RENDER_PRE,
140             preRenderCallback, this);
141
142     evas_event_callback_add(
143             m_canvas,
144             EVAS_CALLBACK_RENDER_POST,
145             postRenderCallback, this);
146
147 }
148
149 void RenderBuffer::stopCanvasUpdate()
150 {
151     LogD("enter");
152     evas_event_callback_del(
153             m_canvas,
154             EVAS_CALLBACK_RENDER_PRE,
155             preRenderCallback);
156
157     evas_event_callback_del(
158             m_canvas,
159             EVAS_CALLBACK_RENDER_POST,
160             postRenderCallback);
161 }
162
163 Evas_Object* RenderBuffer::getWindow()
164 {
165     return m_win;
166 }
167
168 void RenderBuffer::preRenderCallback(void* data, Evas* canvas, void *eventInfo)
169 {
170     LogD("enter");
171     UNUSED_PARAM(eventInfo);
172
173     RenderBuffer *buffer = static_cast<RenderBuffer*>(data);
174     if (!provider_buffer_pixmap_is_support_hw(buffer->m_bufferInfo)) {
175         LogD("not hw backend");
176         return;
177     }
178
179     provider_buffer_pre_render(buffer->m_bufferInfo);
180     evas_damage_rectangle_add(canvas, 0, 0, buffer->getWidth(), buffer->getHeight());
181 }
182
183 void RenderBuffer::postRenderCallback(void* data, Evas* canvas, void* eventInfo)
184 {
185     LogD("enter");
186
187     UNUSED_PARAM(canvas);
188     UNUSED_PARAM(eventInfo);
189
190     RenderBuffer* buffer = static_cast<RenderBuffer*>(data);
191
192     evas_data_argb_unpremul(static_cast<unsigned int*>(buffer->m_bufferAddr), buffer->getWidth() * buffer->getHeight());
193 #ifdef RENDER_BUFFER_VERIFY_SHOT
194     {
195         FILE *fp;
196         static int idx = 0;
197         char filename[256];
198         snprintf(filename, sizeof(filename) - 1, "/tmp/render%d-%dx%d.raw", idx++, buffer->getWidth(), buffer->getHeight());
199         fp = fopen(filename, "w+");
200         if (fp) {
201             LogD("RenderShot: %s(%d)\n", filename, buffer->getWidth() * buffer->getHeight() * sizeof(int));
202             fwrite(buffer->m_bufferAddr, buffer->getWidth() * buffer->getHeight() * sizeof(int), 1, fp);
203             fclose(fp);
204         } else {
205             LogD("Failed to open a file: %s", filename);
206         }
207     }
208 #endif
209     LogD("/tmp/render-%dx%d.raw", buffer->getWidth(), buffer->getHeight());
210
211     if (!provider_buffer_pixmap_is_support_hw(buffer->m_bufferInfo)) {
212         provider_buffer_sync(buffer->m_bufferInfo);
213         buffer->updateBuffer();
214     } else {
215         provider_buffer_post_render(buffer->m_bufferInfo);
216         buffer->updateBuffer();
217     }
218 }
219
220 void RenderBuffer::paintColor(unsigned int color)
221 {
222     LogD("enter");
223
224     if (!provider_buffer_pixmap_is_support_hw(m_bufferInfo)) {
225         memset(m_bufferAddr, color, getWidth() * getHeight() * 4);
226         provider_buffer_sync(m_bufferInfo);
227         updateBuffer();
228     } else {
229         preRenderCallback(this, m_canvas, NULL);
230         memset(m_bufferAddr, color, getWidth() * getHeight() * 4);
231         postRenderCallback(this, m_canvas, NULL);
232     }
233 }
234
235 Evas* RenderBuffer::getCanvas()
236 {
237     return m_canvas;
238 }
239
240 void* RenderBuffer::allocateCallback(void* data, int size)
241 {
242     LogD("enter");
243     UNUSED_PARAM(size);
244
245     RenderBuffer* buffer = static_cast<RenderBuffer*>(data);
246
247     if (buffer->m_bufferInfo) {
248         freeCallback(data, NULL);
249     }
250
251     buffer->m_bufferInfo = buffer->acquireBuffer();
252     if (!buffer->m_bufferInfo) {
253         return NULL;
254     }
255
256     // set buffer address
257     if (!provider_buffer_pixmap_is_support_hw(buffer->m_bufferInfo)) {
258         LogD("s/w evas backend");
259         buffer->m_bufferAddr = provider_buffer_ref(buffer->m_bufferInfo);
260     } else {
261         LogD("h/w evas backend");
262         int ret = provider_buffer_pixmap_create_hw(buffer->m_bufferInfo);
263         if (ret < 0) {
264             LogD("can't create hw pixmap");
265         }
266         buffer->m_bufferAddr = provider_buffer_pixmap_hw_addr(buffer->m_bufferInfo);
267     }
268
269     LogD("success to allocate buffer");
270     return buffer->m_bufferAddr;
271 }
272
273 void RenderBuffer::freeCallback(void* data, void *pix)
274 {
275     LogD("enter");
276     UNUSED_PARAM(pix);
277
278     RenderBuffer* buffer = static_cast<RenderBuffer*>(data);
279
280     // destroy buffer
281     if (!provider_buffer_pixmap_is_support_hw(buffer->m_bufferInfo)) {
282         provider_buffer_unref(buffer->m_bufferAddr);
283     } else {
284         provider_buffer_pixmap_destroy_hw(buffer->m_bufferInfo);
285     }
286
287     provider_buffer_release(buffer->m_bufferInfo);
288
289     buffer->m_bufferInfo = NULL;
290     buffer->m_bufferAddr = NULL;
291
292     LogD("success to free buffer");
293     return;
294 }
295
296 Evas_Object *RenderBuffer::getSnapshot(void)
297 {
298     LogD("enter");
299     Evas_Object *snapshot;
300     void *tmpBuffer;
301
302     snapshot = evas_object_image_add(m_canvas);
303     if (!snapshot)
304         return NULL;
305     evas_object_image_data_set(snapshot, NULL);
306     evas_object_image_colorspace_set(snapshot, EVAS_COLORSPACE_ARGB8888);
307     evas_object_image_alpha_set(snapshot, EINA_TRUE);
308     evas_object_image_size_set(snapshot, getWidth(), getHeight());
309
310     tmpBuffer = malloc(getWidth() * getHeight() * sizeof(int));
311     if (tmpBuffer) {
312         memcpy(tmpBuffer, m_bufferAddr, getWidth() * getHeight() * sizeof(int));
313         evas_data_argb_premul(
314                 static_cast<unsigned int*>(tmpBuffer),
315                 getWidth() * getHeight());
316         evas_object_image_data_set(snapshot, tmpBuffer);
317     } else {
318         LogD("Failed to allocate heap");
319     }
320
321     evas_object_image_data_update_add(snapshot, 0, 0, getWidth(), getHeight());
322     evas_object_image_fill_set(snapshot, 0, 0, getWidth(), getHeight());
323     evas_object_resize(snapshot, getWidth(), getHeight());
324
325     return snapshot;
326 }