TessellationCache.cpp revision ed4ef0bc17c33ecd7e689e3c40244a7c1c6063d0
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)
42ed4ef0bc17c33ecd7e689e3c40244a7c1c6063d0Chris Craik        , aa(false)
4305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        , cap(SkPaint::kDefault_Cap)
4405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        , style(SkPaint::kFill_Style)
4505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        , strokeWidth(1.0f) {
4605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    memset(&shape, 0, sizeof(Shape));
4705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik}
4805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
4905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris CraikTessellationCache::Description::Description(Type type)
5005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        : type(type)
51ed4ef0bc17c33ecd7e689e3c40244a7c1c6063d0Chris Craik        , aa(false)
5205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        , cap(SkPaint::kDefault_Cap)
5305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        , style(SkPaint::kFill_Style)
5405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        , strokeWidth(1.0f) {
5505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    memset(&shape, 0, sizeof(Shape));
5605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik}
5705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
5805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris CraikTessellationCache::Description::Description(Type type, const SkPaint* paint)
5905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        : type(type)
60ed4ef0bc17c33ecd7e689e3c40244a7c1c6063d0Chris Craik        , aa(paint->isAntiAlias())
6105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        , cap(paint->getStrokeCap())
6205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        , style(paint->getStyle())
6305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        , strokeWidth(paint->getStrokeWidth()) {
6405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    memset(&shape, 0, sizeof(Shape));
6505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik}
6605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
6705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikhash_t TessellationCache::Description::hash() const {
6805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    uint32_t hash = JenkinsHashMix(0, type);
69ed4ef0bc17c33ecd7e689e3c40244a7c1c6063d0Chris Craik    hash = JenkinsHashMix(hash, aa);
7005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    hash = JenkinsHashMix(hash, cap);
7105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    hash = JenkinsHashMix(hash, style);
7205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    hash = JenkinsHashMix(hash, android::hash_type(strokeWidth));
7305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    hash = JenkinsHashMixBytes(hash, (uint8_t*) &shape, sizeof(Shape));
7405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    return JenkinsHashWhiten(hash);
7505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik}
7605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
7705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris CraikTessellationCache::ShadowDescription::ShadowDescription()
7805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        : nodeKey(NULL) {
7905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    memset(&matrixData, 0, 16 * sizeof(float));
8005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik}
8105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
8205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris CraikTessellationCache::ShadowDescription::ShadowDescription(const void* nodeKey, const Matrix4* drawTransform)
8305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        : nodeKey(nodeKey) {
8405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    memcpy(&matrixData, drawTransform->data, 16 * sizeof(float));
8505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik}
8605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
8705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikhash_t TessellationCache::ShadowDescription::hash() const {
8805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    uint32_t hash = JenkinsHashMixBytes(0, (uint8_t*) &nodeKey, sizeof(const void*));
8905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    hash = JenkinsHashMixBytes(hash, (uint8_t*) &matrixData, 16 * sizeof(float));
9005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    return JenkinsHashWhiten(hash);
9105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik}
9205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
9305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik///////////////////////////////////////////////////////////////////////////////
9405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik// General purpose tessellation task processing
9505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik///////////////////////////////////////////////////////////////////////////////
9605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
9705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikclass TessellationCache::TessellationTask : public Task<VertexBuffer*> {
9805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikpublic:
9905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    TessellationTask(Tessellator tessellator, const Description& description,
10005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik                const SkPaint* paint)
10105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        : tessellator(tessellator)
10205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        , description(description)
10305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        , paint(*paint) {
10405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    }
10505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
10605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    ~TessellationTask() {}
10705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
10805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    Tessellator tessellator;
10905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    Description description;
11005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
11105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    //copied, since input paint may not be immutable
11205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    const SkPaint paint;
11305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik};
11405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
11505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikclass TessellationCache::TessellationProcessor : public TaskProcessor<VertexBuffer*> {
11605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikpublic:
11705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    TessellationProcessor(Caches& caches)
11805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik            : TaskProcessor<VertexBuffer*>(&caches.tasks) {}
11905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    ~TessellationProcessor() {}
12005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
12105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    virtual void onProcess(const sp<Task<VertexBuffer*> >& task) {
12205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        TessellationTask* t = static_cast<TessellationTask*>(task.get());
12305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        ATRACE_NAME("shape tessellation");
12405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        VertexBuffer* buffer = t->tessellator(t->description, t->paint);
12505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        t->setResult(buffer);
12605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    }
12705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik};
12805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
12905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikstruct TessellationCache::Buffer {
13005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikpublic:
13105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    Buffer(const sp<Task<VertexBuffer*> >& task)
13205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik            : mTask(task)
13305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik            , mBuffer(NULL) {
13405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    }
13505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
13605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    ~Buffer() {
13705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        mTask.clear();
13805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        delete mBuffer;
13905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    }
14005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
14105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    unsigned int getSize() {
14205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        blockOnPrecache();
14305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        return mBuffer->getSize();
14405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    }
14505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
14605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    const VertexBuffer* getVertexBuffer() {
14705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        blockOnPrecache();
14805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        return mBuffer;
14905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    }
15005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
15105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikprivate:
15205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    void blockOnPrecache() {
15305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        if (mTask != NULL) {
15405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik            mBuffer = mTask->getResult();
15505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik            LOG_ALWAYS_FATAL_IF(mBuffer == NULL, "Failed to precache");
15605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik            mTask.clear();
15705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        }
15805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    }
15905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    sp<Task<VertexBuffer*> > mTask;
16005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    VertexBuffer* mBuffer;
16105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik};
16205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
16305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik///////////////////////////////////////////////////////////////////////////////
16405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik// Shadow tessellation task processing
16505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik///////////////////////////////////////////////////////////////////////////////
16605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
16705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikclass ShadowTask : public Task<TessellationCache::vertexBuffer_pair_t*> {
16805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikpublic:
16905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    ShadowTask(const Matrix4* drawTransform, const Rect& localClip, bool opaque,
17005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik            const SkPath* casterPerimeter, const Matrix4* transformXY, const Matrix4* transformZ,
17105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik            const Vector3& lightCenter, float lightRadius)
1721b3be0877a07dac81fd21c898ba917e6ee5354b2Chris Craik        : drawTransform(*drawTransform)
17305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        , localClip(localClip)
17405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        , opaque(opaque)
1751b3be0877a07dac81fd21c898ba917e6ee5354b2Chris Craik        , casterPerimeter(*casterPerimeter)
1761b3be0877a07dac81fd21c898ba917e6ee5354b2Chris Craik        , transformXY(*transformXY)
1771b3be0877a07dac81fd21c898ba917e6ee5354b2Chris Craik        , transformZ(*transformZ)
17805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        , lightCenter(lightCenter)
17905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        , lightRadius(lightRadius) {
18005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    }
18105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
18205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    ~ShadowTask() {
18305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        TessellationCache::vertexBuffer_pair_t* bufferPair = getResult();
18405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        delete bufferPair->getFirst();
18505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        delete bufferPair->getSecond();
18605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        delete bufferPair;
18705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    }
18805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
1891b3be0877a07dac81fd21c898ba917e6ee5354b2Chris Craik    /* Note - we deep copy all task parameters, because *even though* pointers into Allocator
1901b3be0877a07dac81fd21c898ba917e6ee5354b2Chris Craik     * controlled objects (like the SkPath and Matrix4s) should be safe for the entire frame,
1911b3be0877a07dac81fd21c898ba917e6ee5354b2Chris Craik     * certain Allocators are destroyed before trim() is called to flush incomplete tasks.
1921b3be0877a07dac81fd21c898ba917e6ee5354b2Chris Craik     *
1931b3be0877a07dac81fd21c898ba917e6ee5354b2Chris Craik     * These deep copies could be avoided, long term, by cancelling or flushing outstanding tasks
1941b3be0877a07dac81fd21c898ba917e6ee5354b2Chris Craik     * before tearning down single-frame LinearAllocators.
1951b3be0877a07dac81fd21c898ba917e6ee5354b2Chris Craik     */
1961b3be0877a07dac81fd21c898ba917e6ee5354b2Chris Craik    const Matrix4 drawTransform;
19705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    const Rect localClip;
19805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    bool opaque;
1991b3be0877a07dac81fd21c898ba917e6ee5354b2Chris Craik    const SkPath casterPerimeter;
2001b3be0877a07dac81fd21c898ba917e6ee5354b2Chris Craik    const Matrix4 transformXY;
2011b3be0877a07dac81fd21c898ba917e6ee5354b2Chris Craik    const Matrix4 transformZ;
20205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    const Vector3 lightCenter;
20305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    const float lightRadius;
20405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik};
20505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
20605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikstatic void mapPointFakeZ(Vector3& point, const mat4* transformXY, const mat4* transformZ) {
20705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    // map z coordinate with true 3d matrix
20805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    point.z = transformZ->mapZ(point);
20905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
21005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    // map x,y coordinates with draw/Skia matrix
21105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    transformXY->mapPoint(point.x, point.y);
21205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik}
21305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
21405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikstatic void tessellateShadows(
21505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        const Matrix4* drawTransform, const Rect* localClip,
21605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        bool isCasterOpaque, const SkPath* casterPerimeter,
21705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        const Matrix4* casterTransformXY, const Matrix4* casterTransformZ,
21805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        const Vector3& lightCenter, float lightRadius,
21905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        VertexBuffer& ambientBuffer, VertexBuffer& spotBuffer) {
22005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
22105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    // tessellate caster outline into a 2d polygon
22205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    Vector<Vertex> casterVertices2d;
22305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    const float casterRefinementThresholdSquared = 20.0f; // TODO: experiment with this value
22405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    PathTessellator::approximatePathOutlineVertices(*casterPerimeter,
22505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik            casterRefinementThresholdSquared, casterVertices2d);
22605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    if (!ShadowTessellator::isClockwisePath(*casterPerimeter)) {
22705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        ShadowTessellator::reverseVertexArray(casterVertices2d.editArray(),
22805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik                casterVertices2d.size());
22905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    }
23005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
23105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    if (casterVertices2d.size() == 0) return;
23205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
23305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    // map 2d caster poly into 3d
23405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    const int casterVertexCount = casterVertices2d.size();
23505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    Vector3 casterPolygon[casterVertexCount];
23605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    float minZ = FLT_MAX;
23705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    float maxZ = -FLT_MAX;
23805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    for (int i = 0; i < casterVertexCount; i++) {
23905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        const Vertex& point2d = casterVertices2d[i];
24005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        casterPolygon[i] = Vector3(point2d.x, point2d.y, 0);
24105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        mapPointFakeZ(casterPolygon[i], casterTransformXY, casterTransformZ);
24205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        minZ = fmin(minZ, casterPolygon[i].z);
24305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        maxZ = fmax(maxZ, casterPolygon[i].z);
24405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    }
24505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
24605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    // map the centroid of the caster into 3d
24705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    Vector2 centroid =  ShadowTessellator::centroid2d(
24805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik            reinterpret_cast<const Vector2*>(casterVertices2d.array()),
24905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik            casterVertexCount);
25005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    Vector3 centroid3d(centroid.x, centroid.y, 0);
25105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    mapPointFakeZ(centroid3d, casterTransformXY, casterTransformZ);
25205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
25305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    // if the caster intersects the z=0 plane, lift it in Z so it doesn't
25405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    if (minZ < SHADOW_MIN_CASTER_Z) {
25505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        float casterLift = SHADOW_MIN_CASTER_Z - minZ;
25605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        for (int i = 0; i < casterVertexCount; i++) {
25705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik            casterPolygon[i].z += casterLift;
25805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        }
25905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        centroid3d.z += casterLift;
26005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    }
26105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
26205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    // Check whether we want to draw the shadow at all by checking the caster's bounds against clip.
26305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    // We only have ortho projection, so we can just ignore the Z in caster for
26405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    // simple rejection calculation.
26505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    Rect casterBounds(casterPerimeter->getBounds());
26605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    casterTransformXY->mapRect(casterBounds);
26705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
26805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    // actual tessellation of both shadows
26905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    ShadowTessellator::tessellateAmbientShadow(
27005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik            isCasterOpaque, casterPolygon, casterVertexCount, centroid3d,
27105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik            casterBounds, *localClip, maxZ, ambientBuffer);
27205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
27305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    ShadowTessellator::tessellateSpotShadow(
27405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik            isCasterOpaque, casterPolygon, casterVertexCount,
27505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik            *drawTransform, lightCenter, lightRadius, casterBounds, *localClip,
27605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik            spotBuffer);
27705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
27805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    // TODO: set ambientBuffer & spotBuffer's bounds for correct layer damage
27905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik}
28005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
28105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikclass ShadowProcessor : public TaskProcessor<TessellationCache::vertexBuffer_pair_t*> {
28205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikpublic:
28305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    ShadowProcessor(Caches& caches)
28405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik            : TaskProcessor<TessellationCache::vertexBuffer_pair_t*>(&caches.tasks) {}
28505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    ~ShadowProcessor() {}
28605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
28705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    virtual void onProcess(const sp<Task<TessellationCache::vertexBuffer_pair_t*> >& task) {
28805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        ShadowTask* t = static_cast<ShadowTask*>(task.get());
28905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        ATRACE_NAME("shadow tessellation");
29005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
29105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        VertexBuffer* ambientBuffer = new VertexBuffer;
29205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        VertexBuffer* spotBuffer = new VertexBuffer;
2931b3be0877a07dac81fd21c898ba917e6ee5354b2Chris Craik        tessellateShadows(&t->drawTransform, &t->localClip, t->opaque, &t->casterPerimeter,
2941b3be0877a07dac81fd21c898ba917e6ee5354b2Chris Craik                &t->transformXY, &t->transformZ, t->lightCenter, t->lightRadius,
29505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik                *ambientBuffer, *spotBuffer);
29605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
29705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        t->setResult(new TessellationCache::vertexBuffer_pair_t(ambientBuffer, spotBuffer));
29805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    }
29905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik};
30005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
30105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik///////////////////////////////////////////////////////////////////////////////
30205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik// Cache constructor/destructor
30305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik///////////////////////////////////////////////////////////////////////////////
30405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
30505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris CraikTessellationCache::TessellationCache()
30605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        : mSize(0)
30705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        , mMaxSize(MB(DEFAULT_VERTEX_CACHE_SIZE))
30805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        , mCache(LruCache<Description, Buffer*>::kUnlimitedCapacity)
30905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        , mShadowCache(LruCache<ShadowDescription, Task<vertexBuffer_pair_t*>*>::kUnlimitedCapacity) {
31005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    char property[PROPERTY_VALUE_MAX];
31105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    if (property_get(PROPERTY_VERTEX_CACHE_SIZE, property, NULL) > 0) {
31205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        INIT_LOGD("  Setting %s cache size to %sMB", name, property);
31305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        setMaxSize(MB(atof(property)));
31405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    } else {
31505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        INIT_LOGD("  Using default %s cache size of %.2fMB", name, DEFAULT_VERTEX_CACHE_SIZE);
31605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    }
31705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
31805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    mCache.setOnEntryRemovedListener(&mBufferRemovedListener);
31905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    mShadowCache.setOnEntryRemovedListener(&mBufferPairRemovedListener);
32005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    mDebugEnabled = readDebugLevel() & kDebugCaches;
32105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik}
32205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
32305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris CraikTessellationCache::~TessellationCache() {
32405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    mCache.clear();
32505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik}
32605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
32705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik///////////////////////////////////////////////////////////////////////////////
32805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik// Size management
32905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik///////////////////////////////////////////////////////////////////////////////
33005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
33105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikuint32_t TessellationCache::getSize() {
33205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    LruCache<Description, Buffer*>::Iterator iter(mCache);
33305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    uint32_t size = 0;
33405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    while (iter.next()) {
33505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        size += iter.value()->getSize();
33605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    }
33705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    return size;
33805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik}
33905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
34005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikuint32_t TessellationCache::getMaxSize() {
34105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    return mMaxSize;
34205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik}
34305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
34405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikvoid TessellationCache::setMaxSize(uint32_t maxSize) {
34505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    mMaxSize = maxSize;
34605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    while (mSize > mMaxSize) {
34705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        mCache.removeOldest();
34805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    }
34905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik}
35005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
35105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik///////////////////////////////////////////////////////////////////////////////
35205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik// Caching
35305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik///////////////////////////////////////////////////////////////////////////////
35405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
35505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
35605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikvoid TessellationCache::trim() {
3576ef8e0178d6ad9fee5b410da8fd28f97205c23ebChris Craik    // uint32_t size = getSize();
3586ef8e0178d6ad9fee5b410da8fd28f97205c23ebChris Craik    // while (size > mMaxSize) {
3596ef8e0178d6ad9fee5b410da8fd28f97205c23ebChris Craik    //     size -= mCache.peekOldestValue()->getSize();
3606ef8e0178d6ad9fee5b410da8fd28f97205c23ebChris Craik    //     mCache.removeOldest();
3616ef8e0178d6ad9fee5b410da8fd28f97205c23ebChris Craik    // }
3626ef8e0178d6ad9fee5b410da8fd28f97205c23ebChris Craik    mCache.clear(); // Workaround caching tessellation corruption
36305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    mShadowCache.clear();
36405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik}
36505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
36605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikvoid TessellationCache::clear() {
36705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    mCache.clear();
36805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    mShadowCache.clear();
36905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik}
37005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
37105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik///////////////////////////////////////////////////////////////////////////////
37205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik// Callbacks
37305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik///////////////////////////////////////////////////////////////////////////////
37405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
37505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikvoid TessellationCache::BufferRemovedListener::operator()(Description& description,
37605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        Buffer*& buffer) {
37705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    delete buffer;
37805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik}
37905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
38005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik///////////////////////////////////////////////////////////////////////////////
38105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik// Shadows
38205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik///////////////////////////////////////////////////////////////////////////////
38305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
38405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikvoid TessellationCache::precacheShadows(const Matrix4* drawTransform, const Rect& localClip,
38505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        bool opaque, const SkPath* casterPerimeter,
38605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        const Matrix4* transformXY, const Matrix4* transformZ,
38705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        const Vector3& lightCenter, float lightRadius) {
38805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    ShadowDescription key(casterPerimeter, drawTransform);
38905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
39005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    sp<ShadowTask> task = new ShadowTask(drawTransform, localClip, opaque,
39105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik            casterPerimeter, transformXY, transformZ, lightCenter, lightRadius);
39205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    if (mShadowProcessor == NULL) {
39305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        mShadowProcessor = new ShadowProcessor(Caches::getInstance());
39405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    }
39505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    mShadowProcessor->add(task);
39605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
39705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    task->incStrong(NULL); // not using sp<>s, so manually ref while in the cache
39805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    mShadowCache.put(key, task.get());
39905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik}
40005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
40105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikvoid TessellationCache::getShadowBuffers(const Matrix4* drawTransform, const Rect& localClip,
40205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        bool opaque, const SkPath* casterPerimeter,
40305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        const Matrix4* transformXY, const Matrix4* transformZ,
40405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        const Vector3& lightCenter, float lightRadius, vertexBuffer_pair_t& outBuffers) {
40505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    ShadowDescription key(casterPerimeter, drawTransform);
40605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    ShadowTask* task = static_cast<ShadowTask*>(mShadowCache.get(key));
40705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    if (!task) {
40805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        precacheShadows(drawTransform, localClip, opaque, casterPerimeter,
40905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik                transformXY, transformZ, lightCenter, lightRadius);
41005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        task = static_cast<ShadowTask*>(mShadowCache.get(key));
41105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    }
41205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    LOG_ALWAYS_FATAL_IF(task == NULL, "shadow not precached");
41305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    outBuffers = *(task->getResult());
41405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik}
41505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
41605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik///////////////////////////////////////////////////////////////////////////////
41705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik// Tessellation precaching
41805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik///////////////////////////////////////////////////////////////////////////////
41905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
42005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikstatic VertexBuffer* tessellatePath(const SkPath& path, const SkPaint* paint,
42105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        float scaleX, float scaleY) {
42205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    VertexBuffer* buffer = new VertexBuffer();
42305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    Matrix4 matrix;
42405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    matrix.loadScale(scaleX, scaleY, 1);
42505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    PathTessellator::tessellatePath(path, paint, matrix, *buffer);
42605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    return buffer;
42705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik}
42805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
42905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris CraikTessellationCache::Buffer* TessellationCache::getOrCreateBuffer(
43005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        const Description& entry, Tessellator tessellator, const SkPaint* paint) {
43105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    Buffer* buffer = mCache.get(entry);
43205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    if (!buffer) {
43305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        // not cached, enqueue a task to fill the buffer
43405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        sp<TessellationTask> task = new TessellationTask(tessellator, entry, paint);
43505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        buffer = new Buffer(task);
43605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
43705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        if (mProcessor == NULL) {
43805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik            mProcessor = new TessellationProcessor(Caches::getInstance());
43905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        }
44005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        mProcessor->add(task);
44105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        mCache.put(entry, buffer);
44205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    }
44305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    return buffer;
44405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik}
44505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
44605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik///////////////////////////////////////////////////////////////////////////////
44705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik// Rounded rects
44805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik///////////////////////////////////////////////////////////////////////////////
44905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
45005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikstatic VertexBuffer* tessellateRoundRect(const TessellationCache::Description& description,
45105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        const SkPaint& paint) {
45205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    SkRect rect = SkRect::MakeWH(description.shape.roundRect.mWidth,
45305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik            description.shape.roundRect.mHeight);
45405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    float rx = description.shape.roundRect.mRx;
45505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    float ry = description.shape.roundRect.mRy;
45605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    if (paint.getStyle() == SkPaint::kStrokeAndFill_Style) {
45705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        float outset = paint.getStrokeWidth() / 2;
45805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        rect.outset(outset, outset);
45905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        rx += outset;
46005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        ry += outset;
46105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    }
46205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    SkPath path;
46305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    path.addRoundRect(rect, rx, ry);
46405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    return tessellatePath(path, &paint,
46505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik            description.shape.roundRect.mScaleX, description.shape.roundRect.mScaleY);
46605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik}
46705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
46805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris CraikTessellationCache::Buffer* TessellationCache::getRoundRectBuffer(const Matrix4& transform,
46905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        float width, float height, float rx, float ry, const SkPaint* paint) {
47005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    Description entry(Description::kRoundRect, paint);
47105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    entry.shape.roundRect.mWidth = width;
47205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    entry.shape.roundRect.mHeight = height;
47305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    entry.shape.roundRect.mRx = rx;
47405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    entry.shape.roundRect.mRy = ry;
47505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    PathTessellator::extractTessellationScales(transform,
47605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik            &entry.shape.roundRect.mScaleX, &entry.shape.roundRect.mScaleY);
47705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
47805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    return getOrCreateBuffer(entry, &tessellateRoundRect, paint);
47905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik}
48005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikconst VertexBuffer* TessellationCache::getRoundRect(const Matrix4& transform,
48105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        float width, float height, float rx, float ry, const SkPaint* paint) {
48205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    return getRoundRectBuffer(transform, width, height, rx, ry, paint)->getVertexBuffer();
48305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik}
48405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
48505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik}; // namespace uirenderer
48605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik}; // namespace android
487