os/graphics/graphicsdeviceinterface/directgdi/test/tdirectgdieglcontent_cube.cpp
changeset 0 bde4ae8d615e
     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 +	}