aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rwxr-xr-xsrc/gpu/GrContext.cpp168
-rw-r--r--src/gpu/GrGpu.cpp55
-rw-r--r--src/gpu/GrGpu.h64
-rw-r--r--src/gpu/GrTest.cpp13
-rw-r--r--src/gpu/gl/GrGLGpu.cpp108
-rw-r--r--src/gpu/gl/GrGLGpu.h14
-rw-r--r--tests/WritePixelsTest.cpp38
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)));