First public contribution.
1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
16 #include "tdirectgdieglcontent_cube.h"
17 #include "tdisplaymode_mapping.h"
19 #include <graphics/sgimage_sw.h>
20 #include <graphics/fbsdefs.h>
23 /** Camera parameters */
24 const TInt KCameraDistance = 100;
25 const TReal32 KFrustumLeft = -1.f; //left vertical clipping plane
26 const TReal32 KFrustumRight = 1.f; //right vertical clipping plane
27 const TReal32 KFrustumBottom = -1.f;//bottom horizontal clipping plane
28 const TReal32 KFrustumTop = 1.f; //top horizontal clipping plane
29 const TReal32 KFrustumNear = 3.f; //near depth clipping plane
30 const TReal32 KFrustumFar = 1000.f; //far depth clipping plane
32 /* Define vertice coordinates for the cube
33 Duplication of vertices needed for texturing every surface of the cube */
34 static const GLbyte KVertices[24 * 3] =
74 Indices for drawing the triangles.
75 The color of the triangle is determined by
76 the color of the last vertex of the triangle.
78 static const GLubyte KTriangles[12 * 3] =
105 /* Macro for changing the input texture coordinate values from
106 GLubyte [0,255] to GLbyte [-128,127]. See more info below. */
107 #define tex(u,v) (GLbyte)( (u) - 128 ) , (GLbyte)( (v) - 128 )
109 /* Input texture coordinates for each of the object vertices.
110 The coordinates are given in GLbyte [-128,127] format.
111 Since the texture picture coordinates are between values
112 [0,255] for both width and height, we have defined a macro
113 to change the input coordinates into a appropriate form.
114 It is easier to think the texture coordinates as corresponding
115 image pixel coordinates. This alone is not enough because
116 if texture coordinates are not given between values [0,1],
117 texture wrapping will occur. Therefore we need to
118 scale the texture coordinates with appropriate texture matrix,
119 which is defined in AppInit(). */
120 static const GLbyte KTexCoords[24 * 2] =
161 @param aPixelFormat Pixel format of pixmap buffer.
162 @param aSize Size of pixmap buffer.
164 CGLCube* CGLCube::NewL(TUidPixelFormat aPixelFormat, const TSize& aSize)
166 CGLCube* self = NewLC(aPixelFormat, aSize);
167 CleanupStack::Pop(self);
171 CGLCube* CGLCube::NewLC(TUidPixelFormat aPixelFormat, const TSize& aSize)
173 CGLCube* self = new(ELeave) CGLCube();
174 CleanupStack::PushL(self);
175 self->ConstructL(aPixelFormat, aSize);
180 1st phase constructor
187 2nd phase constructor
188 @param aPixelFormat Pixel format of pixmap buffer.
189 @param aSize Size of pixmap buffer.
191 void CGLCube::ConstructL(TUidPixelFormat aPixelFormat, const TSize& aSize)
193 // init graphic environment
194 User::LeaveIfError(SgDriver::Open());
196 User::LeaveIfError(RFbsSession::Connect());
197 InitEglL(aPixelFormat, aSize);
205 // deinit gfx environment
208 RFbsSession::Disconnect();
212 Egl environment initialisation for pixmap surface rendering.
213 @param aPixelFormat Pixel format of pixmap buffer.
214 @param aSize Size of pixmap buffer.
216 void CGLCube::InitEglL(TUidPixelFormat aPixelFormat, const TSize& aSize)
218 // Get the display for drawing graphics
219 iEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
220 if(iEglDisplay == NULL)
222 _LIT(KGetDisplayFailed, "eglGetDisplay failed");
223 User::Panic(KGetDisplayFailed, 0);
226 // Initialize display
227 if(eglInitialize(iEglDisplay, NULL, NULL) == EGL_FALSE)
229 _LIT(KInitializeFailed, "eglInitialize failed");
230 User::Panic(KInitializeFailed, 0);
233 // switch api to GLES
234 eglBindAPI(EGL_OPENGL_ES_API);
236 iImageInfo.iSizeInPixels = aSize;
237 iImageInfo.iPixelFormat = aPixelFormat;
238 iImageInfo.iCpuAccess = ESgCpuAccessNone;
239 iImageInfo.iUsage = ESgUsageOpenGlesTarget|ESgUsageDirectGdiSource;
240 iImageInfo.iShareable = ETrue;
241 iImageInfo.iScreenId = KSgScreenIdMain;
243 for(TInt i=0; i<KEglContentBuffers; i++)
245 User::LeaveIfError(iImages[i].Create(iImageInfo, NULL, 0));
247 EGLint numOfConfigs = 0;
249 // Define properties for the wanted EGLSurface
250 const EGLint attribList[] =
252 EGL_MATCH_NATIVE_PIXMAP, (EGLint)&iImages[i],
253 EGL_SURFACE_TYPE, EGL_PIXMAP_BIT,
254 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT,
258 // Choose an EGLConfig that best matches to the properties in attribList
259 if(eglChooseConfig(iEglDisplay, attribList, &iConfig, 1, &numOfConfigs) == EGL_FALSE)
261 _LIT(KChooseConfigFailed, "eglChooseConfig failed");
262 User::Panic(KChooseConfigFailed, 0);
265 const EGLint ppixmapAttribs[] = { EGL_NONE };
266 iEglSurfaces[i] = eglCreatePixmapSurface(iEglDisplay, iConfig, &iImages[i], ppixmapAttribs);
267 if(iEglSurfaces[i] == NULL)
269 _LIT(KCreatePixmapSurfaceFailed, "eglCreatePixmapSurface failed");
270 User::Panic(KCreatePixmapSurfaceFailed, 0);
273 iEglContext = eglCreateContext(iEglDisplay, iConfig, EGL_NO_CONTEXT, NULL);
274 if(iEglContext == NULL)
276 _LIT(KCreateContextFailed, "eglCreateContext failed");
277 User::Panic(KCreateContextFailed, 0);
280 if(eglMakeCurrent(iEglDisplay, iEglSurfaces[iCurrentImage], iEglSurfaces[iCurrentImage], iEglContext) == EGL_FALSE)
282 _LIT(KMakeCurrentFailed, "eglMakeCurrent failed");
283 User::Panic(KMakeCurrentFailed, 0);
286 // Prepare texture map (shaded chessboard)
287 GLubyte* texData = new(ELeave) GLubyte[64*64*4];
288 for(TInt i=0; i<64; i++)
290 for(TInt j=0; j<64; j++)
292 if((i&8)^(j&8)) // switch 'white' and 'black' fields
294 texData[i*64*4+j*4+0] = i*4; // r
295 texData[i*64*4+j*4+1] = j*4; // g
296 texData[i*64*4+j*4+2] = (i+j)*2; // b
300 texData[i*64*4+j*4+0] = 255-i*4; // r
301 texData[i*64*4+j*4+1] = 255-j*4; // g
302 texData[i*64*4+j*4+2] = 255-(i+j)*2; // b
304 texData[i*64*4+j*4+3] = 255; // alpha
309 glEnable(GL_TEXTURE_2D);
310 glGenTextures(1, &iTexId);
311 glBindTexture(GL_TEXTURE_2D, iTexId);
312 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
313 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
314 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
319 Egl environment destroying.
321 void CGLCube::DeInitEgl()
323 glDeleteTextures(1, &iTexId);
324 eglMakeCurrent(iEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
325 eglDestroyContext(iEglDisplay, iEglContext);
326 for(TInt i=0; i<KEglContentBuffers; i++)
328 eglDestroySurface(iEglDisplay, iEglSurfaces[i]);
331 eglTerminate(iEglDisplay);
336 Render frame of spinning cube.
337 @param aFrame Number of frame to render.
339 void CGLCube::Render(TInt aFrame)
341 if(eglMakeCurrent(iEglDisplay, iEglSurfaces[iCurrentImage], iEglSurfaces[iCurrentImage], iEglContext) == EGL_FALSE)
343 _LIT(KMakeCurrentFailed, "eglMakeCurrent failed");
344 User::Panic(KMakeCurrentFailed, 0);
347 // Set the screen background color.
348 glClearColor(0.f, 0.f, 0.f, 1.f);
350 // Enable back face culling, texturing, and normalization.
351 glEnable(GL_CULL_FACE);
352 glEnable(GL_TEXTURE_2D);
353 glEnable(GL_NORMALIZE);
355 // Initialize viewport and projection.
356 glViewport(0, 0, iImageInfo.iSizeInPixels.iWidth, iImageInfo.iSizeInPixels.iHeight);
358 // Calculate the view frustrum
359 GLfloat aspectRatio = (GLfloat)(iImageInfo.iSizeInPixels.iWidth) / (GLfloat)(iImageInfo.iSizeInPixels.iHeight);
360 glMatrixMode(GL_PROJECTION);
362 glFrustumf(KFrustumLeft * aspectRatio, KFrustumRight * aspectRatio,
363 KFrustumBottom, KFrustumTop,
364 KFrustumNear, KFrustumFar);
366 /* Initialize appropriate texture matrix. First we have to translate the
367 input texture coordinate values to be within a range of [0,255]. Hence
368 we translate the x- and y-coordinate values by 128. Recall that the
369 values in nokTexCoords are between [-128,127], now they are in a range
370 of [0,255]. After that we scale the values by 1/255 to make the values
371 to be in range [0,1]. */
372 glMatrixMode(GL_TEXTURE);
374 glScalef(1.0f/255.0f, 1.0f/255.0f, 1.0f);
375 glTranslatef(128.0f, 128.0f, 0.0f);
377 // Remember to change the matrix mode to modelview.
378 glMatrixMode(GL_MODELVIEW);
380 // Enable vertex and texture arrays.
381 glEnableClientState(GL_VERTEX_ARRAY);
382 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
384 // Set array pointers.
385 glVertexPointer(3, GL_BYTE, 0, KVertices);
386 glTexCoordPointer(2, GL_BYTE, 0, KTexCoords);
388 // Set the initial shading mode
389 glShadeModel(GL_FLAT);
391 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_DONT_CARE);
393 glClear(GL_COLOR_BUFFER_BIT);
395 // Animate and draw box
397 glTranslatex(0 , 0 , -KCameraDistance << 16);
398 glRotatex(aFrame << 18, 1 << 16, 0 , 0 );
399 glRotatex(aFrame << 17, 0 , 1 << 16, 0 );
400 glRotatex(aFrame << 16, 0 , 0 , 1 << 16);
401 glScalex(20 << 16, 20 << 16, 20 << 16);
403 glBindTexture(GL_TEXTURE_2D, iTexId);
404 glDrawElements(GL_TRIANGLES, 12 * 3, GL_UNSIGNED_BYTE, KTriangles);
406 iLastImage = iCurrentImage;
410 Get image id of current frame. Current image to render is switch to next.
411 @param aId Reference to drawable id class to store image id.
413 void CGLCube::GetImage(TSgDrawableId& aId)
418 aId = iImages[iLastImage].Id();
419 // switch to next buffer to prevent overdraw of image by asynchronous rendering
420 if(iLastImage == iCurrentImage)
422 iCurrentImage = (iCurrentImage+1)%KEglContentBuffers;