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"
15 class SkSurface_Gpu : public SkSurface_Base {
17 SK_DECLARE_INST_COUNT(SkSurface_Gpu)
19 SkSurface_Gpu(GrRenderTarget*, const SkSurfaceProps*, bool doClear);
20 virtual ~SkSurface_Gpu();
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;
33 typedef SkSurface_Base INHERITED;
36 ///////////////////////////////////////////////////////////////////////////////
38 SkSurface_Gpu::SkSurface_Gpu(GrRenderTarget* renderTarget, const SkSurfaceProps* props,
40 : INHERITED(renderTarget->width(), renderTarget->height(), props) {
42 deviceFlags |= this->props().isUseDistanceFieldFonts() ? SkGpuDevice::kDFFonts_Flag : 0;
43 fDevice = SkGpuDevice::Create(renderTarget, this->props(), deviceFlags);
45 if (kRGB_565_GrPixelConfig != renderTarget->config() && doClear) {
50 SkSurface_Gpu::~SkSurface_Gpu() {
54 SkCanvas* SkSurface_Gpu::onNewCanvas() {
55 SkCanvas::InitFlags flags = SkCanvas::kDefault_InitFlags;
56 // When we think this works...
57 // flags |= SkCanvas::kConservativeRasterClip_InitFlag;
59 return SkNEW_ARGS(SkCanvas, (fDevice, &this->props(), flags));
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());
68 SkImage* SkSurface_Gpu::onNewImageSnapshot() {
69 return SkImage::NewTexture(fDevice->accessBitmap(false));
72 void SkSurface_Gpu::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y,
73 const SkPaint* paint) {
74 canvas->drawBitmap(fDevice->accessBitmap(false), x, y, paint);
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());
94 SkASSERT(this->getCachedCanvas());
95 SkASSERT(this->getCachedCanvas()->getDevice() == fDevice);
97 this->getCachedCanvas()->setRootDevice(newDevice);
98 SkRefCnt_SafeAssign(fDevice, newDevice);
99 } else if (kDiscard_ContentChangeMode == mode) {
100 this->SkSurface_Gpu::onDiscard();
104 void SkSurface_Gpu::onDiscard() {
105 fDevice->accessRenderTarget()->discard();
108 ///////////////////////////////////////////////////////////////////////////////
110 SkSurface* SkSurface::NewRenderTargetDirect(GrRenderTarget* target, const SkSurfaceProps* props) {
111 if (NULL == target) {
114 return SkNEW_ARGS(SkSurface_Gpu, (target, props, false));
117 SkSurface* SkSurface::NewRenderTarget(GrContext* ctx, const SkImageInfo& info, int sampleCount,
118 const SkSurfaceProps* props) {
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;
130 SkAutoTUnref<GrTexture> tex(ctx->createUncachedTexture(desc, NULL, 0));
135 return SkNEW_ARGS(SkSurface_Gpu, (tex->asRenderTarget(), props, true));
138 SkSurface* SkSurface::NewScratchRenderTarget(GrContext* ctx, const SkImageInfo& info,
139 int sampleCount, const SkSurfaceProps* props) {
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;
151 SkAutoTUnref<GrTexture> tex(ctx->refScratchTexture(desc, GrContext::kExact_ScratchTexMatch));
157 return SkNEW_ARGS(SkSurface_Gpu, (tex->asRenderTarget(), props, true));