Update To 11.40.268.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 #if SK_SUPPORT_GPU
14
15 class SkSurface_Gpu : public SkSurface_Base {
16 public:
17     SK_DECLARE_INST_COUNT(SkSurface_Gpu)
18
19     SkSurface_Gpu(GrRenderTarget*, const SkSurfaceProps*, bool doClear);
20     virtual ~SkSurface_Gpu();
21
22     virtual SkCanvas* onNewCanvas() SK_OVERRIDE;
23     virtual SkSurface* onNewSurface(const SkImageInfo&) SK_OVERRIDE;
24     virtual SkImage* onNewImageSnapshot() SK_OVERRIDE;
25     virtual void onDraw(SkCanvas*, SkScalar x, SkScalar y,
26                         const SkPaint*) SK_OVERRIDE;
27     virtual void onCopyOnWrite(ContentChangeMode) SK_OVERRIDE;
28     virtual void onDiscard() SK_OVERRIDE;
29
30 private:
31     SkGpuDevice* fDevice;
32
33     typedef SkSurface_Base INHERITED;
34 };
35
36 ///////////////////////////////////////////////////////////////////////////////
37
38 SkSurface_Gpu::SkSurface_Gpu(GrRenderTarget* renderTarget, const SkSurfaceProps* props,
39                              bool doClear)
40         : INHERITED(renderTarget->width(), renderTarget->height(), props) {
41     int deviceFlags = 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()->copySurface(newDevice->accessRenderTarget(), rt->asTexture());
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, 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     GrSurfaceDesc desc;
124     desc.fFlags = kRenderTarget_GrSurfaceFlag | kCheckAllocation_GrSurfaceFlag;
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(), 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     GrSurfaceDesc desc;
145     desc.fFlags = kRenderTarget_GrSurfaceFlag | kCheckAllocation_GrSurfaceFlag;
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->refScratchTexture(desc, GrContext::kExact_ScratchTexMatch));
152
153     if (NULL == tex) {
154         return NULL;
155     }
156
157     return SkNEW_ARGS(SkSurface_Gpu, (tex->asRenderTarget(), props, true));
158 }
159
160 #endif