/* * Copyright 2011, The Android Open Source Project * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #define LOG_TAG "GaneshContext" #define LOG_NDEBUG 1 #include "config.h" #include "GaneshContext.h" #include "AndroidLog.h" #include "GLUtils.h" #include "TextureInfo.h" #include "TilesManager.h" #include "TransferQueue.h" #include "android/native_window.h" #if USE(ACCELERATED_COMPOSITING) namespace WebCore { GaneshContext::GaneshContext() : m_grContext(0) , m_tileDeviceSurface(0) , m_surfaceConfig(0) , m_surfaceContext(EGL_NO_CONTEXT) { } GaneshContext* GaneshContext::gInstance = 0; GaneshContext* GaneshContext::instance() { if (!gInstance) gInstance = new GaneshContext(); return gInstance; } GrContext* GaneshContext::getGrContext() { if (!m_grContext) m_grContext = GrContext::Create(kOpenGL_Shaders_GrEngine, 0); return m_grContext; } void GaneshContext::flush() { if (m_grContext) m_grContext->flush(); } SkDevice* GaneshContext::getDeviceForTile(const TileRenderInfo& renderInfo) { // Ganesh should be the only code in the rendering thread that is using GL // and setting the EGLContext. If this is not the case then we need to // reset the Ganesh context to prevent rendering issues. bool contextNeedsReset = false; if (eglGetCurrentContext() != m_surfaceContext) { ALOGV("Warning: EGLContext has Changed! %p, %p", m_surfaceContext, eglGetCurrentContext()); contextNeedsReset = true; } EGLDisplay display; if (!m_surfaceContext) { if(eglGetCurrentContext() != EGL_NO_CONTEXT) ALOGV("ERROR: should not have a context yet"); display = eglGetDisplay(EGL_DEFAULT_DISPLAY); GLUtils::checkEglError("eglGetDisplay"); EGLint majorVersion; EGLint minorVersion; EGLBoolean returnValue = eglInitialize(display, &majorVersion, &minorVersion); GLUtils::checkEglError("eglInitialize", returnValue); EGLint numConfigs; static const EGLint configAttribs[] = { EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 8, EGL_STENCIL_SIZE, 8, EGL_NONE }; eglChooseConfig(display, configAttribs, &m_surfaceConfig, 1, &numConfigs); GLUtils::checkEglError("eglChooseConfig"); static const EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; m_surfaceContext = eglCreateContext(display, m_surfaceConfig, NULL, contextAttribs); GLUtils::checkEglError("eglCreateContext"); } else { display = eglGetCurrentDisplay(); GLUtils::checkEglError("eglGetCurrentDisplay"); } TransferQueue* tileQueue = TilesManager::instance()->transferQueue(); if (tileQueue->m_eglSurface == EGL_NO_SURFACE) { const float tileWidth = renderInfo.tileSize.width(); const float tileHeight = renderInfo.tileSize.height(); ANativeWindow* anw = tileQueue->m_ANW.get(); int result = ANativeWindow_setBuffersGeometry(anw, (int)tileWidth, (int)tileHeight, WINDOW_FORMAT_RGBA_8888); renderInfo.textureInfo->m_width = tileWidth; renderInfo.textureInfo->m_height = tileHeight; tileQueue->m_eglSurface = eglCreateWindowSurface(display, m_surfaceConfig, anw, NULL); GLUtils::checkEglError("eglCreateWindowSurface"); ALOGV("eglCreateWindowSurface"); } EGLBoolean returnValue = eglMakeCurrent(display, tileQueue->m_eglSurface, tileQueue->m_eglSurface, m_surfaceContext); GLUtils::checkEglError("eglMakeCurrent", returnValue); ALOGV("eglMakeCurrent"); if (!m_tileDeviceSurface) { GrPlatformRenderTargetDesc renderTargetDesc; renderTargetDesc.fWidth = TilesManager::tileWidth(); renderTargetDesc.fHeight = TilesManager::tileHeight(); renderTargetDesc.fConfig = kRGBA_8888_PM_GrPixelConfig; renderTargetDesc.fSampleCnt = 0; renderTargetDesc.fStencilBits = 8; renderTargetDesc.fRenderTargetHandle = 0; GrContext* grContext = getGrContext(); GrRenderTarget* renderTarget = grContext->createPlatformRenderTarget(renderTargetDesc); m_tileDeviceSurface = new SkGpuDevice(grContext, renderTarget); renderTarget->unref(); ALOGV("generated device %p", m_tileDeviceSurface); } GLUtils::checkGlError("getDeviceForTile"); // We must reset the Ganesh context only after we are sure we have // re-established our EGLContext as the current context. if (m_tileDeviceSurface && contextNeedsReset) getGrContext()->resetContext(); return m_tileDeviceSurface; } } // namespace WebCore #endif // USE(ACCELERATED_COMPOSITING)