aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/gpu/GrContext.h44
-rw-r--r--include/gpu/GrSurface.h5
-rw-r--r--samplecode/SampleApp.cpp6
-rwxr-xr-xsrc/gpu/GrContext.cpp65
-rw-r--r--src/gpu/GrSurface.cpp6
-rw-r--r--src/gpu/SkGrPixelRef.cpp28
-rw-r--r--src/image/SkSurface_Gpu.cpp2
7 files changed, 102 insertions, 54 deletions
diff --git a/include/gpu/GrContext.h b/include/gpu/GrContext.h
index 366fba993e..4500936b82 100644
--- a/include/gpu/GrContext.h
+++ b/include/gpu/GrContext.h
@@ -597,12 +597,15 @@ public:
* These flags can be used with the read/write pixels functions below.
*/
enum PixelOpsFlags {
- /** The GrContext will not be flushed. This means that the read or write may occur before
- previous draws have executed. */
+ /** The GrContext will not be flushed before the surface read or write. This means that
+ the read or write may occur before previous draws have executed. */
kDontFlush_PixelOpsFlag = 0x1,
+ /** Any surface writes should be flushed to the backend 3D API after the surface operation
+ is complete */
+ kFlushWrites_PixelOp = 0x2,
/** The src for write or dst read is unpremultiplied. This is only respected if both the
config src and dst configs are an RGBA/BGRA 8888 format. */
- kUnpremul_PixelOpsFlag = 0x2,
+ kUnpremul_PixelOpsFlag = 0x4,
};
/**
@@ -695,15 +698,36 @@ public:
uint32_t pixelOpsFlags = 0);
/**
- * Copies a rectangle of texels from src to dst. The size of dst is the size of the rectangle
- * copied and topLeft is the position of the rect in src. The rectangle is clipped to src's
+ * Copies a rectangle of texels from src to dst.
* bounds.
- * @param src the texture to copy from.
- * @param dst the render target to copy to.
- * @param topLeft the point in src that will be copied to the top-left of dst. If NULL,
- * (0, 0) will be used.
+ * @param dst the surface to copy to.
+ * @param src the surface to copy from.
+ * @param srcRect the rectangle of the src that should be copied.
+ * @param dstPoint the translation applied when writing the srcRect's pixels to the dst.
+ * @param pixelOpsFlags see PixelOpsFlags enum above. (kUnpremul_PixelOpsFlag is not allowed).
*/
- void copyTexture(GrTexture* src, GrRenderTarget* dst, const SkIPoint* topLeft = NULL);
+ void copySurface(GrSurface* dst,
+ GrSurface* src,
+ const SkIRect& srcRect,
+ const SkIPoint& dstPoint,
+ uint32_t pixelOpsFlags = 0);
+
+ /** Helper that copies the whole surface but fails when the two surfaces are not identically
+ sized. */
+ bool copySurface(GrSurface* dst, GrSurface* src) {
+ if (NULL == dst || NULL == src || dst->width() != src->width() ||
+ dst->height() != src->height()) {
+ return false;
+ }
+ this->copySurface(dst, src, SkIRect::MakeWH(dst->width(), dst->height()),
+ SkIPoint::Make(0,0));
+ return true;
+ }
+
+ /**
+ * After this returns any pending writes to the surface will have been issued to the backend 3D API.
+ */
+ void flushSurfaceWrites(GrSurface* surface);
/**
* Resolves a render target that has MSAA. The intermediate MSAA buffer is
diff --git a/include/gpu/GrSurface.h b/include/gpu/GrSurface.h
index 23311a2f52..0bbf8d9c12 100644
--- a/include/gpu/GrSurface.h
+++ b/include/gpu/GrSurface.h
@@ -112,6 +112,11 @@ public:
size_t rowBytes = 0,
uint32_t pixelOpsFlags = 0) = 0;
+ /**
+ * After this returns any pending writes to the surface will be issued to the backend 3D API.
+ */
+ void flushWrites();
+
/** Access methods that are only to be used within Skia code. */
inline GrSurfacePriv surfacePriv();
inline const GrSurfacePriv surfacePriv() const;
diff --git a/samplecode/SampleApp.cpp b/samplecode/SampleApp.cpp
index c1905270af..e8146f0582 100644
--- a/samplecode/SampleApp.cpp
+++ b/samplecode/SampleApp.cpp
@@ -298,10 +298,8 @@ public:
SkImageInfo2GrPixelConfig(bm.colorType(),
bm.alphaType()),
bm.getPixels(),
- bm.rowBytes());
-
- // extra flush call, until Brian can figure out what's going on.
- fCurContext->flush();
+ bm.rowBytes(),
+ GrContext::kFlushWrites_PixelOp);
}
}
#endif
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..489a418ce6 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(dst->asRenderTarget(), texture, 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);