1150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph/* 2150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph * Copyright (C) 2017 The Android Open Source Project 3150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph * 4150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph * Licensed under the Apache License, Version 2.0 (the "License"); 5150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph * you may not use this file except in compliance with the License. 6150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph * You may obtain a copy of the License at 7150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph * 8150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph * http://www.apache.org/licenses/LICENSE-2.0 9150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph * 10150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph * Unless required by applicable law or agreed to in writing, software 11150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph * distributed under the License is distributed on an "AS IS" BASIS, 12150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph * See the License for the specific language governing permissions and 14150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph * limitations under the License. 15150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph */ 16150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph 17150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph#include "RenderBase.h" 18150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph#include "glError.h" 19150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph 20150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph#include <log/log.h> 21150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph#include <ui/GraphicBuffer.h> 22150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph 23150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph// Eventually we shouldn't need this dependency, but for now the 24150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph// graphics allocator interface isn't fully supported on all platforms 25150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph// and this is our work around. 26150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolphusing ::android::GraphicBuffer; 27150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph 28150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph 29150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph// OpenGL state shared among all renderers 30150c580464a7a4d6b0ad3362f23f790ded65e7abScott RandolphEGLDisplay RenderBase::sDisplay = EGL_NO_DISPLAY; 31150c580464a7a4d6b0ad3362f23f790ded65e7abScott RandolphEGLContext RenderBase::sContext = EGL_NO_CONTEXT; 32150c580464a7a4d6b0ad3362f23f790ded65e7abScott RandolphEGLSurface RenderBase::sDummySurface = EGL_NO_SURFACE; 33150c580464a7a4d6b0ad3362f23f790ded65e7abScott RandolphGLuint RenderBase::sFrameBuffer = -1; 34150c580464a7a4d6b0ad3362f23f790ded65e7abScott RandolphGLuint RenderBase::sColorBuffer = -1; 35150c580464a7a4d6b0ad3362f23f790ded65e7abScott RandolphGLuint RenderBase::sDepthBuffer = -1; 36150c580464a7a4d6b0ad3362f23f790ded65e7abScott RandolphEGLImageKHR RenderBase::sKHRimage = EGL_NO_IMAGE_KHR; 37150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolphunsigned RenderBase::sWidth = 0; 38150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolphunsigned RenderBase::sHeight = 0; 394a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolphfloat RenderBase::sAspectRatio = 0.0f; 40150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph 41150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph 42150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolphbool RenderBase::prepareGL() { 43150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph // Just trivially return success if we're already prepared 44150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph if (sDisplay != EGL_NO_DISPLAY) { 45150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph return true; 46150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph } 47150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph 48150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph // Hardcoded to RGBx output display 49150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph const EGLint config_attribs[] = { 50150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph // Tag Value 51150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, 52150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph EGL_RED_SIZE, 8, 53150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph EGL_GREEN_SIZE, 8, 54150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph EGL_BLUE_SIZE, 8, 55150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph EGL_NONE 56150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph }; 57150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph 58150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph // Select OpenGL ES v 3 59150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph const EGLint context_attribs[] = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE}; 60150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph 61150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph 62150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph // Set up our OpenGL ES context associated with the default display (though we won't be visible) 63150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); 64150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph if (display == EGL_NO_DISPLAY) { 65150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph ALOGE("Failed to get egl display"); 66150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph return false; 67150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph } 68150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph 69150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph EGLint major = 0; 70150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph EGLint minor = 0; 71150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph if (!eglInitialize(display, &major, &minor)) { 72150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph ALOGE("Failed to initialize EGL: %s", getEGLError()); 73150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph return false; 74150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph } else { 75150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph ALOGI("Intiialized EGL at %d.%d", major, minor); 76150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph } 77150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph 78150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph 79150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph // Select the configuration that "best" matches our desired characteristics 80150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph EGLConfig egl_config; 81150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph EGLint num_configs; 82150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph if (!eglChooseConfig(display, config_attribs, &egl_config, 1, &num_configs)) { 83150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph ALOGE("eglChooseConfig() failed with error: %s", getEGLError()); 84150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph return false; 85150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph } 86150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph 87150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph 88150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph // Create a dummy pbuffer so we have a surface to bind -- we never intend to draw to this 89150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph // because attachRenderTarget will be called first. 90150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph EGLint surface_attribs[] = { EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE }; 91150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph sDummySurface = eglCreatePbufferSurface(display, egl_config, surface_attribs); 92150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph if (sDummySurface == EGL_NO_SURFACE) { 93150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph ALOGE("Failed to create OpenGL ES Dummy surface: %s", getEGLError()); 94150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph return false; 95150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph } else { 96150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph ALOGI("Dummy surface looks good! :)"); 97150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph } 98150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph 99150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph 100150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph // 101150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph // Create the EGL context 102150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph // 103150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph EGLContext context = eglCreateContext(display, egl_config, EGL_NO_CONTEXT, context_attribs); 104150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph if (context == EGL_NO_CONTEXT) { 105150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph ALOGE("Failed to create OpenGL ES Context: %s", getEGLError()); 106150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph return false; 107150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph } 108150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph 109150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph 110150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph // Activate our render target for drawing 111150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph if (!eglMakeCurrent(display, sDummySurface, sDummySurface, context)) { 112150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph ALOGE("Failed to make the OpenGL ES Context current: %s", getEGLError()); 113150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph return false; 114150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph } else { 115150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph ALOGI("We made our context current! :)"); 116150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph } 117150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph 118150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph 119150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph // Report the extensions available on this implementation 120150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph const char* gl_extensions = (const char*) glGetString(GL_EXTENSIONS); 121150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph ALOGI("GL EXTENSIONS:\n %s", gl_extensions); 122150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph 123150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph 124150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph // Reserve handles for the color and depth targets we'll be setting up 125150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph glGenRenderbuffers(1, &sColorBuffer); 126150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph glGenRenderbuffers(1, &sDepthBuffer); 127150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph 128150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph // Set up the frame buffer object we can modify and use for off screen rendering 129150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph glGenFramebuffers(1, &sFrameBuffer); 130150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph glBindFramebuffer(GL_FRAMEBUFFER, sFrameBuffer); 131150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph 132150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph 133150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph // Now that we're assured success, store object handles we constructed 134150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph sDisplay = display; 135150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph sContext = context; 136150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph 137150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph return true; 138150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph} 139150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph 140150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph 141150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolphbool RenderBase::attachRenderTarget(const BufferDesc& tgtBuffer) { 142150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph // Hardcoded to RGBx for now 143150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph if (tgtBuffer.format != HAL_PIXEL_FORMAT_RGBA_8888) { 144150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph ALOGE("Unsupported target buffer format"); 145150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph return false; 146150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph } 147150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph 148150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph // create a GraphicBuffer from the existing handle 149150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph sp<GraphicBuffer> pGfxBuffer = new GraphicBuffer(tgtBuffer.memHandle, 150150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph GraphicBuffer::CLONE_HANDLE, 151150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph tgtBuffer.width, tgtBuffer.height, 152150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph tgtBuffer.format, 1, // layer count 153150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph GRALLOC_USAGE_HW_RENDER, 154150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph tgtBuffer.stride); 155150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph if (pGfxBuffer.get() == nullptr) { 156150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph ALOGE("Failed to allocate GraphicBuffer to wrap image handle"); 157150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph return false; 158150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph } 159150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph 160150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph // Get a GL compatible reference to the graphics buffer we've been given 161150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph EGLint eglImageAttributes[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE}; 162150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph EGLClientBuffer clientBuf = static_cast<EGLClientBuffer>(pGfxBuffer->getNativeBuffer()); 163150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph sKHRimage = eglCreateImageKHR(sDisplay, EGL_NO_CONTEXT, 164150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph EGL_NATIVE_BUFFER_ANDROID, clientBuf, 165150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph eglImageAttributes); 166150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph if (sKHRimage == EGL_NO_IMAGE_KHR) { 167150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph ALOGE("error creating EGLImage for target buffer: %s", getEGLError()); 168150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph return false; 169150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph } 170150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph 171150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph // Construct a render buffer around the external buffer 172150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph glBindRenderbuffer(GL_RENDERBUFFER, sColorBuffer); 173150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, static_cast<GLeglImageOES>(sKHRimage)); 174150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph if (eglGetError() != EGL_SUCCESS) { 175150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph ALOGI("glEGLImageTargetRenderbufferStorageOES => %s", getEGLError()); 176150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph return false; 177150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph } 178150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph 179150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, sColorBuffer); 180150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph if (eglGetError() != EGL_SUCCESS) { 181150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph ALOGE("glFramebufferRenderbuffer => %s", getEGLError()); 182150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph return false; 183150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph } 184150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph 185150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph GLenum checkResult = glCheckFramebufferStatus(GL_FRAMEBUFFER); 186150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph if (checkResult != GL_FRAMEBUFFER_COMPLETE) { 187150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph ALOGE("Offscreen framebuffer not configured successfully (%d: %s)", 188150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph checkResult, getGLFramebufferError()); 189150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph return false; 190150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph } 191150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph 1924a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph // Store the size of our target buffer 1934a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph sWidth = tgtBuffer.width; 1944a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph sHeight = tgtBuffer.height; 1954a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph sAspectRatio = (float)sWidth / sHeight; 1964a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph 1974a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph // Set the viewport 1984a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph glViewport(0, 0, sWidth, sHeight); 1994a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph 2004a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph#if 1 // We don't actually need the clear if we're going to cover the whole screen anyway 2014a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph // Clear the color buffer 2024a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph glClearColor(0.8f, 0.1f, 0.2f, 1.0f); 2034a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph glClear(GL_COLOR_BUFFER_BIT); 2044a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph#endif 2054a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph 2064a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph 207150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph return true; 208150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph} 209150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph 210150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph 211150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolphvoid RenderBase::detachRenderTarget() { 212150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph // Drop our external render target 213150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph if (sKHRimage != EGL_NO_IMAGE_KHR) { 214150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph eglDestroyImageKHR(sDisplay, sKHRimage); 215150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph sKHRimage = EGL_NO_IMAGE_KHR; 216150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph } 217150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph}