TessellationCache.cpp revision 25e5a02d1cbbaa8352be314c45f9cf3599a8f30e
105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik/* 205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik * Copyright (C) 2014 The Android Open Source Project 305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik * 405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik * Licensed under the Apache License, Version 2.0 (the "License"); 505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik * you may not use this file except in compliance with the License. 605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik * You may obtain a copy of the License at 705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik * 805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik * http://www.apache.org/licenses/LICENSE-2.0 905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik * 1005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik * Unless required by applicable law or agreed to in writing, software 1105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik * distributed under the License is distributed on an "AS IS" BASIS, 1205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik * See the License for the specific language governing permissions and 1405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik * limitations under the License. 1505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik */ 1605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 1705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik#include <utils/JenkinsHash.h> 1805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik#include <utils/Trace.h> 1905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 2005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik#include "Caches.h" 2105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik#include "OpenGLRenderer.h" 2205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik#include "PathTessellator.h" 2305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik#include "ShadowTessellator.h" 2405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik#include "TessellationCache.h" 2505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 2605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik#include "thread/Signal.h" 2705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik#include "thread/Task.h" 2805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik#include "thread/TaskProcessor.h" 2905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 3005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craiknamespace android { 3105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craiknamespace uirenderer { 3205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 3305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik/////////////////////////////////////////////////////////////////////////////// 3405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik// Cache entries 3505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik/////////////////////////////////////////////////////////////////////////////// 3605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 3705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris CraikTessellationCache::Description::Description() 3805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik : type(kNone) 396ac174b97246ed40fe780b29561603b61770fa17Chris Craik , scaleX(1.0f) 406ac174b97246ed40fe780b29561603b61770fa17Chris Craik , scaleY(1.0f) 41ed4ef0bc17c33ecd7e689e3c40244a7c1c6063d0Chris Craik , aa(false) 4205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik , cap(SkPaint::kDefault_Cap) 4305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik , style(SkPaint::kFill_Style) 4405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik , strokeWidth(1.0f) { 4505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik memset(&shape, 0, sizeof(Shape)); 4605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik} 4705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 486ac174b97246ed40fe780b29561603b61770fa17Chris CraikTessellationCache::Description::Description(Type type, const Matrix4& transform, const SkPaint& paint) 4905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik : type(type) 506ac174b97246ed40fe780b29561603b61770fa17Chris Craik , aa(paint.isAntiAlias()) 516ac174b97246ed40fe780b29561603b61770fa17Chris Craik , cap(paint.getStrokeCap()) 526ac174b97246ed40fe780b29561603b61770fa17Chris Craik , style(paint.getStyle()) 536ac174b97246ed40fe780b29561603b61770fa17Chris Craik , strokeWidth(paint.getStrokeWidth()) { 546ac174b97246ed40fe780b29561603b61770fa17Chris Craik PathTessellator::extractTessellationScales(transform, &scaleX, &scaleY); 5505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik memset(&shape, 0, sizeof(Shape)); 5605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik} 5705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 5805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikhash_t TessellationCache::Description::hash() const { 5905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik uint32_t hash = JenkinsHashMix(0, type); 60ed4ef0bc17c33ecd7e689e3c40244a7c1c6063d0Chris Craik hash = JenkinsHashMix(hash, aa); 6105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik hash = JenkinsHashMix(hash, cap); 6205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik hash = JenkinsHashMix(hash, style); 6305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik hash = JenkinsHashMix(hash, android::hash_type(strokeWidth)); 646ac174b97246ed40fe780b29561603b61770fa17Chris Craik hash = JenkinsHashMix(hash, android::hash_type(scaleX)); 656ac174b97246ed40fe780b29561603b61770fa17Chris Craik hash = JenkinsHashMix(hash, android::hash_type(scaleY)); 6605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik hash = JenkinsHashMixBytes(hash, (uint8_t*) &shape, sizeof(Shape)); 6705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik return JenkinsHashWhiten(hash); 6805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik} 6905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 706ac174b97246ed40fe780b29561603b61770fa17Chris Craikvoid TessellationCache::Description::setupMatrixAndPaint(Matrix4* matrix, SkPaint* paint) const { 716ac174b97246ed40fe780b29561603b61770fa17Chris Craik matrix->loadScale(scaleX, scaleY, 1.0f); 726ac174b97246ed40fe780b29561603b61770fa17Chris Craik paint->setAntiAlias(aa); 736ac174b97246ed40fe780b29561603b61770fa17Chris Craik paint->setStrokeCap(cap); 746ac174b97246ed40fe780b29561603b61770fa17Chris Craik paint->setStyle(style); 756ac174b97246ed40fe780b29561603b61770fa17Chris Craik paint->setStrokeWidth(strokeWidth); 766ac174b97246ed40fe780b29561603b61770fa17Chris Craik} 776ac174b97246ed40fe780b29561603b61770fa17Chris Craik 7805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris CraikTessellationCache::ShadowDescription::ShadowDescription() 7905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik : nodeKey(NULL) { 8005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik memset(&matrixData, 0, 16 * sizeof(float)); 8105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik} 8205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 8305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris CraikTessellationCache::ShadowDescription::ShadowDescription(const void* nodeKey, const Matrix4* drawTransform) 8405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik : nodeKey(nodeKey) { 8505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik memcpy(&matrixData, drawTransform->data, 16 * sizeof(float)); 8605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik} 8705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 8805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikhash_t TessellationCache::ShadowDescription::hash() const { 8905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik uint32_t hash = JenkinsHashMixBytes(0, (uint8_t*) &nodeKey, sizeof(const void*)); 9005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik hash = JenkinsHashMixBytes(hash, (uint8_t*) &matrixData, 16 * sizeof(float)); 9105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik return JenkinsHashWhiten(hash); 9205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik} 9305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 9405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik/////////////////////////////////////////////////////////////////////////////// 9505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik// General purpose tessellation task processing 9605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik/////////////////////////////////////////////////////////////////////////////// 9705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 9805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikclass TessellationCache::TessellationTask : public Task<VertexBuffer*> { 9905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikpublic: 1006ac174b97246ed40fe780b29561603b61770fa17Chris Craik TessellationTask(Tessellator tessellator, const Description& description) 10105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik : tessellator(tessellator) 1026ac174b97246ed40fe780b29561603b61770fa17Chris Craik , description(description) { 10305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik } 10405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 10505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik ~TessellationTask() {} 10605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 10705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik Tessellator tessellator; 10805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik Description description; 10905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik}; 11005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 11105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikclass TessellationCache::TessellationProcessor : public TaskProcessor<VertexBuffer*> { 11205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikpublic: 11305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik TessellationProcessor(Caches& caches) 11405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik : TaskProcessor<VertexBuffer*>(&caches.tasks) {} 11505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik ~TessellationProcessor() {} 11605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 11705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik virtual void onProcess(const sp<Task<VertexBuffer*> >& task) { 11805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik TessellationTask* t = static_cast<TessellationTask*>(task.get()); 11905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik ATRACE_NAME("shape tessellation"); 1206ac174b97246ed40fe780b29561603b61770fa17Chris Craik VertexBuffer* buffer = t->tessellator(t->description); 12105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik t->setResult(buffer); 12205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik } 12305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik}; 12405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 1251aa5d2d7068147ff781cfe911a93f01593a68c79John Reckclass TessellationCache::Buffer { 12605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikpublic: 12705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik Buffer(const sp<Task<VertexBuffer*> >& task) 12805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik : mTask(task) 12905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik , mBuffer(NULL) { 13005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik } 13105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 13205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik ~Buffer() { 13305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik mTask.clear(); 13405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik delete mBuffer; 13505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik } 13605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 13705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik unsigned int getSize() { 13805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik blockOnPrecache(); 13905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik return mBuffer->getSize(); 14005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik } 14105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 14205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik const VertexBuffer* getVertexBuffer() { 14305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik blockOnPrecache(); 14405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik return mBuffer; 14505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik } 14605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 14705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikprivate: 14805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik void blockOnPrecache() { 14905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik if (mTask != NULL) { 15005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik mBuffer = mTask->getResult(); 15105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik LOG_ALWAYS_FATAL_IF(mBuffer == NULL, "Failed to precache"); 15205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik mTask.clear(); 15305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik } 15405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik } 15505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik sp<Task<VertexBuffer*> > mTask; 15605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik VertexBuffer* mBuffer; 15705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik}; 15805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 15905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik/////////////////////////////////////////////////////////////////////////////// 16005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik// Shadow tessellation task processing 16105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik/////////////////////////////////////////////////////////////////////////////// 16205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 16305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikclass ShadowTask : public Task<TessellationCache::vertexBuffer_pair_t*> { 16405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikpublic: 16505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik ShadowTask(const Matrix4* drawTransform, const Rect& localClip, bool opaque, 16605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik const SkPath* casterPerimeter, const Matrix4* transformXY, const Matrix4* transformZ, 16705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik const Vector3& lightCenter, float lightRadius) 1681b3be0877a07dac81fd21c898ba917e6ee5354b2Chris Craik : drawTransform(*drawTransform) 16905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik , localClip(localClip) 17005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik , opaque(opaque) 1711b3be0877a07dac81fd21c898ba917e6ee5354b2Chris Craik , casterPerimeter(*casterPerimeter) 1721b3be0877a07dac81fd21c898ba917e6ee5354b2Chris Craik , transformXY(*transformXY) 1731b3be0877a07dac81fd21c898ba917e6ee5354b2Chris Craik , transformZ(*transformZ) 17405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik , lightCenter(lightCenter) 17505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik , lightRadius(lightRadius) { 17605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik } 17705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 17805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik ~ShadowTask() { 17905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik TessellationCache::vertexBuffer_pair_t* bufferPair = getResult(); 18005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik delete bufferPair->getFirst(); 18105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik delete bufferPair->getSecond(); 18205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik delete bufferPair; 18305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik } 18405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 1851b3be0877a07dac81fd21c898ba917e6ee5354b2Chris Craik /* Note - we deep copy all task parameters, because *even though* pointers into Allocator 1861b3be0877a07dac81fd21c898ba917e6ee5354b2Chris Craik * controlled objects (like the SkPath and Matrix4s) should be safe for the entire frame, 1871b3be0877a07dac81fd21c898ba917e6ee5354b2Chris Craik * certain Allocators are destroyed before trim() is called to flush incomplete tasks. 1881b3be0877a07dac81fd21c898ba917e6ee5354b2Chris Craik * 1891b3be0877a07dac81fd21c898ba917e6ee5354b2Chris Craik * These deep copies could be avoided, long term, by cancelling or flushing outstanding tasks 1901b3be0877a07dac81fd21c898ba917e6ee5354b2Chris Craik * before tearning down single-frame LinearAllocators. 1911b3be0877a07dac81fd21c898ba917e6ee5354b2Chris Craik */ 1921b3be0877a07dac81fd21c898ba917e6ee5354b2Chris Craik const Matrix4 drawTransform; 19305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik const Rect localClip; 19405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik bool opaque; 1951b3be0877a07dac81fd21c898ba917e6ee5354b2Chris Craik const SkPath casterPerimeter; 1961b3be0877a07dac81fd21c898ba917e6ee5354b2Chris Craik const Matrix4 transformXY; 1971b3be0877a07dac81fd21c898ba917e6ee5354b2Chris Craik const Matrix4 transformZ; 19805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik const Vector3 lightCenter; 19905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik const float lightRadius; 20005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik}; 20105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 20205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikstatic void mapPointFakeZ(Vector3& point, const mat4* transformXY, const mat4* transformZ) { 20305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik // map z coordinate with true 3d matrix 20405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik point.z = transformZ->mapZ(point); 20505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 20605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik // map x,y coordinates with draw/Skia matrix 20705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik transformXY->mapPoint(point.x, point.y); 20805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik} 20905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 21005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikstatic void tessellateShadows( 21105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik const Matrix4* drawTransform, const Rect* localClip, 21205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik bool isCasterOpaque, const SkPath* casterPerimeter, 21305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik const Matrix4* casterTransformXY, const Matrix4* casterTransformZ, 21405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik const Vector3& lightCenter, float lightRadius, 21505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik VertexBuffer& ambientBuffer, VertexBuffer& spotBuffer) { 21605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 21705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik // tessellate caster outline into a 2d polygon 21805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik Vector<Vertex> casterVertices2d; 21925e5a02d1cbbaa8352be314c45f9cf3599a8f30eztenghui const float casterRefinementThresholdSquared = 4.0f; 22005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik PathTessellator::approximatePathOutlineVertices(*casterPerimeter, 22105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik casterRefinementThresholdSquared, casterVertices2d); 22205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik if (!ShadowTessellator::isClockwisePath(*casterPerimeter)) { 22305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik ShadowTessellator::reverseVertexArray(casterVertices2d.editArray(), 22405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik casterVertices2d.size()); 22505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik } 22605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 22705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik if (casterVertices2d.size() == 0) return; 22805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 22905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik // map 2d caster poly into 3d 23005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik const int casterVertexCount = casterVertices2d.size(); 23105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik Vector3 casterPolygon[casterVertexCount]; 23205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik float minZ = FLT_MAX; 23305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik float maxZ = -FLT_MAX; 23405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik for (int i = 0; i < casterVertexCount; i++) { 23505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik const Vertex& point2d = casterVertices2d[i]; 2361aa5d2d7068147ff781cfe911a93f01593a68c79John Reck casterPolygon[i] = (Vector3){point2d.x, point2d.y, 0}; 23705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik mapPointFakeZ(casterPolygon[i], casterTransformXY, casterTransformZ); 23805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik minZ = fmin(minZ, casterPolygon[i].z); 23905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik maxZ = fmax(maxZ, casterPolygon[i].z); 24005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik } 24105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 24205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik // map the centroid of the caster into 3d 24305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik Vector2 centroid = ShadowTessellator::centroid2d( 24405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik reinterpret_cast<const Vector2*>(casterVertices2d.array()), 24505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik casterVertexCount); 2461aa5d2d7068147ff781cfe911a93f01593a68c79John Reck Vector3 centroid3d = {centroid.x, centroid.y, 0}; 24705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik mapPointFakeZ(centroid3d, casterTransformXY, casterTransformZ); 24805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 24905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik // if the caster intersects the z=0 plane, lift it in Z so it doesn't 25005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik if (minZ < SHADOW_MIN_CASTER_Z) { 25105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik float casterLift = SHADOW_MIN_CASTER_Z - minZ; 25205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik for (int i = 0; i < casterVertexCount; i++) { 25305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik casterPolygon[i].z += casterLift; 25405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik } 25505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik centroid3d.z += casterLift; 25605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik } 25705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 25805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik // Check whether we want to draw the shadow at all by checking the caster's bounds against clip. 25905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik // We only have ortho projection, so we can just ignore the Z in caster for 26005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik // simple rejection calculation. 26105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik Rect casterBounds(casterPerimeter->getBounds()); 26205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik casterTransformXY->mapRect(casterBounds); 26305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 26405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik // actual tessellation of both shadows 26505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik ShadowTessellator::tessellateAmbientShadow( 26605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik isCasterOpaque, casterPolygon, casterVertexCount, centroid3d, 26705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik casterBounds, *localClip, maxZ, ambientBuffer); 26805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 26905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik ShadowTessellator::tessellateSpotShadow( 270c50a03d78aaedd0003377e98710e7038bda330e9ztenghui isCasterOpaque, casterPolygon, casterVertexCount, centroid3d, 27105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik *drawTransform, lightCenter, lightRadius, casterBounds, *localClip, 27205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik spotBuffer); 27305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik} 27405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 27505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikclass ShadowProcessor : public TaskProcessor<TessellationCache::vertexBuffer_pair_t*> { 27605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikpublic: 27705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik ShadowProcessor(Caches& caches) 27805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik : TaskProcessor<TessellationCache::vertexBuffer_pair_t*>(&caches.tasks) {} 27905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik ~ShadowProcessor() {} 28005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 28105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik virtual void onProcess(const sp<Task<TessellationCache::vertexBuffer_pair_t*> >& task) { 28205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik ShadowTask* t = static_cast<ShadowTask*>(task.get()); 28305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik ATRACE_NAME("shadow tessellation"); 28405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 28505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik VertexBuffer* ambientBuffer = new VertexBuffer; 28605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik VertexBuffer* spotBuffer = new VertexBuffer; 2871b3be0877a07dac81fd21c898ba917e6ee5354b2Chris Craik tessellateShadows(&t->drawTransform, &t->localClip, t->opaque, &t->casterPerimeter, 2881b3be0877a07dac81fd21c898ba917e6ee5354b2Chris Craik &t->transformXY, &t->transformZ, t->lightCenter, t->lightRadius, 28905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik *ambientBuffer, *spotBuffer); 29005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 29105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik t->setResult(new TessellationCache::vertexBuffer_pair_t(ambientBuffer, spotBuffer)); 29205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik } 29305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik}; 29405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 29505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik/////////////////////////////////////////////////////////////////////////////// 29605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik// Cache constructor/destructor 29705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik/////////////////////////////////////////////////////////////////////////////// 29805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 29905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris CraikTessellationCache::TessellationCache() 30005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik : mSize(0) 30105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik , mMaxSize(MB(DEFAULT_VERTEX_CACHE_SIZE)) 30205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik , mCache(LruCache<Description, Buffer*>::kUnlimitedCapacity) 30305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik , mShadowCache(LruCache<ShadowDescription, Task<vertexBuffer_pair_t*>*>::kUnlimitedCapacity) { 30405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik char property[PROPERTY_VALUE_MAX]; 30505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik if (property_get(PROPERTY_VERTEX_CACHE_SIZE, property, NULL) > 0) { 30605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik INIT_LOGD(" Setting %s cache size to %sMB", name, property); 30705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik setMaxSize(MB(atof(property))); 30805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik } else { 30905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik INIT_LOGD(" Using default %s cache size of %.2fMB", name, DEFAULT_VERTEX_CACHE_SIZE); 31005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik } 31105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 31205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik mCache.setOnEntryRemovedListener(&mBufferRemovedListener); 31305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik mShadowCache.setOnEntryRemovedListener(&mBufferPairRemovedListener); 31405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik mDebugEnabled = readDebugLevel() & kDebugCaches; 31505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik} 31605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 31705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris CraikTessellationCache::~TessellationCache() { 31805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik mCache.clear(); 31905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik} 32005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 32105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik/////////////////////////////////////////////////////////////////////////////// 32205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik// Size management 32305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik/////////////////////////////////////////////////////////////////////////////// 32405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 32505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikuint32_t TessellationCache::getSize() { 32605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik LruCache<Description, Buffer*>::Iterator iter(mCache); 32705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik uint32_t size = 0; 32805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik while (iter.next()) { 32905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik size += iter.value()->getSize(); 33005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik } 33105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik return size; 33205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik} 33305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 33405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikuint32_t TessellationCache::getMaxSize() { 33505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik return mMaxSize; 33605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik} 33705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 33805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikvoid TessellationCache::setMaxSize(uint32_t maxSize) { 33905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik mMaxSize = maxSize; 34005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik while (mSize > mMaxSize) { 34105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik mCache.removeOldest(); 34205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik } 34305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik} 34405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 34505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik/////////////////////////////////////////////////////////////////////////////// 34605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik// Caching 34705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik/////////////////////////////////////////////////////////////////////////////// 34805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 34905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 35005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikvoid TessellationCache::trim() { 35105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik uint32_t size = getSize(); 35205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik while (size > mMaxSize) { 35305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik size -= mCache.peekOldestValue()->getSize(); 35405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik mCache.removeOldest(); 35505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik } 35605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik mShadowCache.clear(); 35705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik} 35805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 35905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikvoid TessellationCache::clear() { 36005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik mCache.clear(); 36105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik mShadowCache.clear(); 36205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik} 36305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 36405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik/////////////////////////////////////////////////////////////////////////////// 36505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik// Callbacks 36605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik/////////////////////////////////////////////////////////////////////////////// 36705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 36805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikvoid TessellationCache::BufferRemovedListener::operator()(Description& description, 36905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik Buffer*& buffer) { 37005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik delete buffer; 37105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik} 37205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 37305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik/////////////////////////////////////////////////////////////////////////////// 37405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik// Shadows 37505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik/////////////////////////////////////////////////////////////////////////////// 37605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 37705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikvoid TessellationCache::precacheShadows(const Matrix4* drawTransform, const Rect& localClip, 37805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik bool opaque, const SkPath* casterPerimeter, 37905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik const Matrix4* transformXY, const Matrix4* transformZ, 38005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik const Vector3& lightCenter, float lightRadius) { 38105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik ShadowDescription key(casterPerimeter, drawTransform); 38205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 38305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik sp<ShadowTask> task = new ShadowTask(drawTransform, localClip, opaque, 38405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik casterPerimeter, transformXY, transformZ, lightCenter, lightRadius); 38505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik if (mShadowProcessor == NULL) { 38605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik mShadowProcessor = new ShadowProcessor(Caches::getInstance()); 38705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik } 38805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik mShadowProcessor->add(task); 38905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 39005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik task->incStrong(NULL); // not using sp<>s, so manually ref while in the cache 39105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik mShadowCache.put(key, task.get()); 39205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik} 39305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 39405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikvoid TessellationCache::getShadowBuffers(const Matrix4* drawTransform, const Rect& localClip, 39505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik bool opaque, const SkPath* casterPerimeter, 39605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik const Matrix4* transformXY, const Matrix4* transformZ, 39705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik const Vector3& lightCenter, float lightRadius, vertexBuffer_pair_t& outBuffers) { 39805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik ShadowDescription key(casterPerimeter, drawTransform); 39905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik ShadowTask* task = static_cast<ShadowTask*>(mShadowCache.get(key)); 40005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik if (!task) { 40105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik precacheShadows(drawTransform, localClip, opaque, casterPerimeter, 40205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik transformXY, transformZ, lightCenter, lightRadius); 40305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik task = static_cast<ShadowTask*>(mShadowCache.get(key)); 40405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik } 40505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik LOG_ALWAYS_FATAL_IF(task == NULL, "shadow not precached"); 40605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik outBuffers = *(task->getResult()); 40705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik} 40805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 40905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik/////////////////////////////////////////////////////////////////////////////// 41005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik// Tessellation precaching 41105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik/////////////////////////////////////////////////////////////////////////////// 41205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 41305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris CraikTessellationCache::Buffer* TessellationCache::getOrCreateBuffer( 4146ac174b97246ed40fe780b29561603b61770fa17Chris Craik const Description& entry, Tessellator tessellator) { 41505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik Buffer* buffer = mCache.get(entry); 41605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik if (!buffer) { 41705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik // not cached, enqueue a task to fill the buffer 4186ac174b97246ed40fe780b29561603b61770fa17Chris Craik sp<TessellationTask> task = new TessellationTask(tessellator, entry); 41905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik buffer = new Buffer(task); 42005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 42105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik if (mProcessor == NULL) { 42205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik mProcessor = new TessellationProcessor(Caches::getInstance()); 42305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik } 42405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik mProcessor->add(task); 42505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik mCache.put(entry, buffer); 42605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik } 42705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik return buffer; 42805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik} 42905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 4306ac174b97246ed40fe780b29561603b61770fa17Chris Craikstatic VertexBuffer* tessellatePath(const TessellationCache::Description& description, 4316ac174b97246ed40fe780b29561603b61770fa17Chris Craik const SkPath& path) { 4326ac174b97246ed40fe780b29561603b61770fa17Chris Craik Matrix4 matrix; 4336ac174b97246ed40fe780b29561603b61770fa17Chris Craik SkPaint paint; 4346ac174b97246ed40fe780b29561603b61770fa17Chris Craik description.setupMatrixAndPaint(&matrix, &paint); 4356ac174b97246ed40fe780b29561603b61770fa17Chris Craik VertexBuffer* buffer = new VertexBuffer(); 4366ac174b97246ed40fe780b29561603b61770fa17Chris Craik PathTessellator::tessellatePath(path, &paint, matrix, *buffer); 4376ac174b97246ed40fe780b29561603b61770fa17Chris Craik return buffer; 4386ac174b97246ed40fe780b29561603b61770fa17Chris Craik} 4396ac174b97246ed40fe780b29561603b61770fa17Chris Craik 44005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik/////////////////////////////////////////////////////////////////////////////// 4416ac174b97246ed40fe780b29561603b61770fa17Chris Craik// RoundRect 44205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik/////////////////////////////////////////////////////////////////////////////// 44305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 4446ac174b97246ed40fe780b29561603b61770fa17Chris Craikstatic VertexBuffer* tessellateRoundRect(const TessellationCache::Description& description) { 4456ac174b97246ed40fe780b29561603b61770fa17Chris Craik SkRect rect = SkRect::MakeWH(description.shape.roundRect.width, 4466ac174b97246ed40fe780b29561603b61770fa17Chris Craik description.shape.roundRect.height); 4476ac174b97246ed40fe780b29561603b61770fa17Chris Craik float rx = description.shape.roundRect.rx; 4486ac174b97246ed40fe780b29561603b61770fa17Chris Craik float ry = description.shape.roundRect.ry; 4496ac174b97246ed40fe780b29561603b61770fa17Chris Craik if (description.style == SkPaint::kStrokeAndFill_Style) { 4506ac174b97246ed40fe780b29561603b61770fa17Chris Craik float outset = description.strokeWidth / 2; 45105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik rect.outset(outset, outset); 45205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik rx += outset; 45305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik ry += outset; 45405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik } 45505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik SkPath path; 45605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik path.addRoundRect(rect, rx, ry); 4576ac174b97246ed40fe780b29561603b61770fa17Chris Craik return tessellatePath(description, path); 45805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik} 45905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 4606ac174b97246ed40fe780b29561603b61770fa17Chris CraikTessellationCache::Buffer* TessellationCache::getRoundRectBuffer( 4616ac174b97246ed40fe780b29561603b61770fa17Chris Craik const Matrix4& transform, const SkPaint& paint, 4626ac174b97246ed40fe780b29561603b61770fa17Chris Craik float width, float height, float rx, float ry) { 4636ac174b97246ed40fe780b29561603b61770fa17Chris Craik Description entry(Description::kRoundRect, transform, paint); 4646ac174b97246ed40fe780b29561603b61770fa17Chris Craik entry.shape.roundRect.width = width; 4656ac174b97246ed40fe780b29561603b61770fa17Chris Craik entry.shape.roundRect.height = height; 4666ac174b97246ed40fe780b29561603b61770fa17Chris Craik entry.shape.roundRect.rx = rx; 4676ac174b97246ed40fe780b29561603b61770fa17Chris Craik entry.shape.roundRect.ry = ry; 4686ac174b97246ed40fe780b29561603b61770fa17Chris Craik return getOrCreateBuffer(entry, &tessellateRoundRect); 46905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik} 4706ac174b97246ed40fe780b29561603b61770fa17Chris Craikconst VertexBuffer* TessellationCache::getRoundRect(const Matrix4& transform, const SkPaint& paint, 4716ac174b97246ed40fe780b29561603b61770fa17Chris Craik float width, float height, float rx, float ry) { 4726ac174b97246ed40fe780b29561603b61770fa17Chris Craik return getRoundRectBuffer(transform, paint, width, height, rx, ry)->getVertexBuffer(); 47305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik} 47405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 47505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik}; // namespace uirenderer 47605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik}; // namespace android 477