Home | History | Annotate | Download | only in renderstate
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 #include <GpuMemoryTracker.h>
     17 #include "renderstate/RenderState.h"
     18 
     19 #include "renderthread/CanvasContext.h"
     20 #include "renderthread/EglManager.h"
     21 #include "utils/GLUtils.h"
     22 #include <algorithm>
     23 
     24 namespace android {
     25 namespace uirenderer {
     26 
     27 RenderState::RenderState(renderthread::RenderThread& thread)
     28         : mRenderThread(thread)
     29         , mViewportWidth(0)
     30         , mViewportHeight(0)
     31         , mFramebuffer(0) {
     32     mThreadId = pthread_self();
     33 }
     34 
     35 RenderState::~RenderState() {
     36     LOG_ALWAYS_FATAL_IF(mBlend || mMeshState || mScissor || mStencil,
     37             "State object lifecycle not managed correctly");
     38 }
     39 
     40 void RenderState::onGLContextCreated() {
     41     LOG_ALWAYS_FATAL_IF(mBlend || mMeshState || mScissor || mStencil,
     42             "State object lifecycle not managed correctly");
     43     GpuMemoryTracker::onGLContextCreated();
     44 
     45     mBlend = new Blend();
     46     mMeshState = new MeshState();
     47     mScissor = new Scissor();
     48     mStencil = new Stencil();
     49 
     50     // This is delayed because the first access of Caches makes GL calls
     51     if (!mCaches) {
     52         mCaches = &Caches::createInstance(*this);
     53     }
     54     mCaches->init();
     55     mCaches->textureCache.setAssetAtlas(&mAssetAtlas);
     56 }
     57 
     58 static void layerLostGlContext(Layer* layer) {
     59     layer->onGlContextLost();
     60 }
     61 
     62 void RenderState::onGLContextDestroyed() {
     63 /*
     64     size_t size = mActiveLayers.size();
     65     if (CC_UNLIKELY(size != 0)) {
     66         ALOGE("Crashing, have %d contexts and %d layers at context destruction. isempty %d",
     67                 mRegisteredContexts.size(), size, mActiveLayers.empty());
     68         mCaches->dumpMemoryUsage();
     69         for (std::set<renderthread::CanvasContext*>::iterator cit = mRegisteredContexts.begin();
     70                 cit != mRegisteredContexts.end(); cit++) {
     71             renderthread::CanvasContext* context = *cit;
     72             ALOGE("Context: %p (root = %p)", context, context->mRootRenderNode.get());
     73             ALOGE("  Prefeteched layers: %zu", context->mPrefetechedLayers.size());
     74             for (std::set<RenderNode*>::iterator pit = context->mPrefetechedLayers.begin();
     75                     pit != context->mPrefetechedLayers.end(); pit++) {
     76                 (*pit)->debugDumpLayers("    ");
     77             }
     78             context->mRootRenderNode->debugDumpLayers("  ");
     79         }
     80 
     81 
     82         if (mActiveLayers.begin() == mActiveLayers.end()) {
     83             ALOGE("set has become empty. wat.");
     84         }
     85         for (std::set<const Layer*>::iterator lit = mActiveLayers.begin();
     86              lit != mActiveLayers.end(); lit++) {
     87             const Layer* layer = *(lit);
     88             ALOGE("Layer %p, state %d, texlayer %d, fbo %d, buildlayered %d",
     89                     layer, layer->state, layer->isTextureLayer(), layer->getFbo(), layer->wasBuildLayered);
     90         }
     91         LOG_ALWAYS_FATAL("%d layers have survived gl context destruction", size);
     92     }
     93 */
     94 
     95     mLayerPool.clear();
     96 
     97     // TODO: reset all cached state in state objects
     98     std::for_each(mActiveLayers.begin(), mActiveLayers.end(), layerLostGlContext);
     99     mAssetAtlas.terminate();
    100 
    101     mCaches->terminate();
    102 
    103     delete mBlend;
    104     mBlend = nullptr;
    105     delete mMeshState;
    106     mMeshState = nullptr;
    107     delete mScissor;
    108     mScissor = nullptr;
    109     delete mStencil;
    110     mStencil = nullptr;
    111 
    112     GpuMemoryTracker::onGLContextDestroyed();
    113 }
    114 
    115 void RenderState::flush(Caches::FlushMode mode) {
    116     switch (mode) {
    117         case Caches::FlushMode::Full:
    118             // fall through
    119         case Caches::FlushMode::Moderate:
    120             // fall through
    121         case Caches::FlushMode::Layers:
    122             mLayerPool.clear();
    123             break;
    124     }
    125     mCaches->flush(mode);
    126 }
    127 
    128 void RenderState::setViewport(GLsizei width, GLsizei height) {
    129     mViewportWidth = width;
    130     mViewportHeight = height;
    131     glViewport(0, 0, mViewportWidth, mViewportHeight);
    132 }
    133 
    134 
    135 void RenderState::getViewport(GLsizei* outWidth, GLsizei* outHeight) {
    136     *outWidth = mViewportWidth;
    137     *outHeight = mViewportHeight;
    138 }
    139 
    140 void RenderState::bindFramebuffer(GLuint fbo) {
    141     if (mFramebuffer != fbo) {
    142         mFramebuffer = fbo;
    143         glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
    144     }
    145 }
    146 
    147 GLuint RenderState::createFramebuffer() {
    148     GLuint ret;
    149     glGenFramebuffers(1, &ret);
    150     return ret;
    151 }
    152 
    153 void RenderState::deleteFramebuffer(GLuint fbo) {
    154     if (mFramebuffer == fbo) {
    155         // GL defines that deleting the currently bound FBO rebinds FBO 0.
    156         // Reflect this in our cached value.
    157         mFramebuffer = 0;
    158     }
    159     glDeleteFramebuffers(1, &fbo);
    160 }
    161 
    162 void RenderState::invokeFunctor(Functor* functor, DrawGlInfo::Mode mode, DrawGlInfo* info) {
    163     if (mode == DrawGlInfo::kModeProcessNoContext) {
    164         // If there's no context we don't need to interrupt as there's
    165         // no gl state to save/restore
    166         (*functor)(mode, info);
    167     } else {
    168         interruptForFunctorInvoke();
    169         (*functor)(mode, info);
    170         resumeFromFunctorInvoke();
    171     }
    172 }
    173 
    174 void RenderState::interruptForFunctorInvoke() {
    175     mCaches->setProgram(nullptr);
    176     mCaches->textureState().resetActiveTexture();
    177     meshState().unbindMeshBuffer();
    178     meshState().unbindIndicesBuffer();
    179     meshState().resetVertexPointers();
    180     meshState().disableTexCoordsVertexArray();
    181     debugOverdraw(false, false);
    182 }
    183 
    184 void RenderState::resumeFromFunctorInvoke() {
    185     glViewport(0, 0, mViewportWidth, mViewportHeight);
    186     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
    187     debugOverdraw(false, false);
    188 
    189     glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    190 
    191     scissor().invalidate();
    192     blend().invalidate();
    193 
    194     mCaches->textureState().activateTexture(0);
    195     mCaches->textureState().resetBoundTextures();
    196 }
    197 
    198 void RenderState::debugOverdraw(bool enable, bool clear) {
    199     if (Properties::debugOverdraw && mFramebuffer == 0) {
    200         if (clear) {
    201             scissor().setEnabled(false);
    202             stencil().clear();
    203         }
    204         if (enable) {
    205             stencil().enableDebugWrite();
    206         } else {
    207             stencil().disable();
    208         }
    209     }
    210 }
    211 
    212 class DecStrongTask : public renderthread::RenderTask {
    213 public:
    214     DecStrongTask(VirtualLightRefBase* object) : mObject(object) {}
    215 
    216     virtual void run() override {
    217         mObject->decStrong(nullptr);
    218         mObject = nullptr;
    219         delete this;
    220     }
    221 
    222 private:
    223     VirtualLightRefBase* mObject;
    224 };
    225 
    226 void RenderState::postDecStrong(VirtualLightRefBase* object) {
    227     if (pthread_equal(mThreadId, pthread_self())) {
    228         object->decStrong(nullptr);
    229     } else {
    230         mRenderThread.queue(new DecStrongTask(object));
    231     }
    232 }
    233 
    234 ///////////////////////////////////////////////////////////////////////////////
    235 // Render
    236 ///////////////////////////////////////////////////////////////////////////////
    237 
    238 void RenderState::render(const Glop& glop, const Matrix4& orthoMatrix) {
    239     const Glop::Mesh& mesh = glop.mesh;
    240     const Glop::Mesh::Vertices& vertices = mesh.vertices;
    241     const Glop::Mesh::Indices& indices = mesh.indices;
    242     const Glop::Fill& fill = glop.fill;
    243 
    244     GL_CHECKPOINT(MODERATE);
    245 
    246     // ---------------------------------------------
    247     // ---------- Program + uniform setup ----------
    248     // ---------------------------------------------
    249     mCaches->setProgram(fill.program);
    250 
    251     if (fill.colorEnabled) {
    252         fill.program->setColor(fill.color);
    253     }
    254 
    255     fill.program->set(orthoMatrix,
    256             glop.transform.modelView,
    257             glop.transform.meshTransform(),
    258             glop.transform.transformFlags & TransformFlags::OffsetByFudgeFactor);
    259 
    260     // Color filter uniforms
    261     if (fill.filterMode == ProgramDescription::ColorFilterMode::Blend) {
    262         const FloatColor& color = fill.filter.color;
    263         glUniform4f(mCaches->program().getUniform("colorBlend"),
    264                 color.r, color.g, color.b, color.a);
    265     } else if (fill.filterMode == ProgramDescription::ColorFilterMode::Matrix) {
    266         glUniformMatrix4fv(mCaches->program().getUniform("colorMatrix"), 1, GL_FALSE,
    267                 fill.filter.matrix.matrix);
    268         glUniform4fv(mCaches->program().getUniform("colorMatrixVector"), 1,
    269                 fill.filter.matrix.vector);
    270     }
    271 
    272     // Round rect clipping uniforms
    273     if (glop.roundRectClipState) {
    274         // TODO: avoid query, and cache values (or RRCS ptr) in program
    275         const RoundRectClipState* state = glop.roundRectClipState;
    276         const Rect& innerRect = state->innerRect;
    277         glUniform4f(fill.program->getUniform("roundRectInnerRectLTRB"),
    278                 innerRect.left, innerRect.top,
    279                 innerRect.right, innerRect.bottom);
    280         glUniformMatrix4fv(fill.program->getUniform("roundRectInvTransform"),
    281                 1, GL_FALSE, &state->matrix.data[0]);
    282 
    283         // add half pixel to round out integer rect space to cover pixel centers
    284         float roundedOutRadius = state->radius + 0.5f;
    285         glUniform1f(fill.program->getUniform("roundRectRadius"),
    286                 roundedOutRadius);
    287     }
    288 
    289     GL_CHECKPOINT(MODERATE);
    290 
    291     // --------------------------------
    292     // ---------- Mesh setup ----------
    293     // --------------------------------
    294     // vertices
    295     meshState().bindMeshBuffer(vertices.bufferObject);
    296     meshState().bindPositionVertexPointer(vertices.position, vertices.stride);
    297 
    298     // indices
    299     meshState().bindIndicesBuffer(indices.bufferObject);
    300 
    301     // texture
    302     if (fill.texture.texture != nullptr) {
    303         const Glop::Fill::TextureData& texture = fill.texture;
    304         // texture always takes slot 0, shader samplers increment from there
    305         mCaches->textureState().activateTexture(0);
    306 
    307         mCaches->textureState().bindTexture(texture.target, texture.texture->id());
    308         if (texture.clamp != GL_INVALID_ENUM) {
    309             texture.texture->setWrap(texture.clamp, false, false, texture.target);
    310         }
    311         if (texture.filter != GL_INVALID_ENUM) {
    312             texture.texture->setFilter(texture.filter, false, false, texture.target);
    313         }
    314 
    315         if (texture.textureTransform) {
    316             glUniformMatrix4fv(fill.program->getUniform("mainTextureTransform"), 1,
    317                     GL_FALSE, &texture.textureTransform->data[0]);
    318         }
    319     }
    320 
    321     // vertex attributes (tex coord, color, alpha)
    322     if (vertices.attribFlags & VertexAttribFlags::TextureCoord) {
    323         meshState().enableTexCoordsVertexArray();
    324         meshState().bindTexCoordsVertexPointer(vertices.texCoord, vertices.stride);
    325     } else {
    326         meshState().disableTexCoordsVertexArray();
    327     }
    328     int colorLocation = -1;
    329     if (vertices.attribFlags & VertexAttribFlags::Color) {
    330         colorLocation = fill.program->getAttrib("colors");
    331         glEnableVertexAttribArray(colorLocation);
    332         glVertexAttribPointer(colorLocation, 4, GL_FLOAT, GL_FALSE, vertices.stride, vertices.color);
    333     }
    334     int alphaLocation = -1;
    335     if (vertices.attribFlags & VertexAttribFlags::Alpha) {
    336         // NOTE: alpha vertex position is computed assuming no VBO
    337         const void* alphaCoords = ((const GLbyte*) vertices.position) + kVertexAlphaOffset;
    338         alphaLocation = fill.program->getAttrib("vtxAlpha");
    339         glEnableVertexAttribArray(alphaLocation);
    340         glVertexAttribPointer(alphaLocation, 1, GL_FLOAT, GL_FALSE, vertices.stride, alphaCoords);
    341     }
    342     // Shader uniforms
    343     SkiaShader::apply(*mCaches, fill.skiaShaderData);
    344 
    345     GL_CHECKPOINT(MODERATE);
    346     Texture* texture = (fill.skiaShaderData.skiaShaderType & kBitmap_SkiaShaderType) ?
    347             fill.skiaShaderData.bitmapData.bitmapTexture : nullptr;
    348     const AutoTexture autoCleanup(texture);
    349 
    350     // ------------------------------------
    351     // ---------- GL state setup ----------
    352     // ------------------------------------
    353     blend().setFactors(glop.blend.src, glop.blend.dst);
    354 
    355     GL_CHECKPOINT(MODERATE);
    356 
    357     // ------------------------------------
    358     // ---------- Actual drawing ----------
    359     // ------------------------------------
    360     if (indices.bufferObject == meshState().getQuadListIBO()) {
    361         // Since the indexed quad list is of limited length, we loop over
    362         // the glDrawXXX method while updating the vertex pointer
    363         GLsizei elementsCount = mesh.elementCount;
    364         const GLbyte* vertexData = static_cast<const GLbyte*>(vertices.position);
    365         while (elementsCount > 0) {
    366             GLsizei drawCount = std::min(elementsCount, (GLsizei) kMaxNumberOfQuads * 6);
    367             meshState().bindPositionVertexPointer(vertexData, vertices.stride);
    368             if (vertices.attribFlags & VertexAttribFlags::TextureCoord) {
    369                 meshState().bindTexCoordsVertexPointer(
    370                         vertexData + kMeshTextureOffset, vertices.stride);
    371             }
    372 
    373             glDrawElements(mesh.primitiveMode, drawCount, GL_UNSIGNED_SHORT, nullptr);
    374             elementsCount -= drawCount;
    375             vertexData += (drawCount / 6) * 4 * vertices.stride;
    376         }
    377     } else if (indices.bufferObject || indices.indices) {
    378         glDrawElements(mesh.primitiveMode, mesh.elementCount, GL_UNSIGNED_SHORT, indices.indices);
    379     } else {
    380         glDrawArrays(mesh.primitiveMode, 0, mesh.elementCount);
    381     }
    382 
    383     GL_CHECKPOINT(MODERATE);
    384 
    385     // -----------------------------------
    386     // ---------- Mesh teardown ----------
    387     // -----------------------------------
    388     if (vertices.attribFlags & VertexAttribFlags::Alpha) {
    389         glDisableVertexAttribArray(alphaLocation);
    390     }
    391     if (vertices.attribFlags & VertexAttribFlags::Color) {
    392         glDisableVertexAttribArray(colorLocation);
    393     }
    394 
    395     GL_CHECKPOINT(MODERATE);
    396 }
    397 
    398 void RenderState::dump() {
    399     blend().dump();
    400     meshState().dump();
    401     scissor().dump();
    402     stencil().dump();
    403 }
    404 
    405 } /* namespace uirenderer */
    406 } /* namespace android */
    407