Home | History | Annotate | Download | only in rendering
      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