/*
 * Copyright 2014 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "GrPictureUtils.h"
#include "SkDevice.h"
#include "SkDraw.h"
#include "SkPaintPriv.h"
#include "SkPicturePlayback.h"

SkPicture::AccelData::Key GPUAccelData::ComputeAccelDataKey() {
    static const SkPicture::AccelData::Key gGPUID = SkPicture::AccelData::GenerateDomain();

    return gGPUID;
}

// The GrGather device performs GPU-backend-specific preprocessing on
// a picture. The results are stored in a GPUAccelData.
//
// Currently the only interesting work is done in drawDevice (i.e., when a
// saveLayer is collapsed back into its parent) and, maybe, in onCreateDevice.
// All the current work could be done much more efficiently by just traversing the
// raw op codes in the SkPicture (although we would still need to replay all the
// clip calls).
class GrGatherDevice : public SkBaseDevice {
public:
    SK_DECLARE_INST_COUNT(GrGatherDevice)

    GrGatherDevice(int width, int height, const SkPicture* picture, GPUAccelData* accelData,
                   int saveLayerDepth) {
        fPicture = picture;
        fSaveLayerDepth = saveLayerDepth;
        fInfo.fValid = true;
        fInfo.fSize.set(width, height);
        fInfo.fPaint = NULL;
        fInfo.fSaveLayerOpID = fPicture->EXPERIMENTAL_curOpID();
        fInfo.fRestoreOpID = 0;
        fInfo.fHasNestedLayers = false;
        fInfo.fIsNested = (2 == fSaveLayerDepth);

        fEmptyBitmap.setInfo(SkImageInfo::MakeUnknown(fInfo.fSize.fWidth, fInfo.fSize.fHeight));
        fAccelData = accelData;
        fAlreadyDrawn = false;
    }

    virtual ~GrGatherDevice() { }

    virtual int width() const SK_OVERRIDE { return fInfo.fSize.width(); }
    virtual int height() const SK_OVERRIDE { return fInfo.fSize.height(); }
    virtual bool isOpaque() const SK_OVERRIDE { return false; }
    virtual SkImageInfo imageInfo() const SK_OVERRIDE {
        return fEmptyBitmap.info();
    }

#ifdef SK_SUPPORT_LEGACY_WRITEPIXELSCONFIG
    virtual void writePixels(const SkBitmap& bitmap, int x, int y,
                             SkCanvas::Config8888 config8888) SK_OVERRIDE {
        NotSupported();
    }
#endif
    virtual GrRenderTarget* accessRenderTarget() SK_OVERRIDE { return NULL; }

protected:
    virtual bool filterTextFlags(const SkPaint& paint, TextFlags*) SK_OVERRIDE {
        return false;
    }
    virtual void clear(SkColor color) SK_OVERRIDE {
        NothingToDo();
    }
    virtual void drawPaint(const SkDraw& draw, const SkPaint& paint) SK_OVERRIDE {
    }
    virtual void drawPoints(const SkDraw& draw, SkCanvas::PointMode mode, size_t count,
                            const SkPoint points[], const SkPaint& paint) SK_OVERRIDE {
    }
    virtual void drawRect(const SkDraw& draw, const SkRect& rect,
                          const SkPaint& paint) SK_OVERRIDE {
    }
    virtual void drawOval(const SkDraw& draw, const SkRect& rect,
                          const SkPaint& paint) SK_OVERRIDE {
    }
    virtual void drawRRect(const SkDraw& draw, const SkRRect& rrect,
                           const SkPaint& paint) SK_OVERRIDE {
    }
    virtual void drawPath(const SkDraw& draw, const SkPath& path,
                          const SkPaint& paint, const SkMatrix* prePathMatrix,
                          bool pathIsMutable) SK_OVERRIDE {
    }
    virtual void drawBitmap(const SkDraw& draw, const SkBitmap& bitmap,
                            const SkMatrix& matrix, const SkPaint& paint) SK_OVERRIDE {
    }
    virtual void drawSprite(const SkDraw&, const SkBitmap& bitmap,
                            int x, int y, const SkPaint& paint) SK_OVERRIDE {
    }
    virtual void drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap,
                                const SkRect* srcOrNull, const SkRect& dst,
                                const SkPaint& paint,
                                SkCanvas::DrawBitmapRectFlags flags) SK_OVERRIDE {
    }
    virtual void drawText(const SkDraw& draw, const void* text, size_t len,
                          SkScalar x, SkScalar y,
                          const SkPaint& paint) SK_OVERRIDE {
    }
    virtual void drawPosText(const SkDraw& draw, const void* text, size_t len,
                             const SkScalar pos[], SkScalar constY,
                             int scalarsPerPos, const SkPaint& paint) SK_OVERRIDE {
    }
    virtual void drawTextOnPath(const SkDraw& draw, const void* text, size_t len,
                                const SkPath& path, const SkMatrix* matrix,
                                const SkPaint& paint) SK_OVERRIDE {
    }
    virtual void drawVertices(const SkDraw& draw, SkCanvas::VertexMode, int vertexCount,
                              const SkPoint verts[], const SkPoint texs[],
                              const SkColor colors[], SkXfermode* xmode,
                              const uint16_t indices[], int indexCount,
                              const SkPaint& paint) SK_OVERRIDE {
    }
    virtual void drawDevice(const SkDraw& draw, SkBaseDevice* deviceIn, int x, int y,
                            const SkPaint& paint) SK_OVERRIDE {
        // deviceIn is the one that is being "restored" back to its parent
        GrGatherDevice* device = static_cast<GrGatherDevice*>(deviceIn);

        if (device->fAlreadyDrawn) {
            return;
        }

        device->fInfo.fRestoreOpID = fPicture->EXPERIMENTAL_curOpID();
        device->fInfo.fCTM = *draw.fMatrix;
        device->fInfo.fCTM.postTranslate(SkIntToScalar(-device->getOrigin().fX),
                                         SkIntToScalar(-device->getOrigin().fY));

        device->fInfo.fOffset = device->getOrigin();

        if (NeedsDeepCopy(paint)) {
            // This NULL acts as a signal that the paint was uncopyable (for now)
            device->fInfo.fPaint = NULL;
            device->fInfo.fValid = false;
        } else {
            device->fInfo.fPaint = SkNEW_ARGS(SkPaint, (paint));
        }

        fAccelData->addSaveLayerInfo(device->fInfo);
        device->fAlreadyDrawn = true;
    }
    // TODO: allow this call to return failure, or move to SkBitmapDevice only.
    virtual const SkBitmap& onAccessBitmap() SK_OVERRIDE {
        return fEmptyBitmap;
    }
#ifdef SK_SUPPORT_LEGACY_READPIXELSCONFIG
    virtual bool onReadPixels(const SkBitmap& bitmap,
                              int x, int y,
                              SkCanvas::Config8888 config8888) SK_OVERRIDE {
        NotSupported();
        return false;
    }
#endif
    virtual void lockPixels() SK_OVERRIDE { NothingToDo(); }
    virtual void unlockPixels() SK_OVERRIDE { NothingToDo(); }
    virtual bool allowImageFilter(const SkImageFilter*) SK_OVERRIDE { return false; }
    virtual bool canHandleImageFilter(const SkImageFilter*) SK_OVERRIDE { return false; }
    virtual bool filterImage(const SkImageFilter*, const SkBitmap&, const SkImageFilter::Context&,
                             SkBitmap* result, SkIPoint* offset) SK_OVERRIDE {
        return false;
    }

private:
    // The picture being processed
    const SkPicture *fPicture;

    SkBitmap fEmptyBitmap; // legacy -- need to remove

    // All information gathered during the gather process is stored here
    GPUAccelData* fAccelData;

    // true if this device has already been drawn back to its parent(s) at least
    // once.
    bool   fAlreadyDrawn;

    // The information regarding the saveLayer call this device represents.
    GPUAccelData::SaveLayerInfo fInfo;

    // The depth of this device in the saveLayer stack
    int fSaveLayerDepth;

    virtual void replaceBitmapBackendForRasterSurface(const SkBitmap&) SK_OVERRIDE {
        NotSupported();
    }

    virtual SkBaseDevice* onCreateDevice(const SkImageInfo& info, Usage usage) SK_OVERRIDE {
        // we expect to only get called via savelayer, in which case it is fine.
        SkASSERT(kSaveLayer_Usage == usage);

        fInfo.fHasNestedLayers = true;
        return SkNEW_ARGS(GrGatherDevice, (info.width(), info.height(), fPicture,
                                           fAccelData, fSaveLayerDepth+1));
    }

    virtual void flush() SK_OVERRIDE {}

    static void NotSupported() {
        SkDEBUGFAIL("this method should never be called");
    }

    static void NothingToDo() {}

    typedef SkBaseDevice INHERITED;
};

// The GrGatherCanvas allows saveLayers but simplifies clipping. It is really
// only intended to be used as:
//
//      GrGatherDevice dev(w, h, picture, accelData);
//      GrGatherCanvas canvas(..., picture);
//      canvas.gather();
//
// which is all just to fill in 'accelData'
class SK_API GrGatherCanvas : public SkCanvas {
public:
    GrGatherCanvas(GrGatherDevice* device, const SkPicture* pict)
        : INHERITED(device)
        , fPicture(pict) {
    }

    void gather() {
        if (NULL == fPicture || 0 == fPicture->width() || 0 == fPicture->height()) {
            return;
        }

        this->clipRect(SkRect::MakeWH(SkIntToScalar(fPicture->width()),
                                      SkIntToScalar(fPicture->height())),
                       SkRegion::kIntersect_Op, false);
        this->drawPicture(fPicture);
    }

protected:
    // disable aa for speed
    virtual void onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle) SK_OVERRIDE {
        this->INHERITED::onClipRect(rect, op, kHard_ClipEdgeStyle);
    }

    // for speed, just respect the bounds, and disable AA. May give us a few
    // false positives and negatives.
    virtual void onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle) SK_OVERRIDE {
        this->updateClipConservativelyUsingBounds(path.getBounds(), op,
                                                  path.isInverseFillType());
    }
    virtual void onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle) SK_OVERRIDE {
        this->updateClipConservativelyUsingBounds(rrect.getBounds(), op, false);
    }

    virtual void onDrawPicture(const SkPicture* picture) SK_OVERRIDE {
        // BBH-based rendering doesn't re-issue many of the operations the gather
        // process cares about (e.g., saves and restores) so it must be disabled.
        if (NULL != picture->fPlayback) {
            picture->fPlayback->setUseBBH(false);
        }
        picture->draw(this);
        if (NULL != picture->fPlayback) {
            picture->fPlayback->setUseBBH(true);
        }
    }

private:
    const SkPicture* fPicture;

    typedef SkCanvas INHERITED;
};

// GatherGPUInfo is only intended to be called within the context of SkGpuDevice's
// EXPERIMENTAL_optimize method.
void GatherGPUInfo(const SkPicture* pict, GPUAccelData* accelData) {
    if (0 == pict->width() || 0 == pict->height()) {
        return ;
    }

    GrGatherDevice device(pict->width(), pict->height(), pict, accelData, 0);
    GrGatherCanvas canvas(&device, pict);

    canvas.gather();
}
