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