aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar robertphillips@google.com <robertphillips@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-10-31 14:48:39 +0000
committerGravatar robertphillips@google.com <robertphillips@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-10-31 14:48:39 +0000
commit97b6b0730dcb0feee9224ff04eb3985ca4bd0216 (patch)
tree516d366d516ac0bd13bb6a137e1d2c45abbfa9a2
parentd3eb336d56b2ad989229c8fb21ea20f5a7b14a32 (diff)
Fleshed out GPU portion of image/surface feature
-rw-r--r--gm/image.cpp44
-rw-r--r--gyp/gpu.gypi3
-rw-r--r--include/core/SkImage.h4
-rw-r--r--src/image/SkImagePriv.h10
-rw-r--r--src/image/SkImage_Base.h2
-rw-r--r--src/image/SkImage_Gpu.cpp80
-rw-r--r--src/image/SkSurface.cpp2
-rw-r--r--src/image/SkSurface_Base.h2
-rw-r--r--src/image/SkSurface_Gpu.cpp155
-rw-r--r--src/image/SkSurface_Picture.cpp6
10 files changed, 180 insertions, 128 deletions
diff --git a/gm/image.cpp b/gm/image.cpp
index a98fa3f333..6f326a8a29 100644
--- a/gm/image.cpp
+++ b/gm/image.cpp
@@ -11,7 +11,13 @@
#include "SkStream.h"
#include "SkData.h"
+#if SK_SUPPORT_GPU
+#include "GrContext.h"
+
+namespace skiagm {
extern GrContext* GetGr();
+};
+#endif
static SkData* fileToData(const char path[]) {
SkFILEStream stream(path);
@@ -109,19 +115,40 @@ public:
protected:
virtual SkString onShortName() {
- return SkString("image");
+ return SkString("image-surface");
}
virtual SkISize onISize() {
- return SkISize::Make(640, 480);
+ return SkISize::Make(800, 500);
}
virtual void onDraw(SkCanvas* canvas) {
drawJpeg(canvas, this->getISize());
- canvas->translate(10, 10);
canvas->scale(2, 2);
+ static const char* kLabel1 = "Original Img";
+ static const char* kLabel2 = "Modified Img";
+ static const char* kLabel3 = "Cur Surface";
+
+ static const char* kLabel4 = "Pre-Alloc Img";
+ static const char* kLabel5 = "New Alloc Img";
+ static const char* kLabel6 = "SkPicture";
+ static const char* kLabel7 = "GPU";
+
+ SkPaint textPaint;
+
+ canvas->drawText(kLabel1, strlen(kLabel1), 10, 60, textPaint);
+ canvas->drawText(kLabel2, strlen(kLabel2), 10, 140, textPaint);
+ canvas->drawText(kLabel3, strlen(kLabel3), 10, 220, textPaint);
+
+ canvas->drawText(kLabel4, strlen(kLabel4), 80, 10, textPaint);
+ canvas->drawText(kLabel5, strlen(kLabel5), 160, 10, textPaint);
+ canvas->drawText(kLabel6, strlen(kLabel6), 250, 10, textPaint);
+ canvas->drawText(kLabel7, strlen(kLabel7), 340, 10, textPaint);
+
+ canvas->translate(80, 20);
+
// since we draw into this directly, we need to start fresh
sk_bzero(fBuffer, fBufferSize);
@@ -134,12 +161,23 @@ protected:
SkAutoTUnref<SkSurface> surf0(SkSurface::NewRasterDirect(info, NULL, fBuffer, RB));
SkAutoTUnref<SkSurface> surf1(SkSurface::NewRaster(info, NULL));
SkAutoTUnref<SkSurface> surf2(SkSurface::NewPicture(info.fWidth, info.fHeight));
+#if SK_SUPPORT_GPU
+ GrContext* ctx = skiagm::GetGr();
+
+ SkAutoTUnref<SkSurface> surf3(SkSurface::NewRenderTarget(ctx, info, NULL, 0));
+#endif
test_surface(canvas, surf0);
canvas->translate(80, 0);
test_surface(canvas, surf1);
canvas->translate(80, 0);
test_surface(canvas, surf2);
+#if SK_SUPPORT_GPU
+ if (NULL != ctx) {
+ canvas->translate(80, 0);
+ test_surface(canvas, surf3);
+ }
+#endif
}
virtual uint32_t onGetFlags() const SK_OVERRIDE {
diff --git a/gyp/gpu.gypi b/gyp/gpu.gypi
index c01174797e..2febe4dd2f 100644
--- a/gyp/gpu.gypi
+++ b/gyp/gpu.gypi
@@ -229,6 +229,9 @@
'<(skia_src_path)/gpu/SkGrPixelRef.cpp',
'<(skia_src_path)/gpu/SkGrTexturePixelRef.cpp',
+ '<(skia_src_path)/image/SkImage_Gpu.cpp',
+ '<(skia_src_path)/image/SkSurface_Gpu.cpp',
+
'<(skia_src_path)/gpu/gl/SkGLContext.cpp'
],
'skgr_native_gl_sources': [
diff --git a/include/core/SkImage.h b/include/core/SkImage.h
index 05350bfbfb..4fe91a3064 100644
--- a/include/core/SkImage.h
+++ b/include/core/SkImage.h
@@ -16,7 +16,6 @@ class SkCanvas;
class SkPaint;
class SkShader;
class GrContext;
-struct GrPlatformTextureDesc;
// need for TileMode
#include "SkShader.h"
@@ -63,13 +62,12 @@ public:
int fHeight;
ColorType fColorType;
AlphaType fAlphaType;
-
};
static SkImage* NewRasterCopy(const Info&, SkColorSpace*, const void* pixels, size_t rowBytes);
static SkImage* NewRasterData(const Info&, SkColorSpace*, SkData* pixels, size_t rowBytes);
static SkImage* NewEncodedData(SkData*);
- static SkImage* NewTexture(GrContext*, const GrPlatformTextureDesc&);
+ static SkImage* NewTexture(GrTexture*);
int width() const { return fWidth; }
int height() const { return fHeight; }
diff --git a/src/image/SkImagePriv.h b/src/image/SkImagePriv.h
index 9332abc7af..3210cae031 100644
--- a/src/image/SkImagePriv.h
+++ b/src/image/SkImagePriv.h
@@ -55,4 +55,14 @@ static inline size_t SkImageMinRowBytes(const SkImage::Info& info) {
// in which case the surface may need to perform a copy-on-write.
extern SkPixelRef* SkBitmapImageGetPixelRef(SkImage* rasterImage);
+// Given an image created with NewTexture, return its GrTexture. This
+// may be called to see if the surface and the image share the same GrTexture,
+// in which case the surface may need to perform a copy-on-write.
+extern GrTexture* SkTextureImageGetTexture(SkImage* rasterImage);
+
+// Update the texture wrapped by an image created with NewTexture. This
+// is called when a surface and image share the same GrTexture and the
+// surface needs to perform a copy-on-write
+extern void SkTextureImageSetTexture(SkImage* image, GrTexture* texture);
+
#endif
diff --git a/src/image/SkImage_Base.h b/src/image/SkImage_Base.h
index ed74610493..648b25914f 100644
--- a/src/image/SkImage_Base.h
+++ b/src/image/SkImage_Base.h
@@ -14,7 +14,7 @@ class SkImage_Base : public SkImage {
public:
SkImage_Base(int width, int height) : INHERITED(width, height) {}
- virtual void onDraw(SkCanvas*, SkScalar, SkScalar, const SkPaint*) = 0;
+ virtual void onDraw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*) = 0;
private:
typedef SkImage INHERITED;
diff --git a/src/image/SkImage_Gpu.cpp b/src/image/SkImage_Gpu.cpp
index e061e2d737..c721077b62 100644
--- a/src/image/SkImage_Gpu.cpp
+++ b/src/image/SkImage_Gpu.cpp
@@ -9,65 +9,77 @@
#include "SkImagePriv.h"
#include "SkBitmap.h"
#include "SkCanvas.h"
-#include "SkData.h"
-#include "SkDataPixelRef.h"
+#include "GrContext.h"
+#include "GrTexture.h"
+#include "SkGrPixelRef.h"
class SkImage_Gpu : public SkImage_Base {
public:
- static bool ValidArgs(GrContext* context,
- const GrPlatformTextureDesc& desc) {
- if (0 == desc.fTextureHandle) {
- return false;
- }
- if (desc.fWidth < 0 || desc.fHeight < 0) {
- return false;
- }
- return true;
- }
+ SK_DECLARE_INST_COUNT(SkImage_Gpu)
- SkImage_Gpu(GrContext* context, const GrPlatformTextureDesc& desc);
+ SkImage_Gpu(GrTexture*);
virtual ~SkImage_Gpu();
- virtual void onDraw(SkCanvas*, SkScalar, SkScalar, const SkPaint*) SK_OVERRIDE;
+ virtual void onDraw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*) SK_OVERRIDE;
+
+ GrTexture* getTexture() { return fTexture; }
+
+ void setTexture(GrTexture* texture);
private:
+ GrTexture* fTexture;
SkBitmap fBitmap;
typedef SkImage_Base INHERITED;
};
+SK_DEFINE_INST_COUNT(SkImage_Gpu)
+
///////////////////////////////////////////////////////////////////////////////
-SkImage_Gpu::SkImage_Gpu(GrContext* context, const GrPlatformTextureDesc& desc)
- : INHERITED(desc.fWidth, desc.fHeight) {
-#if 0
- bool isOpaque;
- SkBitmap::Config config = SkImageInfoToBitmapConfig(info, &isOpaque);
-
- fBitmap.setConfig(config, info.fWidth, info.fHeight, rowBytes);
- fBitmap.setPixelRef(SkNEW_ARGS(SkDataPixelRef, (data)))->unref();
- fBitmap.setIsOpaque(isOpaque);
- fBitmap.setImmutable();
-#endif
+SkImage_Gpu::SkImage_Gpu(GrTexture* texture)
+ : INHERITED(texture->width(), texture->height())
+ , fTexture(texture) {
+
+ SkASSERT(NULL != fTexture);
+ fTexture->ref();
+ fBitmap.setConfig(SkBitmap::kARGB_8888_Config, fTexture->width(), fTexture->height());
+ fBitmap.setPixelRef(new SkGrPixelRef(fTexture))->unref();
}
-SkImage_Gpu::~SkImage_Gpu() {}
+SkImage_Gpu::~SkImage_Gpu() {
+ SkSafeUnref(fTexture);
+}
-void SkImage_Gpu::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) {
+void SkImage_Gpu::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y,
+ const SkPaint* paint) {
canvas->drawBitmap(fBitmap, x, y, paint);
}
-///////////////////////////////////////////////////////////////////////////////
+void SkImage_Gpu::setTexture(GrTexture* texture) {
-SkImage* SkImage::NewRasterCopy(NewTexture(GrContext* context,
- const GrPlatformTextureDesc& desc) {
- if (NULL == context) {
- return NULL;
+ if (texture == fTexture) {
+ return;
}
- if (!SkImage_Gpu::ValidArgs(context, desc)) {
+
+ SkRefCnt_SafeAssign(fTexture, texture);
+ fBitmap.setPixelRef(new SkGrPixelRef(texture))->unref();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+SkImage* SkImage::NewTexture(GrTexture* texture) {
+ if (NULL == texture) {
return NULL;
}
- return SkNEW_ARGS(SkImage_Gpu, (context, desc));
+ return SkNEW_ARGS(SkImage_Gpu, (texture));
+}
+
+GrTexture* SkTextureImageGetTexture(SkImage* image) {
+ return ((SkImage_Gpu*)image)->getTexture();
}
+void SkTextureImageSetTexture(SkImage* image, GrTexture* texture) {
+ ((SkImage_Gpu*)image)->setTexture(texture);
+}
diff --git a/src/image/SkSurface.cpp b/src/image/SkSurface.cpp
index 2860a5863d..92089e38ad 100644
--- a/src/image/SkSurface.cpp
+++ b/src/image/SkSurface.cpp
@@ -43,8 +43,6 @@ void SkSurface_Base::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y,
}
}
-void SkSurface_Base::onCopyOnWrite(SkImage*, SkCanvas*) {}
-
SkCanvas* SkSurface_Base::getCachedCanvas() {
if (NULL == fCachedCanvas) {
fCachedCanvas = this->onNewCanvas();
diff --git a/src/image/SkSurface_Base.h b/src/image/SkSurface_Base.h
index 52b494f237..9d440f4892 100644
--- a/src/image/SkSurface_Base.h
+++ b/src/image/SkSurface_Base.h
@@ -51,7 +51,7 @@ public:
*
* The default implementation does nothing.
*/
- virtual void onCopyOnWrite(SkImage* cachedImage, SkCanvas*);
+ virtual void onCopyOnWrite(SkImage* cachedImage, SkCanvas*) = 0;
inline SkCanvas* getCachedCanvas();
inline SkImage* getCachedImage();
diff --git a/src/image/SkSurface_Gpu.cpp b/src/image/SkSurface_Gpu.cpp
index d707d93423..90d2e274d1 100644
--- a/src/image/SkSurface_Gpu.cpp
+++ b/src/image/SkSurface_Gpu.cpp
@@ -8,125 +8,100 @@
#include "SkSurface_Base.h"
#include "SkImagePriv.h"
#include "SkCanvas.h"
-#include "SkMallocPixelRef.h"
-
-static const size_t kIgnoreRowBytesValue = (size_t)~0;
+#include "SkGpuDevice.h"
class SkSurface_Gpu : public SkSurface_Base {
public:
- static bool Valid(const SkImage::Info&, SkColorSpace*, size_t rb = kIgnoreRowBytesValue);
+ SK_DECLARE_INST_COUNT(SkSurface_Gpu)
- SkSurface_Gpu(const SkImage::Info&, SkColorSpace*, void*, size_t rb);
- SkSurface_Gpu(const SkImage::Info&, SkColorSpace*, SkPixelRef*, size_t rb);
+ SkSurface_Gpu(GrContext*, const SkImage::Info&, int sampleCount);
+ SkSurface_Gpu(GrContext*, GrRenderTarget*);
+ virtual ~SkSurface_Gpu();
virtual SkCanvas* onNewCanvas() SK_OVERRIDE;
virtual SkSurface* onNewSurface(const SkImage::Info&, SkColorSpace*) SK_OVERRIDE;
virtual SkImage* onNewImageShapshot() SK_OVERRIDE;
virtual void onDraw(SkCanvas*, SkScalar x, SkScalar y,
const SkPaint*) SK_OVERRIDE;
+ virtual void onCopyOnWrite(SkImage*, SkCanvas*) SK_OVERRIDE;
private:
- SkBitmap fBitmap;
- bool fWeOwnThePixels;
+ SkGpuDevice* fDevice;
typedef SkSurface_Base INHERITED;
};
-///////////////////////////////////////////////////////////////////////////////
-
-bool SkSurface_Gpu::Valid(const SkImage::Info& info, SkColorSpace* cs,
- size_t rowBytes) {
- static const size_t kMaxTotalSize = SK_MaxS32;
-
- bool isOpaque;
- SkBitmap::Config config = SkImageInfoToBitmapConfig(info, &isOpaque);
-
- int shift = 0;
- switch (config) {
- case SkBitmap::kA8_Config:
- shift = 0;
- break;
- case SkBitmap::kRGB_565_Config:
- shift = 1;
- break;
- case SkBitmap::kARGB_8888_Config:
- shift = 2;
- break;
- default:
- return false;
- }
-
- // TODO: examine colorspace
+SK_DEFINE_INST_COUNT(SkSurface_Gpu)
- if (kIgnoreRowBytesValue == rowBytes) {
- return true;
- }
-
- uint64_t minRB = (uint64_t)info.fWidth << shift;
- if (minRB > rowBytes) {
- return false;
- }
-
- size_t alignedRowBytes = rowBytes >> shift << shift;
- if (alignedRowBytes != rowBytes) {
- return false;
- }
-
- uint64_t size = (uint64_t)info.fHeight * rowBytes;
- if (size > kMaxTotalSize) {
- return false;
- }
-
- return true;
-}
+///////////////////////////////////////////////////////////////////////////////
-SkSurface_Gpu::SkSurface_Gpu(const SkImage::Info& info, SkColorSpace* cs,
- void* pixels, size_t rb)
+SkSurface_Gpu::SkSurface_Gpu(GrContext* ctx, const SkImage::Info& info,
+ int sampleCount)
: INHERITED(info.fWidth, info.fHeight) {
bool isOpaque;
SkBitmap::Config config = SkImageInfoToBitmapConfig(info, &isOpaque);
- fBitmap.setConfig(config, info.fWidth, info.fHeight, rb);
- fBitmap.setPixels(pixels);
- fBitmap.setIsOpaque(isOpaque);
- fWeOwnThePixels = false;
+ fDevice = SkNEW_ARGS(SkGpuDevice, (ctx, config, info.fWidth, info.fHeight, sampleCount));
}
-SkSurface_Gpu::SkSurface_Gpu(const SkImage::Info& info, SkColorSpace* cs,
- SkPixelRef* pr, size_t rb)
- : INHERITED(info.fWidth, info.fHeight) {
- bool isOpaque;
- SkBitmap::Config config = SkImageInfoToBitmapConfig(info, &isOpaque);
-
- fBitmap.setConfig(config, info.fWidth, info.fHeight, rb);
- fBitmap.setPixelRef(pr);
- fBitmap.setIsOpaque(isOpaque);
- fWeOwnThePixels = true;
+SkSurface_Gpu::SkSurface_Gpu(GrContext* ctx, GrRenderTarget* renderTarget)
+ : INHERITED(renderTarget->width(), renderTarget->height()) {
+ fDevice = SkNEW_ARGS(SkGpuDevice, (ctx, renderTarget));
+}
- if (!isOpaque) {
- fBitmap.eraseColor(0);
- }
+SkSurface_Gpu::~SkSurface_Gpu() {
+ SkSafeUnref(fDevice);
}
SkCanvas* SkSurface_Gpu::onNewCanvas() {
- return SkNEW_ARGS(SkCanvas, (fBitmap));
+ return SkNEW_ARGS(SkCanvas, (fDevice));
}
SkSurface* SkSurface_Gpu::onNewSurface(const SkImage::Info& info,
- SkColorSpace* cs) {
- return SkSurface::NewRaster(info, cs);
+ SkColorSpace* cs) {
+ GrRenderTarget* rt = (GrRenderTarget*) fDevice->accessRenderTarget();
+ int sampleCount = rt->numSamples();
+ return SkSurface::NewRenderTarget(fDevice->context(), info, NULL, sampleCount);
}
SkImage* SkSurface_Gpu::onNewImageShapshot() {
- // if we don't own the pixels, we need to make a deep-copy
- // if we do, we need to perform a copy-on-write the next time
- // we draw to this bitmap from our canvas...
- return SkNewImageFromBitmap(fBitmap);
+
+ GrRenderTarget* rt = (GrRenderTarget*) fDevice->accessRenderTarget();
+
+ return SkImage::NewTexture(rt->asTexture());
}
void SkSurface_Gpu::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y,
const SkPaint* paint) {
- canvas->drawBitmap(fBitmap, x, y, paint);
+ canvas->drawBitmap(fDevice->accessBitmap(false), x, y, paint);
+}
+
+// Copy the contents of the SkGpuDevice into a new texture and give that
+// texture to the SkImage. Note that this flushes the SkGpuDevice but
+// doesn't force an OpenGL flush.
+void SkSurface_Gpu::onCopyOnWrite(SkImage* image, SkCanvas* canvas) {
+ GrRenderTarget* rt = (GrRenderTarget*) fDevice->accessRenderTarget();
+
+ // are we sharing our render target with the image?
+ if (rt->asTexture() == SkTextureImageGetTexture(image)) {
+ GrTextureDesc desc;
+ // copyTexture requires a render target as the destination
+ desc.fFlags = kRenderTarget_GrTextureFlagBit;
+ desc.fWidth = fDevice->width();
+ desc.fHeight = fDevice->height();
+ desc.fConfig = SkBitmapConfig2GrPixelConfig(fDevice->config());
+ desc.fSampleCnt = 0;
+
+ GrTexture* tex = fDevice->context()->createUncachedTexture(desc, NULL, 0);
+ if (NULL == tex) {
+ SkTextureImageSetTexture(image, NULL);
+ return;
+ }
+
+ fDevice->context()->copyTexture(rt->asTexture(), tex->asRenderTarget());
+
+ SkTextureImageSetTexture(image, tex);
+ }
}
///////////////////////////////////////////////////////////////////////////////
@@ -145,10 +120,22 @@ SkSurface* SkSurface::NewRenderTarget(GrContext* ctx, const SkImage::Info& info,
if (NULL == ctx) {
return NULL;
}
- if (!SkSurface_Gpu::Valid(info, cs, sampleCount)) {
+
+ bool isOpaque;
+ SkBitmap::Config config = SkImageInfoToBitmapConfig(info, &isOpaque);
+
+ GrTextureDesc desc;
+ desc.fFlags = kRenderTarget_GrTextureFlagBit;
+ desc.fWidth = info.fWidth;
+ desc.fHeight = info.fHeight;
+ desc.fConfig = SkBitmapConfig2GrPixelConfig(config);
+ desc.fSampleCnt = sampleCount;
+
+ GrTexture* tex = ctx->createUncachedTexture(desc, NULL, 0);
+ if (NULL == tex) {
return NULL;
}
-
-// return SkNEW_ARGS(SkSurface_Gpu, (info, cs, pr, rowBytes));
+
+ return SkNEW_ARGS(SkSurface_Gpu, (ctx, tex->asRenderTarget()));
}
diff --git a/src/image/SkSurface_Picture.cpp b/src/image/SkSurface_Picture.cpp
index bac09c59a0..3f82634b31 100644
--- a/src/image/SkSurface_Picture.cpp
+++ b/src/image/SkSurface_Picture.cpp
@@ -24,6 +24,7 @@ public:
virtual SkImage* onNewImageShapshot() SK_OVERRIDE;
virtual void onDraw(SkCanvas*, SkScalar x, SkScalar y,
const SkPaint*) SK_OVERRIDE;
+ virtual void onCopyOnWrite(SkImage*, SkCanvas*) SK_OVERRIDE;
private:
SkPicture* fPicture;
@@ -75,6 +76,11 @@ void SkSurface_Picture::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y,
SkImagePrivDrawPicture(canvas, fPicture, x, y, paint);
}
+void SkSurface_Picture::onCopyOnWrite(SkImage* cachedImage, SkCanvas*) {
+ // We always spawn a copy of the recording picture when we
+ // are asked for a snapshot, so we never need to do anything here.
+}
+
///////////////////////////////////////////////////////////////////////////////