• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(GrContext*, const SkImageInfo&, int sampleCount);
18     SkSurface_Gpu(GrContext*, GrRenderTarget*);
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 
28 private:
29     SkGpuDevice* fDevice;
30 
31     typedef SkSurface_Base INHERITED;
32 };
33 
34 ///////////////////////////////////////////////////////////////////////////////
35 
SkSurface_Gpu(GrContext * ctx,const SkImageInfo & info,int sampleCount)36 SkSurface_Gpu::SkSurface_Gpu(GrContext* ctx, const SkImageInfo& info,
37                              int sampleCount)
38         : INHERITED(info.fWidth, info.fHeight) {
39     SkBitmap::Config config = SkImageInfoToBitmapConfig(info);
40 
41     fDevice = SkNEW_ARGS(SkGpuDevice, (ctx, config, info.fWidth, info.fHeight, sampleCount));
42 
43     if (!SkAlphaTypeIsOpaque(info.fAlphaType)) {
44         fDevice->clear(0x0);
45     }
46 }
47 
SkSurface_Gpu(GrContext * ctx,GrRenderTarget * renderTarget)48 SkSurface_Gpu::SkSurface_Gpu(GrContext* ctx, GrRenderTarget* renderTarget)
49         : INHERITED(renderTarget->width(), renderTarget->height()) {
50     fDevice = SkNEW_ARGS(SkGpuDevice, (ctx, renderTarget));
51 
52     if (kRGB_565_GrPixelConfig != renderTarget->config()) {
53         fDevice->clear(0x0);
54     }
55 }
56 
~SkSurface_Gpu()57 SkSurface_Gpu::~SkSurface_Gpu() {
58     SkSafeUnref(fDevice);
59 }
60 
onNewCanvas()61 SkCanvas* SkSurface_Gpu::onNewCanvas() {
62     return SkNEW_ARGS(SkCanvas, (fDevice));
63 }
64 
onNewSurface(const SkImageInfo & info)65 SkSurface* SkSurface_Gpu::onNewSurface(const SkImageInfo& info) {
66     GrRenderTarget* rt = fDevice->accessRenderTarget();
67     int sampleCount = rt->numSamples();
68     return SkSurface::NewRenderTarget(fDevice->context(), info, sampleCount);
69 }
70 
onNewImageSnapshot()71 SkImage* SkSurface_Gpu::onNewImageSnapshot() {
72     return SkImage::NewTexture(fDevice->accessBitmap(false));
73 }
74 
onDraw(SkCanvas * canvas,SkScalar x,SkScalar y,const SkPaint * paint)75 void SkSurface_Gpu::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y,
76                               const SkPaint* paint) {
77     canvas->drawBitmap(fDevice->accessBitmap(false), x, y, paint);
78 }
79 
80 // Create a new SkGpuDevice and, if necessary, copy the contents of the old
81 // device into it. Note that this flushes the SkGpuDevice but
82 // doesn't force an OpenGL flush.
onCopyOnWrite(ContentChangeMode mode)83 void SkSurface_Gpu::onCopyOnWrite(ContentChangeMode mode) {
84     GrRenderTarget* rt = fDevice->accessRenderTarget();
85     // are we sharing our render target with the image?
86     SkASSERT(NULL != this->getCachedImage());
87     if (rt->asTexture() == SkTextureImageGetTexture(this->getCachedImage())) {
88         SkGpuDevice* newDevice = static_cast<SkGpuDevice*>(
89             fDevice->createCompatibleDevice(fDevice->config(), fDevice->width(),
90             fDevice->height(), fDevice->isOpaque()));
91         SkAutoTUnref<SkGpuDevice> aurd(newDevice);
92         if (kRetain_ContentChangeMode == mode) {
93             fDevice->context()->copyTexture(rt->asTexture(),
94                 reinterpret_cast<GrRenderTarget*>(newDevice->accessRenderTarget()));
95         }
96         SkASSERT(NULL != this->getCachedCanvas());
97         SkASSERT(this->getCachedCanvas()->getDevice() == fDevice);
98         this->getCachedCanvas()->setDevice(newDevice);
99         SkRefCnt_SafeAssign(fDevice, newDevice);
100     }
101 }
102 
103 ///////////////////////////////////////////////////////////////////////////////
104 
NewRenderTargetDirect(GrContext * ctx,GrRenderTarget * target)105 SkSurface* SkSurface::NewRenderTargetDirect(GrContext* ctx,
106                                             GrRenderTarget* target) {
107     if (NULL == ctx || NULL == target) {
108         return NULL;
109     }
110 
111     return SkNEW_ARGS(SkSurface_Gpu, (ctx, target));
112 }
113 
NewRenderTarget(GrContext * ctx,const SkImageInfo & info,int sampleCount)114 SkSurface* SkSurface::NewRenderTarget(GrContext* ctx, const SkImageInfo& info, int sampleCount) {
115     if (NULL == ctx) {
116         return NULL;
117     }
118 
119     SkBitmap::Config config = SkImageInfoToBitmapConfig(info);
120 
121     GrTextureDesc desc;
122     desc.fFlags = kRenderTarget_GrTextureFlagBit | kCheckAllocation_GrTextureFlagBit;
123     desc.fWidth = info.fWidth;
124     desc.fHeight = info.fHeight;
125     desc.fConfig = SkBitmapConfig2GrPixelConfig(config);
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, (ctx, tex->asRenderTarget()));
134 }
135