Fleshed out GPU portion of image/surface feature

https://codereview.appspot.com/6813055/



git-svn-id: http://skia.googlecode.com/svn/trunk@6214 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
robertphillips@google.com 2012-10-31 14:48:39 +00:00
Родитель d3eb336d56
Коммит 97b6b0730d
10 изменённых файлов: 181 добавлений и 129 удалений

Просмотреть файл

@ -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 {

Просмотреть файл

@ -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': [

Просмотреть файл

@ -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; }

Просмотреть файл

@ -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

Просмотреть файл

@ -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;

Просмотреть файл

@ -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);
SkImage_Gpu::SkImage_Gpu(GrTexture* texture)
: INHERITED(texture->width(), texture->height())
, fTexture(texture) {
fBitmap.setConfig(config, info.fWidth, info.fHeight, rowBytes);
fBitmap.setPixelRef(SkNEW_ARGS(SkDataPixelRef, (data)))->unref();
fBitmap.setIsOpaque(isOpaque);
fBitmap.setImmutable();
#endif
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 (!SkImage_Gpu::ValidArgs(context, desc)) {
return NULL;
if (texture == fTexture) {
return;
}
return SkNEW_ARGS(SkImage_Gpu, (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, (texture));
}
GrTexture* SkTextureImageGetTexture(SkImage* image) {
return ((SkImage_Gpu*)image)->getTexture();
}
void SkTextureImageSetTexture(SkImage* image, GrTexture* texture) {
((SkImage_Gpu*)image)->setTexture(texture);
}

Просмотреть файл

@ -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();

Просмотреть файл

@ -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();

Просмотреть файл

@ -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;
};
SK_DEFINE_INST_COUNT(SkSurface_Gpu)
///////////////////////////////////////////////////////////////////////////////
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)
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);
SkSurface_Gpu::SkSurface_Gpu(GrContext* ctx, GrRenderTarget* renderTarget)
: INHERITED(renderTarget->width(), renderTarget->height()) {
fDevice = SkNEW_ARGS(SkGpuDevice, (ctx, renderTarget));
}
fBitmap.setConfig(config, info.fWidth, info.fHeight, rb);
fBitmap.setPixelRef(pr);
fBitmap.setIsOpaque(isOpaque);
fWeOwnThePixels = true;
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()));
}

Просмотреть файл

@ -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.
}
///////////////////////////////////////////////////////////////////////////////