1b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph/* 2b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph * Copyright (C) 2017 The Android Open Source Project 3b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph * 4b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph * Licensed under the Apache License, Version 2.0 (the "License"); 5b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph * you may not use this file except in compliance with the License. 6b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph * You may obtain a copy of the License at 7b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph * 8b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph * http://www.apache.org/licenses/LICENSE-2.0 9b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph * 10b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph * Unless required by applicable law or agreed to in writing, software 11b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph * distributed under the License is distributed on an "AS IS" BASIS, 12b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph * See the License for the specific language governing permissions and 14b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph * limitations under the License. 15b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph */ 16b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 17b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph#include "GlWrapper.h" 18b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 19b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph#include <stdio.h> 20b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph#include <fcntl.h> 21b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph#include <sys/ioctl.h> 22b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 23b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph#include <ui/DisplayInfo.h> 24b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph#include <ui/GraphicBuffer.h> 25b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph#include <ui/GraphicBufferAllocator.h> 26b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph#include <ui/GraphicBufferMapper.h> 27b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 28b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 29b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolphusing namespace android; 30b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 31b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 32b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph// TODO: Consider dropping direct use of GraphicsBufferAllocator and Mapper? 33b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolphusing android::GraphicBuffer; 34b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolphusing android::GraphicBufferAllocator; 35b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolphusing android::GraphicBufferMapper; 36b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolphusing android::sp; 37b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 38b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 39b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolphconst char vertexShaderSource[] = "" 40b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph "#version 300 es \n" 41b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph "layout(location = 0) in vec4 pos; \n" 42b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph "layout(location = 1) in vec2 tex; \n" 43b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph "out vec2 uv; \n" 44b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph "void main() \n" 45b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph "{ \n" 46b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph " gl_Position = pos; \n" 47b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph " uv = tex; \n" 48b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph "} \n"; 49b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 50b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolphconst char pixelShaderSource[] = 51b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph "#version 300 es \n" 52b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph "precision mediump float; \n" 53b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph "uniform sampler2D tex; \n" 54b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph "in vec2 uv; \n" 55b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph "out vec4 color; \n" 56b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph "void main() \n" 57b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph "{ \n" 58b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph " vec4 texel = texture(tex, uv); \n" 59b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph " color = texel; \n" 60b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph "} \n"; 61b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 62b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 63b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolphstatic const char *getEGLError(void) { 64b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph switch (eglGetError()) { 65b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph case EGL_SUCCESS: 66b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph return "EGL_SUCCESS"; 67b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph case EGL_NOT_INITIALIZED: 68b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph return "EGL_NOT_INITIALIZED"; 69b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph case EGL_BAD_ACCESS: 70b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph return "EGL_BAD_ACCESS"; 71b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph case EGL_BAD_ALLOC: 72b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph return "EGL_BAD_ALLOC"; 73b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph case EGL_BAD_ATTRIBUTE: 74b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph return "EGL_BAD_ATTRIBUTE"; 75b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph case EGL_BAD_CONTEXT: 76b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph return "EGL_BAD_CONTEXT"; 77b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph case EGL_BAD_CONFIG: 78b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph return "EGL_BAD_CONFIG"; 79b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph case EGL_BAD_CURRENT_SURFACE: 80b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph return "EGL_BAD_CURRENT_SURFACE"; 81b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph case EGL_BAD_DISPLAY: 82b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph return "EGL_BAD_DISPLAY"; 83b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph case EGL_BAD_SURFACE: 84b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph return "EGL_BAD_SURFACE"; 85b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph case EGL_BAD_MATCH: 86b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph return "EGL_BAD_MATCH"; 87b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph case EGL_BAD_PARAMETER: 88b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph return "EGL_BAD_PARAMETER"; 89b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph case EGL_BAD_NATIVE_PIXMAP: 90b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph return "EGL_BAD_NATIVE_PIXMAP"; 91b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph case EGL_BAD_NATIVE_WINDOW: 92b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph return "EGL_BAD_NATIVE_WINDOW"; 93b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph case EGL_CONTEXT_LOST: 94b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph return "EGL_CONTEXT_LOST"; 95b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph default: 96b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph return "Unknown error"; 97b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 98b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph} 99b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 100b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 101b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph// Given shader source, load and compile it 102b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolphstatic GLuint loadShader(GLenum type, const char *shaderSrc) { 103b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Create the shader object 104b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph GLuint shader = glCreateShader (type); 105b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if (shader == 0) { 106b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph return 0; 107b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 108b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 109b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Load and compile the shader 110b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph glShaderSource(shader, 1, &shaderSrc, nullptr); 111b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph glCompileShader(shader); 112b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 113b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Verify the compilation worked as expected 114b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph GLint compiled = 0; 115b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); 116b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if (!compiled) { 117b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ALOGE("Error compiling shader\n"); 118b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 119b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph GLint size = 0; 120b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &size); 121b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if (size > 0) 122b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph { 123b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Get and report the error message 124b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph char *infoLog = (char*)malloc(size); 125b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph glGetShaderInfoLog(shader, size, nullptr, infoLog); 126b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ALOGE(" msg:\n%s\n", infoLog); 127b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph free(infoLog); 128b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 129b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 130b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph glDeleteShader(shader); 131b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph return 0; 132b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 133b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 134b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph return shader; 135b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph} 136b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 137b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 138b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph// Create a program object given vertex and pixels shader source 139b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolphstatic GLuint buildShaderProgram(const char* vtxSrc, const char* pxlSrc) { 140b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph GLuint program = glCreateProgram(); 141b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if (program == 0) { 142b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ALOGE("Failed to allocate program object\n"); 143b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph return 0; 144b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 145b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 146b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Compile the shaders and bind them to this program 147b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph GLuint vertexShader = loadShader(GL_VERTEX_SHADER, vtxSrc); 148b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if (vertexShader == 0) { 149b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ALOGE("Failed to load vertex shader\n"); 150b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph glDeleteProgram(program); 151b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph return 0; 152b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 153b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pxlSrc); 154b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if (pixelShader == 0) { 155b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ALOGE("Failed to load pixel shader\n"); 156b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph glDeleteProgram(program); 157b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph glDeleteShader(vertexShader); 158b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph return 0; 159b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 160b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph glAttachShader(program, vertexShader); 161b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph glAttachShader(program, pixelShader); 162b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 163b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Link the program 164b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph glLinkProgram(program); 165b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph GLint linked = 0; 166b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph glGetProgramiv(program, GL_LINK_STATUS, &linked); 167b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if (!linked) 168b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph { 169b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ALOGE("Error linking program.\n"); 170b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph GLint size = 0; 171b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph glGetProgramiv(program, GL_INFO_LOG_LENGTH, &size); 172b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if (size > 0) 173b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph { 174b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Get and report the error message 175b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph char *infoLog = (char*)malloc(size); 176b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph glGetProgramInfoLog(program, size, nullptr, infoLog); 177b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ALOGE(" msg: %s\n", infoLog); 178b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph free(infoLog); 179b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 180b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 181b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph glDeleteProgram(program); 182b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph glDeleteShader(vertexShader); 183b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph glDeleteShader(pixelShader); 184b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph return 0; 185b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 186b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 187b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph return program; 188b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph} 189b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 190b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 191b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph// Main entry point 192b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolphbool GlWrapper::initialize() { 193b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // 194b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Create the native full screen window and get a suitable configuration to match it 195b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // 196b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph status_t err; 197b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 198f91b3fccfe62a0361f64c89218d3a7a2443f8d0aScott Randolph mFlinger = new SurfaceComposerClient(); 199f91b3fccfe62a0361f64c89218d3a7a2443f8d0aScott Randolph if (mFlinger == nullptr) { 200f91b3fccfe62a0361f64c89218d3a7a2443f8d0aScott Randolph ALOGE("SurfaceComposerClient couldn't be allocated"); 201f91b3fccfe62a0361f64c89218d3a7a2443f8d0aScott Randolph return false; 202f91b3fccfe62a0361f64c89218d3a7a2443f8d0aScott Randolph } 203b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph err = mFlinger->initCheck(); 204b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if (err != NO_ERROR) { 205b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ALOGE("SurfaceComposerClient::initCheck error: %#x", err); 206b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph return false; 207b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 208b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 209b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Get main display parameters. 210b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph sp <IBinder> mainDpy = SurfaceComposerClient::getBuiltInDisplay( 211b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ISurfaceComposer::eDisplayIdMain); 212b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph DisplayInfo mainDpyInfo; 213b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph err = SurfaceComposerClient::getDisplayInfo(mainDpy, &mainDpyInfo); 214b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if (err != NO_ERROR) { 215b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ALOGE("ERROR: unable to get display characteristics"); 216b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph return false; 217b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 218b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 219b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if (mainDpyInfo.orientation != DISPLAY_ORIENTATION_0 && 220b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph mainDpyInfo.orientation != DISPLAY_ORIENTATION_180) { 221b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // rotated 222b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph mWidth = mainDpyInfo.h; 223b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph mHeight = mainDpyInfo.w; 224b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } else { 225b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph mWidth = mainDpyInfo.w; 226b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph mHeight = mainDpyInfo.h; 227b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 228b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 229b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph mFlingerSurfaceControl = mFlinger->createSurface( 230b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph String8("Evs Display"), mWidth, mHeight, 231b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph PIXEL_FORMAT_RGBX_8888, ISurfaceComposerClient::eOpaque); 232b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if (mFlingerSurfaceControl == nullptr || !mFlingerSurfaceControl->isValid()) { 233b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ALOGE("Failed to create SurfaceControl"); 234b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph return false; 235b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 236b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph mFlingerSurface = mFlingerSurfaceControl->getSurface(); 237b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 238b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 239b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Set up our OpenGL ES context associated with the default display 240b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph mDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); 241b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if (mDisplay == EGL_NO_DISPLAY) { 242b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ALOGE("Failed to get egl display"); 243b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph return false; 244b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 245b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 246b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph EGLint major = 3; 247b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph EGLint minor = 0; 248b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if (!eglInitialize(mDisplay, &major, &minor)) { 249b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ALOGE("Failed to initialize EGL: %s", getEGLError()); 250b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph return false; 251b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 252b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 253b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 254b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph const EGLint config_attribs[] = { 255b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Tag Value 256b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph EGL_RED_SIZE, 8, 257b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph EGL_GREEN_SIZE, 8, 258b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph EGL_BLUE_SIZE, 8, 259b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph EGL_DEPTH_SIZE, 0, 260b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph EGL_NONE 261b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph }; 262b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 263b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Pick the default configuration without constraints (is this good enough?) 264b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph EGLConfig egl_config = {0}; 265b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph EGLint numConfigs = -1; 266b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph eglChooseConfig(mDisplay, config_attribs, &egl_config, 1, &numConfigs); 267b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if (numConfigs != 1) { 268b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ALOGE("Didn't find a suitable format for our display window"); 269b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph return false; 270b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 271b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 272b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Create the EGL render target surface 273b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph mSurface = eglCreateWindowSurface(mDisplay, egl_config, mFlingerSurface.get(), nullptr); 274b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if (mSurface == EGL_NO_SURFACE) { 275b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ALOGE("gelCreateWindowSurface failed."); 276b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph return false; 277b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 278b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 279b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Create the EGL context 280b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // NOTE: Our shader is (currently at least) written to require version 3, so this 281b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // is required. 282b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph const EGLint context_attribs[] = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE}; 283b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph mContext = eglCreateContext(mDisplay, egl_config, EGL_NO_CONTEXT, context_attribs); 284b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if (mContext == EGL_NO_CONTEXT) { 285b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ALOGE("Failed to create OpenGL ES Context: %s", getEGLError()); 286b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph return false; 287b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 288b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 289b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 290b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Activate our render target for drawing 291b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if (!eglMakeCurrent(mDisplay, mSurface, mSurface, mContext)) { 292b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ALOGE("Failed to make the OpenGL ES Context current: %s", getEGLError()); 293b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph return false; 294b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 295b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 296b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 297b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Create the shader program for our simple pipeline 298b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph mShaderProgram = buildShaderProgram(vertexShaderSource, pixelShaderSource); 299b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if (!mShaderProgram) { 300b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ALOGE("Failed to build shader program: %s", getEGLError()); 301b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph return false; 302b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 303b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 304b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Create a GL texture that will eventually wrap our externally created texture surface(s) 305b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph glGenTextures(1, &mTextureMap); 306b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if (mTextureMap <= 0) { 307b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ALOGE("Didn't get a texture handle allocated: %s", getEGLError()); 308b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph return false; 309b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 310b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 311b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 312b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph return true; 313b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph} 314b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 315b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 316b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolphvoid GlWrapper::shutdown() { 317b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 318b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Drop our device textures 319b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if (mKHRimage != EGL_NO_IMAGE_KHR) { 320b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph eglDestroyImageKHR(mDisplay, mKHRimage); 321b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph mKHRimage = EGL_NO_IMAGE_KHR; 322b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 323b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 324b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Release all GL resources 325b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); 326b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph eglDestroySurface(mDisplay, mSurface); 327b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph eglDestroyContext(mDisplay, mContext); 328b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph eglTerminate(mDisplay); 329b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph mSurface = EGL_NO_SURFACE; 330b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph mContext = EGL_NO_CONTEXT; 331b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph mDisplay = EGL_NO_DISPLAY; 332b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 333b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Let go of our SurfaceComposer resources 334b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph mFlingerSurface.clear(); 335b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph mFlingerSurfaceControl.clear(); 336b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph mFlinger.clear(); 337b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph} 338b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 339b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 340b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolphvoid GlWrapper::showWindow() { 341b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if (mFlingerSurfaceControl != nullptr) { 342b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph SurfaceComposerClient::openGlobalTransaction(); 343b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph mFlingerSurfaceControl->setLayer(0x7FFFFFFF); // always on top 344b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph mFlingerSurfaceControl->show(); 345b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph SurfaceComposerClient::closeGlobalTransaction(); 346b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 347b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph} 348b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 349b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 350b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolphvoid GlWrapper::hideWindow() { 351b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if (mFlingerSurfaceControl != nullptr) { 352b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph SurfaceComposerClient::openGlobalTransaction(); 353b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph mFlingerSurfaceControl->hide(); 354b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph SurfaceComposerClient::closeGlobalTransaction(); 355b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 356b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph} 357b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 358b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 359b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolphbool GlWrapper::updateImageTexture(const BufferDesc& buffer) { 360b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 361b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // If we haven't done it yet, create an "image" object to wrap the gralloc buffer 362b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if (mKHRimage == EGL_NO_IMAGE_KHR) { 363b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // create a temporary GraphicBuffer to wrap the provided handle 364b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph sp<GraphicBuffer> pGfxBuffer = new GraphicBuffer( 365b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph buffer.width, 366b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph buffer.height, 367b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph buffer.format, 368b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 1, /* layer count */ 369b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph buffer.usage, 370b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph buffer.stride, 371b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph const_cast<native_handle_t*>(buffer.memHandle.getNativeHandle()), 372b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph false /* keep ownership */ 373b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ); 374b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if (pGfxBuffer.get() == nullptr) { 375b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ALOGE("Failed to allocate GraphicsBuffer to wrap our native handle"); 376b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph return false; 377b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 378b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 379b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 380b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Get a GL compatible reference to the graphics buffer we've been given 381b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph EGLint eglImageAttributes[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE}; 382b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph EGLClientBuffer cbuf = static_cast<EGLClientBuffer>(pGfxBuffer->getNativeBuffer()); 383b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph// TODO: If we pass in a context, we get "bad context" back 384b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph#if 0 385b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph mKHRimage = eglCreateImageKHR(mDisplay, mContext, 386b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph EGL_NATIVE_BUFFER_ANDROID, cbuf, 387b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph eglImageAttributes); 388b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph#else 389b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph mKHRimage = eglCreateImageKHR(mDisplay, EGL_NO_CONTEXT, 390b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph EGL_NATIVE_BUFFER_ANDROID, cbuf, 391b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph eglImageAttributes); 392b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph#endif 393b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if (mKHRimage == EGL_NO_IMAGE_KHR) { 394b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ALOGE("error creating EGLImage: %s", getEGLError()); 395b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph return false; 396b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 397b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 398b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 399b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Update the texture handle we already created to refer to this gralloc buffer 400b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph glActiveTexture(GL_TEXTURE0); 401b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph glBindTexture(GL_TEXTURE_2D, mTextureMap); 402b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, static_cast<GLeglImageOES>(mKHRimage)); 403b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 404b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 405b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 406b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph return true; 407b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph} 408b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 409b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 410b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolphvoid GlWrapper::renderImageToScreen() { 411b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Set the viewport 412b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph glViewport(0, 0, mWidth, mHeight); 413b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 414b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Clear the color buffer 415b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph glClearColor(0.1f, 0.5f, 0.1f, 1.0f); 416b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph glClear(GL_COLOR_BUFFER_BIT); 417b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 418b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Select our screen space simple texture shader 419b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph glUseProgram(mShaderProgram); 420b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 421b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Bind the texture and assign it to the shader's sampler 422b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph glActiveTexture(GL_TEXTURE0); 423b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph glBindTexture(GL_TEXTURE_2D, mTextureMap); 424b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph GLint sampler = glGetUniformLocation(mShaderProgram, "tex"); 425b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph glUniform1i(sampler, 0); 426b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 427b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // We want our image to show up opaque regardless of alpha values 428b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph glDisable(GL_BLEND); 429b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 430b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 431b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Draw a rectangle on the screen 432b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // TODO: We pulled in from the edges for now for diagnostic purposes... 433b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph#if 0 434b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph GLfloat vertsCarPos[] = { -1.0, 1.0, 0.0f, // left top in window space 435b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 1.0, 1.0, 0.0f, // right top 436b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph -1.0, -1.0, 0.0f, // left bottom 437b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 1.0, -1.0, 0.0f // right bottom 438b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph }; 439b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph#else 440b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph GLfloat vertsCarPos[] = { -0.8, 0.8, 0.0f, // left top in window space 441b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 0.8, 0.8, 0.0f, // right top 442b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph -0.8, -0.8, 0.0f, // left bottom 443b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 0.8, -0.8, 0.0f // right bottom 444b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph }; 445b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph#endif 446b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // NOTE: We didn't flip the image in the texture, so V=0 is actually the top of the image 447b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph GLfloat vertsCarTex[] = { 0.0f, 0.0f, // left top 448b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 1.0f, 0.0f, // right top 449b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 0.0f, 1.0f, // left bottom 450b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 1.0f, 1.0f // right bottom 451b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph }; 452b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vertsCarPos); 453b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, vertsCarTex); 454b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph glEnableVertexAttribArray(0); 455b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph glEnableVertexAttribArray(1); 456b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 457b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 458b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 459b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 460b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Clean up and flip the rendered result to the front so it is visible 461b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph glDisableVertexAttribArray(0); 462b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph glDisableVertexAttribArray(1); 463b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 464b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph glFinish(); 465b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 466b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph eglSwapBuffers(mDisplay, mSurface); 467b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph} 468b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 469