diff options
-rwxr-xr-x | src/gpu/GrContext.cpp | 168 | ||||
-rw-r--r-- | src/gpu/GrGpu.cpp | 55 | ||||
-rw-r--r-- | src/gpu/GrGpu.h | 64 | ||||
-rw-r--r-- | src/gpu/GrTest.cpp | 13 | ||||
-rw-r--r-- | src/gpu/gl/GrGLGpu.cpp | 108 | ||||
-rw-r--r-- | src/gpu/gl/GrGLGpu.h | 14 | ||||
-rw-r--r-- | tests/WritePixelsTest.cpp | 38 |
7 files changed, 197 insertions, 263 deletions
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp index 9e1d904dca..1db2cbe627 100755 --- a/src/gpu/GrContext.cpp +++ b/src/gpu/GrContext.cpp @@ -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 (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)) { + // 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; } - if (!(kDontFlush_PixelOpsFlag & pixelOpsFlags) && surface->surfacePriv().hasPendingIO()) { - this->flush(); + // 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<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; - } - } + SkAutoTUnref<const GrFragmentProcessor> fp; + SkMatrix textureMatrix; + textureMatrix.setIDiv(texture->width(), texture->height()); - 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) { - 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); + // allocate a tmp buffer and sw convert the pixels to premul + SkAutoSTMalloc<128 * 128, uint32_t> tmpPixels(0); - if (kFlushWrites_PixelOp & pixelOpsFlags) { - this->flushSurfaceWrites(surface); - } + GrPaint paint; + if (kUnpremul_PixelOpsFlag & pixelOpsFlags) { + if (!GrPixelConfigIs8888(srcConfig)) { + return false; } - } - 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) { + 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) { 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; } diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp index c61979bbfb..728fb88062 100644 --- a/src/gpu/GrGpu.cpp +++ b/src/gpu/GrGpu.cpp @@ -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, diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h index 8bb676d779..857efd0d65 100644 --- a/src/gpu/GrGpu.h +++ b/src/gpu/GrGpu.h @@ -133,7 +133,7 @@ public: */ void resolveRenderTarget(GrRenderTarget* target); - /** Info struct returned by getReadPixelsInfo about performing intermediate draws before + /** Info struct returned by getReadPixelsInfo about performing intermediate draws before reading pixels for performance or correctness. */ struct ReadPixelTempDrawInfo { /** If the GrGpu is requesting that the caller do a draw to an intermediate surface then @@ -173,39 +173,28 @@ public: kRequireDraw_DrawPreference }; + /** 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 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. + * 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 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; - }; + virtual GrPixelConfig preferredWritePixelsConfig(GrPixelConfig writeConfig, + GrPixelConfig surfaceConfig) const { + return writeConfig; + } /** - * 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. + * Called before uploading writing pixels to a GrTexture when the src pixel config doesn't + * match the texture's config. */ - bool getWritePixelsInfo(GrSurface* dstSurface, int width, int height, size_t rowBytes, - GrPixelConfig srcConfig, DrawPreference*, WritePixelTempDrawInfo*); + 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, diff --git a/src/gpu/GrTest.cpp b/src/gpu/GrTest.cpp index fd2908eb76..c6902d006f 100644 --- a/src/gpu/GrTest.cpp +++ b/src/gpu/GrTest.cpp @@ -146,14 +146,13 @@ 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, - 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; } + bool getReadPixelsInfo(GrSurface* srcSurface, int readWidth, int readHeight, size_t rowBytes, + GrPixelConfig readConfig, DrawPreference*, + ReadPixelTempDrawInfo*) override { return false; } void buildProgramDesc(GrProgramDesc*,const GrPrimitiveProcessor&, const GrPipeline&, diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp index 41cf62c66d..101bb216f4 100644 --- a/src/gpu/gl/GrGLGpu.cpp +++ b/src/gpu/gl/GrGLGpu.cpp @@ -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, - GrPixelConfig readConfig, DrawPreference* drawPreference, - ReadPixelTempDrawInfo* tempDrawInfo) { +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; } diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h index 0442e1109b..066a237e59 100644 --- a/src/gpu/gl/GrGLGpu.h +++ b/src/gpu/gl/GrGLGpu.h @@ -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, - GrPixelConfig readConfig, DrawPreference*, - ReadPixelTempDrawInfo*) override; + 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; diff --git a/tests/WritePixelsTest.cpp b/tests/WritePixelsTest.cpp index a06130e36b..fa99d4c9ec 100644 --- a/tests/WritePixelsTest.cpp +++ b/tests/WritePixelsTest.cpp @@ -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))); |