|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2008-2010 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (developer.feedback@nokia.com) |
|
6 ** |
|
7 ** This file is part of the HbServers module of the UI Extensions for Mobile. |
|
8 ** |
|
9 ** GNU Lesser General Public License Usage |
|
10 ** This file may be used under the terms of the GNU Lesser General Public |
|
11 ** License version 2.1 as published by the Free Software Foundation and |
|
12 ** appearing in the file LICENSE.LGPL included in the packaging of this file. |
|
13 ** Please review the following information to ensure the GNU Lesser General |
|
14 ** Public License version 2.1 requirements will be met: |
|
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
16 ** |
|
17 ** In addition, as a special exception, Nokia gives you certain additional |
|
18 ** rights. These rights are described in the Nokia Qt LGPL Exception |
|
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
20 ** |
|
21 ** If you have questions regarding the use of this file, please contact |
|
22 ** Nokia at developer.feedback@nokia.com. |
|
23 ** |
|
24 ****************************************************************************/ |
|
25 |
|
26 #include "hbsgimagerenderer_p.h" |
|
27 #include <QDebug> |
|
28 QHash<unsigned long long, RSgImage*> HbSgImageRenderer::sgImageHash; |
|
29 |
|
30 Q_GLOBAL_STATIC(HbSgImageRenderer, instance) |
|
31 |
|
32 HbSgImageRenderer* HbSgImageRenderer::global() |
|
33 { |
|
34 return instance(); |
|
35 } |
|
36 |
|
37 HbSgImageRenderer::HbSgImageRenderer() : |
|
38 display(EGL_NO_DISPLAY), |
|
39 currentSurface(EGL_NO_SURFACE), |
|
40 eglContext(EGL_NO_CONTEXT), |
|
41 eglConfig(0), |
|
42 init(false) |
|
43 { |
|
44 #ifdef HB_ICON_CACHE_DEBUG |
|
45 eglQueryProfilingData = 0; |
|
46 #endif |
|
47 } |
|
48 |
|
49 HbSgImageRenderer::~ HbSgImageRenderer() |
|
50 { |
|
51 terminate(); |
|
52 #ifdef HB_ICON_CACHE_DEBUG |
|
53 if (prof_data) { |
|
54 free(prof_data); |
|
55 } |
|
56 #endif |
|
57 } |
|
58 |
|
59 bool HbSgImageRenderer::initialize() |
|
60 { |
|
61 if (!init) { |
|
62 display = eglGetDisplay(EGL_DEFAULT_DISPLAY); |
|
63 if (display == EGL_NO_DISPLAY) { |
|
64 return false; |
|
65 } |
|
66 |
|
67 if (eglInitialize(display, 0, 0) == EGL_FALSE) { |
|
68 return false; |
|
69 } |
|
70 |
|
71 eglBindAPI(EGL_OPENVG_API); |
|
72 |
|
73 TInt error = sgDriver.Open(); |
|
74 if (error != KErrNone) { |
|
75 return false; |
|
76 } |
|
77 } |
|
78 |
|
79 init = true; |
|
80 return true; |
|
81 } |
|
82 |
|
83 void HbSgImageRenderer::terminate() |
|
84 { |
|
85 if (init) { |
|
86 if (eglContext != EGL_NO_CONTEXT) { |
|
87 eglDestroyContext(display, eglContext); |
|
88 eglContext = EGL_NO_CONTEXT; |
|
89 } |
|
90 |
|
91 sgDriver.Close(); |
|
92 |
|
93 eglTerminate(display); |
|
94 display = EGL_NO_DISPLAY; |
|
95 |
|
96 init = false; |
|
97 } |
|
98 } |
|
99 |
|
100 bool HbSgImageRenderer::createContext(RSgImage * sgImage) |
|
101 { |
|
102 if (!init && !initialize()) { |
|
103 return false; |
|
104 } |
|
105 |
|
106 const EGLint KConfigAttributes[] = { |
|
107 EGL_MATCH_NATIVE_PIXMAP, (EGLint)sgImage, |
|
108 EGL_RENDERABLE_TYPE, EGL_OPENVG_BIT, |
|
109 EGL_SURFACE_TYPE, EGL_PIXMAP_BIT | EGL_VG_ALPHA_FORMAT_PRE_BIT, |
|
110 EGL_NONE |
|
111 }; |
|
112 |
|
113 EGLint numConfigs = 0; |
|
114 if (eglChooseConfig(display, KConfigAttributes, &eglConfig, 1, &numConfigs) == EGL_FALSE) { |
|
115 return false; |
|
116 } |
|
117 |
|
118 eglContext = eglCreateContext(display, eglConfig, EGL_NO_CONTEXT, 0); |
|
119 |
|
120 return true; |
|
121 } |
|
122 |
|
123 bool HbSgImageRenderer::beginRendering(RSgImage * sgImage) |
|
124 { |
|
125 if (eglContext == EGL_NO_CONTEXT && !createContext(sgImage)) { |
|
126 return false; |
|
127 } |
|
128 |
|
129 const EGLint KPixmapAttributes[] = { |
|
130 EGL_VG_ALPHA_FORMAT, EGL_VG_ALPHA_FORMAT_PRE, |
|
131 EGL_NONE |
|
132 }; |
|
133 |
|
134 currentSurface = eglCreatePixmapSurface(display, eglConfig, sgImage, KPixmapAttributes); |
|
135 if (currentSurface == EGL_NO_SURFACE) { |
|
136 return false; |
|
137 } |
|
138 |
|
139 if (eglMakeCurrent(display, currentSurface, currentSurface, eglContext) == EGL_FALSE) { |
|
140 eglDestroySurface(display, currentSurface); |
|
141 currentSurface = EGL_NO_SURFACE; |
|
142 return false; |
|
143 } |
|
144 |
|
145 return true; |
|
146 } |
|
147 |
|
148 void HbSgImageRenderer::endRendering() |
|
149 { |
|
150 if (currentSurface != EGL_NO_SURFACE) { |
|
151 eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); |
|
152 eglDestroySurface(display, currentSurface); |
|
153 currentSurface = EGL_NO_SURFACE; |
|
154 } |
|
155 } |
|
156 |
|
157 void HbSgImageRenderer::addSgImageToHash(unsigned long long id, RSgImage* sgImage) |
|
158 { |
|
159 sgImageHash.insert(id, sgImage); |
|
160 } |
|
161 |
|
162 void HbSgImageRenderer::removeSgImageFromHash(unsigned long long id) |
|
163 { |
|
164 if (sgImageHash.contains(id)) { |
|
165 RSgImage* sgImage = sgImageHash.value(id); |
|
166 #ifdef HB_ICON_CACHE_DEBUG |
|
167 qDebug() << "Closing handle and removing sgImage with id = " << id; |
|
168 #endif |
|
169 sgImage->Close(); |
|
170 delete sgImage; |
|
171 sgImageHash.remove(id); |
|
172 } |
|
173 } |
|
174 |
|
175 #ifdef HB_ICON_CACHE_DEBUG |
|
176 unsigned long HbSgImageRenderer::totalGPUMemory() |
|
177 { |
|
178 qDebug() <<"Inside HbSgImageRenderer::totalGPUMemory() " ; |
|
179 EGLint data_count; |
|
180 |
|
181 EGLint* prof_data = getProfileData(data_count); |
|
182 if (!prof_data) { |
|
183 qDebug() <<"Inside HbSgImageRenderer::totalGPUMemory() :: prof_data is NULL!" ; |
|
184 return 0; |
|
185 } |
|
186 |
|
187 unsigned long totalMemory = 0; |
|
188 EGLint i = 0; |
|
189 |
|
190 while (i < data_count) { |
|
191 switch (prof_data[i++]) { |
|
192 case EGL_PROF_TOTAL_MEMORY_NOK: { |
|
193 totalMemory = prof_data[i++]; |
|
194 break; |
|
195 } |
|
196 |
|
197 case EGL_PROF_PROCESS_ID_NOK: { |
|
198 i+=2; |
|
199 break; |
|
200 } |
|
201 |
|
202 case EGL_PROF_USED_MEMORY_NOK: |
|
203 case EGL_PROF_PROCESS_USED_PRIVATE_MEMORY_NOK: |
|
204 case EGL_PROF_PROCESS_USED_SHARED_MEMORY_NOK: |
|
205 default: { |
|
206 i++; |
|
207 break; |
|
208 } |
|
209 } |
|
210 } |
|
211 |
|
212 free(prof_data); |
|
213 qDebug() <<"total GPU memory = " << totalMemory; |
|
214 qDebug() <<"Exiting HbSgImageRenderer::totalGPUMemory() " ; |
|
215 return totalMemory; |
|
216 } |
|
217 |
|
218 |
|
219 unsigned long HbSgImageRenderer::freeGPUMemory() |
|
220 { |
|
221 qDebug() <<"Inside HbSgImageRenderer::freeGPUMemory() " ; |
|
222 EGLint data_count; |
|
223 |
|
224 EGLint* prof_data = getProfileData(data_count); |
|
225 if (!prof_data) { |
|
226 qDebug() <<"Inside HbSgImageRenderer::freeGPUMemory() :: prof_data is NULL!" ; |
|
227 return 0; |
|
228 } |
|
229 |
|
230 unsigned long totalMemory = 0; |
|
231 unsigned long usedMemory = 0; |
|
232 |
|
233 EGLint i = 0; |
|
234 while (i < data_count) { |
|
235 switch (prof_data[i++]) { |
|
236 case EGL_PROF_TOTAL_MEMORY_NOK: { |
|
237 totalMemory = prof_data[i++]; |
|
238 break; |
|
239 } |
|
240 |
|
241 case EGL_PROF_USED_MEMORY_NOK: { |
|
242 usedMemory = prof_data[i++]; |
|
243 break; |
|
244 } |
|
245 |
|
246 case EGL_PROF_PROCESS_ID_NOK: { |
|
247 i += 2; |
|
248 break; |
|
249 } |
|
250 |
|
251 case EGL_PROF_PROCESS_USED_PRIVATE_MEMORY_NOK: |
|
252 case EGL_PROF_PROCESS_USED_SHARED_MEMORY_NOK: |
|
253 default: { |
|
254 i++; |
|
255 break; |
|
256 } |
|
257 } |
|
258 } |
|
259 |
|
260 free(prof_data); |
|
261 qDebug() << "free GPU memory = " << totalMemory - usedMemory; |
|
262 qDebug() << "Exiting HbSgImageRenderer::freeGPUMemory() " ; |
|
263 return (totalMemory - usedMemory); |
|
264 } |
|
265 |
|
266 EGLint* HbSgImageRenderer::getProfileData(EGLint & data_count) |
|
267 { |
|
268 EGLint* prof_data = 0; |
|
269 data_count = 0; |
|
270 if (!init && !initialize()) { |
|
271 return 0; |
|
272 } |
|
273 if (!eglQueryProfilingData) { |
|
274 eglQueryProfilingData = (NOK_resource_profiling)eglGetProcAddress("eglQueryProfilingDataNOK"); |
|
275 if (!eglQueryProfilingData) { |
|
276 return 0; |
|
277 } |
|
278 } |
|
279 EGLBoolean success = EGL_TRUE; |
|
280 // Find out how much profiling data is available |
|
281 success = eglQueryProfilingData(display, |
|
282 EGL_PROF_QUERY_GLOBAL_BIT_NOK | |
|
283 EGL_PROF_QUERY_MEMORY_USAGE_BIT_NOK, |
|
284 0, |
|
285 0, |
|
286 &data_count); |
|
287 |
|
288 if (!success) { |
|
289 return 0; |
|
290 } |
|
291 // Allocate room for the profiling data |
|
292 prof_data = (EGLint*)malloc(data_count * sizeof(EGLint)); |
|
293 if (!prof_data) { |
|
294 data_count = 0; |
|
295 return 0; |
|
296 } |
|
297 // Retrieve the profiling data |
|
298 success = eglQueryProfilingData(display, |
|
299 EGL_PROF_QUERY_GLOBAL_BIT_NOK | |
|
300 EGL_PROF_QUERY_MEMORY_USAGE_BIT_NOK, |
|
301 prof_data, |
|
302 data_count, |
|
303 &data_count); |
|
304 if (!success) { |
|
305 data_count = 0; |
|
306 free(prof_data); |
|
307 return 0; |
|
308 } |
|
309 |
|
310 return prof_data; |
|
311 } |
|
312 #endif //HB_ICON_CACHE_DEBUG |