TessellationCache.cpp revision 1b3be0877a07dac81fd21c898ba917e6ee5354b2
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#define LOG_TAG "OpenGLRenderer" 1805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik#define ATRACE_TAG ATRACE_TAG_VIEW 1905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 2005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik#include <utils/JenkinsHash.h> 2105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik#include <utils/Trace.h> 2205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 2305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik#include "Caches.h" 2405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik#include "OpenGLRenderer.h" 2505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik#include "PathTessellator.h" 2605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik#include "ShadowTessellator.h" 2705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik#include "TessellationCache.h" 2805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 2905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik#include "thread/Signal.h" 3005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik#include "thread/Task.h" 3105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik#include "thread/TaskProcessor.h" 3205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 3305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craiknamespace android { 3405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craiknamespace uirenderer { 3505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 3605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik/////////////////////////////////////////////////////////////////////////////// 3705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik// Cache entries 3805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik/////////////////////////////////////////////////////////////////////////////// 3905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 4005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris CraikTessellationCache::Description::Description() 4105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik : type(kNone) 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 4805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris CraikTessellationCache::Description::Description(Type type) 4905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik : type(type) 5005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik , cap(SkPaint::kDefault_Cap) 5105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik , style(SkPaint::kFill_Style) 5205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik , strokeWidth(1.0f) { 5305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik memset(&shape, 0, sizeof(Shape)); 5405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik} 5505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 5605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris CraikTessellationCache::Description::Description(Type type, const SkPaint* paint) 5705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik : type(type) 5805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik , cap(paint->getStrokeCap()) 5905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik , style(paint->getStyle()) 6005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik , strokeWidth(paint->getStrokeWidth()) { 6105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik memset(&shape, 0, sizeof(Shape)); 6205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik} 6305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 6405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikhash_t TessellationCache::Description::hash() const { 6505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik uint32_t hash = JenkinsHashMix(0, type); 6605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik hash = JenkinsHashMix(hash, cap); 6705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik hash = JenkinsHashMix(hash, style); 6805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik hash = JenkinsHashMix(hash, android::hash_type(strokeWidth)); 6905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik hash = JenkinsHashMixBytes(hash, (uint8_t*) &shape, sizeof(Shape)); 7005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik return JenkinsHashWhiten(hash); 7105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik} 7205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 7305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris CraikTessellationCache::ShadowDescription::ShadowDescription() 7405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik : nodeKey(NULL) { 7505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik memset(&matrixData, 0, 16 * sizeof(float)); 7605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik} 7705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 7805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris CraikTessellationCache::ShadowDescription::ShadowDescription(const void* nodeKey, const Matrix4* drawTransform) 7905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik : nodeKey(nodeKey) { 8005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik memcpy(&matrixData, drawTransform->data, 16 * sizeof(float)); 8105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik} 8205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 8305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikhash_t TessellationCache::ShadowDescription::hash() const { 8405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik uint32_t hash = JenkinsHashMixBytes(0, (uint8_t*) &nodeKey, sizeof(const void*)); 8505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik hash = JenkinsHashMixBytes(hash, (uint8_t*) &matrixData, 16 * sizeof(float)); 8605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik return JenkinsHashWhiten(hash); 8705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik} 8805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 8905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik/////////////////////////////////////////////////////////////////////////////// 9005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik// General purpose tessellation task processing 9105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik/////////////////////////////////////////////////////////////////////////////// 9205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 9305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikclass TessellationCache::TessellationTask : public Task<VertexBuffer*> { 9405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikpublic: 9505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik TessellationTask(Tessellator tessellator, const Description& description, 9605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik const SkPaint* paint) 9705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik : tessellator(tessellator) 9805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik , description(description) 9905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik , paint(*paint) { 10005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik } 10105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 10205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik ~TessellationTask() {} 10305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 10405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik Tessellator tessellator; 10505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik Description description; 10605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 10705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik //copied, since input paint may not be immutable 10805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik const SkPaint paint; 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"); 12005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik VertexBuffer* buffer = t->tessellator(t->description, t->paint); 12105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik t->setResult(buffer); 12205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik } 12305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik}; 12405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 12505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikstruct 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; 21905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik const float casterRefinementThresholdSquared = 20.0f; // TODO: experiment with this value 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]; 23605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 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); 24605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 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( 27005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik isCasterOpaque, casterPolygon, casterVertexCount, 27105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik *drawTransform, lightCenter, lightRadius, casterBounds, *localClip, 27205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik spotBuffer); 27305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 27405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik // TODO: set ambientBuffer & spotBuffer's bounds for correct layer damage 27505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik} 27605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 27705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikclass ShadowProcessor : public TaskProcessor<TessellationCache::vertexBuffer_pair_t*> { 27805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikpublic: 27905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik ShadowProcessor(Caches& caches) 28005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik : TaskProcessor<TessellationCache::vertexBuffer_pair_t*>(&caches.tasks) {} 28105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik ~ShadowProcessor() {} 28205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 28305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik virtual void onProcess(const sp<Task<TessellationCache::vertexBuffer_pair_t*> >& task) { 28405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik ShadowTask* t = static_cast<ShadowTask*>(task.get()); 28505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik ATRACE_NAME("shadow tessellation"); 28605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 28705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik VertexBuffer* ambientBuffer = new VertexBuffer; 28805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik VertexBuffer* spotBuffer = new VertexBuffer; 2891b3be0877a07dac81fd21c898ba917e6ee5354b2Chris Craik tessellateShadows(&t->drawTransform, &t->localClip, t->opaque, &t->casterPerimeter, 2901b3be0877a07dac81fd21c898ba917e6ee5354b2Chris Craik &t->transformXY, &t->transformZ, t->lightCenter, t->lightRadius, 29105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik *ambientBuffer, *spotBuffer); 29205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 29305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik t->setResult(new TessellationCache::vertexBuffer_pair_t(ambientBuffer, spotBuffer)); 29405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik } 29505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik}; 29605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 29705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik/////////////////////////////////////////////////////////////////////////////// 29805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik// Cache constructor/destructor 29905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik/////////////////////////////////////////////////////////////////////////////// 30005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 30105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris CraikTessellationCache::TessellationCache() 30205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik : mSize(0) 30305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik , mMaxSize(MB(DEFAULT_VERTEX_CACHE_SIZE)) 30405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik , mCache(LruCache<Description, Buffer*>::kUnlimitedCapacity) 30505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik , mShadowCache(LruCache<ShadowDescription, Task<vertexBuffer_pair_t*>*>::kUnlimitedCapacity) { 30605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik char property[PROPERTY_VALUE_MAX]; 30705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik if (property_get(PROPERTY_VERTEX_CACHE_SIZE, property, NULL) > 0) { 30805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik INIT_LOGD(" Setting %s cache size to %sMB", name, property); 30905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik setMaxSize(MB(atof(property))); 31005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik } else { 31105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik INIT_LOGD(" Using default %s cache size of %.2fMB", name, DEFAULT_VERTEX_CACHE_SIZE); 31205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik } 31305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 31405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik mCache.setOnEntryRemovedListener(&mBufferRemovedListener); 31505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik mShadowCache.setOnEntryRemovedListener(&mBufferPairRemovedListener); 31605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik mDebugEnabled = readDebugLevel() & kDebugCaches; 31705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik} 31805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 31905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris CraikTessellationCache::~TessellationCache() { 32005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik mCache.clear(); 32105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik} 32205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 32305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik/////////////////////////////////////////////////////////////////////////////// 32405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik// Size management 32505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik/////////////////////////////////////////////////////////////////////////////// 32605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 32705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikuint32_t TessellationCache::getSize() { 32805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik LruCache<Description, Buffer*>::Iterator iter(mCache); 32905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik uint32_t size = 0; 33005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik while (iter.next()) { 33105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik size += iter.value()->getSize(); 33205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik } 33305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik return size; 33405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik} 33505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 33605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikuint32_t TessellationCache::getMaxSize() { 33705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik return mMaxSize; 33805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik} 33905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 34005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikvoid TessellationCache::setMaxSize(uint32_t maxSize) { 34105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik mMaxSize = maxSize; 34205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik while (mSize > mMaxSize) { 34305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik mCache.removeOldest(); 34405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik } 34505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik} 34605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 34705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik/////////////////////////////////////////////////////////////////////////////// 34805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik// Caching 34905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik/////////////////////////////////////////////////////////////////////////////// 35005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 35105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 35205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikvoid TessellationCache::trim() { 35305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik uint32_t size = getSize(); 35405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik while (size > mMaxSize) { 35505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik size -= mCache.peekOldestValue()->getSize(); 35605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik mCache.removeOldest(); 35705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik } 35805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik mShadowCache.clear(); 35905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik} 36005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 36105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikvoid TessellationCache::clear() { 36205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik mCache.clear(); 36305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik mShadowCache.clear(); 36405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik} 36505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 36605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik/////////////////////////////////////////////////////////////////////////////// 36705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik// Callbacks 36805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik/////////////////////////////////////////////////////////////////////////////// 36905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 37005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikvoid TessellationCache::BufferRemovedListener::operator()(Description& description, 37105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik Buffer*& buffer) { 37205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik delete buffer; 37305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik} 37405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 37505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik/////////////////////////////////////////////////////////////////////////////// 37605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik// Shadows 37705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik/////////////////////////////////////////////////////////////////////////////// 37805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 37905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikvoid TessellationCache::precacheShadows(const Matrix4* drawTransform, const Rect& localClip, 38005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik bool opaque, const SkPath* casterPerimeter, 38105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik const Matrix4* transformXY, const Matrix4* transformZ, 38205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik const Vector3& lightCenter, float lightRadius) { 38305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik ShadowDescription key(casterPerimeter, drawTransform); 38405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 38505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik sp<ShadowTask> task = new ShadowTask(drawTransform, localClip, opaque, 38605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik casterPerimeter, transformXY, transformZ, lightCenter, lightRadius); 38705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik if (mShadowProcessor == NULL) { 38805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik mShadowProcessor = new ShadowProcessor(Caches::getInstance()); 38905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik } 39005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik mShadowProcessor->add(task); 39105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 39205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik task->incStrong(NULL); // not using sp<>s, so manually ref while in the cache 39305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik mShadowCache.put(key, task.get()); 39405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik} 39505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 39605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikvoid TessellationCache::getShadowBuffers(const Matrix4* drawTransform, const Rect& localClip, 39705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik bool opaque, const SkPath* casterPerimeter, 39805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik const Matrix4* transformXY, const Matrix4* transformZ, 39905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik const Vector3& lightCenter, float lightRadius, vertexBuffer_pair_t& outBuffers) { 40005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik ShadowDescription key(casterPerimeter, drawTransform); 40105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik ShadowTask* task = static_cast<ShadowTask*>(mShadowCache.get(key)); 40205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik if (!task) { 40305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik precacheShadows(drawTransform, localClip, opaque, casterPerimeter, 40405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik transformXY, transformZ, lightCenter, lightRadius); 40505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik task = static_cast<ShadowTask*>(mShadowCache.get(key)); 40605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik } 40705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik LOG_ALWAYS_FATAL_IF(task == NULL, "shadow not precached"); 40805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik outBuffers = *(task->getResult()); 40905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik} 41005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 41105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik/////////////////////////////////////////////////////////////////////////////// 41205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik// Tessellation precaching 41305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik/////////////////////////////////////////////////////////////////////////////// 41405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 41505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikstatic VertexBuffer* tessellatePath(const SkPath& path, const SkPaint* paint, 41605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik float scaleX, float scaleY) { 41705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik VertexBuffer* buffer = new VertexBuffer(); 41805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik Matrix4 matrix; 41905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik matrix.loadScale(scaleX, scaleY, 1); 42005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik PathTessellator::tessellatePath(path, paint, matrix, *buffer); 42105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik return buffer; 42205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik} 42305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 42405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris CraikTessellationCache::Buffer* TessellationCache::getOrCreateBuffer( 42505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik const Description& entry, Tessellator tessellator, const SkPaint* paint) { 42605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik Buffer* buffer = mCache.get(entry); 42705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik if (!buffer) { 42805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik // not cached, enqueue a task to fill the buffer 42905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik sp<TessellationTask> task = new TessellationTask(tessellator, entry, paint); 43005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik buffer = new Buffer(task); 43105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 43205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik if (mProcessor == NULL) { 43305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik mProcessor = new TessellationProcessor(Caches::getInstance()); 43405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik } 43505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik mProcessor->add(task); 43605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik mCache.put(entry, buffer); 43705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik } 43805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik return buffer; 43905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik} 44005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 44105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik/////////////////////////////////////////////////////////////////////////////// 44205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik// Rounded rects 44305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik/////////////////////////////////////////////////////////////////////////////// 44405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 44505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikstatic VertexBuffer* tessellateRoundRect(const TessellationCache::Description& description, 44605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik const SkPaint& paint) { 44705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik SkRect rect = SkRect::MakeWH(description.shape.roundRect.mWidth, 44805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik description.shape.roundRect.mHeight); 44905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik float rx = description.shape.roundRect.mRx; 45005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik float ry = description.shape.roundRect.mRy; 45105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik if (paint.getStyle() == SkPaint::kStrokeAndFill_Style) { 45205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik float outset = paint.getStrokeWidth() / 2; 45305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik rect.outset(outset, outset); 45405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik rx += outset; 45505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik ry += outset; 45605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik } 45705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik SkPath path; 45805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik path.addRoundRect(rect, rx, ry); 45905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik return tessellatePath(path, &paint, 46005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik description.shape.roundRect.mScaleX, description.shape.roundRect.mScaleY); 46105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik} 46205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 46305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris CraikTessellationCache::Buffer* TessellationCache::getRoundRectBuffer(const Matrix4& transform, 46405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik float width, float height, float rx, float ry, const SkPaint* paint) { 46505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik Description entry(Description::kRoundRect, paint); 46605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik entry.shape.roundRect.mWidth = width; 46705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik entry.shape.roundRect.mHeight = height; 46805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik entry.shape.roundRect.mRx = rx; 46905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik entry.shape.roundRect.mRy = ry; 47005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik PathTessellator::extractTessellationScales(transform, 47105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik &entry.shape.roundRect.mScaleX, &entry.shape.roundRect.mScaleY); 47205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 47305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik return getOrCreateBuffer(entry, &tessellateRoundRect, paint); 47405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik} 47505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikconst VertexBuffer* TessellationCache::getRoundRect(const Matrix4& transform, 47605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik float width, float height, float rx, float ry, const SkPaint* paint) { 47705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik return getRoundRectBuffer(transform, width, height, rx, ry, paint)->getVertexBuffer(); 47805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik} 47905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 48005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik}; // namespace uirenderer 48105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik}; // namespace android 482