reed@google.com | 5d4ba88 | 2012-07-31 15:45:27 +0000 | [diff] [blame] | 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" |
robertphillips@google.com | 97b6b07 | 2012-10-31 14:48:39 +0000 | [diff] [blame] | 11 | #include "SkGpuDevice.h" |
reed@google.com | 5d4ba88 | 2012-07-31 15:45:27 +0000 | [diff] [blame] | 12 | |
| 13 | class SkSurface_Gpu : public SkSurface_Base { |
| 14 | public: |
robertphillips@google.com | 97b6b07 | 2012-10-31 14:48:39 +0000 | [diff] [blame] | 15 | SK_DECLARE_INST_COUNT(SkSurface_Gpu) |
reed@google.com | 5d4ba88 | 2012-07-31 15:45:27 +0000 | [diff] [blame] | 16 | |
robertphillips@google.com | 97b6b07 | 2012-10-31 14:48:39 +0000 | [diff] [blame] | 17 | SkSurface_Gpu(GrContext*, const SkImage::Info&, int sampleCount); |
| 18 | SkSurface_Gpu(GrContext*, GrRenderTarget*); |
| 19 | virtual ~SkSurface_Gpu(); |
reed@google.com | 5d4ba88 | 2012-07-31 15:45:27 +0000 | [diff] [blame] | 20 | |
| 21 | virtual SkCanvas* onNewCanvas() SK_OVERRIDE; |
mike@reedtribe.org | b947625 | 2012-11-15 02:37:45 +0000 | [diff] [blame^] | 22 | virtual SkSurface* onNewSurface(const SkImage::Info&) SK_OVERRIDE; |
reed@google.com | 5d4ba88 | 2012-07-31 15:45:27 +0000 | [diff] [blame] | 23 | virtual SkImage* onNewImageShapshot() SK_OVERRIDE; |
| 24 | virtual void onDraw(SkCanvas*, SkScalar x, SkScalar y, |
| 25 | const SkPaint*) SK_OVERRIDE; |
robertphillips@google.com | 97b6b07 | 2012-10-31 14:48:39 +0000 | [diff] [blame] | 26 | virtual void onCopyOnWrite(SkImage*, SkCanvas*) SK_OVERRIDE; |
reed@google.com | 5d4ba88 | 2012-07-31 15:45:27 +0000 | [diff] [blame] | 27 | |
| 28 | private: |
robertphillips@google.com | 97b6b07 | 2012-10-31 14:48:39 +0000 | [diff] [blame] | 29 | SkGpuDevice* fDevice; |
reed@google.com | 5d4ba88 | 2012-07-31 15:45:27 +0000 | [diff] [blame] | 30 | |
| 31 | typedef SkSurface_Base INHERITED; |
| 32 | }; |
| 33 | |
robertphillips@google.com | 97b6b07 | 2012-10-31 14:48:39 +0000 | [diff] [blame] | 34 | SK_DEFINE_INST_COUNT(SkSurface_Gpu) |
| 35 | |
reed@google.com | 5d4ba88 | 2012-07-31 15:45:27 +0000 | [diff] [blame] | 36 | /////////////////////////////////////////////////////////////////////////////// |
| 37 | |
robertphillips@google.com | 97b6b07 | 2012-10-31 14:48:39 +0000 | [diff] [blame] | 38 | SkSurface_Gpu::SkSurface_Gpu(GrContext* ctx, const SkImage::Info& info, |
| 39 | int sampleCount) |
reed@google.com | 5d4ba88 | 2012-07-31 15:45:27 +0000 | [diff] [blame] | 40 | : INHERITED(info.fWidth, info.fHeight) { |
| 41 | bool isOpaque; |
| 42 | SkBitmap::Config config = SkImageInfoToBitmapConfig(info, &isOpaque); |
rmistry@google.com | fbfcd56 | 2012-08-23 18:09:54 +0000 | [diff] [blame] | 43 | |
robertphillips@google.com | 97b6b07 | 2012-10-31 14:48:39 +0000 | [diff] [blame] | 44 | fDevice = SkNEW_ARGS(SkGpuDevice, (ctx, config, info.fWidth, info.fHeight, sampleCount)); |
robertphillips@google.com | ea5d8af | 2012-11-02 17:38:28 +0000 | [diff] [blame] | 45 | |
| 46 | if (!isOpaque) { |
| 47 | fDevice->clear(0x0); |
| 48 | } |
reed@google.com | 5d4ba88 | 2012-07-31 15:45:27 +0000 | [diff] [blame] | 49 | } |
| 50 | |
robertphillips@google.com | 97b6b07 | 2012-10-31 14:48:39 +0000 | [diff] [blame] | 51 | SkSurface_Gpu::SkSurface_Gpu(GrContext* ctx, GrRenderTarget* renderTarget) |
| 52 | : INHERITED(renderTarget->width(), renderTarget->height()) { |
| 53 | fDevice = SkNEW_ARGS(SkGpuDevice, (ctx, renderTarget)); |
robertphillips@google.com | ea5d8af | 2012-11-02 17:38:28 +0000 | [diff] [blame] | 54 | |
| 55 | if (kRGB_565_GrPixelConfig != renderTarget->config()) { |
| 56 | fDevice->clear(0x0); |
| 57 | } |
robertphillips@google.com | 97b6b07 | 2012-10-31 14:48:39 +0000 | [diff] [blame] | 58 | } |
reed@google.com | 5d4ba88 | 2012-07-31 15:45:27 +0000 | [diff] [blame] | 59 | |
robertphillips@google.com | 97b6b07 | 2012-10-31 14:48:39 +0000 | [diff] [blame] | 60 | SkSurface_Gpu::~SkSurface_Gpu() { |
| 61 | SkSafeUnref(fDevice); |
reed@google.com | 5d4ba88 | 2012-07-31 15:45:27 +0000 | [diff] [blame] | 62 | } |
| 63 | |
| 64 | SkCanvas* SkSurface_Gpu::onNewCanvas() { |
robertphillips@google.com | 97b6b07 | 2012-10-31 14:48:39 +0000 | [diff] [blame] | 65 | return SkNEW_ARGS(SkCanvas, (fDevice)); |
reed@google.com | 5d4ba88 | 2012-07-31 15:45:27 +0000 | [diff] [blame] | 66 | } |
| 67 | |
mike@reedtribe.org | b947625 | 2012-11-15 02:37:45 +0000 | [diff] [blame^] | 68 | SkSurface* SkSurface_Gpu::onNewSurface(const SkImage::Info& info) { |
robertphillips@google.com | 97b6b07 | 2012-10-31 14:48:39 +0000 | [diff] [blame] | 69 | GrRenderTarget* rt = (GrRenderTarget*) fDevice->accessRenderTarget(); |
| 70 | int sampleCount = rt->numSamples(); |
mike@reedtribe.org | b947625 | 2012-11-15 02:37:45 +0000 | [diff] [blame^] | 71 | return SkSurface::NewRenderTarget(fDevice->context(), info, sampleCount); |
reed@google.com | 5d4ba88 | 2012-07-31 15:45:27 +0000 | [diff] [blame] | 72 | } |
| 73 | |
| 74 | SkImage* SkSurface_Gpu::onNewImageShapshot() { |
robertphillips@google.com | 97b6b07 | 2012-10-31 14:48:39 +0000 | [diff] [blame] | 75 | |
| 76 | GrRenderTarget* rt = (GrRenderTarget*) fDevice->accessRenderTarget(); |
| 77 | |
| 78 | return SkImage::NewTexture(rt->asTexture()); |
reed@google.com | 5d4ba88 | 2012-07-31 15:45:27 +0000 | [diff] [blame] | 79 | } |
| 80 | |
| 81 | void SkSurface_Gpu::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, |
| 82 | const SkPaint* paint) { |
robertphillips@google.com | 97b6b07 | 2012-10-31 14:48:39 +0000 | [diff] [blame] | 83 | 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. |
| 89 | void 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.com | 671eac6 | 2012-11-01 17:31:02 +0000 | [diff] [blame] | 102 | SkAutoTUnref<GrTexture> tex(fDevice->context()->createUncachedTexture(desc, NULL, 0)); |
robertphillips@google.com | 97b6b07 | 2012-10-31 14:48:39 +0000 | [diff] [blame] | 103 | if (NULL == tex) { |
| 104 | SkTextureImageSetTexture(image, NULL); |
| 105 | return; |
| 106 | } |
skia.committer@gmail.com | f3dc199 | 2012-11-01 02:01:27 +0000 | [diff] [blame] | 107 | |
robertphillips@google.com | 97b6b07 | 2012-10-31 14:48:39 +0000 | [diff] [blame] | 108 | fDevice->context()->copyTexture(rt->asTexture(), tex->asRenderTarget()); |
| 109 | |
| 110 | SkTextureImageSetTexture(image, tex); |
| 111 | } |
reed@google.com | 5d4ba88 | 2012-07-31 15:45:27 +0000 | [diff] [blame] | 112 | } |
| 113 | |
| 114 | /////////////////////////////////////////////////////////////////////////////// |
| 115 | |
| 116 | SkSurface* SkSurface::NewRenderTargetDirect(GrContext* ctx, |
| 117 | GrRenderTarget* target) { |
| 118 | if (NULL == ctx || NULL == target) { |
| 119 | return NULL; |
| 120 | } |
rmistry@google.com | fbfcd56 | 2012-08-23 18:09:54 +0000 | [diff] [blame] | 121 | |
reed@google.com | 5d4ba88 | 2012-07-31 15:45:27 +0000 | [diff] [blame] | 122 | return SkNEW_ARGS(SkSurface_Gpu, (ctx, target)); |
| 123 | } |
| 124 | |
mike@reedtribe.org | b947625 | 2012-11-15 02:37:45 +0000 | [diff] [blame^] | 125 | SkSurface* SkSurface::NewRenderTarget(GrContext* ctx, const SkImage::Info& info, int sampleCount) { |
reed@google.com | 5d4ba88 | 2012-07-31 15:45:27 +0000 | [diff] [blame] | 126 | if (NULL == ctx) { |
| 127 | return NULL; |
| 128 | } |
robertphillips@google.com | 97b6b07 | 2012-10-31 14:48:39 +0000 | [diff] [blame] | 129 | |
| 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.com | 671eac6 | 2012-11-01 17:31:02 +0000 | [diff] [blame] | 140 | SkAutoTUnref<GrTexture> tex(ctx->createUncachedTexture(desc, NULL, 0)); |
robertphillips@google.com | 97b6b07 | 2012-10-31 14:48:39 +0000 | [diff] [blame] | 141 | if (NULL == tex) { |
reed@google.com | 5d4ba88 | 2012-07-31 15:45:27 +0000 | [diff] [blame] | 142 | return NULL; |
| 143 | } |
skia.committer@gmail.com | f3dc199 | 2012-11-01 02:01:27 +0000 | [diff] [blame] | 144 | |
robertphillips@google.com | 97b6b07 | 2012-10-31 14:48:39 +0000 | [diff] [blame] | 145 | return SkNEW_ARGS(SkSurface_Gpu, (ctx, tex->asRenderTarget())); |
reed@google.com | 5d4ba88 | 2012-07-31 15:45:27 +0000 | [diff] [blame] | 146 | } |
| 147 | |