|
1 /* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). |
|
2 * |
|
3 * Permission is hereby granted, free of charge, to any person obtaining a |
|
4 * copy of this software and /or associated documentation files |
|
5 * (the "Materials "), to deal in the Materials without restriction, |
|
6 * including without limitation the rights to use, copy, modify, merge, |
|
7 * publish, distribute, sublicense, and/or sell copies of the Materials, |
|
8 * and to permit persons to whom the Materials are furnished to do so, |
|
9 * subject to the following conditions: |
|
10 * |
|
11 * The above copyright notice and this permission notice shall be included |
|
12 * in all copies or substantial portions of the Materials. |
|
13 * |
|
14 * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
|
15 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
|
16 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
|
17 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, |
|
18 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR |
|
19 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR |
|
20 * THE USE OR OTHER DEALINGS IN THE MATERIALS. |
|
21 * |
|
22 * Initial Contributors: |
|
23 * Nokia Corporation - initial contribution. |
|
24 * |
|
25 * Contributors: |
|
26 * |
|
27 * Description: |
|
28 * |
|
29 */ |
|
30 |
|
31 #include "EGLExtension.h" |
|
32 #include "EGLState.h" |
|
33 #include "EGLImage.h" |
|
34 #include "EGLContext.h" |
|
35 #include "EGLDisplay.h" |
|
36 #include "eglInternal.h" |
|
37 #include "EGLProcess.h" |
|
38 #include "EGLThread.h" |
|
39 #include "EGLOs.h" |
|
40 #include "ImageTarget.h" |
|
41 |
|
42 #include <string.h> |
|
43 |
|
44 typedef struct |
|
45 { |
|
46 const char* extnName; // procedure or extension name |
|
47 ProcPointer procAddr; // address |
|
48 } TExtnInfo; |
|
49 |
|
50 static const TExtnInfo eglProcedures[] = |
|
51 { // list of EGL extension name strings, followed by any EGLI_NEW function names |
|
52 {"eglCreateImageKHR", (ProcPointer)eglCreateImageKHR}, |
|
53 {"eglDestroyImageKHR", (ProcPointer)eglDestroyImageKHR} |
|
54 }; |
|
55 |
|
56 const EGLint KEglProcCount = sizeof(eglProcedures) / sizeof(TExtnInfo); |
|
57 |
|
58 CEGLExtension::CEGLExtension() |
|
59 { |
|
60 } |
|
61 |
|
62 CEGLExtension::~CEGLExtension(void) |
|
63 { |
|
64 } |
|
65 |
|
66 ProcPointer CEGLExtension::eglGetProcAddress(const char* aProcname) |
|
67 { |
|
68 EGLint nameLength = strlen(aProcname); |
|
69 if ((nameLength > 3) && !strncmp(aProcname, "egl", 3)) |
|
70 { // EGL extensions - exhaustive search |
|
71 for (EGLint idx = 0; idx < KEglProcCount; idx++) |
|
72 { |
|
73 if ( strcmp( aProcname, eglProcedures[idx].extnName ) == 0 ) |
|
74 return eglProcedures[idx].procAddr; |
|
75 } |
|
76 } |
|
77 return NULL; |
|
78 } |
|
79 |
|
80 static EImageTarget mapImageTarget( EGLenum target ) |
|
81 { |
|
82 switch(target) |
|
83 { |
|
84 case EGL_GL_TEXTURE_2D_KHR: |
|
85 return IMAGE_TARGET_TEXTURE_2D; |
|
86 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR: |
|
87 return IMAGE_TARGET_TEXTURE_CUBE_MAP_POSITIVE_X; |
|
88 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR: |
|
89 return IMAGE_TARGET_TEXTURE_CUBE_MAP_NEGATIVE_X; |
|
90 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR: |
|
91 return IMAGE_TARGET_TEXTURE_CUBE_MAP_POSITIVE_Y; |
|
92 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR: |
|
93 return IMAGE_TARGET_TEXTURE_CUBE_MAP_NEGATIVE_Y; |
|
94 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR: |
|
95 return IMAGE_TARGET_TEXTURE_CUBE_MAP_POSITIVE_Z; |
|
96 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR: |
|
97 return IMAGE_TARGET_TEXTURE_CUBE_MAP_NEGATIVE_Z; |
|
98 case EGL_GL_RENDERBUFFER_KHR: |
|
99 return IMAGE_TARGET_RENDERBUFFER; |
|
100 default: |
|
101 EGLI_ASSERT(false); |
|
102 } |
|
103 |
|
104 // Not reached. |
|
105 return (EImageTarget)-1; |
|
106 } |
|
107 |
|
108 EGLAPI EGLImageKHR EGLAPIENTRY eglCreateImageKHR( EGLDisplay dpy, |
|
109 EGLContext ctx, |
|
110 EGLenum target, |
|
111 EGLClientBuffer buffer, |
|
112 const EGLint *attrib_list ) |
|
113 { |
|
114 EGLI_ENTER_RET( EGL_NO_IMAGE_KHR ); |
|
115 |
|
116 CEGLImage *image = NULL; |
|
117 CEGLDisplay *display = NULL; |
|
118 CEGLContext *context = NULL; |
|
119 |
|
120 display = state->GetDisplay( dpy ); |
|
121 // Check display |
|
122 //<dpy> must be a valid EGLDisplay |
|
123 if( !display ) |
|
124 { |
|
125 EGLI_LEAVE_RET( EGL_NO_IMAGE_KHR, EGL_BAD_DISPLAY ); |
|
126 } |
|
127 |
|
128 context = display->GetContext( ctx ); |
|
129 // Check context |
|
130 //<ctx> must be a valid OpenVG API context on that display |
|
131 if( !context ) |
|
132 { |
|
133 EGLI_LEAVE_RET( EGL_NO_IMAGE_KHR, EGL_BAD_CONTEXT ); |
|
134 } |
|
135 |
|
136 // Display and context ok, continue... |
|
137 switch( target ) |
|
138 { |
|
139 case EGL_NATIVE_PIXMAP_KHR: |
|
140 { |
|
141 // Not supported |
|
142 // 1) set error code to EGL_BAD_PARAMETER |
|
143 // 2) release lock |
|
144 // 3) return no image |
|
145 EGLI_LEAVE_RET( EGL_NO_IMAGE_KHR, EGL_BAD_PARAMETER ); |
|
146 break; |
|
147 } |
|
148 case EGL_VG_PARENT_IMAGE_KHR: |
|
149 { |
|
150 // Context must be client context and api must be openVG |
|
151 if( context->ClientContext() && EGL_OPENVG_API == context->ClientApi() ) |
|
152 { |
|
153 EGLI_LEAVE_RET( EGL_NO_IMAGE_KHR, EGL_BAD_CONTEXT ); |
|
154 } |
|
155 |
|
156 //<buffer> |
|
157 //must be a handle of a VGImage object valid in the specified context, cast |
|
158 //into the type EGLClientBuffer |
|
159 //Furthermore, the specified VGImage |
|
160 //<buffer> must not be a child image |
|
161 if ( !state->VGInterface()->IsRootImage( buffer ) ) |
|
162 { |
|
163 EGLI_LEAVE_RET( EGL_NO_IMAGE_KHR, EGL_BAD_ACCESS ); |
|
164 } |
|
165 |
|
166 // TODO: |
|
167 /* |
|
168 1) We also need to check that VGImage is not bound |
|
169 to a Pbuffer surface |
|
170 |
|
171 2) VGimage has not been already used to create EGLImage. |
|
172 |
|
173 3) VGImage itself is not created from EGLImage. |
|
174 */ |
|
175 //state->VGInterface()- |
|
176 // 1) |
|
177 if( EGL_PBUFFER_BIT == context->Config()->GetAttribute( EGL_SURFACE_TYPE ) ) |
|
178 { |
|
179 // If VGImage is bound to a Pbuffer no EGLImage |
|
180 EGLI_LEAVE_RET( EGL_NO_IMAGE_KHR, EGL_BAD_ACCESS ); |
|
181 } |
|
182 |
|
183 // Descriptor for pixeldata data values |
|
184 SurfaceDescriptor desc; |
|
185 // data is actual pixeldata |
|
186 void* data = NULL; |
|
187 |
|
188 //Any values |
|
189 //specified in <attr_list> are ignored. |
|
190 |
|
191 // GetImageData will allocate memory for data |
|
192 // data must be deleted in CEGLImage destructor |
|
193 state->VGInterface()->GetImageData( buffer, desc, data ); |
|
194 if ( !data ) |
|
195 { |
|
196 EGLI_LEAVE_RET( EGL_NO_IMAGE_KHR, EGL_BAD_ACCESS ); |
|
197 } |
|
198 |
|
199 // Create CEGLImage. |
|
200 image = EGLI_NEW CEGLImage( target, buffer, desc, data ); |
|
201 |
|
202 // If EGLImage creation fail then return error code. |
|
203 if( !image ) |
|
204 { |
|
205 EGLI_LEAVE_RET( EGL_NO_IMAGE_KHR, EGL_BAD_ALLOC ); |
|
206 } |
|
207 // Add refcount to VGImage |
|
208 state->VGInterface()->AddRef( buffer ); |
|
209 // Add image in array |
|
210 image = display->AddEGLImage( image ); |
|
211 break; |
|
212 } |
|
213 |
|
214 case EGL_GL_TEXTURE_2D_KHR: |
|
215 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR: |
|
216 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR: |
|
217 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR: |
|
218 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR: |
|
219 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR: |
|
220 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR: |
|
221 { |
|
222 // From RFP document |
|
223 // EGL_KHR_gl_image (not required for OpenGL ES 1.1) [R12] |
|
224 /*<ctx> must be a valid OpenGL ES API context on that display.*/ |
|
225 if( context->ClientContext() && (EGL_OPENGL_ES_API != context->ClientApi() || 2 != context->ClientVersion()) ) |
|
226 { |
|
227 EGLI_LEAVE_RET( EGL_NO_IMAGE_KHR, EGL_BAD_CONTEXT ); |
|
228 } |
|
229 |
|
230 |
|
231 // From spec. |
|
232 /*KHR_gl_texture_2D_image requires the presence of an OpenGL ES |
|
233 implementation (1.0 or later and/or 2.0 or later).*/ |
|
234 |
|
235 /*Accepted as an attribute in the <attr_list> parameter of |
|
236 eglCreateImageKHR: EGL_GL_TEXTURE_LEVEL_KHR 0x30BC*/ |
|
237 |
|
238 //EGL_GL_TEXTURE_LEVEL_KHR |
|
239 |
|
240 /*If <target> is EGL_GL_TEXTURE_2D_KHR, |
|
241 <buffer> must be the name of a nonzero, EGL_GL_TEXTURE_2D target texture object, |
|
242 cast into the type EGLClientBuffer. |
|
243 |
|
244 <attr_list> should specify the mipmap level |
|
245 which will be used as the EGLImage source (EGL_GL_TEXTURE_LEVEL_KHR); the |
|
246 specified mipmap level must be part of <buffer>. If not specified, the |
|
247 default value listed in Table bbb will be used, instead. Additional |
|
248 values specified in <attr_list> are ignored. The texture must be complete |
|
249 unless the mipmap level to be used is 0, the texture has mipmap level 0 |
|
250 specified, and no other mipmap levels are specified. */ |
|
251 |
|
252 SurfaceDescriptor surfDesc; |
|
253 EGLint textureLevel = 0; |
|
254 EGLint dataSize; |
|
255 |
|
256 if( attrib_list && attrib_list[0] != EGL_NONE ) |
|
257 { |
|
258 for(int i=0; attrib_list[i] != EGL_NONE ; i+=2) |
|
259 { |
|
260 if( attrib_list[i] == EGL_GL_TEXTURE_LEVEL_KHR ) |
|
261 { |
|
262 textureLevel = attrib_list[i+1]; |
|
263 } |
|
264 } |
|
265 } |
|
266 |
|
267 EImageTarget textureTarget = mapImageTarget(target); |
|
268 |
|
269 IEGLtoGLES2Interface* iFace = (IEGLtoGLES2Interface*)state->GLESInterface(2); |
|
270 EStatus status = iFace->GetTextureInfo( context->ClientContext(), textureTarget, buffer, textureLevel, surfDesc ); |
|
271 if ( status != DGLES2_SUCCESS ) |
|
272 { |
|
273 switch( status ) |
|
274 { |
|
275 case DGLES2_BAD_PARAMETER: |
|
276 case DGLES2_BAD_MATCH: |
|
277 EGLI_LEAVE_RET( EGL_NO_IMAGE_KHR, EGL_BAD_PARAMETER ); |
|
278 break; |
|
279 |
|
280 default: |
|
281 EGLI_ASSERT(false); |
|
282 } |
|
283 EGLI_LEAVE_RET( EGL_NO_IMAGE_KHR, EGL_BAD_ALLOC ); |
|
284 } |
|
285 dataSize = surfDesc.m_stride * surfDesc.m_height; |
|
286 unsigned char* data = new unsigned char [ dataSize ]; |
|
287 |
|
288 iFace->GetTextureData( context->ClientContext(), textureTarget, buffer, textureLevel, data ); |
|
289 |
|
290 // Create CEGLImage. |
|
291 image = EGLI_NEW CEGLImage( target, buffer, surfDesc, data ); |
|
292 |
|
293 // If EGLImage creation fail then return error code. |
|
294 if( !image ) |
|
295 { |
|
296 EGLI_LEAVE_RET( EGL_NO_IMAGE_KHR, EGL_BAD_ALLOC ); |
|
297 } |
|
298 // Add image in array |
|
299 // That array is in display side. |
|
300 image = display->AddEGLImage( image ); |
|
301 break; |
|
302 } |
|
303 case EGL_GL_TEXTURE_3D_KHR: |
|
304 { |
|
305 /*<ctx> must be a valid OpenGL ES API context on that display.*/ |
|
306 //EGL_BAD_PARAMETER |
|
307 // NOT SUPPORTED |
|
308 EGLI_LEAVE_RET( EGL_NO_IMAGE_KHR, EGL_BAD_PARAMETER ); |
|
309 } |
|
310 case EGL_GL_RENDERBUFFER_KHR: |
|
311 { |
|
312 //EGL_BAD_PARAMETER |
|
313 // NOT SUPPORTED |
|
314 EGLI_LEAVE_RET( EGL_NO_IMAGE_KHR, EGL_BAD_PARAMETER ); |
|
315 } |
|
316 |
|
317 default: |
|
318 { |
|
319 //EGL_BAD_PARAMETER |
|
320 EGLI_LEAVE_RET( EGL_NO_IMAGE_KHR, EGL_BAD_PARAMETER ); |
|
321 } |
|
322 } |
|
323 EGLI_LEAVE_RET( image, EGL_SUCCESS ); |
|
324 } |
|
325 |
|
326 EGLAPI EGLBoolean EGLAPIENTRY eglDestroyImageKHR( EGLDisplay dpy, |
|
327 EGLImageKHR image) |
|
328 { |
|
329 // TODO: |
|
330 /* Check display |
|
331 Delete image from display array*/ |
|
332 EGLI_ENTER_RET( EGL_FALSE ); |
|
333 |
|
334 CEGLDisplay *display = NULL; |
|
335 CEGLImage *tempImage = NULL; |
|
336 |
|
337 display = state->GetDisplay( dpy ); |
|
338 // Check display |
|
339 //<dpy> must be a valid EGLDisplay |
|
340 if( !display ) |
|
341 { |
|
342 EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_DISPLAY ); |
|
343 } |
|
344 |
|
345 tempImage = display->GetImage( image ); |
|
346 if( !tempImage ) |
|
347 { |
|
348 EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_PARAMETER ); |
|
349 } |
|
350 |
|
351 // Display and image are both ok... |
|
352 // Let siblings know that image is destroyed... |
|
353 // Delete mother of image... |
|
354 // Remove image... |
|
355 //tempImage |
|
356 display->RemoveEGLImage( image ); |
|
357 |
|
358 return EGL_TRUE; |
|
359 } |
|
360 |