1 /* 2 * Copyright 2011, The Android Open Source Project 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * * Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * * Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #define LOG_TAG "GaneshContext" 27 #define LOG_NDEBUG 1 28 29 #include "config.h" 30 #include "GaneshContext.h" 31 32 #include "AndroidLog.h" 33 #include "GLUtils.h" 34 #include "TextureInfo.h" 35 #include "TilesManager.h" 36 #include "TransferQueue.h" 37 38 #include "android/native_window.h" 39 40 #if USE(ACCELERATED_COMPOSITING) 41 42 namespace WebCore { 43 44 GaneshContext::GaneshContext() 45 : m_grContext(0) 46 , m_tileDeviceSurface(0) 47 , m_surfaceConfig(0) 48 , m_surfaceContext(EGL_NO_CONTEXT) 49 { 50 } 51 52 GaneshContext* GaneshContext::gInstance = 0; 53 54 GaneshContext* GaneshContext::instance() 55 { 56 if (!gInstance) 57 gInstance = new GaneshContext(); 58 return gInstance; 59 } 60 61 GrContext* GaneshContext::getGrContext() 62 { 63 if (!m_grContext) 64 m_grContext = GrContext::Create(kOpenGL_Shaders_GrEngine, 0); 65 return m_grContext; 66 } 67 68 void GaneshContext::flush() 69 { 70 if (m_grContext) 71 m_grContext->flush(); 72 } 73 74 SkDevice* GaneshContext::getDeviceForTile(const TileRenderInfo& renderInfo) 75 { 76 // Ganesh should be the only code in the rendering thread that is using GL 77 // and setting the EGLContext. If this is not the case then we need to 78 // reset the Ganesh context to prevent rendering issues. 79 bool contextNeedsReset = false; 80 if (eglGetCurrentContext() != m_surfaceContext) { 81 ALOGV("Warning: EGLContext has Changed! %p, %p", 82 m_surfaceContext, eglGetCurrentContext()); 83 contextNeedsReset = true; 84 } 85 86 EGLDisplay display; 87 88 if (!m_surfaceContext) { 89 90 if(eglGetCurrentContext() != EGL_NO_CONTEXT) 91 ALOGV("ERROR: should not have a context yet"); 92 93 display = eglGetDisplay(EGL_DEFAULT_DISPLAY); 94 GLUtils::checkEglError("eglGetDisplay"); 95 96 EGLint majorVersion; 97 EGLint minorVersion; 98 EGLBoolean returnValue = eglInitialize(display, &majorVersion, &minorVersion); 99 GLUtils::checkEglError("eglInitialize", returnValue); 100 101 EGLint numConfigs; 102 static const EGLint configAttribs[] = { 103 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, 104 EGL_RED_SIZE, 8, 105 EGL_GREEN_SIZE, 8, 106 EGL_BLUE_SIZE, 8, 107 EGL_ALPHA_SIZE, 8, 108 EGL_STENCIL_SIZE, 8, 109 EGL_NONE 110 }; 111 112 eglChooseConfig(display, configAttribs, &m_surfaceConfig, 1, &numConfigs); 113 GLUtils::checkEglError("eglChooseConfig"); 114 115 static const EGLint contextAttribs[] = { 116 EGL_CONTEXT_CLIENT_VERSION, 2, 117 EGL_NONE 118 }; 119 120 m_surfaceContext = eglCreateContext(display, m_surfaceConfig, NULL, contextAttribs); 121 GLUtils::checkEglError("eglCreateContext"); 122 } else { 123 display = eglGetCurrentDisplay(); 124 GLUtils::checkEglError("eglGetCurrentDisplay"); 125 } 126 127 TransferQueue* tileQueue = TilesManager::instance()->transferQueue(); 128 if (tileQueue->m_eglSurface == EGL_NO_SURFACE) { 129 130 const float tileWidth = renderInfo.tileSize.width(); 131 const float tileHeight = renderInfo.tileSize.height(); 132 133 ANativeWindow* anw = tileQueue->m_ANW.get(); 134 135 int result = ANativeWindow_setBuffersGeometry(anw, (int)tileWidth, 136 (int)tileHeight, WINDOW_FORMAT_RGBA_8888); 137 138 renderInfo.textureInfo->m_width = tileWidth; 139 renderInfo.textureInfo->m_height = tileHeight; 140 tileQueue->m_eglSurface = eglCreateWindowSurface(display, m_surfaceConfig, anw, NULL); 141 142 GLUtils::checkEglError("eglCreateWindowSurface"); 143 ALOGV("eglCreateWindowSurface"); 144 } 145 146 EGLBoolean returnValue = eglMakeCurrent(display, tileQueue->m_eglSurface, tileQueue->m_eglSurface, m_surfaceContext); 147 GLUtils::checkEglError("eglMakeCurrent", returnValue); 148 ALOGV("eglMakeCurrent"); 149 150 if (!m_tileDeviceSurface) { 151 152 GrPlatformRenderTargetDesc renderTargetDesc; 153 renderTargetDesc.fWidth = TilesManager::tileWidth(); 154 renderTargetDesc.fHeight = TilesManager::tileHeight(); 155 renderTargetDesc.fConfig = kRGBA_8888_GrPixelConfig; 156 renderTargetDesc.fSampleCnt = 0; 157 renderTargetDesc.fStencilBits = 8; 158 renderTargetDesc.fRenderTargetHandle = 0; 159 160 GrContext* grContext = getGrContext(); 161 GrRenderTarget* renderTarget = grContext->createPlatformRenderTarget(renderTargetDesc); 162 163 m_tileDeviceSurface = new SkGpuDevice(grContext, renderTarget); 164 renderTarget->unref(); 165 ALOGV("generated device %p", m_tileDeviceSurface); 166 } 167 168 GLUtils::checkGlError("getDeviceForTile"); 169 170 // We must reset the Ganesh context only after we are sure we have 171 // re-established our EGLContext as the current context. 172 if (m_tileDeviceSurface && contextNeedsReset) 173 getGrContext()->resetContext(); 174 175 return m_tileDeviceSurface; 176 } 177 178 179 180 } // namespace WebCore 181 182 #endif // USE(ACCELERATED_COMPOSITING) 183