024c151cea9fb73a146f5269d96c66e300827e3c
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / image / SkSurface_Gpu.cpp
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 #include "SkSurface_Base.h"
9 #include "SkImagePriv.h"
10 #include "SkCanvas.h"
11 #include "SkGpuDevice.h"
12
13 class SkSurface_Gpu : public SkSurface_Base {
14 public:
15     SK_DECLARE_INST_COUNT(SkSurface_Gpu)
16
17     SkSurface_Gpu(GrRenderTarget*, bool cached, const SkSurfaceProps*, bool doClear);
18     virtual ~SkSurface_Gpu();
19
20     virtual SkCanvas* onNewCanvas() SK_OVERRIDE;
21     virtual SkSurface* onNewSurface(const SkImageInfo&) SK_OVERRIDE;
22     virtual SkImage* onNewImageSnapshot() SK_OVERRIDE;
23     virtual void onDraw(SkCanvas*, SkScalar x, SkScalar y,
24                         const SkPaint*) SK_OVERRIDE;
25     virtual void onCopyOnWrite(ContentChangeMode) SK_OVERRIDE;
26     virtual void onDiscard() SK_OVERRIDE;
27
28 private:
29     SkGpuDevice* fDevice;
30
31     typedef SkSurface_Base INHERITED;
32 };
33
34 ///////////////////////////////////////////////////////////////////////////////
35
36 SkSurface_Gpu::SkSurface_Gpu(GrRenderTarget* renderTarget, bool cached, const SkSurfaceProps* props,
37                              bool doClear)
38         : INHERITED(renderTarget->width(), renderTarget->height(), props)
39 {
40     int deviceFlags = 0;
41     deviceFlags |= cached ? SkGpuDevice::kCached_Flag : 0;
42     deviceFlags |= this->props().isUseDistanceFieldFonts() ? SkGpuDevice::kDFFonts_Flag : 0;
43     fDevice = SkGpuDevice::Create(renderTarget, this->props(), deviceFlags);
44
45     if (kRGB_565_GrPixelConfig != renderTarget->config() && doClear) {
46         fDevice->clear(0x0);
47     }
48 }
49
50 SkSurface_Gpu::~SkSurface_Gpu() {
51     SkSafeUnref(fDevice);
52 }
53
54 SkCanvas* SkSurface_Gpu::onNewCanvas() {
55     SkCanvas::InitFlags flags = SkCanvas::kDefault_InitFlags;
56     // When we think this works...
57 //    flags |= SkCanvas::kConservativeRasterClip_InitFlag;
58
59     return SkNEW_ARGS(SkCanvas, (fDevice, &this->props(), flags));
60 }
61
62 SkSurface* SkSurface_Gpu::onNewSurface(const SkImageInfo& info) {
63     GrRenderTarget* rt = fDevice->accessRenderTarget();
64     int sampleCount = rt->numSamples();
65     return SkSurface::NewRenderTarget(fDevice->context(), info, sampleCount, &this->props());
66 }
67
68 SkImage* SkSurface_Gpu::onNewImageSnapshot() {
69     return SkImage::NewTexture(fDevice->accessBitmap(false));
70 }
71
72 void SkSurface_Gpu::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y,
73                               const SkPaint* paint) {
74     canvas->drawBitmap(fDevice->accessBitmap(false), x, y, paint);
75 }
76
77 // Create a new SkGpuDevice and, if necessary, copy the contents of the old
78 // device into it. Note that this flushes the SkGpuDevice but
79 // doesn't force an OpenGL flush.
80 void SkSurface_Gpu::onCopyOnWrite(ContentChangeMode mode) {
81     GrRenderTarget* rt = fDevice->accessRenderTarget();
82     // are we sharing our render target with the image?
83     SkASSERT(this->getCachedImage());
84     if (rt->asTexture() == SkTextureImageGetTexture(this->getCachedImage())) {
85         // We call createCompatibleDevice because it uses the texture cache. This isn't
86         // necessarily correct (http://skbug.com/2252), but never using the cache causes
87         // a Chromium regression. (http://crbug.com/344020)
88         SkGpuDevice* newDevice = static_cast<SkGpuDevice*>(
89             fDevice->createCompatibleDevice(fDevice->imageInfo()));
90         SkAutoTUnref<SkGpuDevice> aurd(newDevice);
91         if (kRetain_ContentChangeMode == mode) {
92             fDevice->context()->copyTexture(rt->asTexture(), newDevice->accessRenderTarget());
93         }
94         SkASSERT(this->getCachedCanvas());
95         SkASSERT(this->getCachedCanvas()->getDevice() == fDevice);
96
97         this->getCachedCanvas()->setRootDevice(newDevice);
98         SkRefCnt_SafeAssign(fDevice, newDevice);
99     } else if (kDiscard_ContentChangeMode == mode) {
100         this->SkSurface_Gpu::onDiscard();
101     }
102 }
103
104 void SkSurface_Gpu::onDiscard() {
105     fDevice->accessRenderTarget()->discard();
106 }
107
108 ///////////////////////////////////////////////////////////////////////////////
109
110 SkSurface* SkSurface::NewRenderTargetDirect(GrRenderTarget* target, const SkSurfaceProps* props) {
111     if (NULL == target) {
112         return NULL;
113     }
114     return SkNEW_ARGS(SkSurface_Gpu, (target, false, props, false));
115 }
116
117 SkSurface* SkSurface::NewRenderTarget(GrContext* ctx, const SkImageInfo& info, int sampleCount,
118                                       const SkSurfaceProps* props) {
119     if (NULL == ctx) {
120         return NULL;
121     }
122
123     GrTextureDesc desc;
124     desc.fFlags = kRenderTarget_GrTextureFlagBit | kCheckAllocation_GrTextureFlagBit;
125     desc.fWidth = info.width();
126     desc.fHeight = info.height();
127     desc.fConfig = SkImageInfo2GrPixelConfig(info);
128     desc.fSampleCnt = sampleCount;
129
130     SkAutoTUnref<GrTexture> tex(ctx->createUncachedTexture(desc, NULL, 0));
131     if (NULL == tex) {
132         return NULL;
133     }
134
135     return SkNEW_ARGS(SkSurface_Gpu, (tex->asRenderTarget(), false, props, true));
136 }
137
138 SkSurface* SkSurface::NewScratchRenderTarget(GrContext* ctx, const SkImageInfo& info,
139                                              int sampleCount, const SkSurfaceProps* props) {
140     if (NULL == ctx) {
141         return NULL;
142     }
143
144     GrTextureDesc desc;
145     desc.fFlags = kRenderTarget_GrTextureFlagBit | kCheckAllocation_GrTextureFlagBit;
146     desc.fWidth = info.width();
147     desc.fHeight = info.height();
148     desc.fConfig = SkImageInfo2GrPixelConfig(info);
149     desc.fSampleCnt = sampleCount;
150
151     SkAutoTUnref<GrTexture> tex(ctx->lockAndRefScratchTexture(desc, GrContext::kExact_ScratchTexMatch));
152
153     if (NULL == tex) {
154         return NULL;
155     }
156
157     return SkNEW_ARGS(SkSurface_Gpu, (tex->asRenderTarget(), true, props, true));
158 }