graphicsdeviceinterface/directgdi/test/tdirectgdieglcontent_cube.cpp
changeset 0 5d03bc08d59c
equal deleted inserted replaced
-1:000000000000 0:5d03bc08d59c
       
     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 	}