2013-08-21 19:27:48 +00:00
|
|
|
/*
|
|
|
|
* Copyright 2013 Google Inc.
|
|
|
|
*
|
|
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
|
|
* found in the LICENSE file.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "GrTest.h"
|
2015-07-28 16:58:39 +00:00
|
|
|
|
2015-08-21 18:08:00 +00:00
|
|
|
#include "GrBatchAtlas.h"
|
2015-05-22 21:01:46 +00:00
|
|
|
#include "GrContextOptions.h"
|
2016-03-02 17:26:36 +00:00
|
|
|
#include "GrDrawContextPriv.h"
|
2015-10-17 14:43:27 +00:00
|
|
|
#include "GrDrawingManager.h"
|
2015-02-13 22:20:05 +00:00
|
|
|
#include "GrGpuResourceCacheAccess.h"
|
2015-02-11 18:49:59 +00:00
|
|
|
#include "GrResourceCache.h"
|
2015-12-09 02:53:44 +00:00
|
|
|
|
|
|
|
#include "SkGpuDevice.h"
|
2015-11-08 16:07:24 +00:00
|
|
|
#include "SkGrPriv.h"
|
2015-02-03 02:26:03 +00:00
|
|
|
#include "SkString.h"
|
2013-08-21 19:27:48 +00:00
|
|
|
|
2015-12-11 14:11:21 +00:00
|
|
|
#include "text/GrBatchFontCache.h"
|
|
|
|
#include "text/GrTextBlobCache.h"
|
|
|
|
|
2015-08-21 18:08:00 +00:00
|
|
|
namespace GrTest {
|
|
|
|
void SetupAlwaysEvictAtlas(GrContext* context) {
|
|
|
|
// These sizes were selected because they allow each atlas to hold a single plot and will thus
|
|
|
|
// stress the atlas
|
|
|
|
int dim = GrBatchAtlas::kGlyphMaxDim;
|
|
|
|
GrBatchAtlasConfig configs[3];
|
|
|
|
configs[kA8_GrMaskFormat].fWidth = dim;
|
|
|
|
configs[kA8_GrMaskFormat].fHeight = dim;
|
2016-02-22 19:25:32 +00:00
|
|
|
configs[kA8_GrMaskFormat].fLog2Width = SkNextLog2(dim);
|
|
|
|
configs[kA8_GrMaskFormat].fLog2Height = SkNextLog2(dim);
|
2015-08-21 18:08:00 +00:00
|
|
|
configs[kA8_GrMaskFormat].fPlotWidth = dim;
|
|
|
|
configs[kA8_GrMaskFormat].fPlotHeight = dim;
|
|
|
|
|
|
|
|
configs[kA565_GrMaskFormat].fWidth = dim;
|
|
|
|
configs[kA565_GrMaskFormat].fHeight = dim;
|
2016-02-22 19:25:32 +00:00
|
|
|
configs[kA565_GrMaskFormat].fLog2Width = SkNextLog2(dim);
|
|
|
|
configs[kA565_GrMaskFormat].fLog2Height = SkNextLog2(dim);
|
2015-08-21 18:08:00 +00:00
|
|
|
configs[kA565_GrMaskFormat].fPlotWidth = dim;
|
|
|
|
configs[kA565_GrMaskFormat].fPlotHeight = dim;
|
|
|
|
|
|
|
|
configs[kARGB_GrMaskFormat].fWidth = dim;
|
|
|
|
configs[kARGB_GrMaskFormat].fHeight = dim;
|
2016-02-22 19:25:32 +00:00
|
|
|
configs[kARGB_GrMaskFormat].fLog2Width = SkNextLog2(dim);
|
|
|
|
configs[kARGB_GrMaskFormat].fLog2Height = SkNextLog2(dim);
|
2015-08-21 18:08:00 +00:00
|
|
|
configs[kARGB_GrMaskFormat].fPlotWidth = dim;
|
|
|
|
configs[kARGB_GrMaskFormat].fPlotHeight = dim;
|
|
|
|
|
|
|
|
context->setTextContextAtlasSizes_ForTesting(configs);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-11-16 14:23:31 +00:00
|
|
|
void GrTestTarget::init(GrContext* ctx, GrDrawTarget* target, GrRenderTarget* rt) {
|
2013-08-21 19:27:48 +00:00
|
|
|
SkASSERT(!fContext);
|
|
|
|
|
|
|
|
fContext.reset(SkRef(ctx));
|
|
|
|
fDrawTarget.reset(SkRef(target));
|
2015-11-16 14:23:31 +00:00
|
|
|
fRenderTarget.reset(SkRef(rt));
|
2013-08-21 19:27:48 +00:00
|
|
|
}
|
|
|
|
|
2015-11-16 19:02:05 +00:00
|
|
|
void GrContext::getTestTarget(GrTestTarget* tar, GrRenderTarget* rt) {
|
2013-08-21 19:27:48 +00:00
|
|
|
this->flush();
|
|
|
|
// We could create a proxy GrDrawTarget that passes through to fGpu until ~GrTextTarget() and
|
|
|
|
// then disconnects. This would help prevent test writers from mixing using the returned
|
|
|
|
// GrDrawTarget and regular drawing. We could also assert or fail in GrContext drawing methods
|
|
|
|
// until ~GrTestTarget().
|
2015-11-16 19:02:05 +00:00
|
|
|
if (!rt) {
|
|
|
|
GrSurfaceDesc desc;
|
|
|
|
desc.fFlags = kRenderTarget_GrSurfaceFlag;
|
|
|
|
desc.fWidth = 32;
|
|
|
|
desc.fHeight = 32;
|
|
|
|
desc.fConfig = kRGBA_8888_GrPixelConfig;
|
|
|
|
desc.fSampleCnt = 0;
|
|
|
|
|
2016-02-25 16:33:02 +00:00
|
|
|
SkAutoTUnref<GrTexture> texture(this->textureProvider()->createTexture(
|
|
|
|
desc, SkBudgeted::kNo, nullptr, 0));
|
2015-11-16 19:02:05 +00:00
|
|
|
if (nullptr == texture) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
SkASSERT(nullptr != texture->asRenderTarget());
|
|
|
|
rt = texture->asRenderTarget();
|
2015-11-16 14:23:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SkAutoTUnref<GrDrawTarget> dt(fDrawingManager->newDrawTarget(rt));
|
|
|
|
tar->init(this, dt, rt);
|
2013-08-21 19:27:48 +00:00
|
|
|
}
|
|
|
|
|
2015-08-03 17:17:44 +00:00
|
|
|
void GrContext::setTextBlobCacheLimit_ForTesting(size_t bytes) {
|
|
|
|
fTextBlobCache->setBudget(bytes);
|
|
|
|
}
|
|
|
|
|
2015-08-19 15:16:43 +00:00
|
|
|
void GrContext::setTextContextAtlasSizes_ForTesting(const GrBatchAtlasConfig* configs) {
|
|
|
|
fBatchFontCache->setAtlasSizes_ForTesting(configs);
|
|
|
|
}
|
|
|
|
|
2013-08-21 19:27:48 +00:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2013-12-18 17:25:33 +00:00
|
|
|
void GrContext::purgeAllUnlockedResources() {
|
2015-02-11 18:49:59 +00:00
|
|
|
fResourceCache->purgeAllUnlocked();
|
2013-12-18 17:25:33 +00:00
|
|
|
}
|
2014-11-05 22:47:41 +00:00
|
|
|
|
2015-12-02 17:05:37 +00:00
|
|
|
void GrContext::resetGpuStats() const {
|
|
|
|
#if GR_GPU_STATS
|
|
|
|
fGpu->stats()->reset();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2015-02-03 02:26:03 +00:00
|
|
|
void GrContext::dumpCacheStats(SkString* out) const {
|
|
|
|
#if GR_CACHE_STATS
|
2015-02-11 18:49:59 +00:00
|
|
|
fResourceCache->dumpStats(out);
|
2015-02-03 02:26:03 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2015-12-02 22:08:25 +00:00
|
|
|
void GrContext::dumpCacheStatsKeyValuePairs(SkTArray<SkString>* keys,
|
|
|
|
SkTArray<double>* values) const {
|
|
|
|
#if GR_CACHE_STATS
|
|
|
|
fResourceCache->dumpStatsKeyValuePairs(keys, values);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2015-02-03 02:26:03 +00:00
|
|
|
void GrContext::printCacheStats() const {
|
|
|
|
SkString out;
|
|
|
|
this->dumpCacheStats(&out);
|
2015-02-19 14:32:12 +00:00
|
|
|
SkDebugf("%s", out.c_str());
|
2015-02-03 02:26:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void GrContext::dumpGpuStats(SkString* out) const {
|
|
|
|
#if GR_GPU_STATS
|
|
|
|
return fGpu->stats()->dump(out);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2015-12-02 17:05:37 +00:00
|
|
|
void GrContext::dumpGpuStatsKeyValuePairs(SkTArray<SkString>* keys,
|
|
|
|
SkTArray<double>* values) const {
|
|
|
|
#if GR_GPU_STATS
|
|
|
|
return fGpu->stats()->dumpKeyValuePairs(keys, values);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2015-02-03 02:26:03 +00:00
|
|
|
void GrContext::printGpuStats() const {
|
|
|
|
SkString out;
|
|
|
|
this->dumpGpuStats(&out);
|
2015-02-19 14:32:12 +00:00
|
|
|
SkDebugf("%s", out.c_str());
|
2015-02-03 02:26:03 +00:00
|
|
|
}
|
|
|
|
|
2015-12-09 02:53:44 +00:00
|
|
|
GrTexture* GrContext::getFontAtlasTexture(GrMaskFormat format) {
|
2015-11-08 16:07:24 +00:00
|
|
|
GrBatchFontCache* cache = this->getBatchFontCache();
|
|
|
|
|
2015-12-09 02:53:44 +00:00
|
|
|
return cache->getTexture(format);
|
|
|
|
}
|
2015-11-08 16:07:24 +00:00
|
|
|
|
2015-12-09 02:53:44 +00:00
|
|
|
void SkGpuDevice::drawTexture(GrTexture* tex, const SkRect& dst, const SkPaint& paint) {
|
2015-11-08 16:07:24 +00:00
|
|
|
GrPaint grPaint;
|
|
|
|
SkMatrix mat;
|
|
|
|
mat.reset();
|
2015-12-09 02:53:44 +00:00
|
|
|
if (!SkPaintToGrPaint(this->context(), paint, mat, &grPaint)) {
|
2015-11-08 16:07:24 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
SkMatrix textureMat;
|
|
|
|
textureMat.reset();
|
2015-12-09 02:53:44 +00:00
|
|
|
textureMat[SkMatrix::kMScaleX] = 1.0f/dst.width();
|
|
|
|
textureMat[SkMatrix::kMScaleY] = 1.0f/dst.height();
|
|
|
|
textureMat[SkMatrix::kMTransX] = -dst.fLeft/dst.width();
|
|
|
|
textureMat[SkMatrix::kMTransY] = -dst.fTop/dst.height();
|
2015-11-08 16:07:24 +00:00
|
|
|
|
2015-12-09 02:53:44 +00:00
|
|
|
grPaint.addColorTextureProcessor(tex, textureMat);
|
2015-11-08 16:07:24 +00:00
|
|
|
|
|
|
|
GrClip clip;
|
2015-12-09 02:53:44 +00:00
|
|
|
fDrawContext->drawRect(clip, grPaint, mat, dst);
|
2015-11-08 16:07:24 +00:00
|
|
|
}
|
|
|
|
|
2015-12-09 02:53:44 +00:00
|
|
|
|
2015-02-03 02:26:03 +00:00
|
|
|
#if GR_GPU_STATS
|
|
|
|
void GrGpu::Stats::dump(SkString* out) {
|
|
|
|
out->appendf("Render Target Binds: %d\n", fRenderTargetBinds);
|
|
|
|
out->appendf("Shader Compilations: %d\n", fShaderCompilations);
|
2015-02-03 05:19:50 +00:00
|
|
|
out->appendf("Textures Created: %d\n", fTextureCreates);
|
|
|
|
out->appendf("Texture Uploads: %d\n", fTextureUploads);
|
2016-01-05 18:41:27 +00:00
|
|
|
out->appendf("Transfers to Texture: %d\n", fTransfersToTexture);
|
2015-04-16 18:22:42 +00:00
|
|
|
out->appendf("Stencil Buffer Creates: %d\n", fStencilAttachmentCreates);
|
2015-09-08 20:42:05 +00:00
|
|
|
out->appendf("Number of draws: %d\n", fNumDraws);
|
2015-02-03 02:26:03 +00:00
|
|
|
}
|
2015-12-02 17:05:37 +00:00
|
|
|
|
|
|
|
void GrGpu::Stats::dumpKeyValuePairs(SkTArray<SkString>* keys, SkTArray<double>* values) {
|
|
|
|
keys->push_back(SkString("render_target_binds")); values->push_back(fRenderTargetBinds);
|
|
|
|
keys->push_back(SkString("shader_compilations")); values->push_back(fShaderCompilations);
|
|
|
|
keys->push_back(SkString("texture_uploads")); values->push_back(fTextureUploads);
|
|
|
|
keys->push_back(SkString("number_of_draws")); values->push_back(fNumDraws);
|
2016-03-23 18:50:26 +00:00
|
|
|
keys->push_back(SkString("number_of_failed_draws")); values->push_back(fNumFailedDraws);
|
2015-12-02 17:05:37 +00:00
|
|
|
}
|
|
|
|
|
2015-02-03 02:26:03 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#if GR_CACHE_STATS
|
2015-11-09 21:51:06 +00:00
|
|
|
void GrResourceCache::getStats(Stats* stats) const {
|
|
|
|
stats->reset();
|
2015-02-03 02:26:03 +00:00
|
|
|
|
2015-11-09 21:51:06 +00:00
|
|
|
stats->fTotal = this->getResourceCount();
|
|
|
|
stats->fNumNonPurgeable = fNonpurgeableResources.count();
|
|
|
|
stats->fNumPurgeable = fPurgeableQueue.count();
|
2015-02-03 02:26:03 +00:00
|
|
|
|
2015-02-17 23:09:34 +00:00
|
|
|
for (int i = 0; i < fNonpurgeableResources.count(); ++i) {
|
2015-11-09 21:51:06 +00:00
|
|
|
stats->update(fNonpurgeableResources[i]);
|
2015-02-17 23:09:34 +00:00
|
|
|
}
|
|
|
|
for (int i = 0; i < fPurgeableQueue.count(); ++i) {
|
2015-11-09 21:51:06 +00:00
|
|
|
stats->update(fPurgeableQueue.at(i));
|
2015-02-03 02:26:03 +00:00
|
|
|
}
|
2015-11-09 21:51:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void GrResourceCache::dumpStats(SkString* out) const {
|
|
|
|
this->validate();
|
|
|
|
|
|
|
|
Stats stats;
|
|
|
|
|
|
|
|
this->getStats(&stats);
|
2015-02-03 02:26:03 +00:00
|
|
|
|
|
|
|
float countUtilization = (100.f * fBudgetedCount) / fMaxCount;
|
|
|
|
float byteUtilization = (100.f * fBudgetedBytes) / fMaxBytes;
|
|
|
|
|
|
|
|
out->appendf("Budget: %d items %d bytes\n", fMaxCount, (int)fMaxBytes);
|
|
|
|
out->appendf("\t\tEntry Count: current %d"
|
2015-06-18 16:12:16 +00:00
|
|
|
" (%d budgeted, %d external(%d borrowed, %d adopted), %d locked, %d scratch %.2g%% full), high %d\n",
|
2015-11-09 21:51:06 +00:00
|
|
|
stats.fTotal, fBudgetedCount, stats.fExternal, stats.fBorrowed,
|
|
|
|
stats.fAdopted, stats.fNumNonPurgeable, stats.fScratch, countUtilization,
|
|
|
|
fHighWaterCount);
|
2015-02-03 02:26:03 +00:00
|
|
|
out->appendf("\t\tEntry Bytes: current %d (budgeted %d, %.2g%% full, %d unbudgeted) high %d\n",
|
2015-02-17 23:09:34 +00:00
|
|
|
SkToInt(fBytes), SkToInt(fBudgetedBytes), byteUtilization,
|
|
|
|
SkToInt(stats.fUnbudgetedSize), SkToInt(fHighWaterBytes));
|
2015-02-03 02:26:03 +00:00
|
|
|
}
|
|
|
|
|
2015-12-02 22:08:25 +00:00
|
|
|
void GrResourceCache::dumpStatsKeyValuePairs(SkTArray<SkString>* keys,
|
|
|
|
SkTArray<double>* values) const {
|
|
|
|
this->validate();
|
|
|
|
|
|
|
|
Stats stats;
|
|
|
|
this->getStats(&stats);
|
|
|
|
|
|
|
|
keys->push_back(SkString("gpu_cache_purgable_entries")); values->push_back(stats.fNumPurgeable);
|
|
|
|
}
|
|
|
|
|
2015-02-03 02:26:03 +00:00
|
|
|
#endif
|
|
|
|
|
2015-02-19 19:38:44 +00:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
void GrResourceCache::changeTimestamp(uint32_t newTimestamp) { fTimestamp = newTimestamp; }
|
2015-02-03 02:26:03 +00:00
|
|
|
|
2016-01-13 15:47:38 +00:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
#define ASSERT_SINGLE_OWNER \
|
2016-03-02 17:26:36 +00:00
|
|
|
SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fDrawContext->fSingleOwner);)
|
|
|
|
#define RETURN_IF_ABANDONED if (fDrawContext->fDrawingManager->abandoned()) { return; }
|
2016-01-13 15:47:38 +00:00
|
|
|
|
2016-03-02 17:26:36 +00:00
|
|
|
void GrDrawContextPriv::testingOnly_drawBatch(const GrPipelineBuilder& pipelineBuilder,
|
|
|
|
GrDrawBatch* batch) {
|
2016-01-13 15:47:38 +00:00
|
|
|
ASSERT_SINGLE_OWNER
|
|
|
|
RETURN_IF_ABANDONED
|
2016-03-02 17:26:36 +00:00
|
|
|
SkDEBUGCODE(fDrawContext->validate();)
|
|
|
|
GR_AUDIT_TRAIL_AUTO_FRAME(fDrawContext->fAuditTrail, "GrDrawContext::testingOnly_drawBatch");
|
2016-01-13 15:47:38 +00:00
|
|
|
|
2016-03-02 17:26:36 +00:00
|
|
|
fDrawContext->getDrawTarget()->drawBatch(pipelineBuilder, batch);
|
2016-01-13 15:47:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#undef ASSERT_SINGLE_OWNER
|
|
|
|
#undef RETURN_IF_ABANDONED
|
|
|
|
|
2014-11-05 22:47:41 +00:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Code for the mock context. It's built on a mock GrGpu class that does nothing.
|
|
|
|
////
|
|
|
|
|
|
|
|
#include "GrGpu.h"
|
|
|
|
|
2015-01-22 18:16:09 +00:00
|
|
|
class GrPipeline;
|
2014-11-11 00:03:14 +00:00
|
|
|
|
2016-01-08 17:12:44 +00:00
|
|
|
class MockCaps : public GrCaps {
|
|
|
|
public:
|
|
|
|
explicit MockCaps(const GrContextOptions& options) : INHERITED(options) {}
|
|
|
|
bool isConfigTexturable(GrPixelConfig config) const override { return false; }
|
|
|
|
bool isConfigRenderable(GrPixelConfig config, bool withMSAA) const override { return false; }
|
|
|
|
private:
|
|
|
|
typedef GrCaps INHERITED;
|
|
|
|
};
|
|
|
|
|
2014-11-05 22:47:41 +00:00
|
|
|
class MockGpu : public GrGpu {
|
|
|
|
public:
|
2015-05-22 21:01:46 +00:00
|
|
|
MockGpu(GrContext* context, const GrContextOptions& options) : INHERITED(context) {
|
2016-01-08 17:12:44 +00:00
|
|
|
fCaps.reset(new MockCaps(options));
|
2015-05-22 21:01:46 +00:00
|
|
|
}
|
2015-03-26 01:17:31 +00:00
|
|
|
~MockGpu() override {}
|
2014-11-05 22:47:41 +00:00
|
|
|
|
2015-07-28 20:26:15 +00:00
|
|
|
bool onGetReadPixelsInfo(GrSurface* srcSurface, int readWidth, int readHeight, size_t rowBytes,
|
|
|
|
GrPixelConfig readConfig, DrawPreference*,
|
|
|
|
ReadPixelTempDrawInfo*) override { return false; }
|
|
|
|
|
2016-02-16 21:00:01 +00:00
|
|
|
bool onGetWritePixelsInfo(GrSurface* dstSurface, int width, int height,
|
2015-07-28 20:26:15 +00:00
|
|
|
GrPixelConfig srcConfig, DrawPreference*,
|
|
|
|
WritePixelTempDrawInfo*) override { return false; }
|
2015-07-23 15:07:21 +00:00
|
|
|
|
2015-03-26 01:17:31 +00:00
|
|
|
void discard(GrRenderTarget*) override {}
|
2014-11-26 20:28:00 +00:00
|
|
|
|
2015-08-21 18:53:29 +00:00
|
|
|
bool onCopySurface(GrSurface* dst,
|
|
|
|
GrSurface* src,
|
|
|
|
const SkIRect& srcRect,
|
|
|
|
const SkIPoint& dstPoint) override { return false; };
|
2014-11-26 20:28:00 +00:00
|
|
|
|
2016-03-07 21:58:26 +00:00
|
|
|
void onGetMultisampleSpecs(GrRenderTarget* rt,
|
|
|
|
const GrStencilSettings&,
|
|
|
|
int* effectiveSampleCnt,
|
|
|
|
SkAutoTDeleteArray<SkPoint>*) override {
|
|
|
|
*effectiveSampleCnt = rt->desc().fSampleCnt;
|
|
|
|
}
|
|
|
|
|
2015-07-13 15:08:25 +00:00
|
|
|
bool initCopySurfaceDstDesc(const GrSurface* src, GrSurfaceDesc* desc) const override {
|
2014-11-26 20:28:00 +00:00
|
|
|
return false;
|
|
|
|
}
|
2014-11-05 22:47:41 +00:00
|
|
|
|
2015-12-03 20:58:06 +00:00
|
|
|
void drawDebugWireRect(GrRenderTarget*, const SkIRect&, GrColor) override {};
|
|
|
|
|
2014-11-26 18:20:45 +00:00
|
|
|
private:
|
2015-03-26 01:17:31 +00:00
|
|
|
void onResetContext(uint32_t resetBits) override {}
|
2014-11-05 22:47:41 +00:00
|
|
|
|
2015-08-12 18:14:50 +00:00
|
|
|
void xferBarrier(GrRenderTarget*, GrXferBarrierType) override {}
|
|
|
|
|
2015-04-22 20:27:39 +00:00
|
|
|
GrTexture* onCreateTexture(const GrSurfaceDesc& desc, GrGpuResource::LifeCycle lifeCycle,
|
2016-02-26 21:20:48 +00:00
|
|
|
const SkTArray<GrMipLevel>& texels) override {
|
2015-08-27 14:41:13 +00:00
|
|
|
return nullptr;
|
2014-11-05 22:47:41 +00:00
|
|
|
}
|
|
|
|
|
2015-04-22 20:27:39 +00:00
|
|
|
GrTexture* onCreateCompressedTexture(const GrSurfaceDesc& desc, GrGpuResource::LifeCycle,
|
2016-02-26 21:20:48 +00:00
|
|
|
const SkTArray<GrMipLevel>& texels) override {
|
2015-08-27 14:41:13 +00:00
|
|
|
return nullptr;
|
2014-11-05 22:47:41 +00:00
|
|
|
}
|
|
|
|
|
2015-06-18 16:12:16 +00:00
|
|
|
GrTexture* onWrapBackendTexture(const GrBackendTextureDesc&,
|
2015-08-27 14:41:13 +00:00
|
|
|
GrWrapOwnership) override { return nullptr; }
|
2014-11-05 22:47:41 +00:00
|
|
|
|
2015-06-18 16:12:16 +00:00
|
|
|
GrRenderTarget* onWrapBackendRenderTarget(const GrBackendRenderTargetDesc&,
|
|
|
|
GrWrapOwnership) override {
|
2015-08-27 14:41:13 +00:00
|
|
|
return nullptr;
|
2014-11-26 18:20:45 +00:00
|
|
|
}
|
2014-11-05 22:47:41 +00:00
|
|
|
|
Add wrapBackendTextureAsRenderTarget API
Skia's GrTextureProvider currently exposes two APIs for wrapping backend
objects:
* wrapBackendTexture - wraps a texture into a GrTexture. Depending on
flags, this GrTexture can be converted to a GrRenderTarget. Skia
manages the render target objects it may create to provide a render
target for the texture. This allows Skia to create stencil buffers
if needed and manager MSAA resolves.
* wrapBackendRenderTarget - wraps a FBO into a GrRenderTarget. This
object cannot be converted to a GrTexture. Skia does not manage
the render target objects for such a GrRenderTarget, and as such
cannot attach stencil buffers or perform MSAA resolves on the
created GrRenderTarget.
Given these two options, wrapBackendTexture provides more versatility
and allows Skia more room for optimization. Chrome currently uses
wrapBackendTexture for this reason.
While these two functions cover most cases, they do not provide a way
for Skia to wrap a texture into a render target (and gain the MSAA and
stencil buffer management), without also creating a GrTexture. This is
problematic in cases where a texture can be bound to a render target,
but cannot be textured from, as is the case in Chrome's limited support
for GL_TEXTURE_RECTANGLE.
To address this, a new function is created:
* wrapBackendTextureAsRenderTarget - wraps a texture into a
GrRenderTarget. As with wrapBackendTexture, the created render
target objects are fully managed by Skia. Unlike wrapBackendTexture
no GrTexture is created, and the created object will never be
textured from.
BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1709163003
Review URL: https://codereview.chromium.org/1709163003
2016-02-24 22:49:51 +00:00
|
|
|
GrRenderTarget* onWrapBackendTextureAsRenderTarget(const GrBackendTextureDesc&,
|
|
|
|
GrWrapOwnership) override {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2016-03-25 19:15:03 +00:00
|
|
|
GrBuffer* onCreateBuffer(GrBufferType, size_t, GrAccessPattern) override { return nullptr; }
|
2015-12-03 17:15:47 +00:00
|
|
|
|
2015-08-06 17:54:13 +00:00
|
|
|
void onClear(GrRenderTarget*, const SkIRect& rect, GrColor color) override {}
|
2014-11-26 16:45:30 +00:00
|
|
|
|
2015-03-26 01:17:31 +00:00
|
|
|
void onClearStencilClip(GrRenderTarget*, const SkIRect& rect, bool insideClip) override {}
|
2014-11-26 20:28:00 +00:00
|
|
|
|
2016-03-17 18:35:45 +00:00
|
|
|
void onDraw(const GrPipeline&,
|
|
|
|
const GrPrimitiveProcessor&,
|
|
|
|
const GrMesh*,
|
|
|
|
int meshCount) override {}
|
2014-11-26 20:28:00 +00:00
|
|
|
|
2015-07-30 14:34:27 +00:00
|
|
|
bool onReadPixels(GrSurface* surface,
|
2014-11-26 20:28:00 +00:00
|
|
|
int left, int top, int width, int height,
|
|
|
|
GrPixelConfig,
|
|
|
|
void* buffer,
|
2015-03-26 01:17:31 +00:00
|
|
|
size_t rowBytes) override {
|
2014-11-05 22:47:41 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-07-30 14:34:27 +00:00
|
|
|
bool onWritePixels(GrSurface* surface,
|
|
|
|
int left, int top, int width, int height,
|
2016-02-26 21:20:48 +00:00
|
|
|
GrPixelConfig config, const SkTArray<GrMipLevel>& texels) override {
|
2014-11-05 22:47:41 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-01-05 18:41:27 +00:00
|
|
|
bool onTransferPixels(GrSurface* surface,
|
|
|
|
int left, int top, int width, int height,
|
2016-03-25 19:15:03 +00:00
|
|
|
GrPixelConfig config, GrBuffer* transferBuffer,
|
2016-01-05 18:41:27 +00:00
|
|
|
size_t offset, size_t rowBytes) override {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-03-26 01:17:31 +00:00
|
|
|
void onResolveRenderTarget(GrRenderTarget* target) override { return; }
|
2014-11-05 22:47:41 +00:00
|
|
|
|
2015-09-14 19:56:10 +00:00
|
|
|
GrStencilAttachment* createStencilAttachmentForRenderTarget(const GrRenderTarget*,
|
|
|
|
int width,
|
|
|
|
int height) override {
|
|
|
|
return nullptr;
|
2014-11-05 22:47:41 +00:00
|
|
|
}
|
|
|
|
|
2015-03-26 01:17:31 +00:00
|
|
|
void clearStencil(GrRenderTarget* target) override {}
|
2014-11-05 22:47:41 +00:00
|
|
|
|
2015-07-14 18:02:52 +00:00
|
|
|
GrBackendObject createTestingOnlyBackendTexture(void* pixels, int w, int h,
|
2016-02-05 15:17:34 +00:00
|
|
|
GrPixelConfig config) override {
|
2016-01-26 17:10:48 +00:00
|
|
|
return 0;
|
2015-07-14 18:02:52 +00:00
|
|
|
}
|
2015-11-11 20:40:42 +00:00
|
|
|
bool isTestingOnlyBackendTexture(GrBackendObject ) const override { return false; }
|
2016-02-05 15:17:34 +00:00
|
|
|
void deleteTestingOnlyBackendTexture(GrBackendObject, bool abandonTexture) override {}
|
2015-07-13 14:19:57 +00:00
|
|
|
|
2014-11-05 22:47:41 +00:00
|
|
|
typedef GrGpu INHERITED;
|
|
|
|
};
|
|
|
|
|
|
|
|
GrContext* GrContext::CreateMockContext() {
|
2015-08-26 20:07:48 +00:00
|
|
|
GrContext* context = new GrContext;
|
2014-11-05 22:47:41 +00:00
|
|
|
|
|
|
|
context->initMockContext();
|
|
|
|
return context;
|
|
|
|
}
|
|
|
|
|
|
|
|
void GrContext::initMockContext() {
|
2015-05-22 21:01:46 +00:00
|
|
|
GrContextOptions options;
|
2016-03-25 19:15:03 +00:00
|
|
|
options.fBufferMapThreshold = 0;
|
2015-08-27 14:41:13 +00:00
|
|
|
SkASSERT(nullptr == fGpu);
|
2015-08-26 20:07:48 +00:00
|
|
|
fGpu = new MockGpu(this, options);
|
2014-11-05 22:47:41 +00:00
|
|
|
SkASSERT(fGpu);
|
2015-11-30 21:27:47 +00:00
|
|
|
this->initCommon(options);
|
2014-11-05 22:47:41 +00:00
|
|
|
|
|
|
|
// We delete these because we want to test the cache starting with zero resources. Also, none of
|
|
|
|
// these objects are required for any of tests that use this context. TODO: make stop allocating
|
|
|
|
// resources in the buffer pools.
|
2015-10-17 14:43:27 +00:00
|
|
|
fDrawingManager->abandon();
|
2014-11-05 22:47:41 +00:00
|
|
|
}
|