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 "RenderState.h" 17 18 #include "renderthread/CanvasContext.h" 19 #include "renderthread/EglManager.h" 20 21 namespace android { 22 namespace uirenderer { 23 24 RenderState::RenderState(renderthread::RenderThread& thread) 25 : mRenderThread(thread) 26 , mCaches(NULL) 27 , mViewportWidth(0) 28 , mViewportHeight(0) 29 , mFramebuffer(0) { 30 mThreadId = pthread_self(); 31 } 32 33 RenderState::~RenderState() { 34 } 35 36 void RenderState::onGLContextCreated() { 37 // This is delayed because the first access of Caches makes GL calls 38 mCaches = &Caches::getInstance(); 39 mCaches->init(); 40 mCaches->setRenderState(this); 41 mCaches->textureCache.setAssetAtlas(&mAssetAtlas); 42 } 43 44 static void layerLostGlContext(Layer* layer) { 45 layer->onGlContextLost(); 46 } 47 48 void RenderState::onGLContextDestroyed() { 49 /* 50 size_t size = mActiveLayers.size(); 51 if (CC_UNLIKELY(size != 0)) { 52 ALOGE("Crashing, have %d contexts and %d layers at context destruction. isempty %d", 53 mRegisteredContexts.size(), size, mActiveLayers.empty()); 54 mCaches->dumpMemoryUsage(); 55 for (std::set<renderthread::CanvasContext*>::iterator cit = mRegisteredContexts.begin(); 56 cit != mRegisteredContexts.end(); cit++) { 57 renderthread::CanvasContext* context = *cit; 58 ALOGE("Context: %p (root = %p)", context, context->mRootRenderNode.get()); 59 ALOGE(" Prefeteched layers: %zu", context->mPrefetechedLayers.size()); 60 for (std::set<RenderNode*>::iterator pit = context->mPrefetechedLayers.begin(); 61 pit != context->mPrefetechedLayers.end(); pit++) { 62 (*pit)->debugDumpLayers(" "); 63 } 64 context->mRootRenderNode->debugDumpLayers(" "); 65 } 66 67 68 if (mActiveLayers.begin() == mActiveLayers.end()) { 69 ALOGE("set has become empty. wat."); 70 } 71 for (std::set<const Layer*>::iterator lit = mActiveLayers.begin(); 72 lit != mActiveLayers.end(); lit++) { 73 const Layer* layer = *(lit); 74 ALOGE("Layer %p, state %d, texlayer %d, fbo %d, buildlayered %d", 75 layer, layer->state, layer->isTextureLayer(), layer->getFbo(), layer->wasBuildLayered); 76 } 77 LOG_ALWAYS_FATAL("%d layers have survived gl context destruction", size); 78 } 79 */ 80 std::for_each(mActiveLayers.begin(), mActiveLayers.end(), layerLostGlContext); 81 mAssetAtlas.terminate(); 82 } 83 84 void RenderState::setViewport(GLsizei width, GLsizei height) { 85 mViewportWidth = width; 86 mViewportHeight = height; 87 glViewport(0, 0, mViewportWidth, mViewportHeight); 88 } 89 90 91 void RenderState::getViewport(GLsizei* outWidth, GLsizei* outHeight) { 92 *outWidth = mViewportWidth; 93 *outHeight = mViewportHeight; 94 } 95 96 void RenderState::bindFramebuffer(GLuint fbo) { 97 if (mFramebuffer != fbo) { 98 mFramebuffer = fbo; 99 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer); 100 } 101 } 102 103 void RenderState::invokeFunctor(Functor* functor, DrawGlInfo::Mode mode, DrawGlInfo* info) { 104 interruptForFunctorInvoke(); 105 (*functor)(mode, info); 106 resumeFromFunctorInvoke(); 107 } 108 109 void RenderState::interruptForFunctorInvoke() { 110 if (mCaches->currentProgram) { 111 if (mCaches->currentProgram->isInUse()) { 112 mCaches->currentProgram->remove(); 113 mCaches->currentProgram = NULL; 114 } 115 } 116 mCaches->resetActiveTexture(); 117 mCaches->unbindMeshBuffer(); 118 mCaches->unbindIndicesBuffer(); 119 mCaches->resetVertexPointers(); 120 mCaches->disableTexCoordsVertexArray(); 121 debugOverdraw(false, false); 122 } 123 124 void RenderState::resumeFromFunctorInvoke() { 125 glViewport(0, 0, mViewportWidth, mViewportHeight); 126 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer); 127 debugOverdraw(false, false); 128 129 glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 130 131 mCaches->scissorEnabled = glIsEnabled(GL_SCISSOR_TEST); 132 mCaches->enableScissor(); 133 mCaches->resetScissor(); 134 135 mCaches->activeTexture(0); 136 mCaches->resetBoundTextures(); 137 138 mCaches->blend = true; 139 glEnable(GL_BLEND); 140 glBlendFunc(mCaches->lastSrcMode, mCaches->lastDstMode); 141 glBlendEquation(GL_FUNC_ADD); 142 } 143 144 void RenderState::debugOverdraw(bool enable, bool clear) { 145 if (mCaches->debugOverdraw && mFramebuffer == 0) { 146 if (clear) { 147 mCaches->disableScissor(); 148 mCaches->stencil.clear(); 149 } 150 if (enable) { 151 mCaches->stencil.enableDebugWrite(); 152 } else { 153 mCaches->stencil.disable(); 154 } 155 } 156 } 157 158 void RenderState::requireGLContext() { 159 assertOnGLThread(); 160 mRenderThread.eglManager().requireGlContext(); 161 } 162 163 void RenderState::assertOnGLThread() { 164 pthread_t curr = pthread_self(); 165 LOG_ALWAYS_FATAL_IF(!pthread_equal(mThreadId, curr), "Wrong thread!"); 166 } 167 168 169 class DecStrongTask : public renderthread::RenderTask { 170 public: 171 DecStrongTask(VirtualLightRefBase* object) : mObject(object) {} 172 173 virtual void run() { 174 mObject->decStrong(0); 175 mObject = 0; 176 delete this; 177 } 178 179 private: 180 VirtualLightRefBase* mObject; 181 }; 182 183 void RenderState::postDecStrong(VirtualLightRefBase* object) { 184 mRenderThread.queue(new DecStrongTask(object)); 185 } 186 187 } /* namespace uirenderer */ 188 } /* namespace android */ 189