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