1/*
2 * Copyright 2012 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef GrSWMaskHelper_DEFINED
9#define GrSWMaskHelper_DEFINED
10
11#include "GrColor.h"
12#include "GrDrawState.h"
13#include "SkBitmap.h"
14#include "SkDraw.h"
15#include "SkMatrix.h"
16#include "SkRasterClip.h"
17#include "SkRegion.h"
18#include "SkTextureCompressor.h"
19#include "SkTypes.h"
20
21class GrAutoScratchTexture;
22class GrContext;
23class GrTexture;
24class SkPath;
25class SkStrokeRec;
26class GrDrawTarget;
27
28/**
29 * The GrSWMaskHelper helps generate clip masks using the software rendering
30 * path. It is intended to be used as:
31 *
32 *   GrSWMaskHelper helper(context);
33 *   helper.init(...);
34 *
35 *      draw one or more paths/rects specifying the required boolean ops
36 *
37 *   toTexture();   // to get it from the internal bitmap to the GPU
38 *
39 * The result of this process will be the final mask (on the GPU) in the
40 * upper left hand corner of the texture.
41 */
42class GrSWMaskHelper : SkNoncopyable {
43public:
44    GrSWMaskHelper(GrContext* context)
45    : fContext(context)
46    , fCompressionMode(kNone_CompressionMode) {
47    }
48
49    // set up the internal state in preparation for draws. Since many masks
50    // may be accumulated in the helper during creation, "resultBounds"
51    // allows the caller to specify the region of interest - to limit the
52    // amount of work. allowCompression should be set to false if you plan on using
53    // your own texture to draw into, and not a scratch texture via getTexture().
54    bool init(const SkIRect& resultBounds, const SkMatrix* matrix, bool allowCompression = true);
55
56    // Draw a single rect into the accumulation bitmap using the specified op
57    void draw(const SkRect& rect, SkRegion::Op op,
58              bool antiAlias, uint8_t alpha);
59
60    // Draw a single path into the accumuation bitmap using the specified op
61    void draw(const SkPath& path, const SkStrokeRec& stroke, SkRegion::Op op,
62              bool antiAlias, uint8_t alpha);
63
64    // Helper function to get a scratch texture suitable for capturing the
65    // result (i.e., right size & format)
66    bool getTexture(GrAutoScratchTexture* texture);
67
68    // Move the mask generation results from the internal bitmap to the gpu.
69    void toTexture(GrTexture* texture);
70
71    // Reset the internal bitmap
72    void clear(uint8_t alpha) {
73        fBM.eraseColor(SkColorSetARGB(alpha, alpha, alpha, alpha));
74    }
75
76    // Canonical usage utility that draws a single path and uploads it
77    // to the GPU. The result is returned in "result".
78    static GrTexture* DrawPathMaskToTexture(GrContext* context,
79                                            const SkPath& path,
80                                            const SkStrokeRec& stroke,
81                                            const SkIRect& resultBounds,
82                                            bool antiAlias,
83                                            SkMatrix* matrix);
84
85    // This utility routine is used to add a path's mask to some other draw.
86    // The ClipMaskManager uses it to accumulate clip masks while the
87    // GrSoftwarePathRenderer uses it to fulfill a drawPath call.
88    // It draws with "texture" as a path mask into "target" using "rect" as
89    // geometry and the current drawState. The current drawState is altered to
90    // accommodate the mask.
91    // Note that this method assumes that the GrPaint::kTotalStages slot in
92    // the draw state can be used to hold the mask texture stage.
93    // This method is really only intended to be used with the
94    // output of DrawPathMaskToTexture.
95    static void DrawToTargetWithPathMask(GrTexture* texture,
96                                         GrDrawTarget* target,
97                                         const SkIRect& rect);
98
99private:
100    GrContext*      fContext;
101    SkMatrix        fMatrix;
102    SkBitmap        fBM;
103    SkDraw          fDraw;
104    SkRasterClip    fRasterClip;
105
106    // This enum says whether or not we should compress the mask:
107    // kNone_CompressionMode: compression is not supported on this device.
108    // kCompress_CompressionMode: compress the bitmap before it gets sent to the gpu
109    // kBlitter_CompressionMode: write to the bitmap using a special compressed blitter.
110    enum CompressionMode {
111        kNone_CompressionMode,
112        kCompress_CompressionMode,
113        kBlitter_CompressionMode,
114    } fCompressionMode;
115
116    // This is the buffer into which we store our compressed data. This buffer is
117    // only allocated (non-null) if fCompressionMode is kBlitter_CompressionMode
118    SkAutoMalloc fCompressedBuffer;
119
120    // This is the desired format within which to compress the
121    // texture. This value is only valid if fCompressionMode is not kNone_CompressionMode.
122    SkTextureCompressor::Format fCompressedFormat;
123
124    // Actually sends the texture data to the GPU. This is called from
125    // toTexture with the data filled in depending on the texture config.
126    void sendTextureData(GrTexture *texture, const GrTextureDesc& desc,
127                         const void *data, int rowbytes);
128
129    // Compresses the bitmap stored in fBM and sends the compressed data
130    // to the GPU to be stored in 'texture' using sendTextureData.
131    void compressTextureData(GrTexture *texture, const GrTextureDesc& desc);
132
133    typedef SkNoncopyable INHERITED;
134};
135
136#endif // GrSWMaskHelper_DEFINED
137