blob: 74fbe0b0b2bbfedf94958b3605c646631a89e600 [file] [log] [blame]
reed@google.com5d4ba882012-07-31 15:45:27 +00001/*
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"
robertphillips@google.com97b6b072012-10-31 14:48:39 +000011#include "SkGpuDevice.h"
reed@google.com5d4ba882012-07-31 15:45:27 +000012
13class SkSurface_Gpu : public SkSurface_Base {
14public:
robertphillips@google.com97b6b072012-10-31 14:48:39 +000015 SK_DECLARE_INST_COUNT(SkSurface_Gpu)
reed@google.com5d4ba882012-07-31 15:45:27 +000016
robertphillips@google.com97b6b072012-10-31 14:48:39 +000017 SkSurface_Gpu(GrContext*, const SkImage::Info&, int sampleCount);
18 SkSurface_Gpu(GrContext*, GrRenderTarget*);
19 virtual ~SkSurface_Gpu();
reed@google.com5d4ba882012-07-31 15:45:27 +000020
21 virtual SkCanvas* onNewCanvas() SK_OVERRIDE;
mike@reedtribe.orgb9476252012-11-15 02:37:45 +000022 virtual SkSurface* onNewSurface(const SkImage::Info&) SK_OVERRIDE;
reed@google.com5d4ba882012-07-31 15:45:27 +000023 virtual SkImage* onNewImageShapshot() SK_OVERRIDE;
24 virtual void onDraw(SkCanvas*, SkScalar x, SkScalar y,
25 const SkPaint*) SK_OVERRIDE;
robertphillips@google.com97b6b072012-10-31 14:48:39 +000026 virtual void onCopyOnWrite(SkImage*, SkCanvas*) SK_OVERRIDE;
reed@google.com5d4ba882012-07-31 15:45:27 +000027
28private:
robertphillips@google.com97b6b072012-10-31 14:48:39 +000029 SkGpuDevice* fDevice;
reed@google.com5d4ba882012-07-31 15:45:27 +000030
31 typedef SkSurface_Base INHERITED;
32};
33
robertphillips@google.com97b6b072012-10-31 14:48:39 +000034SK_DEFINE_INST_COUNT(SkSurface_Gpu)
35
reed@google.com5d4ba882012-07-31 15:45:27 +000036///////////////////////////////////////////////////////////////////////////////
37
robertphillips@google.com97b6b072012-10-31 14:48:39 +000038SkSurface_Gpu::SkSurface_Gpu(GrContext* ctx, const SkImage::Info& info,
39 int sampleCount)
reed@google.com5d4ba882012-07-31 15:45:27 +000040 : INHERITED(info.fWidth, info.fHeight) {
41 bool isOpaque;
42 SkBitmap::Config config = SkImageInfoToBitmapConfig(info, &isOpaque);
rmistry@google.comfbfcd562012-08-23 18:09:54 +000043
robertphillips@google.com97b6b072012-10-31 14:48:39 +000044 fDevice = SkNEW_ARGS(SkGpuDevice, (ctx, config, info.fWidth, info.fHeight, sampleCount));
robertphillips@google.comea5d8af2012-11-02 17:38:28 +000045
46 if (!isOpaque) {
47 fDevice->clear(0x0);
48 }
reed@google.com5d4ba882012-07-31 15:45:27 +000049}
50
robertphillips@google.com97b6b072012-10-31 14:48:39 +000051SkSurface_Gpu::SkSurface_Gpu(GrContext* ctx, GrRenderTarget* renderTarget)
52 : INHERITED(renderTarget->width(), renderTarget->height()) {
53 fDevice = SkNEW_ARGS(SkGpuDevice, (ctx, renderTarget));
robertphillips@google.comea5d8af2012-11-02 17:38:28 +000054
55 if (kRGB_565_GrPixelConfig != renderTarget->config()) {
56 fDevice->clear(0x0);
57 }
robertphillips@google.com97b6b072012-10-31 14:48:39 +000058}
reed@google.com5d4ba882012-07-31 15:45:27 +000059
robertphillips@google.com97b6b072012-10-31 14:48:39 +000060SkSurface_Gpu::~SkSurface_Gpu() {
61 SkSafeUnref(fDevice);
reed@google.com5d4ba882012-07-31 15:45:27 +000062}
63
64SkCanvas* SkSurface_Gpu::onNewCanvas() {
robertphillips@google.com97b6b072012-10-31 14:48:39 +000065 return SkNEW_ARGS(SkCanvas, (fDevice));
reed@google.com5d4ba882012-07-31 15:45:27 +000066}
67
mike@reedtribe.orgb9476252012-11-15 02:37:45 +000068SkSurface* SkSurface_Gpu::onNewSurface(const SkImage::Info& info) {
robertphillips@google.com97b6b072012-10-31 14:48:39 +000069 GrRenderTarget* rt = (GrRenderTarget*) fDevice->accessRenderTarget();
70 int sampleCount = rt->numSamples();
mike@reedtribe.orgb9476252012-11-15 02:37:45 +000071 return SkSurface::NewRenderTarget(fDevice->context(), info, sampleCount);
reed@google.com5d4ba882012-07-31 15:45:27 +000072}
73
74SkImage* SkSurface_Gpu::onNewImageShapshot() {
robertphillips@google.com97b6b072012-10-31 14:48:39 +000075
76 GrRenderTarget* rt = (GrRenderTarget*) fDevice->accessRenderTarget();
77
78 return SkImage::NewTexture(rt->asTexture());
reed@google.com5d4ba882012-07-31 15:45:27 +000079}
80
81void SkSurface_Gpu::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y,
82 const SkPaint* paint) {
robertphillips@google.com97b6b072012-10-31 14:48:39 +000083 canvas->drawBitmap(fDevice->accessBitmap(false), x, y, paint);
84}
85
86// Copy the contents of the SkGpuDevice into a new texture and give that
87// texture to the SkImage. Note that this flushes the SkGpuDevice but
88// doesn't force an OpenGL flush.
89void SkSurface_Gpu::onCopyOnWrite(SkImage* image, SkCanvas* canvas) {
90 GrRenderTarget* rt = (GrRenderTarget*) fDevice->accessRenderTarget();
91
92 // are we sharing our render target with the image?
93 if (rt->asTexture() == SkTextureImageGetTexture(image)) {
94 GrTextureDesc desc;
95 // copyTexture requires a render target as the destination
96 desc.fFlags = kRenderTarget_GrTextureFlagBit;
97 desc.fWidth = fDevice->width();
98 desc.fHeight = fDevice->height();
99 desc.fConfig = SkBitmapConfig2GrPixelConfig(fDevice->config());
100 desc.fSampleCnt = 0;
101
robertphillips@google.com671eac62012-11-01 17:31:02 +0000102 SkAutoTUnref<GrTexture> tex(fDevice->context()->createUncachedTexture(desc, NULL, 0));
robertphillips@google.com97b6b072012-10-31 14:48:39 +0000103 if (NULL == tex) {
104 SkTextureImageSetTexture(image, NULL);
105 return;
106 }
skia.committer@gmail.comf3dc1992012-11-01 02:01:27 +0000107
robertphillips@google.com97b6b072012-10-31 14:48:39 +0000108 fDevice->context()->copyTexture(rt->asTexture(), tex->asRenderTarget());
109
110 SkTextureImageSetTexture(image, tex);
111 }
reed@google.com5d4ba882012-07-31 15:45:27 +0000112}
113
114///////////////////////////////////////////////////////////////////////////////
115
116SkSurface* SkSurface::NewRenderTargetDirect(GrContext* ctx,
117 GrRenderTarget* target) {
118 if (NULL == ctx || NULL == target) {
119 return NULL;
120 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000121
reed@google.com5d4ba882012-07-31 15:45:27 +0000122 return SkNEW_ARGS(SkSurface_Gpu, (ctx, target));
123}
124
mike@reedtribe.orgb9476252012-11-15 02:37:45 +0000125SkSurface* SkSurface::NewRenderTarget(GrContext* ctx, const SkImage::Info& info, int sampleCount) {
reed@google.com5d4ba882012-07-31 15:45:27 +0000126 if (NULL == ctx) {
127 return NULL;
128 }
robertphillips@google.com97b6b072012-10-31 14:48:39 +0000129
130 bool isOpaque;
131 SkBitmap::Config config = SkImageInfoToBitmapConfig(info, &isOpaque);
132
133 GrTextureDesc desc;
134 desc.fFlags = kRenderTarget_GrTextureFlagBit;
135 desc.fWidth = info.fWidth;
136 desc.fHeight = info.fHeight;
137 desc.fConfig = SkBitmapConfig2GrPixelConfig(config);
138 desc.fSampleCnt = sampleCount;
139
robertphillips@google.com671eac62012-11-01 17:31:02 +0000140 SkAutoTUnref<GrTexture> tex(ctx->createUncachedTexture(desc, NULL, 0));
robertphillips@google.com97b6b072012-10-31 14:48:39 +0000141 if (NULL == tex) {
reed@google.com5d4ba882012-07-31 15:45:27 +0000142 return NULL;
143 }
skia.committer@gmail.comf3dc1992012-11-01 02:01:27 +0000144
robertphillips@google.com97b6b072012-10-31 14:48:39 +0000145 return SkNEW_ARGS(SkSurface_Gpu, (ctx, tex->asRenderTarget()));
reed@google.com5d4ba882012-07-31 15:45:27 +0000146}
147