case kRaster_Backend:
bitmap.allocPixels();
erase(bitmap);
- device = new SkDevice(NULL, bitmap, true);
+ device = new SkDevice(bitmap);
break;
case kGPU_Backend:
- device = new SkGpuDevice(context, bitmap, SkGpuDevice::Current3DApiRenderTarget());
+ device = new SkGpuDevice(context, SkGpuDevice::Current3DApiRenderTarget());
// device->clear(0xFFFFFFFF);
break;
case kPDF_Backend:
if (NULL == context) {
return false;
}
- SkGpuCanvas gc(context,
- SkGpuDevice::Current3DApiRenderTarget());
- gc.setDevice(gc.createDevice(bitmap.config(),
- bitmap.width(),
- bitmap.height(),
- bitmap.isOpaque(),
- false))->unref();
+
+ // not a real object, so don't unref it
+ GrRenderTarget* rt = SkGpuDevice::Current3DApiRenderTarget();
+ SkGpuCanvas gc(context, rt);
+ gc.setDevice(new SkGpuDevice(context, rt))->unref();
+
gm->draw(&gc);
- gc.readPixels(&bitmap); // overwrite our previous allocation
+ // the device is as large as the current rendertarget, so we explicitly
+ // only readback the amount we expect (in size)
+ gc.readPixels(SkIRect::MakeSize(size), &bitmap); // overwrite our previous allocation
}
return true;
}
is raster, the pixels will be allocated automatically.
*/
virtual SkDevice* createDevice(SkBitmap::Config, int width, int height,
- bool isOpaque, bool forLayer = false);
+ bool isOpaque);
/**
* Create a new raster device and make it current. This also returns
* the new device.
*/
- SkDevice* setBitmapDevice(const SkBitmap& bitmap, bool forLayer = false);
+ SkDevice* setBitmapDevice(const SkBitmap& bitmap);
/**
* Return the current device factory, or NULL. The reference count of
class SK_API SkDevice : public SkRefCnt {
public:
- SkDevice(SkCanvas*);
- /** Construct a new device, extracting the width/height/config/isOpaque values from
- the bitmap. If transferPixelOwnership is true, and the bitmap claims to own its
- own pixels (getOwnsPixels() == true), then transfer this responsibility to the
- device, and call setOwnsPixels(false) on the bitmap.
+// SkDevice();
- Subclasses may override the destructor, which is virtual, even though this class
- doesn't have one. SkRefCnt does.
-
- @param bitmap A copy of this bitmap is made and stored in the device
+ /**
+ * Construct a new device with the specified bitmap as its backend. It is
+ * valid for the bitmap to have no pixels associated with it. In that case,
+ * any drawing to this device will have no effect.
*/
- SkDevice(SkCanvas*, const SkBitmap& bitmap, bool forOffscreen);
+ SkDevice(const SkBitmap& bitmap);
+
+ /**
+ * Create a new raster device and have the pixels be automatically
+ * allocated. The rowBytes of the device will be computed automatically
+ * based on the config and the width.
+ *
+ * @param config The desired config for the pixels. If the request cannot
+ * be met, the closest matching support config will be used.
+ * @param width width (in pixels) of the device
+ * @param height height (in pixels) of the device
+ * @param isOpaque Set to true if it is known that all of the pixels will
+ * be drawn to opaquely. Used as an accelerator when drawing
+ * these pixels to another device.
+ */
+ SkDevice(SkBitmap::Config config, int width, int height, bool isOpaque = false);
+
virtual ~SkDevice();
/**
// just called by SkCanvas when built as a layer
void setOrigin(int x, int y) { fOrigin.set(x, y); }
- SkCanvas* fCanvas;
SkBitmap fBitmap;
SkIPoint fOrigin;
SkMetaData* fMetaData;
#define SkGpuDevice_DEFINED
#include "SkGr.h"
+#include "SkBitmap.h"
#include "SkDevice.h"
#include "SkRegion.h"
class SK_API SkGpuDevice : public SkDevice {
public:
/**
- * The SkGpuDevice will render to the GrRenderTarget, or if the paremeter is
- * null it will create its own render target and manage that target's
- * lifetime. Setting isSaveLayer to true is for internal use and may cause
- * problems when using the device's bitmap as a src if used externally.
+ * New device that will create an offscreen renderTarget based on the
+ * config, width, height.
+ *
+ * isForSaveLayer is a special flag that should only be set by SkCanvas
+ * internally.
*/
- SkGpuDevice(GrContext*,
- const SkBitmap& bitmap,
- GrRenderTarget* renderTargetOrNull,
- bool isSaveLayer = false);
+ SkGpuDevice(GrContext*, SkBitmap::Config, int width, int height,
+ bool isForSaveLayer = false);
+
+ /**
+ * New device that will render to the specified renderTarget.
+ */
+ SkGpuDevice(GrContext*, GrRenderTarget*);
/**
* Magic value that can be passed to constructor. Causes
virtual SkDrawFilter* setDrawFilter(SkDrawFilter* filter);
virtual SkDevice* createDevice(SkBitmap::Config, int width, int height,
- bool isOpaque, bool isForLayer);
+ bool isOpaque);
private:
SkCanvas* fProxy;
#include "SkCanvas.h"
#include "SkDevice.h"
#include "SkGpuCanvas.h"
+#include "SkGpuDevice.h"
#include "SkGraphics.h"
#include "SkImageEncoder.h"
#include "SkPaint.h"
fGpuCanvas = new SkGpuCanvas(fGrContext, renderTarget);
renderTarget->unref();
- device = fGpuCanvas->createDevice(SkBitmap::kARGB_8888_Config,
- bitmap.width(), bitmap.height(),
- false, false);
+ device = new SkGpuDevice(fGrContext, renderTarget);
fGpuCanvas->setDevice(device)->unref();
fGpuCanvas->concat(canvas->getTotalMatrix());
// when copying from one GPU device to another.
SkRefPtr<SkDevice> primaryDevice(canvas->getDevice());
SkRefPtr<SkDevice> secondDevice(canvas->createDevice(
- SkBitmap::kARGB_8888_Config, 5, 5, true, true));
+ SkBitmap::kARGB_8888_Config, 5, 5, true));
secondDevice->unref();
SkCanvas secondCanvas(secondDevice.get());
: fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) {
inc_canvas();
- SkDevice* device = SkNEW_ARGS(SkDevice, (this, bitmap, false));
+ SkDevice* device = SkNEW_ARGS(SkDevice, (bitmap));
fDeviceFactory = device->getDeviceFactory();
SkASSERT(fDeviceFactory);
fDeviceFactory->ref();
return device;
}
-SkDevice* SkCanvas::setBitmapDevice(const SkBitmap& bitmap, bool forLayer) {
- SkDevice* device = this->setDevice(SkNEW_ARGS(SkDevice, (this, bitmap, forLayer)));
+SkDevice* SkCanvas::setBitmapDevice(const SkBitmap& bitmap) {
+ SkDevice* device = this->setDevice(SkNEW_ARGS(SkDevice, (bitmap)));
device->unref();
return device;
}
SkBitmap::Config config = resolve_config(this, ir, flags, &isOpaque);
SkDevice* device = this->createDevice(config, ir.width(), ir.height(),
- isOpaque, true);
+ isOpaque);
device->setOrigin(ir.fLeft, ir.fTop);
DeviceCM* layer = SkNEW_ARGS(DeviceCM, (device, ir.fLeft, ir.fTop, paint));
device->unref();
}
SkDevice* SkCanvas::createDevice(SkBitmap::Config config, int width, int height,
- bool isOpaque, bool forLayer) {
- return fDeviceFactory->newDevice(this, config, width, height, isOpaque, forLayer);
+ bool isOpaque) {
+ return fDeviceFactory->newDevice(this, config, width, height, isOpaque, true);
}
//////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
-SkDevice::SkDevice(SkCanvas* canvas) : fCanvas(canvas), fMetaData(NULL) {
+#if 0
+SkDevice::SkDevice() : fMetaData(NULL) {
fOrigin.setZero();
fCachedDeviceFactory = NULL;
}
+#endif
-SkDevice::SkDevice(SkCanvas* canvas, const SkBitmap& bitmap, bool isForLayer)
- : fCanvas(canvas), fBitmap(bitmap), fMetaData(NULL) {
+SkDevice::SkDevice(const SkBitmap& bitmap) : fBitmap(bitmap) {
fOrigin.setZero();
- // auto-allocate if we're for offscreen drawing
- if (isForLayer) {
- if (NULL == fBitmap.getPixels() && NULL == fBitmap.pixelRef()) {
- fBitmap.allocPixels();
- if (!fBitmap.isOpaque()) {
- fBitmap.eraseColor(0);
- }
- }
- }
+ fMetaData = NULL;
fCachedDeviceFactory = NULL;
}
+SkDevice::SkDevice(SkBitmap::Config config, int width, int height, bool isOpaque) {
+ fOrigin.setZero();
+ fMetaData = NULL;
+ fCachedDeviceFactory = NULL;
+
+ fBitmap.setConfig(config, width, height);
+ fBitmap.allocPixels();
+ fBitmap.setIsOpaque(isOpaque);
+ if (!isOpaque) {
+ fBitmap.eraseColor(0);
+ }
+}
+
SkDevice::~SkDevice() {
delete fMetaData;
SkSafeUnref(fCachedDeviceFactory);
///////////////////////////////////////////////////////////////////////////////
-SkDevice* SkRasterDeviceFactory::newDevice(SkCanvas* canvas,
+SkDevice* SkRasterDeviceFactory::newDevice(SkCanvas*,
SkBitmap::Config config, int width,
int height, bool isOpaque,
bool isForLayer) {
- SkBitmap bitmap;
- bitmap.setConfig(config, width, height);
- bitmap.setIsOpaque(isOpaque);
-
- return SkNEW_ARGS(SkDevice, (canvas, bitmap, isForLayer));
+ if (isForLayer) {
+ return SkNEW_ARGS(SkDevice, (config, width, height, isOpaque));
+ } else {
+ // should we ever get here?
+ SkBitmap bitmap;
+ bitmap.setConfig(config, width, height);
+ bitmap.setIsOpaque(isOpaque);
+ return SkNEW_ARGS(SkDevice, (bitmap));
+ }
}
return (GrRenderTarget*) -1;
}
-SkGpuDevice::SkGpuDevice(GrContext* context,
- const SkBitmap& bitmap,
- GrRenderTarget* renderTargetOrNull,
- bool isSaveLayer)
- : SkDevice(NULL, bitmap, (NULL == renderTargetOrNull)) {
+static SkBitmap::Config grConfig2skConfig(GrPixelConfig config, bool* isOpaque) {
+ switch (config) {
+ case kAlpha_8_GrPixelConfig:
+ *isOpaque = false;
+ return SkBitmap::kA8_Config;
+ case kRGB_565_GrPixelConfig:
+ *isOpaque = true;
+ return SkBitmap::kRGB_565_Config;
+ case kRGBA_4444_GrPixelConfig:
+ *isOpaque = false;
+ return SkBitmap::kARGB_4444_Config;
+ case kRGBA_8888_GrPixelConfig:
+ case kRGBX_8888_GrPixelConfig:
+ *isOpaque = (kRGBX_8888_GrPixelConfig == config);
+ return SkBitmap::kARGB_8888_Config;
+ default:
+ *isOpaque = false;
+ return SkBitmap::kNo_Config;
+ }
+}
+
+static SkBitmap make_bitmap(GrContext* context, GrRenderTarget* renderTarget) {
+ if (SkGpuDevice::Current3DApiRenderTarget() == renderTarget) {
+ renderTarget = context->createRenderTargetFrom3DApiState();
+ }
+ GrTexture* texture = renderTarget->asTexture();
+ GrPixelConfig config = texture ? texture->config() : kRGBA_8888_GrPixelConfig;
+
+ bool isOpaque;
+ SkBitmap bitmap;
+ bitmap.setConfig(grConfig2skConfig(config, &isOpaque),
+ renderTarget->width(), renderTarget->height());
+ bitmap.setIsOpaque(isOpaque);
+ return bitmap;
+}
+SkGpuDevice::SkGpuDevice(GrContext* context, GrRenderTarget* renderTarget)
+: SkDevice(make_bitmap(context, renderTarget)) {
+
+ fNeedPrepareRenderTarget = false;
+ fDrawProcs = NULL;
+
+ fContext = context;
+ fContext->ref();
+
+ fCache = NULL;
+ fTexture = NULL;
+ fRenderTarget = NULL;
+ fNeedClear = false;
+
+ if (Current3DApiRenderTarget() == renderTarget) {
+ fRenderTarget = fContext->createRenderTargetFrom3DApiState();
+ } else {
+ fRenderTarget = renderTarget;
+ fRenderTarget->ref();
+ }
+
+ SkGrRenderTargetPixelRef* pr = new SkGrRenderTargetPixelRef(fRenderTarget);
+ this->setPixelRef(pr, 0)->unref();
+}
+
+SkGpuDevice::SkGpuDevice(GrContext* context, SkBitmap::Config config, int width,
+ int height, bool isForSaveLayer)
+: SkDevice(config, width, height, false /*isOpaque*/) {
fNeedPrepareRenderTarget = false;
fDrawProcs = NULL;
fRenderTarget = NULL;
fNeedClear = false;
- if (NULL == renderTargetOrNull) {
- SkBitmap::Config c = bitmap.config();
- if (c != SkBitmap::kRGB_565_Config) {
- c = SkBitmap::kARGB_8888_Config;
- }
- SkBitmap bm;
- bm.setConfig(c, this->width(), this->height());
+ if (config != SkBitmap::kRGB_565_Config) {
+ config = SkBitmap::kARGB_8888_Config;
+ }
+ SkBitmap bm;
+ bm.setConfig(config, width, height);
#if CACHE_LAYER_TEXTURES
- fCache = this->lockCachedTexture(bm, GrSamplerState::ClampNoFilter(),
- &fTexture, true);
- if (fCache) {
- SkASSERT(NULL != fTexture);
- SkASSERT(NULL != fTexture->asRenderTarget());
- }
+ fCache = this->lockCachedTexture(bm, GrSamplerState::ClampNoFilter(),
+ &fTexture, true, isForSaveLayer);
+ if (fCache) {
+ SkASSERT(NULL != fTexture);
+ SkASSERT(NULL != fTexture->asRenderTarget());
+ }
#else
- const GrTextureDesc desc = {
- kRenderTarget_GrTextureFlagBit,
- kNone_GrAALevel,
- this->width(),
- this->height(),
- SkGr::Bitmap2PixelConfig(bm)
- };
+ const GrTextureDesc desc = {
+ kRenderTarget_GrTextureFlagBit,
+ kNone_GrAALevel,
+ width,
+ height,
+ SkGr::Bitmap2PixelConfig(bm)
+ };
- fTexture = fContext->createUncachedTexture(desc, NULL, 0);
+ fTexture = fContext->createUncachedTexture(desc, NULL, 0);
#endif
- if (NULL != fTexture) {
- fRenderTarget = fTexture->asRenderTarget();
+ if (NULL != fTexture) {
+ fRenderTarget = fTexture->asRenderTarget();
- GrAssert(NULL != fRenderTarget);
+ GrAssert(NULL != fRenderTarget);
- // we defer the actual clear until our gainFocus()
- fNeedClear = true;
+ // we defer the actual clear until our gainFocus()
+ fNeedClear = true;
- // wrap the bitmap with a pixelref to expose our texture
- SkGrTexturePixelRef* pr = new SkGrTexturePixelRef(fTexture);
- this->setPixelRef(pr, 0)->unref();
- } else {
- GrPrintf("--- failed to create gpu-offscreen [%d %d]\n",
- this->width(), this->height());
- GrAssert(false);
- }
- } else {
- if (Current3DApiRenderTarget() == renderTargetOrNull) {
- fRenderTarget = fContext->createRenderTargetFrom3DApiState();
- } else {
- fRenderTarget = renderTargetOrNull;
- fRenderTarget->ref();
- }
- SkGrRenderTargetPixelRef* pr = new SkGrRenderTargetPixelRef(fRenderTarget);
+ // wrap the bitmap with a pixelref to expose our texture
+ SkGrTexturePixelRef* pr = new SkGrTexturePixelRef(fTexture);
this->setPixelRef(pr, 0)->unref();
+ } else {
+ GrPrintf("--- failed to create gpu-offscreen [%d %d]\n",
+ width, height);
+ GrAssert(false);
}
}
SkDevice* SkGpuDeviceFactory::newDevice(SkCanvas*, SkBitmap::Config config,
int width, int height,
bool isOpaque, bool isLayer) {
- SkBitmap bm;
- bm.setConfig(config, width, height);
- bm.setIsOpaque(isOpaque);
- return new SkGpuDevice(fContext, bm, isLayer ? NULL : fRootRenderTarget);
+ if (isLayer) {
+ return SkNEW_ARGS(SkGpuDevice, (fContext, config, width, height));
+ } else {
+ return SkNEW_ARGS(SkGpuDevice, (fContext, fRootRenderTarget));
+ }
}
SkPDFDevice::SkPDFDevice(const SkISize& pageSize, const SkISize& contentSize,
const SkMatrix& initialTransform)
- : SkDevice(NULL, makeContentBitmap(contentSize, &initialTransform), false),
+ : SkDevice(makeContentBitmap(contentSize, &initialTransform)),
fPageSize(pageSize),
fContentSize(contentSize),
fLastContentEntry(NULL) {
SkPDFDevice::SkPDFDevice(const SkISize& layerSize,
const SkClipStack& existingClipStack,
const SkRegion& existingClipRegion)
- : SkDevice(NULL, makeContentBitmap(layerSize, NULL), false),
+ : SkDevice(makeContentBitmap(layerSize, NULL)),
fPageSize(layerSize),
fContentSize(layerSize),
fExistingClipStack(existingClipStack),
}
SkDevice* SkProxyCanvas::createDevice(SkBitmap::Config config, int width, int height,
- bool isOpaque, bool isForLayer) {
- return fProxy->createDevice(config, width, height, isOpaque, isForLayer);
+ bool isOpaque) {
+ return fProxy->createDevice(config, width, height, isOpaque);
}
if (NULL == canvas) {
canvas = &rasterCanvas;
- device = new SkDevice(canvas, bm, false);
- canvas->setDevice(device)->unref();
- } else {
- canvas->setBitmapDevice(bm);
}
+ canvas->setBitmapDevice(bm);
canvas->clipRegion(fDirtyRgn);
if (updateArea)