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