5dbcca5634
OOP-R, on the gpu thread, creates the DDL, pre-compiles its shaders, draws it, flushes and then deletes the DDL. This process triggered a bug (cf. https://skia-review.googlesource.com/c/skia/+/292818 and crbug.com/1056730). Prior to this CL all the programs were compiled and only at the end was any work flushed - thus it was likely that the bound program would be reset to the correct value when rendering. With this CL, the addition of the flush right before the DDL deletion, makes it more likely that the wrong program will be bound when rendering begins. Change-Id: I60479bd429e132d8652bbffde6c8b71094be6225 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/292257 Reviewed-by: Adlai Holler <adlai@google.com> Commit-Queue: Robert Phillips <robertphillips@google.com>
146 lines
5.5 KiB
C++
146 lines
5.5 KiB
C++
/*
|
|
* 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 DDLTileHelper_DEFINED
|
|
#define DDLTileHelper_DEFINED
|
|
|
|
#include "include/core/SkRect.h"
|
|
#include "include/core/SkRefCnt.h"
|
|
#include "include/core/SkSurfaceCharacterization.h"
|
|
|
|
class DDLPromiseImageHelper;
|
|
class PromiseImageCallbackContext;
|
|
class SkCanvas;
|
|
class SkData;
|
|
class SkDeferredDisplayList;
|
|
class SkDeferredDisplayListRecorder;
|
|
class SkPicture;
|
|
class SkSurface;
|
|
class SkSurfaceCharacterization;
|
|
|
|
class DDLTileHelper {
|
|
public:
|
|
// The TileData class encapsulates the information and behavior of a single tile when
|
|
// rendering with DDLs.
|
|
class TileData {
|
|
public:
|
|
TileData() {}
|
|
~TileData();
|
|
|
|
void init(int id,
|
|
GrContext* context,
|
|
const SkSurfaceCharacterization& dstChar,
|
|
const SkIRect& clip);
|
|
|
|
// Convert the compressedPictureData into an SkPicture replacing each image-index
|
|
// with a promise image.
|
|
void createTileSpecificSKP(SkData* compressedPictureData,
|
|
const DDLPromiseImageHelper& helper);
|
|
|
|
// Create the DDL for this tile (i.e., fill in 'fDisplayList').
|
|
void createDDL();
|
|
|
|
void dropDDL() { fDisplayList.reset(); }
|
|
|
|
// Precompile all the programs required to draw this tile's DDL
|
|
void precompile(GrContext*);
|
|
|
|
// Just draw the re-inflated per-tile SKP directly into this tile w/o going through a DDL
|
|
// first. This is used for determining the overhead of using DDLs (i.e., it replaces
|
|
// a 'createDDL' and 'draw' pair.
|
|
void drawSKPDirectly(GrContext*);
|
|
|
|
// Replay the recorded DDL into the tile surface - filling in 'fBackendTexture'.
|
|
void draw(GrContext*);
|
|
|
|
void reset();
|
|
|
|
int id() const { return fID; }
|
|
SkIRect clipRect() const { return fClip; }
|
|
|
|
SkDeferredDisplayList* ddl() { return fDisplayList.get(); }
|
|
|
|
sk_sp<SkImage> makePromiseImage(SkDeferredDisplayListRecorder*);
|
|
void dropCallbackContext() { fCallbackContext.reset(); }
|
|
|
|
static void CreateBackendTexture(GrContext*, TileData*);
|
|
static void DeleteBackendTexture(GrContext*, TileData*);
|
|
|
|
private:
|
|
sk_sp<SkSurface> makeWrappedTileDest(GrContext* context);
|
|
|
|
sk_sp<PromiseImageCallbackContext> refCallbackContext() { return fCallbackContext; }
|
|
|
|
int fID = -1;
|
|
SkIRect fClip; // in the device space of the final SkSurface
|
|
SkSurfaceCharacterization fCharacterization; // characterization for the tile's surface
|
|
|
|
// The callback context holds (via its SkPromiseImageTexture) the backend texture
|
|
// that is both wrapped in 'fTileSurface' and backs this tile's promise image
|
|
// (i.e., the one returned by 'makePromiseImage').
|
|
sk_sp<PromiseImageCallbackContext> fCallbackContext;
|
|
// 'fTileSurface' wraps the backend texture in 'fCallbackContext' and must exist until
|
|
// after 'fDisplayList' has been flushed (bc it owns the proxy the DDL's destination
|
|
// trampoline points at).
|
|
// TODO: fix the ref-order so we don't need 'fTileSurface' here
|
|
sk_sp<SkSurface> fTileSurface;
|
|
|
|
sk_sp<SkPicture> fReconstitutedPicture;
|
|
SkTArray<sk_sp<SkImage>> fPromiseImages; // All the promise images in the
|
|
// reconstituted picture
|
|
std::unique_ptr<SkDeferredDisplayList> fDisplayList;
|
|
};
|
|
|
|
DDLTileHelper(GrContext* context,
|
|
const SkSurfaceCharacterization& dstChar,
|
|
const SkIRect& viewport,
|
|
int numDivisions);
|
|
|
|
void createSKPPerTile(SkData* compressedPictureData, const DDLPromiseImageHelper& helper);
|
|
|
|
void kickOffThreadedWork(SkTaskGroup* recordingTaskGroup,
|
|
SkTaskGroup* gpuTaskGroup,
|
|
GrContext* gpuThreadContext);
|
|
|
|
void createDDLsInParallel();
|
|
|
|
// Create the DDL that will compose all the tile images into a final result.
|
|
void createComposeDDL();
|
|
SkDeferredDisplayList* composeDDL() const { return fComposeDDL.get(); }
|
|
|
|
void precompileAndDrawAllTiles(GrContext*);
|
|
|
|
// For each tile, create its DDL and then draw it - all on a single thread. This is to allow
|
|
// comparison w/ just drawing the SKP directly (i.e., drawAllTilesDirectly). The
|
|
// DDL creations and draws are interleaved to prevent starvation of the GPU.
|
|
// Note: this is somewhat of a misuse/pessimistic-use of DDLs since they are supposed to
|
|
// be created on a separate thread.
|
|
void interleaveDDLCreationAndDraw(GrContext*);
|
|
|
|
// This draws all the per-tile SKPs directly into all of the tiles w/o converting them to
|
|
// DDLs first - all on a single thread.
|
|
void drawAllTilesDirectly(GrContext*);
|
|
|
|
void dropCallbackContexts();
|
|
void resetAllTiles();
|
|
|
|
int numTiles() const { return fNumDivisions * fNumDivisions; }
|
|
|
|
void createBackendTextures(SkTaskGroup*, GrContext*);
|
|
void deleteBackendTextures(SkTaskGroup*, GrContext*);
|
|
|
|
private:
|
|
int fNumDivisions; // number of tiles along a side
|
|
SkAutoTArray<TileData> fTiles; // 'fNumDivisions' x 'fNumDivisions'
|
|
|
|
std::unique_ptr<SkDeferredDisplayList> fComposeDDL;
|
|
|
|
const SkSurfaceCharacterization fDstCharacterization;
|
|
};
|
|
|
|
#endif
|