check-point for gpu support in SkImage/SkSurface
authorreed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Tue, 31 Jul 2012 15:45:27 +0000 (15:45 +0000)
committerreed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Tue, 31 Jul 2012 15:45:27 +0000 (15:45 +0000)
git-svn-id: http://skia.googlecode.com/svn/trunk@4859 2bbb7eff-a529-9590-31e7-b0007b416f81

include/core/SkImage.h
include/core/SkSurface.h
src/image/SkImage_Gpu.cpp [new file with mode: 0644]
src/image/SkSurface_Gpu.cpp [new file with mode: 0644]

index ebe275e..8fdd9b1 100644 (file)
@@ -15,6 +15,8 @@ class SkData;
 class SkCanvas;
 class SkPaint;
 class SkShader;
+class GrContext;
+struct GrPlatformTextureDesc;
 
 // need for TileMode
 #include "SkShader.h"
@@ -65,6 +67,7 @@ public:
     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&);
 
     int width() const { return fWidth; }
     int height() const { return fHeight; }
index 69889e5..0c20d4a 100644 (file)
@@ -13,6 +13,8 @@
 
 class SkCanvas;
 class SkPaint;
+class GrContext;
+class GrRenderTarget;
 
 /**
  *  SkSurface represents the backend/results of drawing to a canvas. For raster
@@ -50,6 +52,18 @@ public:
      */
     static SkSurface* NewPicture(int width, int height);
 
+    /**
+     *  Return a new surface using the specified render target.
+     */
+    static SkSurface* NewRenderTargetDirect(GrContext*, GrRenderTarget*);
+
+    /**
+     *  Return a new surface whose contents will be drawn to an offscreen
+     *  render target, allocated by the surface.
+     */
+    static SkSurface* NewRenderTarget(GrContext*, const SkImage::Info&,
+                                      SkColorSpace*, int sampleCount = 0);
+
     int width() const { return fWidth; }
     int height() const { return fHeight; }
 
diff --git a/src/image/SkImage_Gpu.cpp b/src/image/SkImage_Gpu.cpp
new file mode 100644 (file)
index 0000000..6ccf10b
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkImage_Base.h"
+#include "SkImagePriv.h"
+#include "SkBitmap.h"
+#include "SkCanvas.h"
+#include "SkData.h"
+#include "SkDataPixelRef.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;
+    }
+
+    SkImage_Gpu(GrContext* context, const GrPlatformTextureDesc& desc);
+    virtual ~SkImage_Gpu();
+
+    virtual void onDraw(SkCanvas*, SkScalar, SkScalar, const SkPaint*) SK_OVERRIDE;
+
+private:
+    SkBitmap    fBitmap;
+
+    typedef SkImage_Base INHERITED;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+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() {}
+
+void SkImage_Gpu::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) {
+    canvas->drawBitmap(fBitmap, x, y, paint);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+SkImage* SkImage::NewRasterCopy(NewTexture(GrContext* context,
+                                           const GrPlatformTextureDesc& desc) {
+    if (NULL == context) {
+        return NULL;
+    }
+    if (!SkImage_Gpu::ValidArgs(context, desc)) {
+        return NULL;
+    }
+    
+    return SkNEW_ARGS(SkImage_Gpu, (context, desc));
+}
+
diff --git a/src/image/SkSurface_Gpu.cpp b/src/image/SkSurface_Gpu.cpp
new file mode 100644 (file)
index 0000000..c6016be
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkSurface_Base.h"
+#include "SkImagePriv.h"
+#include "SkCanvas.h"
+#include "SkMallocPixelRef.h"
+
+static const size_t kIgnoreRowBytesValue = (size_t)~0;
+
+class SkSurface_Gpu : public SkSurface_Base {
+public:
+    static bool Valid(const SkImage::Info&, SkColorSpace*, size_t rb = kIgnoreRowBytesValue);
+
+    SkSurface_Gpu(const SkImage::Info&, SkColorSpace*, void*, size_t rb);
+    SkSurface_Gpu(const SkImage::Info&, SkColorSpace*, SkPixelRef*, size_t rb);
+
+    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;
+
+private:
+    SkBitmap    fBitmap;
+    bool        fWeOwnThePixels;
+
+    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
+
+    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)
+        : 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;
+}
+
+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;
+
+    if (!isOpaque) {
+        fBitmap.eraseColor(0);
+    }
+}
+
+SkCanvas* SkSurface_Gpu::onNewCanvas() {
+    return SkNEW_ARGS(SkCanvas, (fBitmap));
+}
+
+SkSurface* SkSurface_Gpu::onNewSurface(const SkImage::Info& info,
+                                          SkColorSpace* cs) {
+    return SkSurface::NewRaster(info, cs);
+}
+
+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);
+}
+
+void SkSurface_Gpu::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y,
+                              const SkPaint* paint) {
+    canvas->drawBitmap(fBitmap, x, y, paint);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+SkSurface* SkSurface::NewRenderTargetDirect(GrContext* ctx,
+                                            GrRenderTarget* target) {
+    if (NULL == ctx || NULL == target) {
+        return NULL;
+    }
+    
+    return SkNEW_ARGS(SkSurface_Gpu, (ctx, target));
+}
+
+SkSurface* SkSurface::NewRenderTarget(GrContext* ctx, const SkImage::Info& info,
+                                      SkColorSpace*, int sampleCount) {
+    if (NULL == ctx) {
+        return NULL;
+    }
+    if (!SkSurface_Gpu::Valid(info, cs, sampleCount)) {
+        return NULL;
+    }
+    
+//    return SkNEW_ARGS(SkSurface_Gpu, (info, cs, pr, rowBytes));
+}
+