Make GrTextureStripAtlas flush pending IO on newly acquired texture

GrTextureStripAtlas uses its own lock counts to protect against
overwriting its own earlier writes, but that doesn't protect against
IO that was pending when a texture was first acquired.

BUG=chromium:637678
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2262233002

Review-Url: https://codereview.chromium.org/2262233002
This commit is contained in:
ajuma 2016-08-24 08:19:02 -07:00 committed by Commit bot
parent 9d15dab754
commit 95243ebb68
8 changed files with 91 additions and 3 deletions

View File

@ -66,6 +66,7 @@
'<(skia_include_path)/private/GrRenderTargetProxy.h',
'<(skia_include_path)/private/GrSurfaceProxy.h',
'<(skia_include_path)/private/GrTextureProxy.h',
'<(skia_include_path)/private/GrTextureStripAtlas.h',
'<(skia_src_path)/gpu/GrAppliedClip.h',
'<(skia_src_path)/gpu/GrAuditTrail.cpp',
@ -306,7 +307,6 @@
'<(skia_src_path)/gpu/effects/GrTextureDomain.cpp',
'<(skia_src_path)/gpu/effects/GrTextureDomain.h',
'<(skia_src_path)/gpu/effects/GrTextureStripAtlas.cpp',
'<(skia_src_path)/gpu/effects/GrTextureStripAtlas.h',
'<(skia_src_path)/gpu/effects/GrXfermodeFragmentProcessor.cpp',
'<(skia_src_path)/gpu/effects/GrYUVEffect.cpp',
'<(skia_src_path)/gpu/effects/GrYUVEffect.h',

View File

@ -306,6 +306,12 @@ public:
*/
void flushSurfaceWrites(GrSurface* surface);
/**
* After this returns any pending reads or writes to the surface will have been issued to the
* backend 3D API.
*/
void flushSurfaceIO(GrSurface* surface);
/**
* Finalizes all pending reads and writes to the surface and also performs an MSAA resolve
* if necessary.

View File

@ -334,8 +334,8 @@ sk_sp<SkColorFilter> SkTable_ColorFilter::makeComposed(sk_sp<SkColorFilter> inne
#include "GrContext.h"
#include "GrFragmentProcessor.h"
#include "GrInvariantOutput.h"
#include "GrTextureStripAtlas.h"
#include "SkGr.h"
#include "effects/GrTextureStripAtlas.h"
#include "glsl/GrGLSLFragmentProcessor.h"
#include "glsl/GrGLSLFragmentShaderBuilder.h"
#include "glsl/GrGLSLProgramDataManager.h"

View File

@ -943,9 +943,9 @@ SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
#if SK_SUPPORT_GPU
#include "effects/GrTextureStripAtlas.h"
#include "GrContext.h"
#include "GrInvariantOutput.h"
#include "GrTextureStripAtlas.h"
#include "gl/GrGLContext.h"
#include "glsl/GrGLSLFragmentShaderBuilder.h"
#include "glsl/GrGLSLProgramDataManager.h"

View File

@ -594,6 +594,14 @@ void GrContext::flushSurfaceWrites(GrSurface* surface) {
}
}
void GrContext::flushSurfaceIO(GrSurface* surface) {
ASSERT_SINGLE_OWNER
RETURN_IF_ABANDONED
if (surface->surfacePriv().hasPendingIO()) {
this->flush();
}
}
////////////////////////////////////////////////////////////////////////////////
int GrContext::getRecommendedSampleCount(GrPixelConfig config,
SkScalar dpi) const {

View File

@ -209,6 +209,10 @@ void GrTextureStripAtlas::lockTexture() {
if (!fTexture) {
return;
}
// We will be issuing writes to the surface using kDontFlush_PixelOpsFlag, so we
// need to make sure any existing IO is flushed
fDesc.fContext->flushSurfaceIO(fTexture);
fDesc.fContext->textureProvider()->assignUniqueKeyToTexture(key, fTexture);
// This is a new texture, so all of our cache info is now invalid
this->initLRU();

View File

@ -0,0 +1,70 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "Test.h"
#if SK_SUPPORT_GPU
#include "GrContext.h"
#include "GrGpu.h"
#include "GrTextureStripAtlas.h"
#include "GrTypes.h"
#include "SkGpuDevice.h"
// This tests that GrTextureStripAtlas flushes pending IO on the texture it acquires.
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrTextureStripAtlasFlush, reporter, ctxInfo) {
GrContext* context = ctxInfo.grContext();
GrSurfaceDesc desc;
desc.fWidth = 32;
desc.fHeight = 32;
desc.fConfig = kRGBA_8888_GrPixelConfig;
GrTexture* texture = context->textureProvider()->createTexture(desc, SkBudgeted::kYes,
nullptr, 0);
GrSurfaceDesc targetDesc = desc;
targetDesc.fFlags = kRenderTarget_GrSurfaceFlag;
GrTexture* target = context->textureProvider()->createTexture(targetDesc, SkBudgeted::kYes,
nullptr, 0);
SkAutoTMalloc<uint32_t> pixels(desc.fWidth * desc.fHeight);
memset(pixels.get(), 0xFF, sizeof(uint32_t) * desc.fWidth * desc.fHeight);
texture->writePixels(0, 0, desc.fWidth, desc.fHeight, kRGBA_8888_GrPixelConfig, pixels.get());
// Add a pending read to the texture, and then make it available for reuse.
context->copySurface(target, texture);
texture->unref();
// Create an atlas with parameters that allow it to reuse the texture.
GrTextureStripAtlas::Desc atlasDesc;
atlasDesc.fContext = context;
atlasDesc.fConfig = desc.fConfig;
atlasDesc.fWidth = desc.fWidth;
atlasDesc.fHeight = desc.fHeight;
atlasDesc.fRowHeight = 1;
GrTextureStripAtlas* atlas = GrTextureStripAtlas::GetAtlas(atlasDesc);
// Write to the atlas' texture.
SkImageInfo info = SkImageInfo::MakeN32(desc.fWidth, desc.fHeight, kPremul_SkAlphaType);
size_t rowBytes = desc.fWidth * GrBytesPerPixel(desc.fConfig);
SkBitmap bitmap;
bitmap.allocPixels(info, rowBytes);
memset(bitmap.getPixels(), 1, rowBytes * desc.fHeight);
atlas->lockRow(bitmap);
if (!context->caps()->preferVRAMUseOverFlushes())
REPORTER_ASSERT(reporter, texture == atlas->getTexture());
// The atlas' use of its texture shouldn't change which pixels got copied to the target.
SkAutoTMalloc<uint32_t> actualPixels(desc.fWidth * desc.fHeight);
bool success = target->readPixels(0, 0, desc.fWidth, desc.fHeight, kRGBA_8888_GrPixelConfig,
actualPixels.get());
REPORTER_ASSERT(reporter, success);
REPORTER_ASSERT(reporter,
!memcmp(pixels.get(), actualPixels.get(),
sizeof(uint32_t) * desc.fWidth * desc.fHeight));
target->unref();
}
#endif