RenderState.cpp revision 5e00c7ce063116c11315639f0035aca8ad73e8cc
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 24namespace android { 25namespace uirenderer { 26 27RenderState::RenderState(renderthread::RenderThread& thread) 28 : mRenderThread(thread) 29 , mViewportWidth(0) 30 , mViewportHeight(0) 31 , mFramebuffer(0) { 32 mThreadId = pthread_self(); 33} 34 35RenderState::~RenderState() { 36 LOG_ALWAYS_FATAL_IF(mBlend || mMeshState || mScissor || mStencil, 37 "State object lifecycle not managed correctly"); 38} 39 40void 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 58static void layerLostGlContext(Layer* layer) { 59 layer->onGlContextLost(); 60} 61 62void RenderState::onGLContextDestroyed() { 63 mLayerPool.clear(); 64 65 // TODO: reset all cached state in state objects 66 std::for_each(mActiveLayers.begin(), mActiveLayers.end(), layerLostGlContext); 67 mAssetAtlas.terminate(); 68 69 mCaches->terminate(); 70 71 delete mBlend; 72 mBlend = nullptr; 73 delete mMeshState; 74 mMeshState = nullptr; 75 delete mScissor; 76 mScissor = nullptr; 77 delete mStencil; 78 mStencil = nullptr; 79 80 GpuMemoryTracker::onGLContextDestroyed(); 81} 82 83void RenderState::flush(Caches::FlushMode mode) { 84 switch (mode) { 85 case Caches::FlushMode::Full: 86 // fall through 87 case Caches::FlushMode::Moderate: 88 // fall through 89 case Caches::FlushMode::Layers: 90 mLayerPool.clear(); 91 break; 92 } 93 mCaches->flush(mode); 94} 95 96void RenderState::setViewport(GLsizei width, GLsizei height) { 97 mViewportWidth = width; 98 mViewportHeight = height; 99 glViewport(0, 0, mViewportWidth, mViewportHeight); 100} 101 102 103void RenderState::getViewport(GLsizei* outWidth, GLsizei* outHeight) { 104 *outWidth = mViewportWidth; 105 *outHeight = mViewportHeight; 106} 107 108void RenderState::bindFramebuffer(GLuint fbo) { 109 if (mFramebuffer != fbo) { 110 mFramebuffer = fbo; 111 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer); 112 } 113} 114 115GLuint RenderState::createFramebuffer() { 116 GLuint ret; 117 glGenFramebuffers(1, &ret); 118 return ret; 119} 120 121void RenderState::deleteFramebuffer(GLuint fbo) { 122 if (mFramebuffer == fbo) { 123 // GL defines that deleting the currently bound FBO rebinds FBO 0. 124 // Reflect this in our cached value. 125 mFramebuffer = 0; 126 } 127 glDeleteFramebuffers(1, &fbo); 128} 129 130void RenderState::invokeFunctor(Functor* functor, DrawGlInfo::Mode mode, DrawGlInfo* info) { 131 if (mode == DrawGlInfo::kModeProcessNoContext) { 132 // If there's no context we don't need to interrupt as there's 133 // no gl state to save/restore 134 (*functor)(mode, info); 135 } else { 136 interruptForFunctorInvoke(); 137 (*functor)(mode, info); 138 resumeFromFunctorInvoke(); 139 } 140} 141 142void RenderState::interruptForFunctorInvoke() { 143 mCaches->setProgram(nullptr); 144 mCaches->textureState().resetActiveTexture(); 145 meshState().unbindMeshBuffer(); 146 meshState().unbindIndicesBuffer(); 147 meshState().resetVertexPointers(); 148 meshState().disableTexCoordsVertexArray(); 149 debugOverdraw(false, false); 150} 151 152void RenderState::resumeFromFunctorInvoke() { 153 glViewport(0, 0, mViewportWidth, mViewportHeight); 154 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer); 155 debugOverdraw(false, false); 156 157 glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 158 159 scissor().invalidate(); 160 blend().invalidate(); 161 162 mCaches->textureState().activateTexture(0); 163 mCaches->textureState().resetBoundTextures(); 164} 165 166void RenderState::debugOverdraw(bool enable, bool clear) { 167 if (Properties::debugOverdraw && mFramebuffer == 0) { 168 if (clear) { 169 scissor().setEnabled(false); 170 stencil().clear(); 171 } 172 if (enable) { 173 stencil().enableDebugWrite(); 174 } else { 175 stencil().disable(); 176 } 177 } 178} 179 180class DecStrongTask : public renderthread::RenderTask { 181public: 182 explicit DecStrongTask(VirtualLightRefBase* object) : mObject(object) {} 183 184 virtual void run() override { 185 mObject->decStrong(nullptr); 186 mObject = nullptr; 187 delete this; 188 } 189 190private: 191 VirtualLightRefBase* mObject; 192}; 193 194void RenderState::postDecStrong(VirtualLightRefBase* object) { 195 if (pthread_equal(mThreadId, pthread_self())) { 196 object->decStrong(nullptr); 197 } else { 198 mRenderThread.queue(new DecStrongTask(object)); 199 } 200} 201 202/////////////////////////////////////////////////////////////////////////////// 203// Render 204/////////////////////////////////////////////////////////////////////////////// 205 206void RenderState::render(const Glop& glop, const Matrix4& orthoMatrix) { 207 const Glop::Mesh& mesh = glop.mesh; 208 const Glop::Mesh::Vertices& vertices = mesh.vertices; 209 const Glop::Mesh::Indices& indices = mesh.indices; 210 const Glop::Fill& fill = glop.fill; 211 212 GL_CHECKPOINT(MODERATE); 213 214 // --------------------------------------------- 215 // ---------- Program + uniform setup ---------- 216 // --------------------------------------------- 217 mCaches->setProgram(fill.program); 218 219 if (fill.colorEnabled) { 220 fill.program->setColor(fill.color); 221 } 222 223 fill.program->set(orthoMatrix, 224 glop.transform.modelView, 225 glop.transform.meshTransform(), 226 glop.transform.transformFlags & TransformFlags::OffsetByFudgeFactor); 227 228 // Color filter uniforms 229 if (fill.filterMode == ProgramDescription::ColorFilterMode::Blend) { 230 const FloatColor& color = fill.filter.color; 231 glUniform4f(mCaches->program().getUniform("colorBlend"), 232 color.r, color.g, color.b, color.a); 233 } else if (fill.filterMode == ProgramDescription::ColorFilterMode::Matrix) { 234 glUniformMatrix4fv(mCaches->program().getUniform("colorMatrix"), 1, GL_FALSE, 235 fill.filter.matrix.matrix); 236 glUniform4fv(mCaches->program().getUniform("colorMatrixVector"), 1, 237 fill.filter.matrix.vector); 238 } 239 240 // Round rect clipping uniforms 241 if (glop.roundRectClipState) { 242 // TODO: avoid query, and cache values (or RRCS ptr) in program 243 const RoundRectClipState* state = glop.roundRectClipState; 244 const Rect& innerRect = state->innerRect; 245 glUniform4f(fill.program->getUniform("roundRectInnerRectLTRB"), 246 innerRect.left, innerRect.top, 247 innerRect.right, innerRect.bottom); 248 glUniformMatrix4fv(fill.program->getUniform("roundRectInvTransform"), 249 1, GL_FALSE, &state->matrix.data[0]); 250 251 // add half pixel to round out integer rect space to cover pixel centers 252 float roundedOutRadius = state->radius + 0.5f; 253 glUniform1f(fill.program->getUniform("roundRectRadius"), 254 roundedOutRadius); 255 } 256 257 GL_CHECKPOINT(MODERATE); 258 259 // -------------------------------- 260 // ---------- Mesh setup ---------- 261 // -------------------------------- 262 // vertices 263 meshState().bindMeshBuffer(vertices.bufferObject); 264 meshState().bindPositionVertexPointer(vertices.position, vertices.stride); 265 266 // indices 267 meshState().bindIndicesBuffer(indices.bufferObject); 268 269 // texture 270 if (fill.texture.texture != nullptr) { 271 const Glop::Fill::TextureData& texture = fill.texture; 272 // texture always takes slot 0, shader samplers increment from there 273 mCaches->textureState().activateTexture(0); 274 275 mCaches->textureState().bindTexture(texture.target, texture.texture->id()); 276 if (texture.clamp != GL_INVALID_ENUM) { 277 texture.texture->setWrap(texture.clamp, false, false, texture.target); 278 } 279 if (texture.filter != GL_INVALID_ENUM) { 280 texture.texture->setFilter(texture.filter, false, false, texture.target); 281 } 282 283 if (texture.textureTransform) { 284 glUniformMatrix4fv(fill.program->getUniform("mainTextureTransform"), 1, 285 GL_FALSE, &texture.textureTransform->data[0]); 286 } 287 } 288 289 // vertex attributes (tex coord, color, alpha) 290 if (vertices.attribFlags & VertexAttribFlags::TextureCoord) { 291 meshState().enableTexCoordsVertexArray(); 292 meshState().bindTexCoordsVertexPointer(vertices.texCoord, vertices.stride); 293 } else { 294 meshState().disableTexCoordsVertexArray(); 295 } 296 int colorLocation = -1; 297 if (vertices.attribFlags & VertexAttribFlags::Color) { 298 colorLocation = fill.program->getAttrib("colors"); 299 glEnableVertexAttribArray(colorLocation); 300 glVertexAttribPointer(colorLocation, 4, GL_FLOAT, GL_FALSE, vertices.stride, vertices.color); 301 } 302 int alphaLocation = -1; 303 if (vertices.attribFlags & VertexAttribFlags::Alpha) { 304 // NOTE: alpha vertex position is computed assuming no VBO 305 const void* alphaCoords = ((const GLbyte*) vertices.position) + kVertexAlphaOffset; 306 alphaLocation = fill.program->getAttrib("vtxAlpha"); 307 glEnableVertexAttribArray(alphaLocation); 308 glVertexAttribPointer(alphaLocation, 1, GL_FLOAT, GL_FALSE, vertices.stride, alphaCoords); 309 } 310 // Shader uniforms 311 SkiaShader::apply(*mCaches, fill.skiaShaderData); 312 313 GL_CHECKPOINT(MODERATE); 314 Texture* texture = (fill.skiaShaderData.skiaShaderType & kBitmap_SkiaShaderType) ? 315 fill.skiaShaderData.bitmapData.bitmapTexture : nullptr; 316 const AutoTexture autoCleanup(texture); 317 318 // ------------------------------------ 319 // ---------- GL state setup ---------- 320 // ------------------------------------ 321 blend().setFactors(glop.blend.src, glop.blend.dst); 322 323 GL_CHECKPOINT(MODERATE); 324 325 // ------------------------------------ 326 // ---------- Actual drawing ---------- 327 // ------------------------------------ 328 if (indices.bufferObject == meshState().getQuadListIBO()) { 329 // Since the indexed quad list is of limited length, we loop over 330 // the glDrawXXX method while updating the vertex pointer 331 GLsizei elementsCount = mesh.elementCount; 332 const GLbyte* vertexData = static_cast<const GLbyte*>(vertices.position); 333 while (elementsCount > 0) { 334 GLsizei drawCount = std::min(elementsCount, (GLsizei) kMaxNumberOfQuads * 6); 335 meshState().bindPositionVertexPointer(vertexData, vertices.stride); 336 if (vertices.attribFlags & VertexAttribFlags::TextureCoord) { 337 meshState().bindTexCoordsVertexPointer( 338 vertexData + kMeshTextureOffset, vertices.stride); 339 } 340 341 glDrawElements(mesh.primitiveMode, drawCount, GL_UNSIGNED_SHORT, nullptr); 342 elementsCount -= drawCount; 343 vertexData += (drawCount / 6) * 4 * vertices.stride; 344 } 345 } else if (indices.bufferObject || indices.indices) { 346 glDrawElements(mesh.primitiveMode, mesh.elementCount, GL_UNSIGNED_SHORT, indices.indices); 347 } else { 348 glDrawArrays(mesh.primitiveMode, 0, mesh.elementCount); 349 } 350 351 GL_CHECKPOINT(MODERATE); 352 353 // ----------------------------------- 354 // ---------- Mesh teardown ---------- 355 // ----------------------------------- 356 if (vertices.attribFlags & VertexAttribFlags::Alpha) { 357 glDisableVertexAttribArray(alphaLocation); 358 } 359 if (vertices.attribFlags & VertexAttribFlags::Color) { 360 glDisableVertexAttribArray(colorLocation); 361 } 362 363 GL_CHECKPOINT(MODERATE); 364} 365 366void RenderState::dump() { 367 blend().dump(); 368 meshState().dump(); 369 scissor().dump(); 370 stencil().dump(); 371} 372 373} /* namespace uirenderer */ 374} /* namespace android */ 375