16f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens/******************************************************************************
26f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
36f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens @File         OGLES2HelloAPI_Windows.cpp
46f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
56f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens @Title        OpenGL ES 2.0 HelloAPI Tutorial
66f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
76f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens @Version
86f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
96f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens @Copyright    Copyright (c) Imagination Technologies Limited.
106f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
116f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens @Platform
126f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
136f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens @Description  Basic Tutorial that shows step-by-step how to initialize OpenGL ES
146f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens               2.0, use it for drawing a triangle and terminate it.
156f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
166f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens******************************************************************************/
176f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens#include <stdio.h>
186f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens#include <windows.h>
196f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens#include <TCHAR.h>
206f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
216f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens#include <EGL/egl.h>
226f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens#include <GLES2/gl2.h>
236f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
246f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens/******************************************************************************
256f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens Defines
266f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens******************************************************************************/
276f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens// Windows class name to register
286f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens#define	WINDOW_CLASS _T("PVRShellClass")
296f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
306f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens// Width and height of the window
316f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens#define WINDOW_WIDTH	640
326f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens#define WINDOW_HEIGHT	480
336f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
346f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens// Index to bind the attributes to vertex shaders
356f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens#define VERTEX_ARRAY	0
366f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
376f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens/******************************************************************************
386f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens Global variables
396f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens******************************************************************************/
406f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
416f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens// Variable set in the message handler to finish the demo
426f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capensbool	g_bDemoDone = false;
436f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
446f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens/*!****************************************************************************
456f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens @Function		WndProc
466f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens @Input			hWnd		Handle to the window
476f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens @Input			message		Specifies the message
486f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens @Input			wParam		Additional message information
496f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens @Input			lParam		Additional message information
506f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens @Return		LRESULT		result code to OS
516f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens @Description	Processes messages for the main window
526f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens******************************************************************************/
536f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas CapensLRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
546f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens{
556f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	switch (message)
566f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	{
576f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		/*
586f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens			Here we are handling 2 system messages: screen saving and monitor power.
596f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens			They are especially relevent on mobile devices.
606f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		*/
616f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		case WM_SYSCOMMAND:
626f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		{
636f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens			switch (wParam)
646f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens			{
656f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens				case SC_SCREENSAVE:					// Screensaver trying to start ?
666f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens				case SC_MONITORPOWER:				// Monitor trying to enter powersave ?
676f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens				return 0;							// Prevent this from happening
686f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens			}
696f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens			break;
706f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		}
716f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
726f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		// Handles the close message when a user clicks the quit icon of the window
736f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		case WM_CLOSE:
746f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens			g_bDemoDone = true;
756f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens			PostQuitMessage(0);
766f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens			return 1;
776f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
786f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		default:
796f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens			break;
806f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	}
816f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
826f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	// Calls the default window procedure for messages we did not handle
836f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	return DefWindowProc(hWnd, message, wParam, lParam);
846f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens}
856f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
866f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens/*!****************************************************************************
876f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens @Function		TestEGLError
886f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens @Input			pszLocation		location in the program where the error took
896f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens								place. ie: function name
906f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens @Return		bool			true if no EGL error was detected
916f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens @Description	Tests for an EGL error and prints it
926f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens******************************************************************************/
936f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capensbool TestEGLError(HWND hWnd, char* pszLocation)
946f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens{
956f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	/*
966f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		eglGetError returns the last error that has happened using egl,
976f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		not the status of the last called function. The user has to
986f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		check after every single egl call or at least once every frame.
996f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	*/
1006f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	EGLint iErr = eglGetError();
1016f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	if (iErr != EGL_SUCCESS)
1026f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	{
1036f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		TCHAR pszStr[256];
1046f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		_stprintf(pszStr, _T("%s failed (%d).\n"), pszLocation, iErr);
1056f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		MessageBox(hWnd, pszStr, _T("Error"), MB_OK|MB_ICONEXCLAMATION);
1066f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		return false;
1076f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	}
1086f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
1096f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	return true;
1106f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens}
1116f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
1126f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens/*!****************************************************************************
1136f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens @Function		WinMain
1146f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens @Input			hInstance		Application instance from OS
1156f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens @Input			hPrevInstance	Always NULL
1166f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens @Input			lpCmdLine		command line from OS
1176f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens @Input			nCmdShow		Specifies how the window is to be shown
1186f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens @Return		int				result code to OS
1196f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens @Description	Main function of the program
1206f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens******************************************************************************/
1216f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capensint WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, TCHAR *lpCmdLine, int nCmdShow)
1226f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens{
1236f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	// Windows variables
1246f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	HWND				hWnd	= 0;
1256f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	HDC					hDC		= 0;
1266f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
1276f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	// EGL variables
1286f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	EGLDisplay			eglDisplay	= 0;
1296f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	EGLConfig			eglConfig	= 0;
1306f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	EGLSurface			eglSurface	= 0;
1316f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	EGLContext			eglContext	= 0;
1326f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	EGLNativeWindowType	eglWindow	= 0;
1336f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
1346f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	// Matrix used for projection model view (PMVMatrix)
1356f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	float pfIdentity[] =
1366f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	{
1376f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		1.0f,0.0f,0.0f,0.0f,
1386f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		0.0f,1.0f,0.0f,0.0f,
1396f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		0.0f,0.0f,1.0f,0.0f,
1406f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		0.0f,0.0f,0.0f,1.0f
1416f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	};
1426f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
1436f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	// Fragment and vertex shaders code
1446f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	char* pszFragShader = "\
1456f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		void main (void)\
1466f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		{\
1476f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens			gl_FragColor = vec4(1.0, 1.0, 0.66 ,1.0);\
1486f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		}";
1496f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	char* pszVertShader = "\
1506f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		attribute highp vec4	myVertex;\
1516f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		uniform mediump mat4	myPMVMatrix;\
1526f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		void main(void)\
1536f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		{\
1546f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens			gl_Position = myPMVMatrix * myVertex;\
1556f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		}";
1566f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
1576f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	/*
1586f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		Step 0 - Create a EGLNativeWindowType that we can use for OpenGL ES output
1596f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	*/
1606f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
1616f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	// Register the windows class
1626f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	WNDCLASS sWC;
1636f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens    sWC.style = CS_HREDRAW | CS_VREDRAW;
1646f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	sWC.lpfnWndProc = WndProc;
1656f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens    sWC.cbClsExtra = 0;
1666f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens    sWC.cbWndExtra = 0;
1676f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens    sWC.hInstance = hInstance;
1686f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens    sWC.hIcon = 0;
1696f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens    sWC.hCursor = 0;
1706f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens    sWC.lpszMenuName = 0;
1716f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	sWC.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
1726f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens    sWC.lpszClassName = WINDOW_CLASS;
1736f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	unsigned int nWidth = WINDOW_WIDTH;
1746f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	unsigned int nHeight = WINDOW_HEIGHT;
1756f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
1766f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	ATOM registerClass = RegisterClass(&sWC);
1776f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	if (!registerClass)
1786f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	{
1796f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		MessageBox(0, _T("Failed to register the window class"), _T("Error"), MB_OK | MB_ICONEXCLAMATION);
1806f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	}
1816f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
1826f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	// Create the eglWindow
1836f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	RECT	sRect;
1846f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	SetRect(&sRect, 0, 0, nWidth, nHeight);
1856f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	AdjustWindowRectEx(&sRect, WS_CAPTION | WS_SYSMENU, false, 0);
1866f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	hWnd = CreateWindow( WINDOW_CLASS, _T("HelloAPI"), WS_VISIBLE | WS_SYSMENU,
1876f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens						 0, 0, nWidth, nHeight, NULL, NULL, hInstance, NULL);
1886f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	eglWindow = hWnd;
1896f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
1906f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	// Get the associated device context
1916f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	hDC = GetDC(hWnd);
1926f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	if (!hDC)
1936f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	{
1946f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		MessageBox(0, _T("Failed to create the device context"), _T("Error"), MB_OK|MB_ICONEXCLAMATION);
1956f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		goto cleanup;
1966f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	}
1976f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
1986f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	/*
1996f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		Step 1 - Get the default display.
2006f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		EGL uses the concept of a "display" which in most environments
2016f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		corresponds to a single physical screen. Since we usually want
2026f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		to draw to the main screen or only have a single screen to begin
2036f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		with, we let EGL pick the default display.
2046f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		Querying other displays is platform specific.
2056f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	*/
2066f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	eglDisplay = eglGetDisplay(hDC);
2076f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
2086f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens    if(eglDisplay == EGL_NO_DISPLAY)
2096f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens         eglDisplay = eglGetDisplay((EGLNativeDisplayType) EGL_DEFAULT_DISPLAY);
2106f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	/*
2116f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		Step 2 - Initialize EGL.
2126f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		EGL has to be initialized with the display obtained in the
2136f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		previous step. We cannot use other EGL functions except
2146f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		eglGetDisplay and eglGetError before eglInitialize has been
2156f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		called.
2166f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		If we're not interested in the EGL version number we can just
2176f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		pass NULL for the second and third parameters.
2186f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	*/
2196f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	EGLint iMajorVersion, iMinorVersion;
2206f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	if (!eglInitialize(eglDisplay, &iMajorVersion, &iMinorVersion))
2216f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	{
2226f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		MessageBox(0, _T("eglInitialize() failed."), _T("Error"), MB_OK|MB_ICONEXCLAMATION);
2236f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		goto cleanup;
2246f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	}
2256f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
2266f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	/*
2276f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		Step 3 - Make OpenGL ES the current API.
2286f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		EGL provides ways to set up OpenGL ES and OpenVG contexts
2296f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		(and possibly other graphics APIs in the future), so we need
2306f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		to specify the "current API".
2316f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	*/
2326f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	eglBindAPI(EGL_OPENGL_ES_API);
2336f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	if (!TestEGLError(hWnd, "eglBindAPI"))
2346f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	{
2356f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		goto cleanup;
2366f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	}
2376f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
2386f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	/*
2396f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		Step 4 - Specify the required configuration attributes.
2406f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		An EGL "configuration" describes the pixel format and type of
2416f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		surfaces that can be used for drawing.
2426f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		For now we just want to use the default Windows surface,
2436f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		i.e. it will be visible on screen. The list
2446f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		has to contain key/value pairs, terminated with EGL_NONE.
2456f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	 */
2466f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	const EGLint pi32ConfigAttribs[] =
2476f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	{
2486f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		EGL_LEVEL,				0,
2496f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		EGL_SURFACE_TYPE,		EGL_WINDOW_BIT,
2506f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		EGL_RENDERABLE_TYPE,	EGL_OPENGL_ES2_BIT,
2516f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		EGL_NATIVE_RENDERABLE,	EGL_FALSE,
2526f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		EGL_DEPTH_SIZE,			EGL_DONT_CARE,
2536f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		EGL_NONE
2546f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	};
2556f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
2566f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	/*
2576f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		Step 5 - Find a config that matches all requirements.
2586f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		eglChooseConfig provides a list of all available configurations
2596f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		that meet or exceed the requirements given as the second
2606f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		argument. In most cases we just want the first config that meets
2616f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		all criteria, so we can limit the number of configs returned to 1.
2626f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	*/
2636f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	EGLint iConfigs;
2646f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	if (!eglChooseConfig(eglDisplay, pi32ConfigAttribs, &eglConfig, 1, &iConfigs) || (iConfigs != 1))
2656f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	{
2666f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		MessageBox(0, _T("eglChooseConfig() failed."), _T("Error"), MB_OK|MB_ICONEXCLAMATION);
2676f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		goto cleanup;
2686f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	}
2696f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
2706f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	/*
2716f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		Step 6 - Create a surface to draw to.
2726f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		Use the config picked in the previous step and the native window
2736f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		handle when available to create a window surface. A window surface
2746f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		is one that will be visible on screen inside the native display (or
2756f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		fullscreen if there is no windowing system).
2766f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		Pixmaps and pbuffers are surfaces which only exist in off-screen
2776f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		memory.
2786f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	*/
2796f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	eglSurface = eglCreateWindowSurface(eglDisplay, eglConfig, eglWindow, NULL);
2806f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
2816f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens    if(eglSurface == EGL_NO_SURFACE)
2826f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens    {
2836f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens        eglGetError(); // Clear error
2846f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens        eglSurface = eglCreateWindowSurface(eglDisplay, eglConfig, NULL, NULL);
2856f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	}
2866f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
2876f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	if (!TestEGLError(hWnd, "eglCreateWindowSurface"))
2886f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	{
2896f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		goto cleanup;
2906f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	}
2916f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
2926f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	/*
2936f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		Step 7 - Create a context.
2946f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		EGL has to create a context for OpenGL ES. Our OpenGL ES resources
2956f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		like textures will only be valid inside this context
2966f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		(or shared contexts)
2976f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	*/
2986f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	EGLint ai32ContextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
2996f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	eglContext = eglCreateContext(eglDisplay, eglConfig, NULL, ai32ContextAttribs);
3006f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	if (!TestEGLError(hWnd, "eglCreateContext"))
3016f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	{
3026f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		goto cleanup;
3036f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	}
3046f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
3056f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	/*
3066f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		Step 8 - Bind the context to the current thread and use our
3076f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		window surface for drawing and reading.
3086f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		Contexts are bound to a thread. This means you don't have to
3096f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		worry about other threads and processes interfering with your
3106f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		OpenGL ES application.
3116f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		We need to specify a surface that will be the target of all
3126f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		subsequent drawing operations, and one that will be the source
3136f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		of read operations. They can be the same surface.
3146f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	*/
3156f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext);
3166f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	if (!TestEGLError(hWnd, "eglMakeCurrent"))
3176f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	{
3186f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		goto cleanup;
3196f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	}
3206f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
3216f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	/*
3226f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		Step 9 - Draw something with OpenGL ES.
3236f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		At this point everything is initialized and we're ready to use
3246f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		OpenGL ES to draw something on the screen.
3256f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	*/
3266f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
3276f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	GLuint uiFragShader, uiVertShader;		/* Used to hold the fragment and vertex shader handles */
3286f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	GLuint uiProgramObject;					/* Used to hold the program handle (made out of the two previous shaders */
3296f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
3306f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	// Create the fragment shader object
3316f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	uiFragShader = glCreateShader(GL_FRAGMENT_SHADER);
3326f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
3336f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	// Load the source code into it
3346f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	glShaderSource(uiFragShader, 1, (const char**)&pszFragShader, NULL);
3356f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
3366f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	// Compile the source code
3376f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	glCompileShader(uiFragShader);
3386f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
3396f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	// Check if compilation succeeded
3406f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	GLint bShaderCompiled;
3416f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens    glGetShaderiv(uiFragShader, GL_COMPILE_STATUS, &bShaderCompiled);
3426f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
3436f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	if (!bShaderCompiled)
3446f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	{
3456f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
3466f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		// An error happened, first retrieve the length of the log message
3476f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		int i32InfoLogLength, i32CharsWritten;
3486f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		glGetShaderiv(uiFragShader, GL_INFO_LOG_LENGTH, &i32InfoLogLength);
3496f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
3506f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		// Allocate enough space for the message and retrieve it
3516f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		char* pszInfoLog = new char[i32InfoLogLength];
3526f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens        glGetShaderInfoLog(uiFragShader, i32InfoLogLength, &i32CharsWritten, pszInfoLog);
3536f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
3546f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		// Displays the error in a dialog box
3556f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		MessageBox(hWnd, i32InfoLogLength ? pszInfoLog : _T(""), _T("Failed to compile fragment shader"), MB_OK|MB_ICONEXCLAMATION);
3566f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		delete[] pszInfoLog;
3576f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
3586f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		goto cleanup;
3596f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	}
3606f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
3616f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	// Loads the vertex shader in the same way
3626f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	uiVertShader = glCreateShader(GL_VERTEX_SHADER);
3636f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	glShaderSource(uiVertShader, 1, (const char**)&pszVertShader, NULL);
3646f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	glCompileShader(uiVertShader);
3656f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens    glGetShaderiv(uiVertShader, GL_COMPILE_STATUS, &bShaderCompiled);
3666f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	if (!bShaderCompiled)
3676f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	{
3686f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
3696f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		int i32InfoLogLength, i32CharsWritten;
3706f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		glGetShaderiv(uiVertShader, GL_INFO_LOG_LENGTH, &i32InfoLogLength);
3716f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		char* pszInfoLog = new char[i32InfoLogLength];
3726f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens        glGetShaderInfoLog(uiVertShader, i32InfoLogLength, &i32CharsWritten, pszInfoLog);
3736f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
3746f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		MessageBox(hWnd, i32InfoLogLength ? pszInfoLog : _T(""), _T("Failed to compile vertex shader"), MB_OK|MB_ICONEXCLAMATION);
3756f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
3766f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		delete[] pszInfoLog;
3776f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
3786f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		goto cleanup;
3796f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	}
3806f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
3816f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	// Create the shader program
3826f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens    uiProgramObject = glCreateProgram();
3836f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
3846f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	// Attach the fragment and vertex shaders to it
3856f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens    glAttachShader(uiProgramObject, uiFragShader);
3866f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens    glAttachShader(uiProgramObject, uiVertShader);
3876f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
3886f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	// Bind the custom vertex attribute "myVertex" to location VERTEX_ARRAY
3896f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens    glBindAttribLocation(uiProgramObject, VERTEX_ARRAY, "myVertex");
3906f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
3916f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	// Link the program
3926f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens    glLinkProgram(uiProgramObject);
3936f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
3946f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	// Check if linking succeeded in the same way we checked for compilation success
3956f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens    GLint bLinked;
3966f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens    glGetProgramiv(uiProgramObject, GL_LINK_STATUS, &bLinked);
3976f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	if (!bLinked)
3986f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	{
3996f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		int i32InfoLogLength, i32CharsWritten;
4006f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		glGetProgramiv(uiProgramObject, GL_INFO_LOG_LENGTH, &i32InfoLogLength);
4016f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		char* pszInfoLog = new char[i32InfoLogLength];
4026f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		glGetProgramInfoLog(uiProgramObject, i32InfoLogLength, &i32CharsWritten, pszInfoLog);
4036f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
4046f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		MessageBox(hWnd, i32InfoLogLength ? pszInfoLog : _T(""), _T("Failed to link program"), MB_OK|MB_ICONEXCLAMATION);
4056f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
4066f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		delete[] pszInfoLog;
4076f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		goto cleanup;
4086f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	}
4096f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
4106f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	// Actually use the created program
4116f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens    glUseProgram(uiProgramObject);
4126f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
4136f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	// Sets the clear color.
4146f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	// The colours are passed per channel (red,green,blue,alpha) as float values from 0.0 to 1.0
4156f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	glClearColor(0.6f, 0.8f, 1.0f, 1.0f);
4166f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
4176f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	// Enable culling
4186f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	glEnable(GL_CULL_FACE);
4196f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
4206f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	// We're going to draw a triangle to the screen so create a vertex buffer object for our triangle
4216f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	GLuint	ui32Vbo; // Vertex buffer object handle
4226f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
4236f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	// Interleaved vertex data
4246f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	GLfloat afVertices[] = {	-0.4f,-0.4f,0.0f, // Position
4256f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens								0.4f ,-0.4f,0.0f,
4266f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens								0.0f ,0.4f ,0.0f};
4276f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
4286f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	// Generate the vertex buffer object (VBO)
4296f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	glGenBuffers(1, &ui32Vbo);
4306f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
4316f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	// Bind the VBO so we can fill it with data
4326f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	glBindBuffer(GL_ARRAY_BUFFER, ui32Vbo);
4336f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
4346f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	// Set the buffer's data
4356f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	unsigned int uiSize = 3 * (sizeof(GLfloat) * 3); // Calc afVertices size (3 vertices * stride (3 GLfloats per vertex))
4366f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	glBufferData(GL_ARRAY_BUFFER, uiSize, afVertices, GL_STATIC_DRAW);
4376f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
4386f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	// Draws a triangle for 800 frames
4396f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	for(int i = 0; i < 800; ++i)
4406f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	{
4416f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		// Check if the message handler finished the demo
4426f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		if (g_bDemoDone) break;
4436f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
4446f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		/*
4456f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens			Clears the color buffer.
4466f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens			glClear() can also be used to clear the depth or stencil buffer
4476f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens			(GL_DEPTH_BUFFER_BIT or GL_STENCIL_BUFFER_BIT)
4486f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		*/
4496f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		glClear(GL_COLOR_BUFFER_BIT);
4506f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
4516f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		/*
4526f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens			Bind the projection model view matrix (PMVMatrix) to
4536f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens			the associated uniform variable in the shader
4546f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		*/
4556f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
4566f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		// First gets the location of that variable in the shader using its name
4576f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		int i32Location = glGetUniformLocation(uiProgramObject, "myPMVMatrix");
4586f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
4596f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		// Then passes the matrix to that variable
4606f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		glUniformMatrix4fv( i32Location, 1, GL_FALSE, pfIdentity);
4616f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
4626f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		/*
4636f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens			Enable the custom vertex attribute at index VERTEX_ARRAY.
4646f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens			We previously binded that index to the variable in our shader "vec4 MyVertex;"
4656f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		*/
4666f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		glEnableVertexAttribArray(VERTEX_ARRAY);
4676f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
4686f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		// Sets the vertex data to this attribute index
4696f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		glVertexAttribPointer(VERTEX_ARRAY, 3, GL_FLOAT, GL_FALSE, 0, 0);
4706f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
4716f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		/*
4726f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens			Draws a non-indexed triangle array from the pointers previously given.
4736f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens			This function allows the use of other primitive types : triangle strips, lines, ...
4746f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens			For indexed geometry, use the function glDrawElements() with an index list.
4756f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		*/
4766f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		glDrawArrays(GL_TRIANGLES, 0, 3);
4776f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
4786f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		/*
4796f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens			Swap Buffers.
4806f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens			Brings to the native display the current render surface.
4816f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		*/
4826f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		eglSwapBuffers(eglDisplay, eglSurface);
4836f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		if (!TestEGLError(hWnd, "eglSwapBuffers"))
4846f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		{
4856f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens			goto cleanup;
4866f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		}
4876f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
4886f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		// Managing the window messages
4896f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		MSG msg;
4906f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		PeekMessage(&msg, hWnd, NULL, NULL, PM_REMOVE);
4916f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		TranslateMessage(&msg);
4926f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		DispatchMessage(&msg);
4936f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
4946f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	}
4956f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
4966f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	// Frees the OpenGL handles for the program and the 2 shaders
4976f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	glDeleteProgram(uiProgramObject);
4986f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	glDeleteShader(uiFragShader);
4996f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	glDeleteShader(uiVertShader);
5006f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
5016f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	// Delete the VBO as it is no longer needed
5026f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	glDeleteBuffers(1, &ui32Vbo);
5036f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
5046f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	/*
5056f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		Step 10 - Terminate OpenGL ES and destroy the window (if present).
5066f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		eglTerminate takes care of destroying any context or surface created
5076f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		with this display, so we don't need to call eglDestroySurface or
5086f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		eglDestroyContext here.
5096f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	*/
5106f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capenscleanup:
5116f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
5126f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	eglTerminate(eglDisplay);
5136f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
5146f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	/*
5156f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		Step 11 - Destroy the eglWindow.
5166f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens		Again, this is platform specific and delegated to a separate function.
5176f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	*/
5186f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
5196f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	// Release the device context
5206f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	if (hDC) ReleaseDC(hWnd, hDC);
5216f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
5226f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	// Destroy the eglWindow
5236f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens	return 0;
5246f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens}
5256f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
5266f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens/******************************************************************************
5276f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens End of file (OGLES2HelloAPI_Windows.cpp)
5286f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens******************************************************************************/
5296f1f1567b9ab9394d3048d2cdf2786bc5bd1749bNicolas Capens
530