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