target->setClip(&fReplacementClip);
}
-bool GrDrawTarget::copySurface(GrSurface* dst,
- GrSurface* src,
+namespace {
+// returns true if the read/written rect intersects the src/dst and false if not.
+bool clip_srcrect_and_dstpoint(const GrSurface* dst,
+ const GrSurface* src,
const SkIRect& srcRect,
- const SkIPoint& dstPoint) {
- SkIRect clippedSrcRect(srcRect);
- SkIPoint clippedDstPoint(dstPoint);
+ const SkIPoint& dstPoint,
+ SkIRect* clippedSrcRect,
+ SkIPoint* clippedDstPoint) {
+ *clippedSrcRect = srcRect;
+ *clippedDstPoint = dstPoint;
- // clip the left edge to src and dst bounds, adjusting dstPoint if neceessary
- if (clippedSrcRect.fLeft < 0) {
- clippedDstPoint.fX -= clippedSrcRect.fLeft;
- clippedSrcRect.fLeft = 0;
+ // clip the left edge to src and dst bounds, adjusting dstPoint if necessary
+ if (clippedSrcRect->fLeft < 0) {
+ clippedDstPoint->fX -= clippedSrcRect->fLeft;
+ clippedSrcRect->fLeft = 0;
}
- if (clippedDstPoint.fX < 0) {
- clippedSrcRect.fLeft -= clippedDstPoint.fX;
- clippedDstPoint.fX = 0;
+ if (clippedDstPoint->fX < 0) {
+ clippedSrcRect->fLeft -= clippedDstPoint->fX;
+ clippedDstPoint->fX = 0;
}
- // clip the top edge to src and dst bounds, adjusting dstPoint if neceessary
- if (clippedSrcRect.fTop < 0) {
- clippedDstPoint.fY -= clippedSrcRect.fTop;
- clippedSrcRect.fTop = 0;
+ // clip the top edge to src and dst bounds, adjusting dstPoint if necessary
+ if (clippedSrcRect->fTop < 0) {
+ clippedDstPoint->fY -= clippedSrcRect->fTop;
+ clippedSrcRect->fTop = 0;
}
- if (clippedDstPoint.fY < 0) {
- clippedSrcRect.fTop -= clippedDstPoint.fY;
- clippedDstPoint.fY = 0;
+ if (clippedDstPoint->fY < 0) {
+ clippedSrcRect->fTop -= clippedDstPoint->fY;
+ clippedDstPoint->fY = 0;
}
// clip the right edge to the src and dst bounds.
- if (clippedSrcRect.fRight > src->width()) {
- clippedSrcRect.fRight = src->width();
+ if (clippedSrcRect->fRight > src->width()) {
+ clippedSrcRect->fRight = src->width();
}
- if (clippedDstPoint.fX + clippedSrcRect.width() > dst->width()) {
- clippedSrcRect.fRight = clippedSrcRect.fLeft + dst->width() - clippedDstPoint.fX;
+ if (clippedDstPoint->fX + clippedSrcRect->width() > dst->width()) {
+ clippedSrcRect->fRight = clippedSrcRect->fLeft + dst->width() - clippedDstPoint->fX;
}
// clip the bottom edge to the src and dst bounds.
- if (clippedSrcRect.fBottom > src->height()) {
- clippedSrcRect.fBottom = src->height();
+ if (clippedSrcRect->fBottom > src->height()) {
+ clippedSrcRect->fBottom = src->height();
}
- if (clippedDstPoint.fY + clippedSrcRect.height() > dst->height()) {
- clippedSrcRect.fBottom = clippedSrcRect.fTop + dst->height() - clippedDstPoint.fY;
+ if (clippedDstPoint->fY + clippedSrcRect->height() > dst->height()) {
+ clippedSrcRect->fBottom = clippedSrcRect->fTop + dst->height() - clippedDstPoint->fY;
}
// The above clipping steps may have inverted the rect if it didn't intersect either the src or
// dst bounds.
- if (clippedSrcRect.isEmpty()) {
+ return !clippedSrcRect->isEmpty();
+}
+}
+
+bool GrDrawTarget::copySurface(GrSurface* dst,
+ GrSurface* src,
+ const SkIRect& srcRect,
+ const SkIPoint& dstPoint) {
+ GrAssert(NULL != dst);
+ GrAssert(NULL != src);
+
+ SkIRect clippedSrcRect;
+ SkIPoint clippedDstPoint;
+ // If the rect is outside the src or dst then we've already succeeded.
+ if (!clip_srcrect_and_dstpoint(dst,
+ src,
+ srcRect,
+ dstPoint,
+ &clippedSrcRect,
+ &clippedDstPoint)) {
+ GrAssert(this->canCopySurface(dst, src, srcRect, dstPoint));
return true;
}
GrSurface* src,
const SkIRect& srcRect,
const SkIPoint& dstPoint) {
+ GrAssert(NULL != dst);
+ GrAssert(NULL != src);
+
+ SkIRect clippedSrcRect;
+ SkIPoint clippedDstPoint;
+ // If the rect is outside the src or dst then we're guaranteed success
+ if (!clip_srcrect_and_dstpoint(dst,
+ src,
+ srcRect,
+ dstPoint,
+ &clippedSrcRect,
+ &clippedDstPoint)) {
+ return true;
+ }
+ return this->onCanCopySurface(dst, src, clippedSrcRect, clippedDstPoint);
+}
+
+bool GrDrawTarget::onCanCopySurface(GrSurface* dst,
+ GrSurface* src,
+ const SkIRect& srcRect,
+ const SkIPoint& dstPoint) {
// Check that the read/write rects are contained within the src/dst bounds.
GrAssert(!srcRect.isEmpty());
GrAssert(SkIRect::MakeWH(src->width(), src->height()).contains(srcRect));
GrAssert(dstPoint.fX + srcRect.width() <= dst->width() &&
dstPoint.fY + srcRect.height() <= dst->height());
- return NULL != dst->asRenderTarget() && NULL != src->asTexture();
+ return !dst->isSameAs(src) && NULL != dst->asRenderTarget() && NULL != src->asTexture();
}
bool GrDrawTarget::onCopySurface(GrSurface* dst,
GrSurface* src,
const SkIRect& srcRect,
const SkIPoint& dstPoint) {
- if (!GrDrawTarget::canCopySurface(dst, src, srcRect, dstPoint)) {
+ if (!GrDrawTarget::onCanCopySurface(dst, src, srcRect, dstPoint)) {
return false;
}
GrSurface* src,
const SkIRect& srcRect,
const SkIPoint& dstPoint);
+ /**
+ * Function that determines whether a copySurface call would succeed without
+ * performing the copy.
+ */
+ bool canCopySurface(GrSurface* dst,
+ GrSurface* src,
+ const SkIRect& srcRect,
+ const SkIPoint& dstPoint);
/**
* Release any resources that are cached but not currently in use. This
// classes must keep this consistent with their implementation of onCopySurface(). The inputs
// are the same as onCopySurface(), i.e. srcRect and dstPoint are clipped to be inside the src
// and dst bounds.
- virtual bool canCopySurface(GrSurface* dst,
- GrSurface* src,
- const SkIRect& srcRect,
- const SkIPoint& dstPoint);
+ virtual bool onCanCopySurface(GrSurface* dst,
+ GrSurface* src,
+ const SkIRect& srcRect,
+ const SkIPoint& dstPoint);
GrContext* getContext() { return fContext; }
const GrContext* getContext() const { return fContext; }
fIndexPool.reset();
fClips.reset();
fClipOrigins.reset();
+ fCopySurfaces.reset();
fClipSet = true;
}
int currClear = 0;
int currDraw = 0;
int currStencilPath = 0;
+ int currCopySurface = 0;
for (int c = 0; c < numCmds; ++c) {
switch (fCmds[c]) {
fClears[currClear].fRenderTarget);
++currClear;
break;
+ case kCopySurface_Cmd:
+ fDstGpu->copySurface(fCopySurfaces[currCopySurface].fDst.get(),
+ fCopySurfaces[currCopySurface].fSrc.get(),
+ fCopySurfaces[currCopySurface].fSrcRect,
+ fCopySurfaces[currCopySurface].fDstPoint);
+ ++currCopySurface;
+ break;
}
}
// we should have consumed all the states, clips, etc.
GrAssert(fClipOrigins.count() == currClip);
GrAssert(fClears.count() == currClear);
GrAssert(fDraws.count() == currDraw);
+ GrAssert(fCopySurfaces.count() == currCopySurface);
fDstGpu->setDrawState(prevDrawState);
prevDrawState->unref();
return true;
}
+bool GrInOrderDrawBuffer::onCopySurface(GrSurface* dst,
+ GrSurface* src,
+ const SkIRect& srcRect,
+ const SkIPoint& dstPoint) {
+ if (fDstGpu->canCopySurface(dst, src, srcRect, dstPoint)) {
+ CopySurface* cs = this->recordCopySurface();
+ cs->fDst.reset(SkRef(dst));
+ cs->fSrc.reset(SkRef(src));
+ cs->fSrcRect = srcRect;
+ cs->fDstPoint = dstPoint;
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool GrInOrderDrawBuffer::onCanCopySurface(GrSurface* dst,
+ GrSurface* src,
+ const SkIRect& srcRect,
+ const SkIPoint& dstPoint) {
+ return fDstGpu->canCopySurface(dst, src, srcRect, dstPoint);
+}
+
void GrInOrderDrawBuffer::willReserveVertexAndIndexSpace(
int vertexCount,
int indexCount) {
return &fClears.push_back();
}
+GrInOrderDrawBuffer::CopySurface* GrInOrderDrawBuffer::recordCopySurface() {
+ fCmds.push_back(kCopySurface_Cmd);
+ return &fCopySurfaces.push_back();
+}
+
+
void GrInOrderDrawBuffer::clipWillBeSet(const GrClipData* newClipData) {
INHERITED::clipWillBeSet(newClipData);
fClipSet = true;
* responsibility to ensure that all referenced textures, buffers, and render-targets are associated
* in the GrGpu object that the buffer is played back into. The buffer requires VB and IB pools to
* store geometry.
- */
+ */
class GrInOrderDrawBuffer : public GrDrawTarget {
public:
kSetState_Cmd = 3,
kSetClip_Cmd = 4,
kClear_Cmd = 5,
+ kCopySurface_Cmd = 6,
};
class DrawRecord : public DrawInfo {
const GrIndexBuffer* fIndexBuffer;
};
- struct StencilPath {
+ struct StencilPath : GrNoncopyable {
StencilPath();
SkAutoTUnref<const GrPath> fPath;
SkPath::FillType fFill;
};
- struct Clear {
+ struct Clear : GrNoncopyable {
Clear() : fRenderTarget(NULL) {}
~Clear() { GrSafeUnref(fRenderTarget); }
GrRenderTarget* fRenderTarget;
};
+ struct CopySurface : GrNoncopyable {
+ SkAutoTUnref<GrSurface> fDst;
+ SkAutoTUnref<GrSurface> fSrc;
+ SkIRect fSrcRect;
+ SkIPoint fDstPoint;
+ };
+
// overrides from GrDrawTarget
virtual void onDraw(const DrawInfo&) SK_OVERRIDE;
virtual void onDrawRect(const GrRect& rect,
virtual void geometrySourceWillPop(const GeometrySrcState& restoredState) SK_OVERRIDE;
virtual void willReserveVertexAndIndexSpace(int vertexCount,
int indexCount) SK_OVERRIDE;
+ virtual bool onCopySurface(GrSurface* dst,
+ GrSurface* src,
+ const SkIRect& srcRect,
+ const SkIPoint& dstPoint) SK_OVERRIDE;
+ virtual bool onCanCopySurface(GrSurface* dst,
+ GrSurface* src,
+ const SkIRect& srcRect,
+ const SkIPoint& dstPoint) SK_OVERRIDE;
+
bool quickInsideClip(const SkRect& devBounds);
// Attempts to concat instances from info onto the previous draw. info must represent an
DrawRecord* recordDraw(const DrawInfo&);
StencilPath* recordStencilPath();
Clear* recordClear();
+ CopySurface* recordCopySurface();
+ // TODO: Use a single allocator for commands and records
enum {
kCmdPreallocCnt = 32,
kDrawPreallocCnt = 8,
kClipPreallocCnt = 8,
kClearPreallocCnt = 4,
kGeoPoolStatePreAllocCnt = 4,
+ kCopySurfacePreallocCnt = 4,
};
SkSTArray<kCmdPreallocCnt, uint8_t, true> fCmds;
GrSTAllocator<kStatePreallocCnt, StencilPath> fStencilPaths;
GrSTAllocator<kStatePreallocCnt, GrDrawState::DeferredState> fStates;
GrSTAllocator<kClearPreallocCnt, Clear> fClears;
-
- GrSTAllocator<kClipPreallocCnt, SkClipStack> fClips;
- GrSTAllocator<kClipPreallocCnt, SkIPoint> fClipOrigins;
+ GrSTAllocator<kCopySurfacePreallocCnt, CopySurface> fCopySurfaces;
+ GrSTAllocator<kClipPreallocCnt, SkClipStack> fClips;
+ GrSTAllocator<kClipPreallocCnt, SkIPoint> fClipOrigins;
GrDrawTarget* fDstGpu;