os/graphics/graphicsdeviceinterface/directgdi/test/tdirectgdieglcontent_cube.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     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".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 //
    15 
    16 #include "tdirectgdieglcontent_cube.h"
    17 #include "tdisplaymode_mapping.h"
    18 #include <fbs.h>
    19 #include <graphics/sgimage_sw.h>
    20 #include <graphics/fbsdefs.h>
    21 
    22 // CONSTANTS
    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
    31 
    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] =
    35 	{
    36 	/* top */
    37 	-1,  1,  1,
    38 	1,  1,  1,
    39 	1, -1,  1,
    40 	-1, -1,  1,
    41 
    42 	/* front */
    43 	1,  1,  1,
    44 	1,  1, -1,
    45 	1, -1, -1,
    46 	1, -1,  1,
    47 
    48 	/* right */
    49 	-1,  1,  1,
    50 	-1,  1, -1,
    51 	1,  1, -1,
    52 	1,  1,  1,
    53 
    54 	/* left */
    55 	1, -1,  1,
    56 	1, -1, -1,
    57 	-1, -1, -1,
    58 	-1, -1,  1,
    59 
    60 	/* back */
    61 	-1, -1,  1,
    62 	-1, -1, -1,
    63 	-1,  1, -1,
    64 	-1,  1,  1,
    65 
    66 	/* bottom */
    67 	-1,  1, -1,
    68 	1,  1, -1,
    69 	1, -1, -1,
    70 	-1, -1, -1
    71 	};
    72 
    73 /**
    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.
    77 */
    78 static const GLubyte KTriangles[12 * 3] =
    79 	{
    80 	/* top */
    81 	1,0,3,
    82 	1,3,2,
    83 
    84 	/* front */
    85 	5,4,7,
    86 	5,7,6,
    87 
    88 	/* right */
    89 	9,8,11,
    90 	9,11,10,
    91 
    92 	/* left */
    93 	13,12,15,
    94 	13,15,14,
    95 
    96 	/* back */
    97 	17,16,19,
    98 	17,19,18,
    99 
   100 	/* bottom */
   101 	21,22,23,
   102 	21,23,20
   103 	};
   104 
   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 )
   108 
   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] = 
   121 	{
   122 	/* top */
   123 	tex(0,0), 
   124 	tex(255,0),
   125 	tex(255,255), 
   126 	tex(0,255), 
   127 
   128 	/* front */
   129 	tex(0,255),
   130 	tex(127,255),
   131 	tex(127,127),
   132 	tex(0,127),
   133 
   134 	/* right */
   135 	tex(127,255),
   136 	tex(255,255),
   137 	tex(255,127),
   138 	tex(127,127),
   139 
   140 	/* left */
   141 	tex(0,127),
   142 	tex(127,127),
   143 	tex(127,0),
   144 	tex(0,0),
   145 
   146 	/* back */
   147 	tex(127,127),
   148 	tex(255,127),
   149 	tex(255,0),
   150 	tex(127,0),
   151 
   152 	/* bottom */
   153 	tex(255,255),
   154 	tex(255,0),
   155 	tex(0,0),
   156 	tex(0,255)
   157 	};
   158 
   159 /**
   160 Static constructor.
   161 @param aPixelFormat Pixel format of pixmap buffer.
   162 @param aSize Size of pixmap buffer.
   163 */
   164 CGLCube* CGLCube::NewL(TUidPixelFormat aPixelFormat, const TSize& aSize)
   165 	{
   166 	CGLCube* self = NewLC(aPixelFormat, aSize);
   167 	CleanupStack::Pop(self);
   168 	return self;
   169 	}
   170 
   171 CGLCube* CGLCube::NewLC(TUidPixelFormat aPixelFormat, const TSize& aSize)
   172 	{
   173 	CGLCube* self = new(ELeave) CGLCube();
   174 	CleanupStack::PushL(self);
   175 	self->ConstructL(aPixelFormat, aSize);
   176 	return self;
   177 	}
   178 
   179 /**
   180 1st phase constructor
   181 */
   182 CGLCube::CGLCube()
   183 	{
   184 	}
   185 
   186 /**
   187 2nd phase constructor
   188 @param aPixelFormat Pixel format of pixmap buffer.
   189 @param aSize Size of pixmap buffer.
   190 */
   191 void CGLCube::ConstructL(TUidPixelFormat aPixelFormat, const TSize& aSize)
   192 	{
   193 	// init graphic environment
   194 	User::LeaveIfError(SgDriver::Open());
   195 	FbsStartup();
   196 	User::LeaveIfError(RFbsSession::Connect());	
   197 	InitEglL(aPixelFormat, aSize);
   198 	}
   199 
   200 /**
   201 Destructor
   202 */
   203 CGLCube::~CGLCube()
   204 	{
   205 	// deinit gfx environment
   206 	DeInitEgl();
   207 	SgDriver::Close();
   208 	RFbsSession::Disconnect();
   209 	}
   210 
   211 /**
   212 Egl environment initialisation for pixmap surface rendering.
   213 @param aPixelFormat Pixel format of pixmap buffer.
   214 @param aSize Size of pixmap buffer.
   215 */
   216 void CGLCube::InitEglL(TUidPixelFormat aPixelFormat, const TSize& aSize)
   217 	{
   218 	// Get the display for drawing graphics
   219 	iEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
   220 	if(iEglDisplay == NULL)
   221 		{
   222 		_LIT(KGetDisplayFailed, "eglGetDisplay failed");
   223 		User::Panic(KGetDisplayFailed, 0);
   224 		}
   225 
   226 	// Initialize display
   227 	if(eglInitialize(iEglDisplay, NULL, NULL) == EGL_FALSE)
   228 		{
   229 		_LIT(KInitializeFailed, "eglInitialize failed");
   230 		User::Panic(KInitializeFailed, 0);
   231 		}
   232 
   233 	// switch api to GLES
   234 	eglBindAPI(EGL_OPENGL_ES_API);
   235 	
   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;
   242 
   243 	for(TInt i=0; i<KEglContentBuffers; i++)
   244 		{
   245 		User::LeaveIfError(iImages[i].Create(iImageInfo, NULL, 0));
   246 
   247 		EGLint numOfConfigs = 0; 
   248 
   249 		// Define properties for the wanted EGLSurface 
   250 		const EGLint attribList[] =
   251 			{
   252 			EGL_MATCH_NATIVE_PIXMAP, (EGLint)&iImages[i],
   253 			EGL_SURFACE_TYPE, EGL_PIXMAP_BIT,
   254 			EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT,
   255 			EGL_NONE
   256 			};
   257 
   258 		// Choose an EGLConfig that best matches to the properties in attribList
   259 		if(eglChooseConfig(iEglDisplay, attribList, &iConfig, 1, &numOfConfigs) == EGL_FALSE)
   260 			{
   261 			_LIT(KChooseConfigFailed, "eglChooseConfig failed");
   262 			User::Panic(KChooseConfigFailed, 0);
   263 			}
   264 
   265 		const EGLint ppixmapAttribs[] = { EGL_NONE };
   266 		iEglSurfaces[i] = eglCreatePixmapSurface(iEglDisplay, iConfig, &iImages[i], ppixmapAttribs);
   267 		if(iEglSurfaces[i] == NULL)
   268 			{
   269 			_LIT(KCreatePixmapSurfaceFailed, "eglCreatePixmapSurface failed");
   270 			User::Panic(KCreatePixmapSurfaceFailed, 0);
   271 			}
   272 		}
   273 	iEglContext = eglCreateContext(iEglDisplay, iConfig, EGL_NO_CONTEXT, NULL);
   274 	if(iEglContext == NULL)
   275 		{
   276 		_LIT(KCreateContextFailed, "eglCreateContext failed");
   277 		User::Panic(KCreateContextFailed, 0);
   278 		}
   279 
   280 	if(eglMakeCurrent(iEglDisplay, iEglSurfaces[iCurrentImage], iEglSurfaces[iCurrentImage], iEglContext) == EGL_FALSE)
   281 		{
   282 		_LIT(KMakeCurrentFailed, "eglMakeCurrent failed");
   283 		User::Panic(KMakeCurrentFailed, 0);
   284 		}
   285 
   286 	// Prepare texture map (shaded chessboard)
   287 	GLubyte* texData = new(ELeave) GLubyte[64*64*4];
   288 	for(TInt i=0; i<64; i++)
   289 		{
   290 		for(TInt j=0; j<64; j++)
   291 			{
   292 			if((i&8)^(j&8)) // switch 'white' and 'black' fields
   293 				{
   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
   297 				}
   298 			else
   299 				{
   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
   303 				}
   304 			texData[i*64*4+j*4+3] = 255; // alpha
   305 			}
   306 		}
   307 
   308 	// Generate texture
   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);
   315 	delete [] texData;
   316 	}
   317 
   318 /**
   319 Egl environment destroying.
   320 */
   321 void CGLCube::DeInitEgl()
   322 	{
   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++)
   327 		{
   328 		eglDestroySurface(iEglDisplay, iEglSurfaces[i]);
   329 		iImages[i].Close();
   330 		}
   331 	eglTerminate(iEglDisplay);
   332 	eglReleaseThread();
   333 	}
   334 
   335 /**
   336 Render frame of spinning cube.
   337 @param aFrame Number of frame to render.
   338 */
   339 void CGLCube::Render(TInt aFrame)
   340 	{
   341 	if(eglMakeCurrent(iEglDisplay, iEglSurfaces[iCurrentImage], iEglSurfaces[iCurrentImage], iEglContext) == EGL_FALSE)
   342 		{
   343 		_LIT(KMakeCurrentFailed, "eglMakeCurrent failed");
   344 		User::Panic(KMakeCurrentFailed, 0);
   345 		}
   346 
   347 	// Set the screen background color. 
   348 	glClearColor(0.f, 0.f, 0.f, 1.f);
   349 
   350 	// Enable back face culling, texturing, and normalization.
   351 	glEnable(GL_CULL_FACE);
   352 	glEnable(GL_TEXTURE_2D);
   353 	glEnable(GL_NORMALIZE);
   354 
   355 	// Initialize viewport and projection. 
   356 	glViewport(0, 0, iImageInfo.iSizeInPixels.iWidth, iImageInfo.iSizeInPixels.iHeight);
   357 
   358 	// Calculate the view frustrum
   359 	GLfloat aspectRatio = (GLfloat)(iImageInfo.iSizeInPixels.iWidth) / (GLfloat)(iImageInfo.iSizeInPixels.iHeight);
   360 	glMatrixMode(GL_PROJECTION);
   361 	glLoadIdentity();
   362 	glFrustumf(KFrustumLeft * aspectRatio, KFrustumRight * aspectRatio,
   363 			KFrustumBottom, KFrustumTop,
   364 			KFrustumNear, KFrustumFar);
   365 
   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);
   373 	glLoadIdentity();
   374 	glScalef(1.0f/255.0f, 1.0f/255.0f, 1.0f);
   375 	glTranslatef(128.0f, 128.0f, 0.0f);
   376 
   377 	// Remember to change the matrix mode to modelview.
   378 	glMatrixMode(GL_MODELVIEW);
   379 
   380 	// Enable vertex and texture arrays.
   381 	glEnableClientState(GL_VERTEX_ARRAY);
   382 	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
   383 
   384 	// Set array pointers. 
   385 	glVertexPointer(3, GL_BYTE, 0, KVertices);
   386 	glTexCoordPointer(2, GL_BYTE, 0, KTexCoords);
   387 
   388 	// Set the initial shading mode 
   389 	glShadeModel(GL_FLAT);
   390 
   391 	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_DONT_CARE);
   392 
   393 	glClear(GL_COLOR_BUFFER_BIT);
   394 
   395 	// Animate and draw box 
   396 	glLoadIdentity();
   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);
   402 
   403 	glBindTexture(GL_TEXTURE_2D, iTexId);
   404 	glDrawElements(GL_TRIANGLES, 12 * 3, GL_UNSIGNED_BYTE, KTriangles);
   405 
   406 	iLastImage = iCurrentImage;
   407 	}
   408 
   409 /**
   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.
   412 */
   413 void CGLCube::GetImage(TSgDrawableId& aId)
   414 	{
   415 	// finish rendering
   416 	glFinish();
   417 
   418 	aId = iImages[iLastImage].Id();
   419 	// switch to next buffer to prevent overdraw of image by asynchronous rendering
   420 	if(iLastImage == iCurrentImage)
   421 		{
   422 		iCurrentImage = (iCurrentImage+1)%KEglContentBuffers;
   423 		}
   424 	}