diff options
author | 2014-10-02 10:42:24 -0700 | |
---|---|---|
committer | 2014-10-02 10:42:24 -0700 | |
commit | cf99b00980b6c9c557e71abf1a7c9f9b21217262 (patch) | |
tree | 78d53c2e98762fb6e810603c104d03e356c26876 /src | |
parent | f0e2154b45ab2bb0d7fa5a9d38955260ce42831c (diff) |
GrContext::copyTexture->GrContext::copySurface.
Add a flush writes pixel ops flag.
Add an explicit flush writes for GrSurface.
BUG=skia:2977
Review URL: https://codereview.chromium.org/622663002
Diffstat (limited to 'src')
-rwxr-xr-x | src/gpu/GrContext.cpp | 65 | ||||
-rw-r--r-- | src/gpu/GrSurface.cpp | 6 | ||||
-rw-r--r-- | src/gpu/SkGrPixelRef.cpp | 28 | ||||
-rw-r--r-- | src/image/SkSurface_Gpu.cpp | 2 |
4 files changed, 61 insertions, 40 deletions
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp index 46a5576b11..d0f3cc5671 100755 --- a/src/gpu/GrContext.cpp +++ b/src/gpu/GrContext.cpp @@ -1374,6 +1374,8 @@ bool GrContext::writeTexturePixels(GrTexture* texture, return fGpu->writeTexturePixels(texture, left, top, width, height, config, buffer, rowBytes); + + // No need to check the kFlushWrites flag here since we issued the write directly to fGpu. } bool GrContext::readTexturePixels(GrTexture* texture, @@ -1403,7 +1405,8 @@ bool GrContext::readTexturePixels(GrTexture* texture, ast.set(this, desc, kExact_ScratchTexMatch); GrTexture* dst = ast.texture(); if (dst && (target = dst->asRenderTarget())) { - this->copyTexture(texture, target, NULL); + this->copySurface(target, texture, SkIRect::MakeXYWH(top, left, width, height), + SkIPoint::Make(0,0)); return this->readRenderTargetPixels(target, left, top, width, height, config, buffer, rowBytes, @@ -1591,29 +1594,26 @@ void GrContext::discardRenderTarget(GrRenderTarget* renderTarget) { target->discard(renderTarget); } -void GrContext::copyTexture(GrTexture* src, GrRenderTarget* dst, const SkIPoint* topLeft) { +void GrContext::copySurface(GrSurface* dst, GrSurface* src, const SkIRect& srcRect, + const SkIPoint& dstPoint, uint32_t pixelOpsFlags) { if (NULL == src || NULL == dst) { return; } ASSERT_OWNED_RESOURCE(src); ASSERT_OWNED_RESOURCE(dst); - SkIRect srcRect = SkIRect::MakeWH(dst->width(), dst->height()); - if (topLeft) { - srcRect.offset(*topLeft); - } - SkIRect srcBounds = SkIRect::MakeWH(src->width(), src->height()); - if (!srcRect.intersect(srcBounds)) { - return; - } + // Since we're going to the draw target and not GPU, no need to check kNoFlush + // here. GrDrawTarget* target = this->prepareToDraw(NULL, BUFFERED_DRAW, NULL, NULL); if (NULL == target) { return; } - SkIPoint dstPoint; - dstPoint.setZero(); target->copySurface(dst, src, srcRect, dstPoint); + + if (kFlushWrites_PixelOp & pixelOpsFlags) { + this->flush(); + } } bool GrContext::writeRenderTargetPixels(GrRenderTarget* renderTarget, @@ -1621,7 +1621,7 @@ bool GrContext::writeRenderTargetPixels(GrRenderTarget* renderTarget, GrPixelConfig srcConfig, const void* buffer, size_t rowBytes, - uint32_t flags) { + uint32_t pixelOpsFlags) { ASSERT_OWNED_RESOURCE(renderTarget); if (NULL == renderTarget) { @@ -1646,11 +1646,11 @@ bool GrContext::writeRenderTargetPixels(GrRenderTarget* renderTarget, // At least some drivers on the Mac get confused when glTexImage2D is called on a texture // attached to an FBO. The FBO still sees the old image. TODO: determine what OS versions and/or // HW is affected. - if (renderTarget->asTexture() && !(kUnpremul_PixelOpsFlag & flags) && + if (renderTarget->asTexture() && !(kUnpremul_PixelOpsFlag & pixelOpsFlags) && fGpu->canWriteTexturePixels(renderTarget->asTexture(), srcConfig)) { return this->writeTexturePixels(renderTarget->asTexture(), left, top, width, height, - srcConfig, buffer, rowBytes, flags); + srcConfig, buffer, rowBytes, pixelOpsFlags); } #endif @@ -1683,7 +1683,7 @@ bool GrContext::writeRenderTargetPixels(GrRenderTarget* renderTarget, // allocate a tmp buffer and sw convert the pixels to premul SkAutoSTMalloc<128 * 128, uint32_t> tmpPixels(0); - if (kUnpremul_PixelOpsFlag & flags) { + if (kUnpremul_PixelOpsFlag & pixelOpsFlags) { if (!GrPixelConfigIs8888(srcConfig)) { return false; } @@ -1724,25 +1724,42 @@ bool GrContext::writeRenderTargetPixels(GrRenderTarget* renderTarget, if (!this->writeTexturePixels(texture, 0, 0, width, height, writeConfig, buffer, rowBytes, - flags & ~kUnpremul_PixelOpsFlag)) { + pixelOpsFlags & ~kUnpremul_PixelOpsFlag)) { return false; } SkMatrix matrix; matrix.setTranslate(SkIntToScalar(left), SkIntToScalar(top)); + // This function can be called in the midst of drawing another object (e.g., when uploading a // SW-rasterized clip while issuing a draw). So we push the current geometry state before // drawing a rect to the render target. - GrDrawTarget* drawTarget = this->prepareToDraw(NULL, kYes_BufferedDraw, NULL, NULL); - GrDrawTarget::AutoGeometryAndStatePush agasp(drawTarget, GrDrawTarget::kReset_ASRInit, &matrix); - GrDrawState* drawState = drawTarget->drawState(); - drawState->addColorProcessor(fp); - drawState->setRenderTarget(renderTarget); - drawState->disableState(GrDrawState::kClip_StateBit); - drawTarget->drawSimpleRect(SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height))); + // The bracket ensures we pop the stack if we wind up flushing below. + { + GrDrawTarget* drawTarget = this->prepareToDraw(NULL, kYes_BufferedDraw, NULL, NULL); + GrDrawTarget::AutoGeometryAndStatePush agasp(drawTarget, GrDrawTarget::kReset_ASRInit, + &matrix); + GrDrawState* drawState = drawTarget->drawState(); + drawState->addColorProcessor(fp); + drawState->setRenderTarget(renderTarget); + drawState->disableState(GrDrawState::kClip_StateBit); + drawTarget->drawSimpleRect(SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height))); + } + + if (kFlushWrites_PixelOp & pixelOpsFlags) { + this->flush(); + } + return true; } + +void GrContext::flushSurfaceWrites(GrSurface* surface) { + if (surface->surfacePriv().hasPendingWrite()) { + this->flush(); + } +} + //////////////////////////////////////////////////////////////////////////////// GrDrawTarget* GrContext::prepareToDraw(const GrPaint* paint, diff --git a/src/gpu/GrSurface.cpp b/src/gpu/GrSurface.cpp index 37fd73f4f4..d067f07d0d 100644 --- a/src/gpu/GrSurface.cpp +++ b/src/gpu/GrSurface.cpp @@ -48,6 +48,12 @@ bool GrSurface::savePixels(const char* filename) { return true; } +void GrSurface::flushWrites() { + if (!this->wasDestroyed()) { + this->getContext()->flushSurfaceWrites(this); + } +} + bool GrSurface::hasPendingRead() const { const GrTexture* thisTex = this->asTexture(); if (thisTex && thisTex->internalHasPendingRead()) { diff --git a/src/gpu/SkGrPixelRef.cpp b/src/gpu/SkGrPixelRef.cpp index fcf22e350b..0fe219f6f0 100644 --- a/src/gpu/SkGrPixelRef.cpp +++ b/src/gpu/SkGrPixelRef.cpp @@ -64,19 +64,18 @@ static SkGrPixelRef* copy_to_new_texture_pixelref(GrTexture* texture, SkColorTyp } GrTextureDesc desc; - SkIPoint pointStorage; - SkIPoint* topLeft; - if (subset != NULL) { + SkIRect srcRect; + + if (!subset) { + desc.fWidth = texture->width(); + desc.fHeight = texture->height(); + srcRect = SkIRect::MakeWH(texture->width(), texture->height()); + } else { SkASSERT(SkIRect::MakeWH(texture->width(), texture->height()).contains(*subset)); // Create a new texture that is the size of subset. desc.fWidth = subset->width(); desc.fHeight = subset->height(); - pointStorage.set(subset->x(), subset->y()); - topLeft = &pointStorage; - } else { - desc.fWidth = texture->width(); - desc.fHeight = texture->height(); - topLeft = NULL; + srcRect = *subset; } desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit; desc.fConfig = SkImageInfo2GrPixelConfig(dstCT, kPremul_SkAlphaType); @@ -86,13 +85,12 @@ static SkGrPixelRef* copy_to_new_texture_pixelref(GrTexture* texture, SkColorTyp return NULL; } - context->copyTexture(texture, dst->asRenderTarget(), topLeft); - // Blink is relying on the above copy being sent to GL immediately in the case when the source - // is a WebGL canvas backing store. We could have a TODO to remove this flush, but we have a - // larger TODO to remove SkGrPixelRef entirely. - context->flush(); - + // is a WebGL canvas backing store. We could have a TODO to remove this flush flag, but we have + // a larger TODO to remove SkGrPixelRef entirely. + context->copySurface(texture, dst->asRenderTarget(), srcRect, SkIPoint::Make(0,0), + GrContext::kFlushWrites_PixelOp); + SkImageInfo info = SkImageInfo::Make(desc.fWidth, desc.fHeight, dstCT, kPremul_SkAlphaType); SkGrPixelRef* pixelRef = SkNEW_ARGS(SkGrPixelRef, (info, dst)); SkSafeUnref(dst); diff --git a/src/image/SkSurface_Gpu.cpp b/src/image/SkSurface_Gpu.cpp index 024c151cea..fb087ea24b 100644 --- a/src/image/SkSurface_Gpu.cpp +++ b/src/image/SkSurface_Gpu.cpp @@ -89,7 +89,7 @@ void SkSurface_Gpu::onCopyOnWrite(ContentChangeMode mode) { fDevice->createCompatibleDevice(fDevice->imageInfo())); SkAutoTUnref<SkGpuDevice> aurd(newDevice); if (kRetain_ContentChangeMode == mode) { - fDevice->context()->copyTexture(rt->asTexture(), newDevice->accessRenderTarget()); + fDevice->context()->copySurface(newDevice->accessRenderTarget(), rt->asTexture()); } SkASSERT(this->getCachedCanvas()); SkASSERT(this->getCachedCanvas()->getDevice() == fDevice); |