Revert of Move draw on upload decision in GrGpu (patchset #4 id:50001 of https://codereview.chromium.org/1257073003/)
Reason for revert: breaking write pixels test on bots Original issue's description: > Move draw on upload decision in GrGpu > > BUG=skia: > > Committed: https://skia.googlesource.com/skia/+/0341b4427e5f037e3b501ed6e57dfdb7b40f150e TBR=robertphillips@google.com NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true BUG=skia: Review URL: https://codereview.chromium.org/1260293004
This commit is contained in:
parent
efa1ece07e
commit
c3fb74693e
@ -329,96 +329,76 @@ bool GrContext::writeSurfacePixels(GrSurface* surface,
|
||||
GrPixelConfig srcConfig, const void* buffer, size_t rowBytes,
|
||||
uint32_t pixelOpsFlags) {
|
||||
RETURN_FALSE_IF_ABANDONED
|
||||
{
|
||||
GrTexture* texture = NULL;
|
||||
if (!(kUnpremul_PixelOpsFlag & pixelOpsFlags) && (texture = surface->asTexture()) &&
|
||||
fGpu->canWriteTexturePixels(texture, srcConfig) &&
|
||||
(!fCaps->useDrawInsteadOfPartialRenderTargetWrite() || !surface->asRenderTarget() ||
|
||||
(width == texture->width() && height == texture->height()))) {
|
||||
|
||||
if (!(kDontFlush_PixelOpsFlag & pixelOpsFlags) &&
|
||||
surface->surfacePriv().hasPendingIO()) {
|
||||
this->flush();
|
||||
}
|
||||
return fGpu->writeTexturePixels(texture, left, top, width, height,
|
||||
srcConfig, buffer, rowBytes);
|
||||
// Don't need to check kFlushWrites_PixelOp here, we just did a direct write so the
|
||||
// upload is already flushed.
|
||||
}
|
||||
}
|
||||
|
||||
// Trim the params here so that if we wind up making a temporary surface it can be as small as
|
||||
// necessary and because GrGpu::getWritePixelsInfo requires it.
|
||||
// necessary.
|
||||
if (!GrSurfacePriv::AdjustWritePixelParams(surface->width(), surface->height(),
|
||||
GrBytesPerPixel(srcConfig), &left, &top, &width,
|
||||
&height, &buffer, &rowBytes)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool applyPremulToSrc = false;
|
||||
// If we didn't do a direct texture write then we upload the pixels to a texture and draw.
|
||||
GrRenderTarget* renderTarget = surface->asRenderTarget();
|
||||
if (!renderTarget) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We ignore the preferred config unless it is a R/B swap of the src config. In that case
|
||||
// we will upload the original src data to a scratch texture but we will spoof it as the swapped
|
||||
// config. This scratch will then have R and B swapped. We correct for this by swapping again
|
||||
// when drawing the scratch to the dst using a conversion effect.
|
||||
bool swapRAndB = false;
|
||||
GrPixelConfig writeConfig = srcConfig;
|
||||
if (GrPixelConfigSwapRAndB(srcConfig) ==
|
||||
fGpu->preferredWritePixelsConfig(srcConfig, renderTarget->config())) {
|
||||
writeConfig = GrPixelConfigSwapRAndB(srcConfig);
|
||||
swapRAndB = true;
|
||||
}
|
||||
|
||||
GrSurfaceDesc desc;
|
||||
desc.fWidth = width;
|
||||
desc.fHeight = height;
|
||||
desc.fConfig = writeConfig;
|
||||
SkAutoTUnref<GrTexture> texture(this->textureProvider()->refScratchTexture(desc,
|
||||
GrTextureProvider::kApprox_ScratchTexMatch));
|
||||
if (!texture) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SkAutoTUnref<const GrFragmentProcessor> fp;
|
||||
SkMatrix textureMatrix;
|
||||
textureMatrix.setIDiv(texture->width(), texture->height());
|
||||
|
||||
// allocate a tmp buffer and sw convert the pixels to premul
|
||||
SkAutoSTMalloc<128 * 128, uint32_t> tmpPixels(0);
|
||||
|
||||
GrPaint paint;
|
||||
if (kUnpremul_PixelOpsFlag & pixelOpsFlags) {
|
||||
if (!GrPixelConfigIs8888(srcConfig)) {
|
||||
return false;
|
||||
}
|
||||
applyPremulToSrc = true;
|
||||
}
|
||||
GrGpu::DrawPreference drawPreference = applyPremulToSrc ?
|
||||
GrGpu::kCallerPrefersDraw_DrawPreference :
|
||||
GrGpu::kNoDraw_DrawPreference;
|
||||
GrGpu::WritePixelTempDrawInfo tempDrawInfo;
|
||||
if (!fGpu->getWritePixelsInfo(surface, width, height, rowBytes, srcConfig, &drawPreference,
|
||||
&tempDrawInfo)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(kDontFlush_PixelOpsFlag & pixelOpsFlags) && surface->surfacePriv().hasPendingIO()) {
|
||||
this->flush();
|
||||
}
|
||||
|
||||
SkAutoTUnref<GrTexture> tempTexture;
|
||||
if (GrGpu::kNoDraw_DrawPreference != drawPreference) {
|
||||
tempTexture.reset(this->textureProvider()->refScratchTexture(
|
||||
tempDrawInfo.fTempSurfaceDesc, GrTextureProvider::kApprox_ScratchTexMatch));
|
||||
if (!tempTexture && GrGpu::kRequireDraw_DrawPreference == drawPreference) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (tempTexture) {
|
||||
SkAutoTUnref<const GrFragmentProcessor> fp;
|
||||
SkMatrix textureMatrix;
|
||||
textureMatrix.setIDiv(tempTexture->width(), tempTexture->height());
|
||||
GrPaint paint;
|
||||
if (applyPremulToSrc) {
|
||||
fp.reset(this->createUPMToPMEffect(paint.getProcessorDataManager(), tempTexture,
|
||||
tempDrawInfo.fSwapRAndB, textureMatrix));
|
||||
// If premultiplying was the only reason for the draw, fall back to a straight write.
|
||||
if (!fp && GrGpu::kCallerPrefersDraw_DrawPreference == drawPreference) {
|
||||
tempTexture.reset(NULL);
|
||||
}
|
||||
}
|
||||
if (tempTexture) {
|
||||
fp.reset(this->createUPMToPMEffect(paint.getProcessorDataManager(), texture, swapRAndB,
|
||||
textureMatrix));
|
||||
// handle the unpremul step on the CPU if we couldn't create an effect to do it.
|
||||
if (!fp) {
|
||||
fp.reset(GrConfigConversionEffect::Create(
|
||||
paint.getProcessorDataManager(), tempTexture, tempDrawInfo.fSwapRAndB,
|
||||
GrConfigConversionEffect::kNone_PMConversion, textureMatrix));
|
||||
if (!fp) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
GrRenderTarget* renderTarget = surface->asRenderTarget();
|
||||
SkASSERT(renderTarget);
|
||||
if (tempTexture->surfacePriv().hasPendingIO()) {
|
||||
this->flush();
|
||||
}
|
||||
if (!fGpu->writeTexturePixels(tempTexture, 0, 0, width, height,
|
||||
tempDrawInfo.fTempSurfaceDesc.fConfig, buffer,
|
||||
rowBytes)) {
|
||||
return false;
|
||||
}
|
||||
SkMatrix matrix;
|
||||
matrix.setTranslate(SkIntToScalar(left), SkIntToScalar(top));
|
||||
GrDrawContext* drawContext = this->drawContext();
|
||||
if (!drawContext) {
|
||||
return false;
|
||||
}
|
||||
paint.addColorProcessor(fp);
|
||||
SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height));
|
||||
drawContext->drawRect(renderTarget, GrClip::WideOpen(), paint, matrix, rect, NULL);
|
||||
|
||||
if (kFlushWrites_PixelOp & pixelOpsFlags) {
|
||||
this->flushSurfaceWrites(surface);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!tempTexture) {
|
||||
SkASSERT(surface->asTexture());
|
||||
// allocate a tmp buffer and sw convert the pixels to premul
|
||||
SkAutoSTMalloc<128 * 128, uint32_t> tmpPixels(0);
|
||||
if (applyPremulToSrc) {
|
||||
size_t tmpRowBytes = 4 * width;
|
||||
tmpPixels.reset(width * height);
|
||||
if (!sw_convert_to_premul(srcConfig, width, height, rowBytes, buffer, tmpRowBytes,
|
||||
@ -428,9 +408,45 @@ bool GrContext::writeSurfacePixels(GrSurface* surface,
|
||||
rowBytes = tmpRowBytes;
|
||||
buffer = tmpPixels.get();
|
||||
}
|
||||
return fGpu->writeTexturePixels(surface->asTexture(), left, top, width, height, srcConfig,
|
||||
buffer, rowBytes);
|
||||
}
|
||||
|
||||
if (!fp) {
|
||||
fp.reset(GrConfigConversionEffect::Create(paint.getProcessorDataManager(),
|
||||
texture,
|
||||
swapRAndB,
|
||||
GrConfigConversionEffect::kNone_PMConversion,
|
||||
textureMatrix));
|
||||
}
|
||||
|
||||
// Even if the client told us not to flush, we still flush here. The client may have known that
|
||||
// writes to the original surface caused no data hazards, but they can't know that the scratch
|
||||
// we just got is safe.
|
||||
if (texture->surfacePriv().hasPendingIO()) {
|
||||
this->flush();
|
||||
}
|
||||
if (!fGpu->writeTexturePixels(texture, 0, 0, width, height,
|
||||
writeConfig, buffer, rowBytes)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SkMatrix matrix;
|
||||
matrix.setTranslate(SkIntToScalar(left), SkIntToScalar(top));
|
||||
|
||||
GrDrawContext* drawContext = this->drawContext();
|
||||
if (!drawContext) {
|
||||
return false;
|
||||
}
|
||||
|
||||
paint.addColorProcessor(fp);
|
||||
|
||||
SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height));
|
||||
|
||||
drawContext->drawRect(renderTarget, GrClip::WideOpen(), paint, matrix, rect, NULL);
|
||||
|
||||
if (kFlushWrites_PixelOp & pixelOpsFlags) {
|
||||
this->flushSurfaceWrites(surface);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -232,61 +232,6 @@ void GrGpu::clearStencilClip(const SkIRect& rect,
|
||||
this->onClearStencilClip(renderTarget, rect, insideClip);
|
||||
}
|
||||
|
||||
bool GrGpu::getReadPixelsInfo(GrSurface* srcSurface, int width, int height, size_t rowBytes,
|
||||
GrPixelConfig readConfig, DrawPreference* drawPreference,
|
||||
ReadPixelTempDrawInfo* tempDrawInfo) {
|
||||
SkASSERT(drawPreference);
|
||||
SkASSERT(tempDrawInfo);
|
||||
SkASSERT(kGpuPrefersDraw_DrawPreference != *drawPreference);
|
||||
|
||||
if (!this->onGetReadPixelsInfo(srcSurface, width, height, rowBytes, readConfig, drawPreference,
|
||||
tempDrawInfo)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check to see if we're going to request that the caller draw when drawing is not possible.
|
||||
if (!srcSurface->asTexture() ||
|
||||
!this->caps()->isConfigRenderable(tempDrawInfo->fTempSurfaceDesc.fConfig, false)) {
|
||||
// If we don't have a fallback to a straight read then fail.
|
||||
if (kRequireDraw_DrawPreference == *drawPreference) {
|
||||
return false;
|
||||
}
|
||||
*drawPreference = kNoDraw_DrawPreference;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
bool GrGpu::getWritePixelsInfo(GrSurface* dstSurface, int width, int height, size_t rowBytes,
|
||||
GrPixelConfig srcConfig, DrawPreference* drawPreference,
|
||||
WritePixelTempDrawInfo* tempDrawInfo) {
|
||||
SkASSERT(drawPreference);
|
||||
SkASSERT(tempDrawInfo);
|
||||
SkASSERT(kGpuPrefersDraw_DrawPreference != *drawPreference);
|
||||
|
||||
if (this->caps()->useDrawInsteadOfPartialRenderTargetWrite() &&
|
||||
SkToBool(dstSurface->asRenderTarget()) &&
|
||||
(width < dstSurface->width() || height < dstSurface->height())) {
|
||||
ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
|
||||
}
|
||||
|
||||
if (!this->onGetWritePixelsInfo(dstSurface, width, height, rowBytes, srcConfig, drawPreference,
|
||||
tempDrawInfo)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check to see if we're going to request that the caller draw when drawing is not possible.
|
||||
if (!dstSurface->asRenderTarget() ||
|
||||
!this->caps()->isConfigTexturable(tempDrawInfo->fTempSurfaceDesc.fConfig)) {
|
||||
// If we don't have a fallback to a straight upload then fail.
|
||||
if (kRequireDraw_DrawPreference == *drawPreference ||
|
||||
!this->caps()->isConfigTexturable(srcConfig)) {
|
||||
return false;
|
||||
}
|
||||
*drawPreference = kNoDraw_DrawPreference;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GrGpu::readPixels(GrRenderTarget* target,
|
||||
int left, int top, int width, int height,
|
||||
GrPixelConfig config, void* buffer,
|
||||
|
@ -173,39 +173,28 @@ public:
|
||||
kRequireDraw_DrawPreference
|
||||
};
|
||||
|
||||
/**
|
||||
* Used to negotiate whether and how an intermediate draw should or must be performed before
|
||||
* a readPixels call. If this returns false then GrGpu could not deduce an intermediate draw
|
||||
* that would allow a successful readPixels call. The passed width, height, and rowBytes,
|
||||
* must be non-zero and already reflect clipping to the src bounds.
|
||||
*/
|
||||
bool getReadPixelsInfo(GrSurface* srcSurface, int readWidth, int readHeight, size_t rowBytes,
|
||||
GrPixelConfig readConfig, DrawPreference*, ReadPixelTempDrawInfo*);
|
||||
|
||||
/** Info struct returned by getWritePixelsInfo about performing an intermediate draw in order
|
||||
to write pixels to a GrSurface for either performance or correctness reasons. */
|
||||
struct WritePixelTempDrawInfo {
|
||||
/** If the GrGpu is requesting that the caller upload to an intermediate surface and draw
|
||||
that to the dst then this is the descriptor for the intermediate surface. The caller
|
||||
should upload the pixels such that the upper left pixel of the upload rect is at 0,0 in
|
||||
the intermediate surface.*/
|
||||
GrSurfaceDesc fTempSurfaceDesc;
|
||||
/** If set, fTempSurfaceDesc's config will be a R/B swap of the src pixel config. The caller
|
||||
should upload the pixels as is such that R and B will be swapped in the intermediate
|
||||
surface. When the intermediate is drawn to the dst the shader should swap R/B again
|
||||
such that the correct swizzle results in the dst. This is done to work around either
|
||||
performance or API restrictions in the backend 3D API implementation. */
|
||||
bool fSwapRAndB;
|
||||
};
|
||||
/** Used to negotiates whether and how an intermediate draw should or must be performed before
|
||||
a readPixels call. If this returns false then GrGpu could not deduce an intermediate draw
|
||||
that would allow a successful readPixels call. */
|
||||
virtual bool getReadPixelsInfo(GrSurface* srcSurface, int readWidth, int readHeight,
|
||||
size_t rowBytes, GrPixelConfig readConfig, DrawPreference*,
|
||||
ReadPixelTempDrawInfo *) = 0;
|
||||
|
||||
/**
|
||||
* Used to negotiate whether and how an intermediate surface should be used to write pixels to
|
||||
* a GrSurface. If this returns false then GrGpu could not deduce an intermediate draw
|
||||
* that would allow a successful transfer of the src pixels to the dst. The passed width,
|
||||
* height, and rowBytes, must be non-zero and already reflect clipping to the dst bounds.
|
||||
* Gets a preferred 8888 config to use for writing pixel data to a surface with
|
||||
* config surfaceConfig. The returned config must have at least as many bits per channel as the
|
||||
* writeConfig param.
|
||||
*/
|
||||
bool getWritePixelsInfo(GrSurface* dstSurface, int width, int height, size_t rowBytes,
|
||||
GrPixelConfig srcConfig, DrawPreference*, WritePixelTempDrawInfo*);
|
||||
virtual GrPixelConfig preferredWritePixelsConfig(GrPixelConfig writeConfig,
|
||||
GrPixelConfig surfaceConfig) const {
|
||||
return writeConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called before uploading writing pixels to a GrTexture when the src pixel config doesn't
|
||||
* match the texture's config.
|
||||
*/
|
||||
virtual bool canWriteTexturePixels(const GrTexture*, GrPixelConfig srcConfig) const = 0;
|
||||
|
||||
/**
|
||||
* Reads a rectangle of pixels from a render target.
|
||||
@ -412,16 +401,6 @@ protected:
|
||||
unsigned int* ref,
|
||||
unsigned int* mask);
|
||||
|
||||
static void ElevateDrawPreference(GrGpu::DrawPreference* preference,
|
||||
GrGpu::DrawPreference elevation) {
|
||||
GR_STATIC_ASSERT(GrGpu::kCallerPrefersDraw_DrawPreference > GrGpu::kNoDraw_DrawPreference);
|
||||
GR_STATIC_ASSERT(GrGpu::kGpuPrefersDraw_DrawPreference >
|
||||
GrGpu::kCallerPrefersDraw_DrawPreference);
|
||||
GR_STATIC_ASSERT(GrGpu::kRequireDraw_DrawPreference >
|
||||
GrGpu::kGpuPrefersDraw_DrawPreference);
|
||||
*preference = SkTMax(*preference, elevation);
|
||||
}
|
||||
|
||||
const GrTraceMarkerSet& getActiveTraceMarkers() const { return fActiveTraceMarkers; }
|
||||
|
||||
Stats fStats;
|
||||
@ -461,13 +440,6 @@ private:
|
||||
// overridden by backend-specific derived class to perform the draw call.
|
||||
virtual void onDraw(const DrawArgs&, const GrNonInstancedVertices&) = 0;
|
||||
|
||||
virtual bool onGetReadPixelsInfo(GrSurface* srcSurface, int readWidth, int readHeight,
|
||||
size_t rowBytes, GrPixelConfig readConfig, DrawPreference*,
|
||||
ReadPixelTempDrawInfo*) = 0;
|
||||
virtual bool onGetWritePixelsInfo(GrSurface* dstSurface, int width, int height, size_t rowBytes,
|
||||
GrPixelConfig srcConfig, DrawPreference*,
|
||||
WritePixelTempDrawInfo*) = 0;
|
||||
|
||||
virtual bool onReadPixels(GrRenderTarget* target,
|
||||
int left, int top, int width, int height,
|
||||
GrPixelConfig,
|
||||
|
@ -146,15 +146,14 @@ public:
|
||||
fCaps.reset(SkNEW_ARGS(GrCaps, (options)));
|
||||
}
|
||||
~MockGpu() override {}
|
||||
bool canWriteTexturePixels(const GrTexture*, GrPixelConfig srcConfig) const override {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool onGetReadPixelsInfo(GrSurface* srcSurface, int readWidth, int readHeight, size_t rowBytes,
|
||||
bool getReadPixelsInfo(GrSurface* srcSurface, int readWidth, int readHeight, size_t rowBytes,
|
||||
GrPixelConfig readConfig, DrawPreference*,
|
||||
ReadPixelTempDrawInfo*) override { return false; }
|
||||
|
||||
bool onGetWritePixelsInfo(GrSurface* dstSurface, int width, int height, size_t rowBytes,
|
||||
GrPixelConfig srcConfig, DrawPreference*,
|
||||
WritePixelTempDrawInfo*) override { return false; }
|
||||
|
||||
void buildProgramDesc(GrProgramDesc*,const GrPrimitiveProcessor&,
|
||||
const GrPipeline&,
|
||||
const GrBatchTracker&) const override {}
|
||||
|
@ -268,6 +268,38 @@ void GrGLGpu::contextAbandoned() {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GrPixelConfig GrGLGpu::preferredWritePixelsConfig(GrPixelConfig writeConfig,
|
||||
GrPixelConfig surfaceConfig) const {
|
||||
if (GR_GL_RGBA_8888_PIXEL_OPS_SLOW && kRGBA_8888_GrPixelConfig == writeConfig) {
|
||||
return kBGRA_8888_GrPixelConfig;
|
||||
} else {
|
||||
return writeConfig;
|
||||
}
|
||||
}
|
||||
|
||||
bool GrGLGpu::canWriteTexturePixels(const GrTexture* texture, GrPixelConfig srcConfig) const {
|
||||
if (kIndex_8_GrPixelConfig == srcConfig || kIndex_8_GrPixelConfig == texture->config()) {
|
||||
return false;
|
||||
}
|
||||
if (srcConfig != texture->config() && kGLES_GrGLStandard == this->glStandard()) {
|
||||
// In general ES2 requires the internal format of the texture and the format of the src
|
||||
// pixels to match. However, It may or may not be possible to upload BGRA data to a RGBA
|
||||
// texture. It depends upon which extension added BGRA. The Apple extension allows it
|
||||
// (BGRA's internal format is RGBA) while the EXT extension does not (BGRA is its own
|
||||
// internal format).
|
||||
if (this->glCaps().isConfigTexturable(kBGRA_8888_GrPixelConfig) &&
|
||||
!this->glCaps().bgraIsInternalFormat() &&
|
||||
kBGRA_8888_GrPixelConfig == srcConfig &&
|
||||
kRGBA_8888_GrPixelConfig == texture->config()) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void GrGLGpu::onResetContext(uint32_t resetBits) {
|
||||
// we don't use the zb at all
|
||||
if (resetBits & kMisc_GrGLBackendState) {
|
||||
@ -505,53 +537,6 @@ GrRenderTarget* GrGLGpu::onWrapBackendRenderTarget(const GrBackendRenderTargetDe
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool GrGLGpu::onGetWritePixelsInfo(GrSurface* dstSurface, int width, int height,
|
||||
size_t rowBytes, GrPixelConfig srcConfig,
|
||||
DrawPreference* drawPreference,
|
||||
WritePixelTempDrawInfo* tempDrawInfo) {
|
||||
if (kIndex_8_GrPixelConfig == srcConfig || GrPixelConfigIsCompressed(dstSurface->config())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
tempDrawInfo->fSwapRAndB = false;
|
||||
|
||||
// These settings we will always want if a temp draw is performed. Initially set the config
|
||||
// to srcConfig, though that may be modified if we decide to do a R/G swap.
|
||||
tempDrawInfo->fTempSurfaceDesc.fFlags = kNone_GrSurfaceFlags;
|
||||
tempDrawInfo->fTempSurfaceDesc.fConfig = srcConfig;
|
||||
tempDrawInfo->fTempSurfaceDesc.fWidth = width;
|
||||
tempDrawInfo->fTempSurfaceDesc.fHeight = height;
|
||||
tempDrawInfo->fTempSurfaceDesc.fSampleCnt = 0;
|
||||
tempDrawInfo->fTempSurfaceDesc.fOrigin = kTopLeft_GrSurfaceOrigin; // no CPU y-flip for TL.
|
||||
|
||||
bool configsAreRBSwaps = GrPixelConfigSwapRAndB(srcConfig) == dstSurface->config();
|
||||
|
||||
if (configsAreRBSwaps) {
|
||||
if (!this->caps()->isConfigTexturable(srcConfig)) {
|
||||
ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
|
||||
tempDrawInfo->fTempSurfaceDesc.fConfig = dstSurface->config();
|
||||
tempDrawInfo->fSwapRAndB = true;
|
||||
} else if (GR_GL_RGBA_8888_PIXEL_OPS_SLOW && kRGBA_8888_GrPixelConfig == srcConfig) {
|
||||
ElevateDrawPreference(drawPreference, kGpuPrefersDraw_DrawPreference);
|
||||
tempDrawInfo->fTempSurfaceDesc.fConfig = dstSurface->config();
|
||||
tempDrawInfo->fSwapRAndB = true;
|
||||
} else if (kGLES_GrGLStandard == this->glStandard() &&
|
||||
this->glCaps().bgraIsInternalFormat()) {
|
||||
// The internal format and external formats must match texture uploads so we can't
|
||||
// swizzle while uploading when BGRA is a distinct internal format.
|
||||
ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
|
||||
tempDrawInfo->fTempSurfaceDesc.fConfig = dstSurface->config();
|
||||
tempDrawInfo->fSwapRAndB = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!this->glCaps().unpackFlipYSupport() &&
|
||||
kBottomLeft_GrSurfaceOrigin == dstSurface->origin()) {
|
||||
ElevateDrawPreference(drawPreference, kGpuPrefersDraw_DrawPreference);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GrGLGpu::onWriteTexturePixels(GrTexture* texture,
|
||||
int left, int top, int width, int height,
|
||||
@ -1719,9 +1704,21 @@ static bool read_pixels_pays_for_y_flip(GrRenderTarget* renderTarget, const GrGL
|
||||
return caps.packRowLengthSupport() || GrBytesPerPixel(config) * width == rowBytes;
|
||||
}
|
||||
|
||||
bool GrGLGpu::onGetReadPixelsInfo(GrSurface* srcSurface, int width, int height, size_t rowBytes,
|
||||
void elevate_draw_preference(GrGpu::DrawPreference* preference, GrGpu::DrawPreference elevation) {
|
||||
GR_STATIC_ASSERT(GrGpu::kCallerPrefersDraw_DrawPreference > GrGpu::kNoDraw_DrawPreference);
|
||||
GR_STATIC_ASSERT(GrGpu::kGpuPrefersDraw_DrawPreference >
|
||||
GrGpu::kCallerPrefersDraw_DrawPreference);
|
||||
GR_STATIC_ASSERT(GrGpu::kRequireDraw_DrawPreference > GrGpu::kGpuPrefersDraw_DrawPreference);
|
||||
*preference = SkTMax(*preference, elevation);
|
||||
}
|
||||
|
||||
bool GrGLGpu::getReadPixelsInfo(GrSurface* srcSurface, int width, int height, size_t rowBytes,
|
||||
GrPixelConfig readConfig, DrawPreference* drawPreference,
|
||||
ReadPixelTempDrawInfo* tempDrawInfo) {
|
||||
SkASSERT(drawPreference);
|
||||
SkASSERT(tempDrawInfo);
|
||||
SkASSERT(kGpuPrefersDraw_DrawPreference != *drawPreference);
|
||||
|
||||
if (GrPixelConfigIsCompressed(readConfig)) {
|
||||
return false;
|
||||
}
|
||||
@ -1753,23 +1750,26 @@ bool GrGLGpu::onGetReadPixelsInfo(GrSurface* srcSurface, int width, int height,
|
||||
// Better to do a draw with a R/B swap and then read as the original config.
|
||||
tempDrawInfo->fTempSurfaceDesc.fConfig = srcConfig;
|
||||
tempDrawInfo->fSwapRAndB = true;
|
||||
ElevateDrawPreference(drawPreference, kGpuPrefersDraw_DrawPreference);
|
||||
elevate_draw_preference(drawPreference, kGpuPrefersDraw_DrawPreference);
|
||||
} else if (readConfig == kBGRA_8888_GrPixelConfig &&
|
||||
!this->glCaps().readPixelsSupported(this->glInterface(), GR_GL_BGRA,
|
||||
GR_GL_UNSIGNED_BYTE, srcConfig)) {
|
||||
tempDrawInfo->fTempSurfaceDesc.fConfig = kRGBA_8888_GrPixelConfig;
|
||||
tempDrawInfo->fSwapRAndB = true;
|
||||
ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
|
||||
elevate_draw_preference(drawPreference, kRequireDraw_DrawPreference);
|
||||
}
|
||||
|
||||
GrRenderTarget* srcAsRT = srcSurface->asRenderTarget();
|
||||
if (!srcAsRT) {
|
||||
ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
|
||||
elevate_draw_preference(drawPreference, kRequireDraw_DrawPreference);
|
||||
} else if (read_pixels_pays_for_y_flip(srcAsRT, this->glCaps(), width, height, readConfig,
|
||||
rowBytes)) {
|
||||
ElevateDrawPreference(drawPreference, kGpuPrefersDraw_DrawPreference);
|
||||
elevate_draw_preference(drawPreference, kGpuPrefersDraw_DrawPreference);
|
||||
}
|
||||
|
||||
if (kRequireDraw_DrawPreference == *drawPreference && !srcSurface->asTexture()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -57,13 +57,15 @@ public:
|
||||
// Used by GrGLProgram to configure OpenGL state.
|
||||
void bindTexture(int unitIdx, const GrTextureParams& params, GrGLTexture* texture);
|
||||
|
||||
bool onGetReadPixelsInfo(GrSurface* srcSurface, int readWidth, int readHeight, size_t rowBytes,
|
||||
bool getReadPixelsInfo(GrSurface* srcSurface, int readWidth, int readHeight, size_t rowBytes,
|
||||
GrPixelConfig readConfig, DrawPreference*,
|
||||
ReadPixelTempDrawInfo*) override;
|
||||
|
||||
bool onGetWritePixelsInfo(GrSurface* dstSurface, int width, int height,
|
||||
size_t rowBytes, GrPixelConfig srcConfig, DrawPreference*,
|
||||
WritePixelTempDrawInfo*) override;
|
||||
|
||||
// GrGpu overrides
|
||||
GrPixelConfig preferredWritePixelsConfig(GrPixelConfig writeConfig,
|
||||
GrPixelConfig surfaceConfig) const override;
|
||||
bool canWriteTexturePixels(const GrTexture*, GrPixelConfig srcConfig) const override;
|
||||
|
||||
bool initCopySurfaceDstDesc(const GrSurface* src, GrSurfaceDesc* desc) const override;
|
||||
|
||||
|
@ -27,7 +27,7 @@ static const SkRect DEV_RECT_S = SkRect::MakeWH(DEV_W * SK_Scalar1,
|
||||
DEV_H * SK_Scalar1);
|
||||
static const U8CPU DEV_PAD = 0xee;
|
||||
|
||||
static SkPMColor get_canvas_color(int x, int y) {
|
||||
static SkPMColor getCanvasColor(int x, int y) {
|
||||
SkASSERT(x >= 0 && x < DEV_W);
|
||||
SkASSERT(y >= 0 && y < DEV_H);
|
||||
|
||||
@ -57,7 +57,7 @@ static SkPMColor get_canvas_color(int x, int y) {
|
||||
}
|
||||
|
||||
// assumes any premu/.unpremul has been applied
|
||||
static uint32_t pack_color_type(SkColorType ct, U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
|
||||
static uint32_t packColorType(SkColorType ct, U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
|
||||
uint32_t r32;
|
||||
uint8_t* result = reinterpret_cast<uint8_t*>(&r32);
|
||||
switch (ct) {
|
||||
@ -80,7 +80,7 @@ static uint32_t pack_color_type(SkColorType ct, U8CPU a, U8CPU r, U8CPU g, U8CPU
|
||||
return r32;
|
||||
}
|
||||
|
||||
static uint32_t get_bitmap_color(int x, int y, int w, SkColorType ct, SkAlphaType at) {
|
||||
static uint32_t getBitmapColor(int x, int y, int w, SkColorType ct, SkAlphaType at) {
|
||||
int n = y * w + x;
|
||||
U8CPU b = n & 0xff;
|
||||
U8CPU g = (n >> 8) & 0xff;
|
||||
@ -108,16 +108,16 @@ static uint32_t get_bitmap_color(int x, int y, int w, SkColorType ct, SkAlphaTyp
|
||||
g = SkMulDiv255Ceiling(g, a);
|
||||
b = SkMulDiv255Ceiling(b, a);
|
||||
}
|
||||
return pack_color_type(ct, a, r, g , b);
|
||||
return packColorType(ct, a, r, g , b);
|
||||
}
|
||||
|
||||
static void fill_canvas(SkCanvas* canvas) {
|
||||
static void fillCanvas(SkCanvas* canvas) {
|
||||
SkBitmap bmp;
|
||||
if (bmp.isNull()) {
|
||||
bmp.allocN32Pixels(DEV_W, DEV_H);
|
||||
for (int y = 0; y < DEV_H; ++y) {
|
||||
for (int x = 0; x < DEV_W; ++x) {
|
||||
*bmp.getAddr32(x, y) = get_canvas_color(x, y);
|
||||
*bmp.getAddr32(x, y) = getCanvasColor(x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -164,7 +164,7 @@ static SkPMColor convert_to_PMColor(SkColorType ct, SkAlphaType at, uint32_t col
|
||||
return color;
|
||||
}
|
||||
|
||||
static bool check_pixel(SkPMColor a, SkPMColor b, bool didPremulConversion) {
|
||||
static bool checkPixel(SkPMColor a, SkPMColor b, bool didPremulConversion) {
|
||||
if (!didPremulConversion) {
|
||||
return a == b;
|
||||
}
|
||||
@ -219,21 +219,21 @@ static bool check_write(skiatest::Reporter* reporter, SkCanvas* canvas, const Sk
|
||||
if (writeRect.contains(cx, cy)) {
|
||||
int bx = cx - writeX;
|
||||
int by = cy - writeY;
|
||||
uint32_t bmpColor8888 = get_bitmap_color(bx, by, bitmap.width(),
|
||||
uint32_t bmpColor8888 = getBitmapColor(bx, by, bitmap.width(),
|
||||
bmInfo.colorType(), bmInfo.alphaType());
|
||||
bool mul = (kUnpremul_SkAlphaType == bmInfo.alphaType());
|
||||
SkPMColor bmpPMColor = convert_to_PMColor(bmInfo.colorType(), bmInfo.alphaType(),
|
||||
bmpColor8888);
|
||||
if (!check_pixel(bmpPMColor, canvasPixel, mul)) {
|
||||
ERRORF(reporter, "Expected canvas pixel at %d, %d to be 0x%08x, got 0x%08x. "
|
||||
"Write performed premul: %d", cx, cy, bmpPMColor, canvasPixel, mul);
|
||||
bool check = checkPixel(bmpPMColor, canvasPixel, mul);
|
||||
REPORTER_ASSERT(reporter, check);
|
||||
if (!check) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
SkPMColor testColor = get_canvas_color(cx, cy);
|
||||
if (canvasPixel != testColor) {
|
||||
ERRORF(reporter, "Canvas pixel outside write rect at %d, %d changed."
|
||||
" Should be 0x%08x, got 0x%08x. ", cx, cy, testColor, canvasPixel);
|
||||
bool check;
|
||||
SkPMColor testColor = getCanvasColor(cx, cy);
|
||||
REPORTER_ASSERT(reporter, check = (canvasPixel == testColor));
|
||||
if (!check) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -282,7 +282,7 @@ static const CanvasConfig gCanvasConfigs[] = {
|
||||
// a custom pixelRef (which also has to specify its rowBytes), so we have to be
|
||||
// sure that the two rowBytes match (and the infos match).
|
||||
//
|
||||
static bool alloc_row_bytes(SkBitmap* bm, const SkImageInfo& info, size_t rowBytes) {
|
||||
static bool allocRowBytes(SkBitmap* bm, const SkImageInfo& info, size_t rowBytes) {
|
||||
if (!bm->setInfo(info, rowBytes)) {
|
||||
return false;
|
||||
}
|
||||
@ -328,13 +328,13 @@ static SkSurface* create_surface(const CanvasConfig& c, GrContext* grCtx) {
|
||||
static bool setup_bitmap(SkBitmap* bm, SkColorType ct, SkAlphaType at, int w, int h, int tightRB) {
|
||||
size_t rowBytes = tightRB ? 0 : 4 * w + 60;
|
||||
SkImageInfo info = SkImageInfo::Make(w, h, ct, at);
|
||||
if (!alloc_row_bytes(bm, info, rowBytes)) {
|
||||
if (!allocRowBytes(bm, info, rowBytes)) {
|
||||
return false;
|
||||
}
|
||||
SkAutoLockPixels alp(*bm);
|
||||
for (int y = 0; y < h; ++y) {
|
||||
for (int x = 0; x < w; ++x) {
|
||||
*bm->getAddr32(x, y) = get_bitmap_color(x, y, w, ct, at);
|
||||
*bm->getAddr32(x, y) = getBitmapColor(x, y, w, ct, at);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@ -451,7 +451,7 @@ DEF_GPUTEST(WritePixels, reporter, factory) {
|
||||
const SkColorType ct = gSrcConfigs[c].fColorType;
|
||||
const SkAlphaType at = gSrcConfigs[c].fAlphaType;
|
||||
|
||||
fill_canvas(&canvas);
|
||||
fillCanvas(&canvas);
|
||||
SkBitmap bmp;
|
||||
REPORTER_ASSERT(reporter, setup_bitmap(&bmp, ct, at, rect.width(),
|
||||
rect.height(), SkToBool(tightBmp)));
|
||||
|
Loading…
Reference in New Issue
Block a user