TessellationCache.cpp revision 05f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5
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) 16805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik : drawTransform(drawTransform) 16905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik , localClip(localClip) 17005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik , opaque(opaque) 17105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik , casterPerimeter(casterPerimeter) 17205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik , transformXY(transformXY) 17305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris 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 18505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik // Note - only the localClip is deep copied, since other pointers point at Allocator controlled 18605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik // objects, which are safe for the entire frame 18705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik const Matrix4* drawTransform; 18805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik const Rect localClip; 18905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik bool opaque; 19005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik const SkPath* casterPerimeter; 19105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik const Matrix4* transformXY; 19205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik const Matrix4* transformZ; 19305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik const Vector3 lightCenter; 19405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik const float lightRadius; 19505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik}; 19605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 19705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikstatic void mapPointFakeZ(Vector3& point, const mat4* transformXY, const mat4* transformZ) { 19805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik // map z coordinate with true 3d matrix 19905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik point.z = transformZ->mapZ(point); 20005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 20105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik // map x,y coordinates with draw/Skia matrix 20205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik transformXY->mapPoint(point.x, point.y); 20305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik} 20405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 20505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikstatic void tessellateShadows( 20605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik const Matrix4* drawTransform, const Rect* localClip, 20705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik bool isCasterOpaque, const SkPath* casterPerimeter, 20805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik const Matrix4* casterTransformXY, const Matrix4* casterTransformZ, 20905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik const Vector3& lightCenter, float lightRadius, 21005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik VertexBuffer& ambientBuffer, VertexBuffer& spotBuffer) { 21105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 21205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik // tessellate caster outline into a 2d polygon 21305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik Vector<Vertex> casterVertices2d; 21405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik const float casterRefinementThresholdSquared = 20.0f; // TODO: experiment with this value 21505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik PathTessellator::approximatePathOutlineVertices(*casterPerimeter, 21605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik casterRefinementThresholdSquared, casterVertices2d); 21705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik if (!ShadowTessellator::isClockwisePath(*casterPerimeter)) { 21805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik ShadowTessellator::reverseVertexArray(casterVertices2d.editArray(), 21905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik casterVertices2d.size()); 22005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik } 22105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 22205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik if (casterVertices2d.size() == 0) return; 22305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 22405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik // map 2d caster poly into 3d 22505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik const int casterVertexCount = casterVertices2d.size(); 22605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik Vector3 casterPolygon[casterVertexCount]; 22705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik float minZ = FLT_MAX; 22805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik float maxZ = -FLT_MAX; 22905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik for (int i = 0; i < casterVertexCount; i++) { 23005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik const Vertex& point2d = casterVertices2d[i]; 23105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik casterPolygon[i] = Vector3(point2d.x, point2d.y, 0); 23205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik mapPointFakeZ(casterPolygon[i], casterTransformXY, casterTransformZ); 23305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik minZ = fmin(minZ, casterPolygon[i].z); 23405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik maxZ = fmax(maxZ, casterPolygon[i].z); 23505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik } 23605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 23705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik // map the centroid of the caster into 3d 23805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik Vector2 centroid = ShadowTessellator::centroid2d( 23905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik reinterpret_cast<const Vector2*>(casterVertices2d.array()), 24005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik casterVertexCount); 24105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik Vector3 centroid3d(centroid.x, centroid.y, 0); 24205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik mapPointFakeZ(centroid3d, casterTransformXY, casterTransformZ); 24305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 24405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik // if the caster intersects the z=0 plane, lift it in Z so it doesn't 24505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik if (minZ < SHADOW_MIN_CASTER_Z) { 24605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik float casterLift = SHADOW_MIN_CASTER_Z - minZ; 24705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik for (int i = 0; i < casterVertexCount; i++) { 24805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik casterPolygon[i].z += casterLift; 24905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik } 25005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik centroid3d.z += casterLift; 25105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik } 25205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 25305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik // Check whether we want to draw the shadow at all by checking the caster's bounds against clip. 25405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik // We only have ortho projection, so we can just ignore the Z in caster for 25505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik // simple rejection calculation. 25605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik Rect casterBounds(casterPerimeter->getBounds()); 25705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik casterTransformXY->mapRect(casterBounds); 25805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 25905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik // actual tessellation of both shadows 26005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik ShadowTessellator::tessellateAmbientShadow( 26105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik isCasterOpaque, casterPolygon, casterVertexCount, centroid3d, 26205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik casterBounds, *localClip, maxZ, ambientBuffer); 26305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 26405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik ShadowTessellator::tessellateSpotShadow( 26505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik isCasterOpaque, casterPolygon, casterVertexCount, 26605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik *drawTransform, lightCenter, lightRadius, casterBounds, *localClip, 26705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik spotBuffer); 26805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 26905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik // TODO: set ambientBuffer & spotBuffer's bounds for correct layer damage 27005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik} 27105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 27205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikclass ShadowProcessor : public TaskProcessor<TessellationCache::vertexBuffer_pair_t*> { 27305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikpublic: 27405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik ShadowProcessor(Caches& caches) 27505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik : TaskProcessor<TessellationCache::vertexBuffer_pair_t*>(&caches.tasks) {} 27605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik ~ShadowProcessor() {} 27705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 27805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik virtual void onProcess(const sp<Task<TessellationCache::vertexBuffer_pair_t*> >& task) { 27905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik ShadowTask* t = static_cast<ShadowTask*>(task.get()); 28005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik ATRACE_NAME("shadow tessellation"); 28105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 28205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik VertexBuffer* ambientBuffer = new VertexBuffer; 28305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik VertexBuffer* spotBuffer = new VertexBuffer; 28405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik tessellateShadows(t->drawTransform, &t->localClip, t->opaque, t->casterPerimeter, 28505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik t->transformXY, t->transformZ, t->lightCenter, t->lightRadius, 28605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik *ambientBuffer, *spotBuffer); 28705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 28805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik t->setResult(new TessellationCache::vertexBuffer_pair_t(ambientBuffer, spotBuffer)); 28905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik } 29005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik}; 29105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 29205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik/////////////////////////////////////////////////////////////////////////////// 29305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik// Cache constructor/destructor 29405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik/////////////////////////////////////////////////////////////////////////////// 29505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 29605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris CraikTessellationCache::TessellationCache() 29705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik : mSize(0) 29805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik , mMaxSize(MB(DEFAULT_VERTEX_CACHE_SIZE)) 29905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik , mCache(LruCache<Description, Buffer*>::kUnlimitedCapacity) 30005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik , mShadowCache(LruCache<ShadowDescription, Task<vertexBuffer_pair_t*>*>::kUnlimitedCapacity) { 30105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik char property[PROPERTY_VALUE_MAX]; 30205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik if (property_get(PROPERTY_VERTEX_CACHE_SIZE, property, NULL) > 0) { 30305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik INIT_LOGD(" Setting %s cache size to %sMB", name, property); 30405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik setMaxSize(MB(atof(property))); 30505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik } else { 30605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik INIT_LOGD(" Using default %s cache size of %.2fMB", name, DEFAULT_VERTEX_CACHE_SIZE); 30705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik } 30805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 30905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik mCache.setOnEntryRemovedListener(&mBufferRemovedListener); 31005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik mShadowCache.setOnEntryRemovedListener(&mBufferPairRemovedListener); 31105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik mDebugEnabled = readDebugLevel() & kDebugCaches; 31205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik} 31305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 31405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris CraikTessellationCache::~TessellationCache() { 31505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik mCache.clear(); 31605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik} 31705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 31805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik/////////////////////////////////////////////////////////////////////////////// 31905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik// Size management 32005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik/////////////////////////////////////////////////////////////////////////////// 32105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 32205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikuint32_t TessellationCache::getSize() { 32305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik LruCache<Description, Buffer*>::Iterator iter(mCache); 32405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik uint32_t size = 0; 32505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik while (iter.next()) { 32605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik size += iter.value()->getSize(); 32705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik } 32805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik return size; 32905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik} 33005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 33105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikuint32_t TessellationCache::getMaxSize() { 33205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik return mMaxSize; 33305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik} 33405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 33505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikvoid TessellationCache::setMaxSize(uint32_t maxSize) { 33605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik mMaxSize = maxSize; 33705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik while (mSize > mMaxSize) { 33805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik mCache.removeOldest(); 33905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik } 34005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik} 34105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 34205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik/////////////////////////////////////////////////////////////////////////////// 34305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik// Caching 34405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik/////////////////////////////////////////////////////////////////////////////// 34505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 34605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 34705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikvoid TessellationCache::trim() { 34805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik uint32_t size = getSize(); 34905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik while (size > mMaxSize) { 35005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik size -= mCache.peekOldestValue()->getSize(); 35105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik mCache.removeOldest(); 35205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik } 35305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik mShadowCache.clear(); 35405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik} 35505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 35605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikvoid TessellationCache::clear() { 35705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik mCache.clear(); 35805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik mShadowCache.clear(); 35905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik} 36005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 36105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik/////////////////////////////////////////////////////////////////////////////// 36205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik// Callbacks 36305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik/////////////////////////////////////////////////////////////////////////////// 36405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 36505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikvoid TessellationCache::BufferRemovedListener::operator()(Description& description, 36605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik Buffer*& buffer) { 36705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik delete buffer; 36805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik} 36905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 37005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik/////////////////////////////////////////////////////////////////////////////// 37105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik// Shadows 37205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik/////////////////////////////////////////////////////////////////////////////// 37305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 37405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikvoid TessellationCache::precacheShadows(const Matrix4* drawTransform, const Rect& localClip, 37505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik bool opaque, const SkPath* casterPerimeter, 37605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik const Matrix4* transformXY, const Matrix4* transformZ, 37705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik const Vector3& lightCenter, float lightRadius) { 37805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik ShadowDescription key(casterPerimeter, drawTransform); 37905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 38005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik sp<ShadowTask> task = new ShadowTask(drawTransform, localClip, opaque, 38105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik casterPerimeter, transformXY, transformZ, lightCenter, lightRadius); 38205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik if (mShadowProcessor == NULL) { 38305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik mShadowProcessor = new ShadowProcessor(Caches::getInstance()); 38405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik } 38505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik mShadowProcessor->add(task); 38605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 38705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik task->incStrong(NULL); // not using sp<>s, so manually ref while in the cache 38805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik mShadowCache.put(key, task.get()); 38905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik} 39005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 39105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikvoid TessellationCache::getShadowBuffers(const Matrix4* drawTransform, const Rect& localClip, 39205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik bool opaque, const SkPath* casterPerimeter, 39305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik const Matrix4* transformXY, const Matrix4* transformZ, 39405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik const Vector3& lightCenter, float lightRadius, vertexBuffer_pair_t& outBuffers) { 39505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik ShadowDescription key(casterPerimeter, drawTransform); 39605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik ShadowTask* task = static_cast<ShadowTask*>(mShadowCache.get(key)); 39705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik if (!task) { 39805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik precacheShadows(drawTransform, localClip, opaque, casterPerimeter, 39905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik transformXY, transformZ, lightCenter, lightRadius); 40005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik task = static_cast<ShadowTask*>(mShadowCache.get(key)); 40105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik } 40205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik LOG_ALWAYS_FATAL_IF(task == NULL, "shadow not precached"); 40305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik outBuffers = *(task->getResult()); 40405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik} 40505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 40605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik/////////////////////////////////////////////////////////////////////////////// 40705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik// Tessellation precaching 40805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik/////////////////////////////////////////////////////////////////////////////// 40905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 41005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikstatic VertexBuffer* tessellatePath(const SkPath& path, const SkPaint* paint, 41105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik float scaleX, float scaleY) { 41205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik VertexBuffer* buffer = new VertexBuffer(); 41305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik Matrix4 matrix; 41405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik matrix.loadScale(scaleX, scaleY, 1); 41505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik PathTessellator::tessellatePath(path, paint, matrix, *buffer); 41605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik return buffer; 41705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik} 41805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 41905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris CraikTessellationCache::Buffer* TessellationCache::getOrCreateBuffer( 42005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik const Description& entry, Tessellator tessellator, const SkPaint* paint) { 42105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik Buffer* buffer = mCache.get(entry); 42205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik if (!buffer) { 42305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik // not cached, enqueue a task to fill the buffer 42405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik sp<TessellationTask> task = new TessellationTask(tessellator, entry, paint); 42505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik buffer = new Buffer(task); 42605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 42705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik if (mProcessor == NULL) { 42805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik mProcessor = new TessellationProcessor(Caches::getInstance()); 42905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik } 43005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik mProcessor->add(task); 43105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik mCache.put(entry, buffer); 43205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik } 43305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik return buffer; 43405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik} 43505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 43605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik/////////////////////////////////////////////////////////////////////////////// 43705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik// Rounded rects 43805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik/////////////////////////////////////////////////////////////////////////////// 43905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 44005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikstatic VertexBuffer* tessellateRoundRect(const TessellationCache::Description& description, 44105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik const SkPaint& paint) { 44205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik SkRect rect = SkRect::MakeWH(description.shape.roundRect.mWidth, 44305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik description.shape.roundRect.mHeight); 44405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik float rx = description.shape.roundRect.mRx; 44505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik float ry = description.shape.roundRect.mRy; 44605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik if (paint.getStyle() == SkPaint::kStrokeAndFill_Style) { 44705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik float outset = paint.getStrokeWidth() / 2; 44805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik rect.outset(outset, outset); 44905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik rx += outset; 45005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik ry += outset; 45105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik } 45205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik SkPath path; 45305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik path.addRoundRect(rect, rx, ry); 45405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik return tessellatePath(path, &paint, 45505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik description.shape.roundRect.mScaleX, description.shape.roundRect.mScaleY); 45605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik} 45705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 45805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris CraikTessellationCache::Buffer* TessellationCache::getRoundRectBuffer(const Matrix4& transform, 45905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik float width, float height, float rx, float ry, const SkPaint* paint) { 46005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik Description entry(Description::kRoundRect, paint); 46105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik entry.shape.roundRect.mWidth = width; 46205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik entry.shape.roundRect.mHeight = height; 46305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik entry.shape.roundRect.mRx = rx; 46405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik entry.shape.roundRect.mRy = ry; 46505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik PathTessellator::extractTessellationScales(transform, 46605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik &entry.shape.roundRect.mScaleX, &entry.shape.roundRect.mScaleY); 46705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 46805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik return getOrCreateBuffer(entry, &tessellateRoundRect, paint); 46905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik} 47005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikconst VertexBuffer* TessellationCache::getRoundRect(const Matrix4& transform, 47105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik float width, float height, float rx, float ry, const SkPaint* paint) { 47205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik return getRoundRectBuffer(transform, width, height, rx, ry, paint)->getVertexBuffer(); 47305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik} 47405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 47505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik}; // namespace uirenderer 47605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik}; // namespace android 477