michael@0: michael@0: /* michael@0: * Copyright 2011 Google Inc. michael@0: * michael@0: * Use of this source code is governed by a BSD-style license that can be michael@0: * found in the LICENSE file. michael@0: */ michael@0: michael@0: michael@0: michael@0: #ifndef SkGPipePriv_DEFINED michael@0: #define SkGPipePriv_DEFINED michael@0: michael@0: #include "SkTypes.h" michael@0: michael@0: #define UNIMPLEMENTED michael@0: michael@0: // these must be contiguous, 0...N-1 michael@0: enum PaintFlats { michael@0: kColorFilter_PaintFlat, michael@0: kDrawLooper_PaintFlat, michael@0: kImageFilter_PaintFlat, michael@0: kMaskFilter_PaintFlat, michael@0: kPathEffect_PaintFlat, michael@0: kRasterizer_PaintFlat, michael@0: kShader_PaintFlat, michael@0: kXfermode_PaintFlat, michael@0: michael@0: kLast_PaintFlat = kXfermode_PaintFlat michael@0: }; michael@0: #define kCount_PaintFlats (kLast_PaintFlat + 1) michael@0: michael@0: enum DrawOps { michael@0: kSkip_DrawOp, // skip an addition N bytes (N == data) michael@0: michael@0: // these match Canvas apis michael@0: kClipPath_DrawOp, michael@0: kClipRegion_DrawOp, michael@0: kClipRect_DrawOp, michael@0: kClipRRect_DrawOp, michael@0: kConcat_DrawOp, michael@0: kDrawBitmap_DrawOp, michael@0: kDrawBitmapMatrix_DrawOp, michael@0: kDrawBitmapNine_DrawOp, michael@0: kDrawBitmapRectToRect_DrawOp, michael@0: kDrawClear_DrawOp, michael@0: kDrawData_DrawOp, michael@0: kDrawDRRect_DrawOp, michael@0: kDrawOval_DrawOp, michael@0: kDrawPaint_DrawOp, michael@0: kDrawPath_DrawOp, michael@0: kDrawPicture_DrawOp, michael@0: kDrawPoints_DrawOp, michael@0: kDrawPosText_DrawOp, michael@0: kDrawPosTextH_DrawOp, michael@0: kDrawRect_DrawOp, michael@0: kDrawRRect_DrawOp, michael@0: kDrawSprite_DrawOp, michael@0: kDrawText_DrawOp, michael@0: kDrawTextOnPath_DrawOp, michael@0: kDrawVertices_DrawOp, michael@0: kRestore_DrawOp, michael@0: kRotate_DrawOp, michael@0: kSave_DrawOp, michael@0: kSaveLayer_DrawOp, michael@0: kScale_DrawOp, michael@0: kSetMatrix_DrawOp, michael@0: kSkew_DrawOp, michael@0: kTranslate_DrawOp, michael@0: michael@0: kPaintOp_DrawOp, michael@0: kSetTypeface_DrawOp, michael@0: kSetAnnotation_DrawOp, michael@0: michael@0: kDef_Typeface_DrawOp, michael@0: kDef_Flattenable_DrawOp, michael@0: kDef_Bitmap_DrawOp, michael@0: kDef_Factory_DrawOp, michael@0: michael@0: // these are signals to playback, not drawing verbs michael@0: kReportFlags_DrawOp, michael@0: kShareBitmapHeap_DrawOp, michael@0: kDone_DrawOp, michael@0: }; michael@0: michael@0: /** michael@0: * DrawOp packs into a 32bit int as follows michael@0: * michael@0: * DrawOp:8 - Flags:4 - Data:20 michael@0: * michael@0: * Flags and Data are called out separately, so we can reuse Data between michael@0: * different Ops that might have different Flags. e.g. Data might be a Paint michael@0: * index for both drawRect (no flags) and saveLayer (does have flags). michael@0: * michael@0: * All Ops that take a SkPaint use their Data field to store the index to michael@0: * the paint (previously defined with kPaintOp_DrawOp). michael@0: */ michael@0: michael@0: #define DRAWOPS_OP_BITS 8 michael@0: #define DRAWOPS_FLAG_BITS 4 michael@0: #define DRAWOPS_DATA_BITS 20 michael@0: michael@0: #define DRAWOPS_OP_MASK ((1 << DRAWOPS_OP_BITS) - 1) michael@0: #define DRAWOPS_FLAG_MASK ((1 << DRAWOPS_FLAG_BITS) - 1) michael@0: #define DRAWOPS_DATA_MASK ((1 << DRAWOPS_DATA_BITS) - 1) michael@0: michael@0: static inline unsigned DrawOp_unpackOp(uint32_t op32) { michael@0: return (op32 >> (DRAWOPS_FLAG_BITS + DRAWOPS_DATA_BITS)); michael@0: } michael@0: michael@0: static inline unsigned DrawOp_unpackFlags(uint32_t op32) { michael@0: return (op32 >> DRAWOPS_DATA_BITS) & DRAWOPS_FLAG_MASK; michael@0: } michael@0: michael@0: static inline unsigned DrawOp_unpackData(uint32_t op32) { michael@0: return op32 & DRAWOPS_DATA_MASK; michael@0: } michael@0: michael@0: static inline uint32_t DrawOp_packOpFlagData(DrawOps op, unsigned flags, unsigned data) { michael@0: SkASSERT(0 == (op & ~DRAWOPS_OP_MASK)); michael@0: SkASSERT(0 == (flags & ~DRAWOPS_FLAG_MASK)); michael@0: SkASSERT(0 == (data & ~DRAWOPS_DATA_MASK)); michael@0: michael@0: return (op << (DRAWOPS_FLAG_BITS + DRAWOPS_DATA_BITS)) | michael@0: (flags << DRAWOPS_DATA_BITS) | michael@0: data; michael@0: } michael@0: michael@0: /** DrawOp specific flag bits michael@0: */ michael@0: michael@0: enum { michael@0: kSaveLayer_HasBounds_DrawOpFlag = 1 << 0, michael@0: kSaveLayer_HasPaint_DrawOpFlag = 1 << 1, michael@0: }; michael@0: enum { michael@0: kClear_HasColor_DrawOpFlag = 1 << 0 michael@0: }; michael@0: enum { michael@0: kDrawTextOnPath_HasMatrix_DrawOpFlag = 1 << 0 michael@0: }; michael@0: enum { michael@0: kDrawVertices_HasTexs_DrawOpFlag = 1 << 0, michael@0: kDrawVertices_HasColors_DrawOpFlag = 1 << 1, michael@0: kDrawVertices_HasIndices_DrawOpFlag = 1 << 2, michael@0: kDrawVertices_HasXfermode_DrawOpFlag = 1 << 3, michael@0: }; michael@0: enum { michael@0: kDrawBitmap_HasPaint_DrawOpFlag = 1 << 0, michael@0: // Specific to drawBitmapRect, but needs to be different from HasPaint, michael@0: // which is used for all drawBitmap calls, so include it here. michael@0: kDrawBitmap_HasSrcRect_DrawOpFlag = 1 << 1, michael@0: // SkCanvas::DrawBitmapRectFlags::kBleed_DrawBitmapRectFlag is michael@0: // converted into and out of this flag to save space michael@0: kDrawBitmap_Bleed_DrawOpFlag = 1 << 2, michael@0: }; michael@0: enum { michael@0: kClip_HasAntiAlias_DrawOpFlag = 1 << 0, michael@0: }; michael@0: /////////////////////////////////////////////////////////////////////////////// michael@0: michael@0: class BitmapInfo : SkNoncopyable { michael@0: public: michael@0: BitmapInfo(SkBitmap* bitmap, uint32_t genID, int toBeDrawnCount) michael@0: : fBitmap(bitmap) michael@0: , fGenID(genID) michael@0: , fBytesAllocated(0) michael@0: , fMoreRecentlyUsed(NULL) michael@0: , fLessRecentlyUsed(NULL) michael@0: , fToBeDrawnCount(toBeDrawnCount) michael@0: {} michael@0: michael@0: ~BitmapInfo() { michael@0: SkASSERT(0 == fToBeDrawnCount); michael@0: SkDELETE(fBitmap); michael@0: } michael@0: michael@0: void addDraws(int drawsToAdd) { michael@0: if (0 == fToBeDrawnCount) { michael@0: // The readers will only ever decrement the count, so once the michael@0: // count is zero, the writer will be the only one modifying it, michael@0: // so it does not need to be an atomic operation. michael@0: fToBeDrawnCount = drawsToAdd; michael@0: } else { michael@0: sk_atomic_add(&fToBeDrawnCount, drawsToAdd); michael@0: } michael@0: } michael@0: michael@0: void decDraws() { michael@0: sk_atomic_dec(&fToBeDrawnCount); michael@0: } michael@0: michael@0: int drawCount() const { michael@0: return fToBeDrawnCount; michael@0: } michael@0: michael@0: SkBitmap* fBitmap; michael@0: // Store the generation ID of the original bitmap, since copying does michael@0: // not copy this field, so fBitmap's generation ID will not be useful michael@0: // for comparing. michael@0: // FIXME: Is it reasonable to make copying a bitmap/pixelref copy the michael@0: // generation ID? michael@0: uint32_t fGenID; michael@0: // Keep track of the bytes allocated for this bitmap. When replacing the michael@0: // bitmap or removing this BitmapInfo we know how much memory has been michael@0: // reclaimed. michael@0: size_t fBytesAllocated; michael@0: // TODO: Generalize the LRU caching mechanism michael@0: BitmapInfo* fMoreRecentlyUsed; michael@0: BitmapInfo* fLessRecentlyUsed; michael@0: private: michael@0: int fToBeDrawnCount; michael@0: }; michael@0: michael@0: static inline bool shouldFlattenBitmaps(uint32_t flags) { michael@0: return SkToBool(flags & SkGPipeWriter::kCrossProcess_Flag michael@0: && !(flags & SkGPipeWriter::kSharedAddressSpace_Flag)); michael@0: } michael@0: michael@0: /////////////////////////////////////////////////////////////////////////////// michael@0: michael@0: enum PaintOps { michael@0: kReset_PaintOp, // no arg michael@0: michael@0: kFlags_PaintOp, // arg inline michael@0: kColor_PaintOp, // arg 32 michael@0: kStyle_PaintOp, // arg inline michael@0: kJoin_PaintOp, // arg inline michael@0: kCap_PaintOp, // arg inline michael@0: kWidth_PaintOp, // arg scalar michael@0: kMiter_PaintOp, // arg scalar michael@0: michael@0: kEncoding_PaintOp, // arg inline - text michael@0: kHinting_PaintOp, // arg inline - text michael@0: kAlign_PaintOp, // arg inline - text michael@0: kTextSize_PaintOp, // arg scalar - text michael@0: kTextScaleX_PaintOp,// arg scalar - text michael@0: kTextSkewX_PaintOp, // arg scalar - text michael@0: kTypeface_PaintOp, // arg inline (index) - text michael@0: michael@0: kFlatIndex_PaintOp, // flags=paintflat, data=index michael@0: }; michael@0: michael@0: #define PAINTOPS_OP_BITS 8 michael@0: #define PAINTOPS_FLAG_BITS 4 michael@0: #define PAINTOPS_DATA_BITS 20 michael@0: michael@0: #define PAINTOPS_OP_MASK ((1 << PAINTOPS_OP_BITS) - 1) michael@0: #define PAINTOPS_FLAG_MASK ((1 << PAINTOPS_FLAG_BITS) - 1) michael@0: #define PAINTOPS_DATA_MASK ((1 << PAINTOPS_DATA_BITS) - 1) michael@0: michael@0: static inline unsigned PaintOp_unpackOp(uint32_t op32) { michael@0: return (op32 >> (PAINTOPS_FLAG_BITS + PAINTOPS_DATA_BITS)); michael@0: } michael@0: michael@0: static inline unsigned PaintOp_unpackFlags(uint32_t op32) { michael@0: return (op32 >> PAINTOPS_DATA_BITS) & PAINTOPS_FLAG_MASK; michael@0: } michael@0: michael@0: static inline unsigned PaintOp_unpackData(uint32_t op32) { michael@0: return op32 & PAINTOPS_DATA_MASK; michael@0: } michael@0: michael@0: static inline uint32_t PaintOp_packOp(PaintOps op) { michael@0: SkASSERT(0 == (op & ~PAINTOPS_OP_MASK)); michael@0: michael@0: return op << (PAINTOPS_FLAG_BITS + PAINTOPS_DATA_BITS); michael@0: } michael@0: michael@0: static inline uint32_t PaintOp_packOpData(PaintOps op, unsigned data) { michael@0: SkASSERT(0 == (op & ~PAINTOPS_OP_MASK)); michael@0: SkASSERT(0 == (data & ~PAINTOPS_DATA_MASK)); michael@0: michael@0: return (op << (PAINTOPS_FLAG_BITS + PAINTOPS_DATA_BITS)) | data; michael@0: } michael@0: michael@0: static inline uint32_t PaintOp_packOpFlagData(PaintOps op, unsigned flags, unsigned data) { michael@0: SkASSERT(0 == (op & ~PAINTOPS_OP_MASK)); michael@0: SkASSERT(0 == (flags & ~PAINTOPS_FLAG_MASK)); michael@0: SkASSERT(0 == (data & ~PAINTOPS_DATA_MASK)); michael@0: michael@0: return (op << (PAINTOPS_FLAG_BITS + PAINTOPS_DATA_BITS)) | michael@0: (flags << PAINTOPS_DATA_BITS) | michael@0: data; michael@0: } michael@0: michael@0: #endif