1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/graphics/graphicsdeviceinterface/directgdi/test/tdirectgdieglcontent_cube.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,424 @@
1.4 +// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +//
1.18 +
1.19 +#include "tdirectgdieglcontent_cube.h"
1.20 +#include "tdisplaymode_mapping.h"
1.21 +#include <fbs.h>
1.22 +#include <graphics/sgimage_sw.h>
1.23 +#include <graphics/fbsdefs.h>
1.24 +
1.25 +// CONSTANTS
1.26 +/** Camera parameters */
1.27 +const TInt KCameraDistance = 100;
1.28 +const TReal32 KFrustumLeft = -1.f; //left vertical clipping plane
1.29 +const TReal32 KFrustumRight = 1.f; //right vertical clipping plane
1.30 +const TReal32 KFrustumBottom = -1.f;//bottom horizontal clipping plane
1.31 +const TReal32 KFrustumTop = 1.f; //top horizontal clipping plane
1.32 +const TReal32 KFrustumNear = 3.f; //near depth clipping plane
1.33 +const TReal32 KFrustumFar = 1000.f; //far depth clipping plane
1.34 +
1.35 +/* Define vertice coordinates for the cube
1.36 + Duplication of vertices needed for texturing every surface of the cube */
1.37 +static const GLbyte KVertices[24 * 3] =
1.38 + {
1.39 + /* top */
1.40 + -1, 1, 1,
1.41 + 1, 1, 1,
1.42 + 1, -1, 1,
1.43 + -1, -1, 1,
1.44 +
1.45 + /* front */
1.46 + 1, 1, 1,
1.47 + 1, 1, -1,
1.48 + 1, -1, -1,
1.49 + 1, -1, 1,
1.50 +
1.51 + /* right */
1.52 + -1, 1, 1,
1.53 + -1, 1, -1,
1.54 + 1, 1, -1,
1.55 + 1, 1, 1,
1.56 +
1.57 + /* left */
1.58 + 1, -1, 1,
1.59 + 1, -1, -1,
1.60 + -1, -1, -1,
1.61 + -1, -1, 1,
1.62 +
1.63 + /* back */
1.64 + -1, -1, 1,
1.65 + -1, -1, -1,
1.66 + -1, 1, -1,
1.67 + -1, 1, 1,
1.68 +
1.69 + /* bottom */
1.70 + -1, 1, -1,
1.71 + 1, 1, -1,
1.72 + 1, -1, -1,
1.73 + -1, -1, -1
1.74 + };
1.75 +
1.76 +/**
1.77 +Indices for drawing the triangles.
1.78 +The color of the triangle is determined by
1.79 +the color of the last vertex of the triangle.
1.80 +*/
1.81 +static const GLubyte KTriangles[12 * 3] =
1.82 + {
1.83 + /* top */
1.84 + 1,0,3,
1.85 + 1,3,2,
1.86 +
1.87 + /* front */
1.88 + 5,4,7,
1.89 + 5,7,6,
1.90 +
1.91 + /* right */
1.92 + 9,8,11,
1.93 + 9,11,10,
1.94 +
1.95 + /* left */
1.96 + 13,12,15,
1.97 + 13,15,14,
1.98 +
1.99 + /* back */
1.100 + 17,16,19,
1.101 + 17,19,18,
1.102 +
1.103 + /* bottom */
1.104 + 21,22,23,
1.105 + 21,23,20
1.106 + };
1.107 +
1.108 +/* Macro for changing the input texture coordinate values from
1.109 + GLubyte [0,255] to GLbyte [-128,127]. See more info below. */
1.110 +#define tex(u,v) (GLbyte)( (u) - 128 ) , (GLbyte)( (v) - 128 )
1.111 +
1.112 +/* Input texture coordinates for each of the object vertices.
1.113 + The coordinates are given in GLbyte [-128,127] format.
1.114 + Since the texture picture coordinates are between values
1.115 + [0,255] for both width and height, we have defined a macro
1.116 + to change the input coordinates into a appropriate form.
1.117 + It is easier to think the texture coordinates as corresponding
1.118 + image pixel coordinates. This alone is not enough because
1.119 + if texture coordinates are not given between values [0,1],
1.120 + texture wrapping will occur. Therefore we need to
1.121 + scale the texture coordinates with appropriate texture matrix,
1.122 + which is defined in AppInit(). */
1.123 +static const GLbyte KTexCoords[24 * 2] =
1.124 + {
1.125 + /* top */
1.126 + tex(0,0),
1.127 + tex(255,0),
1.128 + tex(255,255),
1.129 + tex(0,255),
1.130 +
1.131 + /* front */
1.132 + tex(0,255),
1.133 + tex(127,255),
1.134 + tex(127,127),
1.135 + tex(0,127),
1.136 +
1.137 + /* right */
1.138 + tex(127,255),
1.139 + tex(255,255),
1.140 + tex(255,127),
1.141 + tex(127,127),
1.142 +
1.143 + /* left */
1.144 + tex(0,127),
1.145 + tex(127,127),
1.146 + tex(127,0),
1.147 + tex(0,0),
1.148 +
1.149 + /* back */
1.150 + tex(127,127),
1.151 + tex(255,127),
1.152 + tex(255,0),
1.153 + tex(127,0),
1.154 +
1.155 + /* bottom */
1.156 + tex(255,255),
1.157 + tex(255,0),
1.158 + tex(0,0),
1.159 + tex(0,255)
1.160 + };
1.161 +
1.162 +/**
1.163 +Static constructor.
1.164 +@param aPixelFormat Pixel format of pixmap buffer.
1.165 +@param aSize Size of pixmap buffer.
1.166 +*/
1.167 +CGLCube* CGLCube::NewL(TUidPixelFormat aPixelFormat, const TSize& aSize)
1.168 + {
1.169 + CGLCube* self = NewLC(aPixelFormat, aSize);
1.170 + CleanupStack::Pop(self);
1.171 + return self;
1.172 + }
1.173 +
1.174 +CGLCube* CGLCube::NewLC(TUidPixelFormat aPixelFormat, const TSize& aSize)
1.175 + {
1.176 + CGLCube* self = new(ELeave) CGLCube();
1.177 + CleanupStack::PushL(self);
1.178 + self->ConstructL(aPixelFormat, aSize);
1.179 + return self;
1.180 + }
1.181 +
1.182 +/**
1.183 +1st phase constructor
1.184 +*/
1.185 +CGLCube::CGLCube()
1.186 + {
1.187 + }
1.188 +
1.189 +/**
1.190 +2nd phase constructor
1.191 +@param aPixelFormat Pixel format of pixmap buffer.
1.192 +@param aSize Size of pixmap buffer.
1.193 +*/
1.194 +void CGLCube::ConstructL(TUidPixelFormat aPixelFormat, const TSize& aSize)
1.195 + {
1.196 + // init graphic environment
1.197 + User::LeaveIfError(SgDriver::Open());
1.198 + FbsStartup();
1.199 + User::LeaveIfError(RFbsSession::Connect());
1.200 + InitEglL(aPixelFormat, aSize);
1.201 + }
1.202 +
1.203 +/**
1.204 +Destructor
1.205 +*/
1.206 +CGLCube::~CGLCube()
1.207 + {
1.208 + // deinit gfx environment
1.209 + DeInitEgl();
1.210 + SgDriver::Close();
1.211 + RFbsSession::Disconnect();
1.212 + }
1.213 +
1.214 +/**
1.215 +Egl environment initialisation for pixmap surface rendering.
1.216 +@param aPixelFormat Pixel format of pixmap buffer.
1.217 +@param aSize Size of pixmap buffer.
1.218 +*/
1.219 +void CGLCube::InitEglL(TUidPixelFormat aPixelFormat, const TSize& aSize)
1.220 + {
1.221 + // Get the display for drawing graphics
1.222 + iEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
1.223 + if(iEglDisplay == NULL)
1.224 + {
1.225 + _LIT(KGetDisplayFailed, "eglGetDisplay failed");
1.226 + User::Panic(KGetDisplayFailed, 0);
1.227 + }
1.228 +
1.229 + // Initialize display
1.230 + if(eglInitialize(iEglDisplay, NULL, NULL) == EGL_FALSE)
1.231 + {
1.232 + _LIT(KInitializeFailed, "eglInitialize failed");
1.233 + User::Panic(KInitializeFailed, 0);
1.234 + }
1.235 +
1.236 + // switch api to GLES
1.237 + eglBindAPI(EGL_OPENGL_ES_API);
1.238 +
1.239 + iImageInfo.iSizeInPixels = aSize;
1.240 + iImageInfo.iPixelFormat = aPixelFormat;
1.241 + iImageInfo.iCpuAccess = ESgCpuAccessNone;
1.242 + iImageInfo.iUsage = ESgUsageOpenGlesTarget|ESgUsageDirectGdiSource;
1.243 + iImageInfo.iShareable = ETrue;
1.244 + iImageInfo.iScreenId = KSgScreenIdMain;
1.245 +
1.246 + for(TInt i=0; i<KEglContentBuffers; i++)
1.247 + {
1.248 + User::LeaveIfError(iImages[i].Create(iImageInfo, NULL, 0));
1.249 +
1.250 + EGLint numOfConfigs = 0;
1.251 +
1.252 + // Define properties for the wanted EGLSurface
1.253 + const EGLint attribList[] =
1.254 + {
1.255 + EGL_MATCH_NATIVE_PIXMAP, (EGLint)&iImages[i],
1.256 + EGL_SURFACE_TYPE, EGL_PIXMAP_BIT,
1.257 + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT,
1.258 + EGL_NONE
1.259 + };
1.260 +
1.261 + // Choose an EGLConfig that best matches to the properties in attribList
1.262 + if(eglChooseConfig(iEglDisplay, attribList, &iConfig, 1, &numOfConfigs) == EGL_FALSE)
1.263 + {
1.264 + _LIT(KChooseConfigFailed, "eglChooseConfig failed");
1.265 + User::Panic(KChooseConfigFailed, 0);
1.266 + }
1.267 +
1.268 + const EGLint ppixmapAttribs[] = { EGL_NONE };
1.269 + iEglSurfaces[i] = eglCreatePixmapSurface(iEglDisplay, iConfig, &iImages[i], ppixmapAttribs);
1.270 + if(iEglSurfaces[i] == NULL)
1.271 + {
1.272 + _LIT(KCreatePixmapSurfaceFailed, "eglCreatePixmapSurface failed");
1.273 + User::Panic(KCreatePixmapSurfaceFailed, 0);
1.274 + }
1.275 + }
1.276 + iEglContext = eglCreateContext(iEglDisplay, iConfig, EGL_NO_CONTEXT, NULL);
1.277 + if(iEglContext == NULL)
1.278 + {
1.279 + _LIT(KCreateContextFailed, "eglCreateContext failed");
1.280 + User::Panic(KCreateContextFailed, 0);
1.281 + }
1.282 +
1.283 + if(eglMakeCurrent(iEglDisplay, iEglSurfaces[iCurrentImage], iEglSurfaces[iCurrentImage], iEglContext) == EGL_FALSE)
1.284 + {
1.285 + _LIT(KMakeCurrentFailed, "eglMakeCurrent failed");
1.286 + User::Panic(KMakeCurrentFailed, 0);
1.287 + }
1.288 +
1.289 + // Prepare texture map (shaded chessboard)
1.290 + GLubyte* texData = new(ELeave) GLubyte[64*64*4];
1.291 + for(TInt i=0; i<64; i++)
1.292 + {
1.293 + for(TInt j=0; j<64; j++)
1.294 + {
1.295 + if((i&8)^(j&8)) // switch 'white' and 'black' fields
1.296 + {
1.297 + texData[i*64*4+j*4+0] = i*4; // r
1.298 + texData[i*64*4+j*4+1] = j*4; // g
1.299 + texData[i*64*4+j*4+2] = (i+j)*2; // b
1.300 + }
1.301 + else
1.302 + {
1.303 + texData[i*64*4+j*4+0] = 255-i*4; // r
1.304 + texData[i*64*4+j*4+1] = 255-j*4; // g
1.305 + texData[i*64*4+j*4+2] = 255-(i+j)*2; // b
1.306 + }
1.307 + texData[i*64*4+j*4+3] = 255; // alpha
1.308 + }
1.309 + }
1.310 +
1.311 + // Generate texture
1.312 + glEnable(GL_TEXTURE_2D);
1.313 + glGenTextures(1, &iTexId);
1.314 + glBindTexture(GL_TEXTURE_2D, iTexId);
1.315 + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1.316 + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1.317 + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
1.318 + delete [] texData;
1.319 + }
1.320 +
1.321 +/**
1.322 +Egl environment destroying.
1.323 +*/
1.324 +void CGLCube::DeInitEgl()
1.325 + {
1.326 + glDeleteTextures(1, &iTexId);
1.327 + eglMakeCurrent(iEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
1.328 + eglDestroyContext(iEglDisplay, iEglContext);
1.329 + for(TInt i=0; i<KEglContentBuffers; i++)
1.330 + {
1.331 + eglDestroySurface(iEglDisplay, iEglSurfaces[i]);
1.332 + iImages[i].Close();
1.333 + }
1.334 + eglTerminate(iEglDisplay);
1.335 + eglReleaseThread();
1.336 + }
1.337 +
1.338 +/**
1.339 +Render frame of spinning cube.
1.340 +@param aFrame Number of frame to render.
1.341 +*/
1.342 +void CGLCube::Render(TInt aFrame)
1.343 + {
1.344 + if(eglMakeCurrent(iEglDisplay, iEglSurfaces[iCurrentImage], iEglSurfaces[iCurrentImage], iEglContext) == EGL_FALSE)
1.345 + {
1.346 + _LIT(KMakeCurrentFailed, "eglMakeCurrent failed");
1.347 + User::Panic(KMakeCurrentFailed, 0);
1.348 + }
1.349 +
1.350 + // Set the screen background color.
1.351 + glClearColor(0.f, 0.f, 0.f, 1.f);
1.352 +
1.353 + // Enable back face culling, texturing, and normalization.
1.354 + glEnable(GL_CULL_FACE);
1.355 + glEnable(GL_TEXTURE_2D);
1.356 + glEnable(GL_NORMALIZE);
1.357 +
1.358 + // Initialize viewport and projection.
1.359 + glViewport(0, 0, iImageInfo.iSizeInPixels.iWidth, iImageInfo.iSizeInPixels.iHeight);
1.360 +
1.361 + // Calculate the view frustrum
1.362 + GLfloat aspectRatio = (GLfloat)(iImageInfo.iSizeInPixels.iWidth) / (GLfloat)(iImageInfo.iSizeInPixels.iHeight);
1.363 + glMatrixMode(GL_PROJECTION);
1.364 + glLoadIdentity();
1.365 + glFrustumf(KFrustumLeft * aspectRatio, KFrustumRight * aspectRatio,
1.366 + KFrustumBottom, KFrustumTop,
1.367 + KFrustumNear, KFrustumFar);
1.368 +
1.369 + /* Initialize appropriate texture matrix. First we have to translate the
1.370 + input texture coordinate values to be within a range of [0,255]. Hence
1.371 + we translate the x- and y-coordinate values by 128. Recall that the
1.372 + values in nokTexCoords are between [-128,127], now they are in a range
1.373 + of [0,255]. After that we scale the values by 1/255 to make the values
1.374 + to be in range [0,1]. */
1.375 + glMatrixMode(GL_TEXTURE);
1.376 + glLoadIdentity();
1.377 + glScalef(1.0f/255.0f, 1.0f/255.0f, 1.0f);
1.378 + glTranslatef(128.0f, 128.0f, 0.0f);
1.379 +
1.380 + // Remember to change the matrix mode to modelview.
1.381 + glMatrixMode(GL_MODELVIEW);
1.382 +
1.383 + // Enable vertex and texture arrays.
1.384 + glEnableClientState(GL_VERTEX_ARRAY);
1.385 + glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1.386 +
1.387 + // Set array pointers.
1.388 + glVertexPointer(3, GL_BYTE, 0, KVertices);
1.389 + glTexCoordPointer(2, GL_BYTE, 0, KTexCoords);
1.390 +
1.391 + // Set the initial shading mode
1.392 + glShadeModel(GL_FLAT);
1.393 +
1.394 + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_DONT_CARE);
1.395 +
1.396 + glClear(GL_COLOR_BUFFER_BIT);
1.397 +
1.398 + // Animate and draw box
1.399 + glLoadIdentity();
1.400 + glTranslatex(0 , 0 , -KCameraDistance << 16);
1.401 + glRotatex(aFrame << 18, 1 << 16, 0 , 0 );
1.402 + glRotatex(aFrame << 17, 0 , 1 << 16, 0 );
1.403 + glRotatex(aFrame << 16, 0 , 0 , 1 << 16);
1.404 + glScalex(20 << 16, 20 << 16, 20 << 16);
1.405 +
1.406 + glBindTexture(GL_TEXTURE_2D, iTexId);
1.407 + glDrawElements(GL_TRIANGLES, 12 * 3, GL_UNSIGNED_BYTE, KTriangles);
1.408 +
1.409 + iLastImage = iCurrentImage;
1.410 + }
1.411 +
1.412 +/**
1.413 +Get image id of current frame. Current image to render is switch to next.
1.414 +@param aId Reference to drawable id class to store image id.
1.415 +*/
1.416 +void CGLCube::GetImage(TSgDrawableId& aId)
1.417 + {
1.418 + // finish rendering
1.419 + glFinish();
1.420 +
1.421 + aId = iImages[iLastImage].Id();
1.422 + // switch to next buffer to prevent overdraw of image by asynchronous rendering
1.423 + if(iLastImage == iCurrentImage)
1.424 + {
1.425 + iCurrentImage = (iCurrentImage+1)%KEglContentBuffers;
1.426 + }
1.427 + }