BakedOpDispatcher.cpp revision 15c3f19a445b8df575911a16e8a6dba755a084b5
19e7fcfda28fde747ba4e026772007cea77374e16Chris Craik/* 29e7fcfda28fde747ba4e026772007cea77374e16Chris Craik * Copyright (C) 2015 The Android Open Source Project 39e7fcfda28fde747ba4e026772007cea77374e16Chris Craik * 49e7fcfda28fde747ba4e026772007cea77374e16Chris Craik * Licensed under the Apache License, Version 2.0 (the "License"); 59e7fcfda28fde747ba4e026772007cea77374e16Chris Craik * you may not use this file except in compliance with the License. 69e7fcfda28fde747ba4e026772007cea77374e16Chris Craik * You may obtain a copy of the License at 79e7fcfda28fde747ba4e026772007cea77374e16Chris Craik * 89e7fcfda28fde747ba4e026772007cea77374e16Chris Craik * http://www.apache.org/licenses/LICENSE-2.0 99e7fcfda28fde747ba4e026772007cea77374e16Chris Craik * 109e7fcfda28fde747ba4e026772007cea77374e16Chris Craik * Unless required by applicable law or agreed to in writing, software 119e7fcfda28fde747ba4e026772007cea77374e16Chris Craik * distributed under the License is distributed on an "AS IS" BASIS, 129e7fcfda28fde747ba4e026772007cea77374e16Chris Craik * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139e7fcfda28fde747ba4e026772007cea77374e16Chris Craik * See the License for the specific language governing permissions and 149e7fcfda28fde747ba4e026772007cea77374e16Chris Craik * limitations under the License. 159e7fcfda28fde747ba4e026772007cea77374e16Chris Craik */ 169e7fcfda28fde747ba4e026772007cea77374e16Chris Craik 179e7fcfda28fde747ba4e026772007cea77374e16Chris Craik#include "BakedOpDispatcher.h" 189e7fcfda28fde747ba4e026772007cea77374e16Chris Craik 199e7fcfda28fde747ba4e026772007cea77374e16Chris Craik#include "BakedOpRenderer.h" 209e7fcfda28fde747ba4e026772007cea77374e16Chris Craik#include "Caches.h" 219e7fcfda28fde747ba4e026772007cea77374e16Chris Craik#include "Glop.h" 229e7fcfda28fde747ba4e026772007cea77374e16Chris Craik#include "GlopBuilder.h" 239e7fcfda28fde747ba4e026772007cea77374e16Chris Craik#include "renderstate/OffscreenBufferPool.h" 249e7fcfda28fde747ba4e026772007cea77374e16Chris Craik#include "renderstate/RenderState.h" 259e7fcfda28fde747ba4e026772007cea77374e16Chris Craik#include "utils/GLUtils.h" 269e7fcfda28fde747ba4e026772007cea77374e16Chris Craik#include "VertexBuffer.h" 279e7fcfda28fde747ba4e026772007cea77374e16Chris Craik 289e7fcfda28fde747ba4e026772007cea77374e16Chris Craik#include <algorithm> 299e7fcfda28fde747ba4e026772007cea77374e16Chris Craik#include <math.h> 309e7fcfda28fde747ba4e026772007cea77374e16Chris Craik 319e7fcfda28fde747ba4e026772007cea77374e16Chris Craiknamespace android { 329e7fcfda28fde747ba4e026772007cea77374e16Chris Craiknamespace uirenderer { 339e7fcfda28fde747ba4e026772007cea77374e16Chris Craik 3415c3f19a445b8df575911a16e8a6dba755a084b5Chris Craikstatic void storeTexturedRect(TextureVertex* vertices, const Rect& bounds, const Rect& texCoord) { 3515c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik vertices[0] = { bounds.left, bounds.top, texCoord.left, texCoord.top }; 3615c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik vertices[1] = { bounds.right, bounds.top, texCoord.right, texCoord.top }; 3715c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik vertices[2] = { bounds.left, bounds.bottom, texCoord.left, texCoord.bottom }; 3815c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik vertices[3] = { bounds.right, bounds.bottom, texCoord.right, texCoord.bottom }; 3915c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik} 4015c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik 4115c3f19a445b8df575911a16e8a6dba755a084b5Chris Craikvoid BakedOpDispatcher::onMergedBitmapOps(BakedOpRenderer& renderer, 4215c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik const MergedBakedOpList& opList) { 4315c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik 4415c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik const BakedOpState& firstState = *(opList.states[0]); 4515c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik const SkBitmap* bitmap = (static_cast<const BitmapOp*>(opList.states[0]->op))->bitmap; 4615c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik 4715c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik AssetAtlas::Entry* entry = renderer.renderState().assetAtlas().getEntry(bitmap->pixelRef()); 4815c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik Texture* texture = entry ? entry->texture : renderer.caches().textureCache.get(bitmap); 4915c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik if (!texture) return; 5015c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik const AutoTexture autoCleanup(texture); 5115c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik 5215c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik TextureVertex vertices[opList.count * 4]; 5315c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik Rect texCoords(0, 0, 1, 1); 5415c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik if (entry) { 5515c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik entry->uvMapper.map(texCoords); 5615c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik } 5715c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik // init to non-empty, so we can safely expandtoCoverRect 5815c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik Rect totalBounds = firstState.computedState.clippedBounds; 5915c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik for (size_t i = 0; i < opList.count; i++) { 6015c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik const BakedOpState& state = *(opList.states[i]); 6115c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik TextureVertex* rectVerts = &vertices[i * 4]; 6215c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik Rect opBounds = state.computedState.clippedBounds; 6315c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik if (CC_LIKELY(state.computedState.transform.isPureTranslate())) { 6415c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik // pure translate, so snap (same behavior as onBitmapOp) 6515c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik opBounds.snapToPixelBoundaries(); 6615c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik } 6715c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik storeTexturedRect(rectVerts, opBounds, texCoords); 6815c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik renderer.dirtyRenderTarget(opBounds); 6915c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik 7015c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik totalBounds.expandToCover(opBounds); 7115c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik } 7215c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik 7315c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik const int textureFillFlags = (bitmap->colorType() == kAlpha_8_SkColorType) 7415c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik ? TextureFillFlags::IsAlphaMaskTexture : TextureFillFlags::None; 7515c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik Glop glop; 7615c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik GlopBuilder(renderer.renderState(), renderer.caches(), &glop) 7715c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik .setRoundRectClipState(firstState.roundRectClipState) 7815c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik .setMeshTexturedIndexedQuads(vertices, opList.count * 6) 7915c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik .setFillTexturePaint(*texture, textureFillFlags, firstState.op->paint, firstState.alpha) 8015c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik .setTransform(Matrix4::identity(), TransformFlags::None) 8115c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik .setModelViewOffsetRect(0, 0, totalBounds) // don't snap here, we snap per-quad above 8215c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik .build(); 8315c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik renderer.renderGlop(nullptr, opList.clipSideFlags ? &opList.clip : nullptr, glop); 8415c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik} 8515c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik 8615c3f19a445b8df575911a16e8a6dba755a084b5Chris Craikstatic void renderTextShadow(BakedOpRenderer& renderer, FontRenderer& fontRenderer, 8715c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik const TextOp& op, const BakedOpState& state) { 8815c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik renderer.caches().textureState().activateTexture(0); 8915c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik 9015c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik PaintUtils::TextShadow textShadow; 9115c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik if (!PaintUtils::getTextShadow(op.paint, &textShadow)) { 9215c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik LOG_ALWAYS_FATAL("failed to query shadow attributes"); 9315c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik } 9415c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik 9515c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik renderer.caches().dropShadowCache.setFontRenderer(fontRenderer); 9615c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik ShadowTexture* texture = renderer.caches().dropShadowCache.get( 9715c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik op.paint, (const char*) op.glyphs, 9815c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik op.glyphCount, textShadow.radius, op.positions); 9915c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik // If the drop shadow exceeds the max texture size or couldn't be 10015c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik // allocated, skip drawing 10115c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik if (!texture) return; 10215c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik const AutoTexture autoCleanup(texture); 10315c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik 10415c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik const float sx = op.x - texture->left + textShadow.dx; 10515c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik const float sy = op.y - texture->top + textShadow.dy; 10615c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik 10715c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik Glop glop; 10815c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik GlopBuilder(renderer.renderState(), renderer.caches(), &glop) 10915c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik .setRoundRectClipState(state.roundRectClipState) 11015c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik .setMeshTexturedUnitQuad(nullptr) 11115c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik .setFillShadowTexturePaint(*texture, textShadow.color, *op.paint, state.alpha) 11215c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik .setTransform(state.computedState.transform, TransformFlags::None) 11315c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik .setModelViewMapUnitToRect(Rect(sx, sy, sx + texture->width, sy + texture->height)) 11415c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik .build(); 11515c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik renderer.renderGlop(state, glop); 11615c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik} 11715c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik 11815c3f19a445b8df575911a16e8a6dba755a084b5Chris Craikenum class TextRenderType { 11915c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik Defer, 12015c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik Flush 12115c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik}; 12215c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik 12315c3f19a445b8df575911a16e8a6dba755a084b5Chris Craikstatic void renderTextOp(BakedOpRenderer& renderer, const TextOp& op, const BakedOpState& state, 12415c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik const Rect* renderClip, TextRenderType renderType) { 12515c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik FontRenderer& fontRenderer = renderer.caches().fontRenderer.getFontRenderer(); 12615c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik 12715c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik if (CC_UNLIKELY(PaintUtils::hasTextShadow(op.paint))) { 12815c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik fontRenderer.setFont(op.paint, SkMatrix::I()); 12915c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik renderTextShadow(renderer, fontRenderer, op, state); 13015c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik } 13115c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik 13215c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik float x = op.x; 13315c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik float y = op.y; 13415c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik const Matrix4& transform = state.computedState.transform; 13515c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik const bool pureTranslate = transform.isPureTranslate(); 13615c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik if (CC_LIKELY(pureTranslate)) { 13715c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik x = floorf(x + transform.getTranslateX() + 0.5f); 13815c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik y = floorf(y + transform.getTranslateY() + 0.5f); 13915c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik fontRenderer.setFont(op.paint, SkMatrix::I()); 14015c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik fontRenderer.setTextureFiltering(false); 14115c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik } else if (CC_UNLIKELY(transform.isPerspective())) { 14215c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik fontRenderer.setFont(op.paint, SkMatrix::I()); 14315c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik fontRenderer.setTextureFiltering(true); 14415c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik } else { 14515c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik // We only pass a partial transform to the font renderer. That partial 14615c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik // matrix defines how glyphs are rasterized. Typically we want glyphs 14715c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik // to be rasterized at their final size on screen, which means the partial 14815c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik // matrix needs to take the scale factor into account. 14915c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik // When a partial matrix is used to transform glyphs during rasterization, 15015c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik // the mesh is generated with the inverse transform (in the case of scale, 15115c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik // the mesh is generated at 1.0 / scale for instance.) This allows us to 15215c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik // apply the full transform matrix at draw time in the vertex shader. 15315c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik // Applying the full matrix in the shader is the easiest way to handle 15415c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik // rotation and perspective and allows us to always generated quads in the 15515c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik // font renderer which greatly simplifies the code, clipping in particular. 15615c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik float sx, sy; 15715c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik transform.decomposeScale(sx, sy); 15815c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik fontRenderer.setFont(op.paint, SkMatrix::MakeScale( 15915c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik roundf(std::max(1.0f, sx)), 16015c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik roundf(std::max(1.0f, sy)))); 16115c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik fontRenderer.setTextureFiltering(true); 16215c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik } 16315c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik Rect layerBounds(FLT_MAX / 2.0f, FLT_MAX / 2.0f, FLT_MIN / 2.0f, FLT_MIN / 2.0f); 16415c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik 16515c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik int alpha = PaintUtils::getAlphaDirect(op.paint) * state.alpha; 16615c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik SkXfermode::Mode mode = PaintUtils::getXfermodeDirect(op.paint); 16715c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik TextDrawFunctor functor(&renderer, &state, renderClip, 16815c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik x, y, pureTranslate, alpha, mode, op.paint); 16915c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik 17015c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik bool forceFinish = (renderType == TextRenderType::Flush); 17115c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik bool mustDirtyRenderTarget = renderer.offscreenRenderTarget(); 17215c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik const Rect* localOpClip = pureTranslate ? &state.computedState.clipRect : nullptr; 17315c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik fontRenderer.renderPosText(op.paint, localOpClip, 17415c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik (const char*) op.glyphs, op.glyphCount, x, y, 17515c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik op.positions, mustDirtyRenderTarget ? &layerBounds : nullptr, &functor, forceFinish); 17615c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik 17715c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik if (mustDirtyRenderTarget) { 17815c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik if (!pureTranslate) { 17915c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik transform.mapRect(layerBounds); 18015c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik } 18115c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik renderer.dirtyRenderTarget(layerBounds); 18215c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik } 18315c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik} 18415c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik 18515c3f19a445b8df575911a16e8a6dba755a084b5Chris Craikvoid BakedOpDispatcher::onMergedTextOps(BakedOpRenderer& renderer, 18615c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik const MergedBakedOpList& opList) { 18715c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik const Rect* clip = opList.clipSideFlags ? &opList.clip : nullptr; 18815c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik for (size_t i = 0; i < opList.count; i++) { 18915c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik const BakedOpState& state = *(opList.states[i]); 19015c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik const TextOp& op = *(static_cast<const TextOp*>(state.op)); 19115c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik TextRenderType renderType = (i + 1 == opList.count) 19215c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik ? TextRenderType::Flush : TextRenderType::Defer; 19315c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik renderTextOp(renderer, op, state, clip, renderType); 19415c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik } 19515c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik} 19615c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik 1979e7fcfda28fde747ba4e026772007cea77374e16Chris Craikvoid BakedOpDispatcher::onRenderNodeOp(BakedOpRenderer&, const RenderNodeOp&, const BakedOpState&) { 1989e7fcfda28fde747ba4e026772007cea77374e16Chris Craik LOG_ALWAYS_FATAL("unsupported operation"); 1999e7fcfda28fde747ba4e026772007cea77374e16Chris Craik} 2009e7fcfda28fde747ba4e026772007cea77374e16Chris Craik 20115c3f19a445b8df575911a16e8a6dba755a084b5Chris Craikvoid BakedOpDispatcher::onBeginLayerOp(BakedOpRenderer&, const BeginLayerOp&, const BakedOpState&) { 2029e7fcfda28fde747ba4e026772007cea77374e16Chris Craik LOG_ALWAYS_FATAL("unsupported operation"); 2039e7fcfda28fde747ba4e026772007cea77374e16Chris Craik} 2049e7fcfda28fde747ba4e026772007cea77374e16Chris Craik 20515c3f19a445b8df575911a16e8a6dba755a084b5Chris Craikvoid BakedOpDispatcher::onEndLayerOp(BakedOpRenderer&, const EndLayerOp&, const BakedOpState&) { 2069e7fcfda28fde747ba4e026772007cea77374e16Chris Craik LOG_ALWAYS_FATAL("unsupported operation"); 2079e7fcfda28fde747ba4e026772007cea77374e16Chris Craik} 2089e7fcfda28fde747ba4e026772007cea77374e16Chris Craik 2099e7fcfda28fde747ba4e026772007cea77374e16Chris Craikvoid BakedOpDispatcher::onBitmapOp(BakedOpRenderer& renderer, const BitmapOp& op, const BakedOpState& state) { 2109e7fcfda28fde747ba4e026772007cea77374e16Chris Craik Texture* texture = renderer.getTexture(op.bitmap); 2119e7fcfda28fde747ba4e026772007cea77374e16Chris Craik if (!texture) return; 2129e7fcfda28fde747ba4e026772007cea77374e16Chris Craik const AutoTexture autoCleanup(texture); 2139e7fcfda28fde747ba4e026772007cea77374e16Chris Craik 2149e7fcfda28fde747ba4e026772007cea77374e16Chris Craik const int textureFillFlags = (op.bitmap->colorType() == kAlpha_8_SkColorType) 2159e7fcfda28fde747ba4e026772007cea77374e16Chris Craik ? TextureFillFlags::IsAlphaMaskTexture : TextureFillFlags::None; 2169e7fcfda28fde747ba4e026772007cea77374e16Chris Craik Glop glop; 2179e7fcfda28fde747ba4e026772007cea77374e16Chris Craik GlopBuilder(renderer.renderState(), renderer.caches(), &glop) 2189e7fcfda28fde747ba4e026772007cea77374e16Chris Craik .setRoundRectClipState(state.roundRectClipState) 2199e7fcfda28fde747ba4e026772007cea77374e16Chris Craik .setMeshTexturedUnitQuad(texture->uvMapper) 2209e7fcfda28fde747ba4e026772007cea77374e16Chris Craik .setFillTexturePaint(*texture, textureFillFlags, op.paint, state.alpha) 2219e7fcfda28fde747ba4e026772007cea77374e16Chris Craik .setTransform(state.computedState.transform, TransformFlags::None) 2229e7fcfda28fde747ba4e026772007cea77374e16Chris Craik .setModelViewMapUnitToRectSnap(Rect(0, 0, texture->width, texture->height)) 2239e7fcfda28fde747ba4e026772007cea77374e16Chris Craik .build(); 2249e7fcfda28fde747ba4e026772007cea77374e16Chris Craik renderer.renderGlop(state, glop); 2259e7fcfda28fde747ba4e026772007cea77374e16Chris Craik} 2269e7fcfda28fde747ba4e026772007cea77374e16Chris Craik 2279e7fcfda28fde747ba4e026772007cea77374e16Chris Craikvoid BakedOpDispatcher::onLinesOp(BakedOpRenderer& renderer, const LinesOp& op, const BakedOpState& state) { 2289e7fcfda28fde747ba4e026772007cea77374e16Chris Craik LOG_ALWAYS_FATAL("todo"); 2299e7fcfda28fde747ba4e026772007cea77374e16Chris Craik} 2309e7fcfda28fde747ba4e026772007cea77374e16Chris Craik 2319e7fcfda28fde747ba4e026772007cea77374e16Chris Craikvoid BakedOpDispatcher::onRectOp(BakedOpRenderer& renderer, const RectOp& op, const BakedOpState& state) { 2329e7fcfda28fde747ba4e026772007cea77374e16Chris Craik Glop glop; 2339e7fcfda28fde747ba4e026772007cea77374e16Chris Craik GlopBuilder(renderer.renderState(), renderer.caches(), &glop) 2349e7fcfda28fde747ba4e026772007cea77374e16Chris Craik .setRoundRectClipState(state.roundRectClipState) 2359e7fcfda28fde747ba4e026772007cea77374e16Chris Craik .setMeshUnitQuad() 2369e7fcfda28fde747ba4e026772007cea77374e16Chris Craik .setFillPaint(*op.paint, state.alpha) 2379e7fcfda28fde747ba4e026772007cea77374e16Chris Craik .setTransform(state.computedState.transform, TransformFlags::None) 2389e7fcfda28fde747ba4e026772007cea77374e16Chris Craik .setModelViewMapUnitToRect(op.unmappedBounds) 2399e7fcfda28fde747ba4e026772007cea77374e16Chris Craik .build(); 2409e7fcfda28fde747ba4e026772007cea77374e16Chris Craik renderer.renderGlop(state, glop); 2419e7fcfda28fde747ba4e026772007cea77374e16Chris Craik} 2429e7fcfda28fde747ba4e026772007cea77374e16Chris Craik 2439e7fcfda28fde747ba4e026772007cea77374e16Chris Craiknamespace VertexBufferRenderFlags { 2449e7fcfda28fde747ba4e026772007cea77374e16Chris Craik enum { 2459e7fcfda28fde747ba4e026772007cea77374e16Chris Craik Offset = 0x1, 2469e7fcfda28fde747ba4e026772007cea77374e16Chris Craik ShadowInterp = 0x2, 2479e7fcfda28fde747ba4e026772007cea77374e16Chris Craik }; 2489e7fcfda28fde747ba4e026772007cea77374e16Chris Craik} 2499e7fcfda28fde747ba4e026772007cea77374e16Chris Craik 2509e7fcfda28fde747ba4e026772007cea77374e16Chris Craikstatic void renderVertexBuffer(BakedOpRenderer& renderer, const BakedOpState& state, 2519e7fcfda28fde747ba4e026772007cea77374e16Chris Craik const VertexBuffer& vertexBuffer, float translateX, float translateY, 2529e7fcfda28fde747ba4e026772007cea77374e16Chris Craik SkPaint& paint, int vertexBufferRenderFlags) { 2539e7fcfda28fde747ba4e026772007cea77374e16Chris Craik if (CC_LIKELY(vertexBuffer.getVertexCount())) { 2549e7fcfda28fde747ba4e026772007cea77374e16Chris Craik bool shadowInterp = vertexBufferRenderFlags & VertexBufferRenderFlags::ShadowInterp; 2559e7fcfda28fde747ba4e026772007cea77374e16Chris Craik const int transformFlags = TransformFlags::OffsetByFudgeFactor; 2569e7fcfda28fde747ba4e026772007cea77374e16Chris Craik Glop glop; 2579e7fcfda28fde747ba4e026772007cea77374e16Chris Craik GlopBuilder(renderer.renderState(), renderer.caches(), &glop) 2589e7fcfda28fde747ba4e026772007cea77374e16Chris Craik .setRoundRectClipState(state.roundRectClipState) 2599e7fcfda28fde747ba4e026772007cea77374e16Chris Craik .setMeshVertexBuffer(vertexBuffer, shadowInterp) 2609e7fcfda28fde747ba4e026772007cea77374e16Chris Craik .setFillPaint(paint, state.alpha) 2619e7fcfda28fde747ba4e026772007cea77374e16Chris Craik .setTransform(state.computedState.transform, transformFlags) 2629e7fcfda28fde747ba4e026772007cea77374e16Chris Craik .setModelViewOffsetRect(translateX, translateY, vertexBuffer.getBounds()) 2639e7fcfda28fde747ba4e026772007cea77374e16Chris Craik .build(); 2649e7fcfda28fde747ba4e026772007cea77374e16Chris Craik renderer.renderGlop(state, glop); 2659e7fcfda28fde747ba4e026772007cea77374e16Chris Craik } 2669e7fcfda28fde747ba4e026772007cea77374e16Chris Craik} 2679e7fcfda28fde747ba4e026772007cea77374e16Chris Craik 2689e7fcfda28fde747ba4e026772007cea77374e16Chris Craikstatic void renderShadow(BakedOpRenderer& renderer, const BakedOpState& state, float casterAlpha, 2699e7fcfda28fde747ba4e026772007cea77374e16Chris Craik const VertexBuffer* ambientShadowVertexBuffer, const VertexBuffer* spotShadowVertexBuffer) { 2709e7fcfda28fde747ba4e026772007cea77374e16Chris Craik SkPaint paint; 2719e7fcfda28fde747ba4e026772007cea77374e16Chris Craik paint.setAntiAlias(true); // want to use AlphaVertex 2729e7fcfda28fde747ba4e026772007cea77374e16Chris Craik 2739e7fcfda28fde747ba4e026772007cea77374e16Chris Craik // The caller has made sure casterAlpha > 0. 2749e7fcfda28fde747ba4e026772007cea77374e16Chris Craik uint8_t ambientShadowAlpha = renderer.getLightInfo().ambientShadowAlpha; 2759e7fcfda28fde747ba4e026772007cea77374e16Chris Craik if (CC_UNLIKELY(Properties::overrideAmbientShadowStrength >= 0)) { 2769e7fcfda28fde747ba4e026772007cea77374e16Chris Craik ambientShadowAlpha = Properties::overrideAmbientShadowStrength; 2779e7fcfda28fde747ba4e026772007cea77374e16Chris Craik } 2789e7fcfda28fde747ba4e026772007cea77374e16Chris Craik if (ambientShadowVertexBuffer && ambientShadowAlpha > 0) { 2799e7fcfda28fde747ba4e026772007cea77374e16Chris Craik paint.setAlpha((uint8_t)(casterAlpha * ambientShadowAlpha)); 2809e7fcfda28fde747ba4e026772007cea77374e16Chris Craik renderVertexBuffer(renderer, state, *ambientShadowVertexBuffer, 0, 0, 2819e7fcfda28fde747ba4e026772007cea77374e16Chris Craik paint, VertexBufferRenderFlags::ShadowInterp); 2829e7fcfda28fde747ba4e026772007cea77374e16Chris Craik } 2839e7fcfda28fde747ba4e026772007cea77374e16Chris Craik 2849e7fcfda28fde747ba4e026772007cea77374e16Chris Craik uint8_t spotShadowAlpha = renderer.getLightInfo().spotShadowAlpha; 2859e7fcfda28fde747ba4e026772007cea77374e16Chris Craik if (CC_UNLIKELY(Properties::overrideSpotShadowStrength >= 0)) { 2869e7fcfda28fde747ba4e026772007cea77374e16Chris Craik spotShadowAlpha = Properties::overrideSpotShadowStrength; 2879e7fcfda28fde747ba4e026772007cea77374e16Chris Craik } 2889e7fcfda28fde747ba4e026772007cea77374e16Chris Craik if (spotShadowVertexBuffer && spotShadowAlpha > 0) { 2899e7fcfda28fde747ba4e026772007cea77374e16Chris Craik paint.setAlpha((uint8_t)(casterAlpha * spotShadowAlpha)); 2909e7fcfda28fde747ba4e026772007cea77374e16Chris Craik renderVertexBuffer(renderer, state, *spotShadowVertexBuffer, 0, 0, 2919e7fcfda28fde747ba4e026772007cea77374e16Chris Craik paint, VertexBufferRenderFlags::ShadowInterp); 2929e7fcfda28fde747ba4e026772007cea77374e16Chris Craik } 2939e7fcfda28fde747ba4e026772007cea77374e16Chris Craik} 2949e7fcfda28fde747ba4e026772007cea77374e16Chris Craik 2959e7fcfda28fde747ba4e026772007cea77374e16Chris Craikvoid BakedOpDispatcher::onShadowOp(BakedOpRenderer& renderer, const ShadowOp& op, const BakedOpState& state) { 2969e7fcfda28fde747ba4e026772007cea77374e16Chris Craik TessellationCache::vertexBuffer_pair_t buffers; 2979e7fcfda28fde747ba4e026772007cea77374e16Chris Craik renderer.caches().tessellationCache.getShadowBuffers(&state.computedState.transform, 2989e7fcfda28fde747ba4e026772007cea77374e16Chris Craik op.localClipRect, op.casterAlpha >= 1.0f, op.casterPath, 2999e7fcfda28fde747ba4e026772007cea77374e16Chris Craik &op.shadowMatrixXY, &op.shadowMatrixZ, 3009e7fcfda28fde747ba4e026772007cea77374e16Chris Craik op.lightCenter, renderer.getLightInfo().lightRadius, 3019e7fcfda28fde747ba4e026772007cea77374e16Chris Craik buffers); 3029e7fcfda28fde747ba4e026772007cea77374e16Chris Craik 3039e7fcfda28fde747ba4e026772007cea77374e16Chris Craik renderShadow(renderer, state, op.casterAlpha, buffers.first, buffers.second); 3049e7fcfda28fde747ba4e026772007cea77374e16Chris Craik} 3059e7fcfda28fde747ba4e026772007cea77374e16Chris Craik 3069e7fcfda28fde747ba4e026772007cea77374e16Chris Craikvoid BakedOpDispatcher::onSimpleRectsOp(BakedOpRenderer& renderer, const SimpleRectsOp& op, const BakedOpState& state) { 3079e7fcfda28fde747ba4e026772007cea77374e16Chris Craik Glop glop; 3089e7fcfda28fde747ba4e026772007cea77374e16Chris Craik GlopBuilder(renderer.renderState(), renderer.caches(), &glop) 3099e7fcfda28fde747ba4e026772007cea77374e16Chris Craik .setRoundRectClipState(state.roundRectClipState) 3109e7fcfda28fde747ba4e026772007cea77374e16Chris Craik .setMeshIndexedQuads(&op.vertices[0], op.vertexCount / 4) 3119e7fcfda28fde747ba4e026772007cea77374e16Chris Craik .setFillPaint(*op.paint, state.alpha) 3129e7fcfda28fde747ba4e026772007cea77374e16Chris Craik .setTransform(state.computedState.transform, TransformFlags::None) 3139e7fcfda28fde747ba4e026772007cea77374e16Chris Craik .setModelViewOffsetRect(0, 0, op.unmappedBounds) 3149e7fcfda28fde747ba4e026772007cea77374e16Chris Craik .build(); 3159e7fcfda28fde747ba4e026772007cea77374e16Chris Craik renderer.renderGlop(state, glop); 3169e7fcfda28fde747ba4e026772007cea77374e16Chris Craik} 3179e7fcfda28fde747ba4e026772007cea77374e16Chris Craik 3189e7fcfda28fde747ba4e026772007cea77374e16Chris Craikvoid BakedOpDispatcher::onTextOp(BakedOpRenderer& renderer, const TextOp& op, const BakedOpState& state) { 31915c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik const Rect* clip = state.computedState.clipSideFlags ? &state.computedState.clipRect : nullptr; 32015c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik renderTextOp(renderer, op, state, clip, TextRenderType::Flush); 3219e7fcfda28fde747ba4e026772007cea77374e16Chris Craik} 3229e7fcfda28fde747ba4e026772007cea77374e16Chris Craik 3239e7fcfda28fde747ba4e026772007cea77374e16Chris Craikvoid BakedOpDispatcher::onLayerOp(BakedOpRenderer& renderer, const LayerOp& op, const BakedOpState& state) { 3249e7fcfda28fde747ba4e026772007cea77374e16Chris Craik OffscreenBuffer* buffer = *op.layerHandle; 3259e7fcfda28fde747ba4e026772007cea77374e16Chris Craik 3269e7fcfda28fde747ba4e026772007cea77374e16Chris Craik // TODO: extend this to handle HW layers & paint properties which 3279e7fcfda28fde747ba4e026772007cea77374e16Chris Craik // reside in node.properties().layerProperties() 3289e7fcfda28fde747ba4e026772007cea77374e16Chris Craik float layerAlpha = op.alpha * state.alpha; 3299e7fcfda28fde747ba4e026772007cea77374e16Chris Craik Glop glop; 3309e7fcfda28fde747ba4e026772007cea77374e16Chris Craik GlopBuilder(renderer.renderState(), renderer.caches(), &glop) 3319e7fcfda28fde747ba4e026772007cea77374e16Chris Craik .setRoundRectClipState(state.roundRectClipState) 3329e7fcfda28fde747ba4e026772007cea77374e16Chris Craik .setMeshTexturedIndexedVbo(buffer->vbo, buffer->elementCount) 3339e7fcfda28fde747ba4e026772007cea77374e16Chris Craik .setFillLayer(buffer->texture, op.colorFilter, layerAlpha, op.mode, Blend::ModeOrderSwap::NoSwap) 3349e7fcfda28fde747ba4e026772007cea77374e16Chris Craik .setTransform(state.computedState.transform, TransformFlags::None) 3359e7fcfda28fde747ba4e026772007cea77374e16Chris Craik .setModelViewOffsetRectSnap(op.unmappedBounds.left, op.unmappedBounds.top, 3369e7fcfda28fde747ba4e026772007cea77374e16Chris Craik Rect(op.unmappedBounds.getWidth(), op.unmappedBounds.getHeight())) 3379e7fcfda28fde747ba4e026772007cea77374e16Chris Craik .build(); 3389e7fcfda28fde747ba4e026772007cea77374e16Chris Craik renderer.renderGlop(state, glop); 3399e7fcfda28fde747ba4e026772007cea77374e16Chris Craik 3409e7fcfda28fde747ba4e026772007cea77374e16Chris Craik if (op.destroy) { 3419e7fcfda28fde747ba4e026772007cea77374e16Chris Craik renderer.renderState().layerPool().putOrDelete(buffer); 3429e7fcfda28fde747ba4e026772007cea77374e16Chris Craik } 3439e7fcfda28fde747ba4e026772007cea77374e16Chris Craik} 3449e7fcfda28fde747ba4e026772007cea77374e16Chris Craik 3459e7fcfda28fde747ba4e026772007cea77374e16Chris Craik} // namespace uirenderer 3469e7fcfda28fde747ba4e026772007cea77374e16Chris Craik} // namespace android 347