/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include "ClipArea.h"
#include "Rect.h"
#include "utils/Macros.h"
#include <vector>
#include <unordered_map>
struct SkRect;
namespace android {
namespace uirenderer {
class BakedOpState;
struct BeginLayerOp;
class BatchBase;
class LinearAllocator;
struct MergedBakedOpList;
class MergingOpBatch;
class OffscreenBuffer;
class OpBatch;
class RenderNode;
typedef int batchid_t;
typedef const void* mergeid_t;
namespace OpBatchType {
enum {
Bitmap,
MergedPatch,
AlphaVertices,
Vertices,
AlphaMaskTexture,
Text,
ColorText,
Shadow,
TextureLayer,
Functor,
CopyToLayer,
CopyFromLayer,
Count // must be last
};
}
typedef void (*BakedOpReceiver)(void*, const BakedOpState&);
typedef void (*MergedOpReceiver)(void*, const MergedBakedOpList& opList);
/**
* Stores the deferred render operations and state used to compute ordering
* for a single FBO/layer.
*/
class LayerBuilder {
// Prevent copy/assign because users may stash pointer to offscreenBuffer and viewportClip
PREVENT_COPY_AND_ASSIGN(LayerBuilder);
public:
// Create LayerBuilder for Fbo0
LayerBuilder(uint32_t width, uint32_t height, const Rect& repaintRect)
: LayerBuilder(width, height, repaintRect, nullptr, nullptr) {};
// Create LayerBuilder for an offscreen layer, where beginLayerOp is present for a
// saveLayer, renderNode is present for a HW layer.
LayerBuilder(uint32_t width, uint32_t height,
const Rect& repaintRect, const BeginLayerOp* beginLayerOp, RenderNode* renderNode);
// iterate back toward target to see if anything drawn since should overlap the new op
// if no target, merging ops still iterate to find similar batch to insert after
void locateInsertIndex(int batchId, const Rect& clippedBounds,
BatchBase** targetBatch, size_t* insertBatchIndex) const;
void deferUnmergeableOp(LinearAllocator& allocator, BakedOpState* op, batchid_t batchId);
// insertion point of a new batch, will hopefully be immediately after similar batch
// (generally, should be similar shader)
void deferMergeableOp(LinearAllocator& allocator,
BakedOpState* op, batchid_t batchId, mergeid_t mergeId);
void replayBakedOpsImpl(void* arg, BakedOpReceiver* receivers, MergedOpReceiver*) const;
void deferLayerClear(const Rect& dstRect);
bool empty() const {
return mBatches.empty();
}
void clear();
void dump() const;
const uint32_t width;
const uint32_t height;
const Rect repaintRect;
const ClipRect repaintClip;
OffscreenBuffer* offscreenBuffer;
const BeginLayerOp* beginLayerOp;
const RenderNode* renderNode;
// list of deferred CopyFromLayer ops, to be deferred upon encountering EndUnclippedLayerOps
std::vector<BakedOpState*> activeUnclippedSaveLayers;
private:
void onDeferOp(LinearAllocator& allocator, const BakedOpState* bakedState);
void flushLayerClears(LinearAllocator& allocator);
std::vector<BatchBase*> mBatches;
/**
* Maps the mergeid_t returned by an op's getMergeId() to the most recently seen
* MergingDrawBatch of that id. These ids are unique per draw type and guaranteed to not
* collide, which avoids the need to resolve mergeid collisions.
*/
std::unordered_map<mergeid_t, MergingOpBatch*> mMergingBatchLookup[OpBatchType::Count];
// Maps batch ids to the most recent *non-merging* batch of that id
OpBatch* mBatchLookup[OpBatchType::Count] = { nullptr };
std::vector<Rect> mClearRects;
};
}; // namespace uirenderer
}; // namespace android