blob: 5fb5804e337059ad9f388ec12b0d774e06518024 [file] [log] [blame]
/*
* Copyright 2018 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef GrDDLTextureStripAtlas_DEFINED
#define GrDDLTextureStripAtlas_DEFINED
#include "GrTextureStripAtlas.h"
#include "SkBitmap.h"
#include "SkTDArray.h"
/**
* The DDL version of the texture strip atlas consolidates individual strips into a larger texture
* until some limit is reached, at which point a new large texture is started.
* This can lead to the same strip being duplicated in VRAM. This can happen if a strip appears once
* early in a rendering (that has, say, a lot of gradients) and then again later in the rendering
* when one of the large textures has been filled. The second, probably more common, case is
* if the same strip is used in different DDL recordings. Since the texture strip atlases aren't
* dedupped across threads, if the same strip is used in two different DDL recordings it will
* be duplicated in both of the DDL recorders' atlases.
* Note, one additional feature of the DDL texture strip atlases is that, if DDL recording is ended
* before one of the large textures is full, the large texture will be "shrunk" to fit its
* contents.
*/
class GrDDLTextureStripAtlas final : public GrTextureStripAtlas {
public:
~GrDDLTextureStripAtlas() final;
// Overrides from GrTextureStripAtlas
void lockRow(int row) final { /* The DDL version doesn't lock & unlock individual rows */}
void unlockRow(int row) final { /* The DDL version doesn't lock & unlock individual rows */}
// Caution: this method will only return the appropriate proxy after a successful 'addStrip'
// call has been made. Additionally, the proxy return will be fully lazy (i.e., its final
// height will be unknown).
sk_sp<GrTextureProxy> asTextureProxyRef() const final {
SkASSERT(fCurProxy);
return fCurProxy;
}
private:
friend class GrTextureStripAtlasManager; // for ctor
// Overrides from GrTextureStripAtlas
int addStrip(GrContext*, const SkBitmap&) final;
void finish(GrProxyProvider*) final;
/**
* The state of a single row in our cache. For the DDL texture strip atlas we hold onto all
* the individual strip bitmaps and, upon finish, combine them all into a single bitmap.
*/
struct AtlasRow : ::SkNoncopyable {
AtlasRow() {}
SkBitmap fBitmap;
};
/**
* Only the GrTextureStripAtlasManager is allowed to create GrDDLTextureStripAtlas
*/
GrDDLTextureStripAtlas(const Desc& desc);
/**
* Searches the key table for a key and returns the index if found; if not found, it returns
* the bitwise not of the index at which we could insert the key to maintain a sorted list.
**/
int searchByKey(uint32_t key);
SkDEBUGCODE(void validate();)
sk_sp<GrTextureProxy> fCurProxy; // the lazy proxy that will be split off in the finish call
SkBitmap* fAtlasBitmap; // the bitmap backing 'fCurProxy'
const uint16_t fMaxNumRows;
uint16_t fCurRow;
AtlasRow* fRows; // We just store the source bitmap for each row.
// A list of pointers to AtlasRows that currently contain cached images, sorted by key
SkTDArray<AtlasRow*> fKeyTable;
typedef GrTextureStripAtlas INHERITED;
};
#endif