2 * Copyright 2012 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
8 #include "SkSurface_Base.h"
9 #include "SkImagePriv.h"
11 #include "SkGpuDevice.h"
13 class SkSurface_Gpu : public SkSurface_Base {
15 SK_DECLARE_INST_COUNT(SkSurface_Gpu)
17 SkSurface_Gpu(GrRenderTarget*, bool cached, TextRenderMode trm,
18 SkSurface::RenderTargetFlags flags);
19 virtual ~SkSurface_Gpu();
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;
32 typedef SkSurface_Base INHERITED;
35 ///////////////////////////////////////////////////////////////////////////////
37 SkSurface_Gpu::SkSurface_Gpu(GrRenderTarget* renderTarget, bool cached, TextRenderMode trm,
38 SkSurface::RenderTargetFlags flags)
39 : INHERITED(renderTarget->width(), renderTarget->height()) {
41 deviceFlags |= cached ? SkGpuDevice::kCached_Flag : 0;
42 deviceFlags |= (kDistanceField_TextRenderMode == trm) ? SkGpuDevice::kDFFonts_Flag : 0;
43 fDevice = SkGpuDevice::Create(renderTarget, deviceFlags);
45 if (kRGB_565_GrPixelConfig != renderTarget->config() &&
46 !(flags & kDontClear_RenderTargetFlag)) {
51 SkSurface_Gpu::~SkSurface_Gpu() {
55 SkCanvas* SkSurface_Gpu::onNewCanvas() {
56 return SkNEW_ARGS(SkCanvas, (fDevice));
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);
65 SkImage* SkSurface_Gpu::onNewImageSnapshot() {
66 return SkImage::NewTexture(fDevice->accessBitmap(false));
69 void SkSurface_Gpu::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y,
70 const SkPaint* paint) {
71 canvas->drawBitmap(fDevice->accessBitmap(false), x, y, paint);
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());
91 SkASSERT(NULL != this->getCachedCanvas());
92 SkASSERT(this->getCachedCanvas()->getDevice() == fDevice);
94 this->getCachedCanvas()->setRootDevice(newDevice);
95 SkRefCnt_SafeAssign(fDevice, newDevice);
96 } else if (kDiscard_ContentChangeMode == mode) {
97 this->SkSurface_Gpu::onDiscard();
101 void SkSurface_Gpu::onDiscard() {
102 fDevice->accessRenderTarget()->discard();
105 ///////////////////////////////////////////////////////////////////////////////
107 SkSurface* SkSurface::NewRenderTargetDirect(GrRenderTarget* target, TextRenderMode trm,
108 RenderTargetFlags flags) {
109 if (NULL == target) {
112 return SkNEW_ARGS(SkSurface_Gpu, (target, false, trm, flags));
115 SkSurface* SkSurface::NewRenderTarget(GrContext* ctx, const SkImageInfo& info, int sampleCount,
116 TextRenderMode trm, RenderTargetFlags flags) {
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;
128 SkAutoTUnref<GrTexture> tex(ctx->createUncachedTexture(desc, NULL, 0));
133 return SkNEW_ARGS(SkSurface_Gpu, (tex->asRenderTarget(), false, trm, flags));
136 SkSurface* SkSurface::NewScratchRenderTarget(GrContext* ctx, const SkImageInfo& info,
137 int sampleCount, TextRenderMode trm,
138 RenderTargetFlags flags) {
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;
150 SkAutoTUnref<GrTexture> tex(ctx->lockAndRefScratchTexture(desc, GrContext::kExact_ScratchTexMatch));
156 return SkNEW_ARGS(SkSurface_Gpu, (tex->asRenderTarget(), true, trm, flags));