Refactor SkCanvas so that backends don't need to override it.
Methods or classes that should go away are marked deprecated. The only thing I know of that breaks backward compatibility is SkCanvas((SkDevice*)NULL), but that is fairly unlikely to occur in the wild because that constructor had a default value of NULL. Review URL: http://codereview.appspot.com/2103045 git-svn-id: http://skia.googlecode.com/svn/trunk@604 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
60eaa398eb
commit
8d84fac294
@ -29,6 +29,7 @@
|
||||
|
||||
class SkBounder;
|
||||
class SkDevice;
|
||||
class SkDeviceFactory;
|
||||
class SkDraw;
|
||||
class SkDrawFilter;
|
||||
class SkPicture;
|
||||
@ -51,29 +52,37 @@ class SkShape;
|
||||
*/
|
||||
class SkCanvas : public SkRefCnt {
|
||||
public:
|
||||
/** Construct a canvas with the specified bitmap to draw into.
|
||||
/** Construct a canvas with the given device factory.
|
||||
@param factory Specify the factory for generating additional devices.
|
||||
The factory may be null, in which case SkDeviceFactory
|
||||
will be used.
|
||||
*/
|
||||
explicit SkCanvas(SkDeviceFactory* factory = NULL);
|
||||
|
||||
/** Construct a canvas with the specified device to draw into. The device
|
||||
factory will be retrieved from the passed device.
|
||||
@param device Specifies a device for the canvas to draw into.
|
||||
*/
|
||||
explicit SkCanvas(SkDevice* device);
|
||||
|
||||
/** Deprecated - Construct a canvas with the specified bitmap to draw into.
|
||||
@param bitmap Specifies a bitmap for the canvas to draw into. Its
|
||||
structure are copied to the canvas.
|
||||
*/
|
||||
explicit SkCanvas(const SkBitmap& bitmap);
|
||||
/** Construct a canvas with the specified device to draw into.
|
||||
@param device Specifies a device for the canvas to draw into. The
|
||||
device may be null.
|
||||
*/
|
||||
explicit SkCanvas(SkDevice* device = NULL);
|
||||
virtual ~SkCanvas();
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/** If this subclass of SkCanvas supports GL viewports, return true and set
|
||||
size (if not null) to the size of the viewport. If it is not supported,
|
||||
ignore vp and return false.
|
||||
/** If the Device supports GL viewports, return true and set size (if not
|
||||
null) to the size of the viewport. If it is not supported, ignore size
|
||||
and return false.
|
||||
*/
|
||||
virtual bool getViewport(SkIPoint* size) const;
|
||||
|
||||
/** If this subclass of SkCanvas supports GL viewports, return true and set
|
||||
the viewport to the specified x and y dimensions. If it is not
|
||||
supported, ignore x and y and return false.
|
||||
/** If the Device supports GL viewports, return true and set the viewport
|
||||
to the specified x and y dimensions. If it is not supported, ignore x
|
||||
and y and return false.
|
||||
*/
|
||||
virtual bool setViewport(int x, int y);
|
||||
|
||||
@ -89,9 +98,10 @@ public:
|
||||
*/
|
||||
SkDevice* setDevice(SkDevice* device);
|
||||
|
||||
/** Specify a bitmap for the canvas to draw into. This is a help method for
|
||||
setDevice(), and it creates a device for the bitmap by calling
|
||||
createDevice(). The structure of the bitmap is copied into the device.
|
||||
/** Deprecated - Specify a bitmap for the canvas to draw into. This is a
|
||||
helper method for setDevice(), and it creates a device for the bitmap by
|
||||
calling createDevice(). The structure of the bitmap is copied into the
|
||||
device.
|
||||
*/
|
||||
virtual SkDevice* setBitmapDevice(const SkBitmap& bitmap);
|
||||
|
||||
@ -749,6 +759,7 @@ private:
|
||||
|
||||
SkBounder* fBounder;
|
||||
SkDevice* fLastDeviceToGainFocus;
|
||||
SkDeviceFactory* fDeviceFactory;
|
||||
|
||||
void prepareForDeviceDraw(SkDevice*);
|
||||
|
||||
|
@ -22,26 +22,52 @@
|
||||
#include "SkCanvas.h"
|
||||
#include "SkColor.h"
|
||||
|
||||
class SkDevice;
|
||||
class SkDraw;
|
||||
struct SkIRect;
|
||||
class SkMatrix;
|
||||
class SkRegion;
|
||||
|
||||
/** \class SkDeviceFactory
|
||||
|
||||
Devices that extend SkDevice should also provide a SkDeviceFactory class
|
||||
to pass into SkCanvas. Doing so will eliminate the need to extend
|
||||
SkCanvas as well.
|
||||
*/
|
||||
class SkDeviceFactory : public SkRefCnt {
|
||||
public:
|
||||
virtual SkDevice* newDevice(SkBitmap::Config config, int width, int height,
|
||||
bool isOpaque, bool isForLayer) = 0;
|
||||
|
||||
enum Capabilities {
|
||||
kGL_Capability = 0x1, //!< mask to indicate this device supports GL
|
||||
kAll_Capabilities = 0x1
|
||||
};
|
||||
virtual uint32_t getDeviceCapabilities() = 0;
|
||||
};
|
||||
|
||||
class SkRasterDeviceFactory : public SkDeviceFactory {
|
||||
public:
|
||||
virtual SkDevice* newDevice(SkBitmap::Config config, int width, int height,
|
||||
bool isOpaque, bool isForLayer);
|
||||
virtual uint32_t getDeviceCapabilities() { return 0; }
|
||||
};
|
||||
|
||||
class SkDevice : public SkRefCnt {
|
||||
public:
|
||||
SkDevice();
|
||||
/** 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.
|
||||
|
||||
Subclasses may override the destructor, which is virtual, even though this class
|
||||
doesn't have one. SkRefCnt does.
|
||||
/** Construct a new device, extracting the width/height/config/isOpaque
|
||||
values from the bitmap. 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
|
||||
*/
|
||||
SkDevice(const SkBitmap& bitmap);
|
||||
|
||||
virtual SkDeviceFactory* getDeviceFactory() {
|
||||
return SkNEW(SkRasterDeviceFactory);
|
||||
}
|
||||
|
||||
/** Return the width of the device (in pixels).
|
||||
*/
|
||||
int width() const { return fBitmap.width(); }
|
||||
|
@ -18,62 +18,35 @@
|
||||
#define SkGLCanvas_DEFINED
|
||||
|
||||
#include "SkCanvas.h"
|
||||
#include "SkGLDevice.h"
|
||||
|
||||
#ifdef SK_BUILD_FOR_MAC
|
||||
#include <OpenGL/gl.h>
|
||||
#elif defined(ANDROID)
|
||||
#include <GLES/gl.h>
|
||||
#endif
|
||||
|
||||
class SkGLDevice;
|
||||
class SkGLClipIter;
|
||||
|
||||
// Deprecated. You should now use SkGLDevice and SkGLDeviceFactory with
|
||||
// SkCanvas.
|
||||
class SkGLCanvas : public SkCanvas {
|
||||
public:
|
||||
// notice, we do NOT allow the SkCanvas(bitmap) constructor, since that
|
||||
// does not create a SkGLDevice, which we require
|
||||
SkGLCanvas();
|
||||
virtual ~SkGLCanvas();
|
||||
SkGLCanvas() : SkCanvas(SkNEW(SkGLDeviceFactory)) {}
|
||||
|
||||
// overrides from SkCanvas
|
||||
|
||||
virtual bool getViewport(SkIPoint*) const;
|
||||
virtual bool setViewport(int width, int height);
|
||||
|
||||
virtual SkDevice* createDevice(SkBitmap::Config, int width, int height,
|
||||
bool isOpaque, bool isForLayer);
|
||||
|
||||
// settings for the global texture cache
|
||||
|
||||
static size_t GetTextureCacheMaxCount();
|
||||
static void SetTextureCacheMaxCount(size_t count);
|
||||
|
||||
static size_t GetTextureCacheMaxSize();
|
||||
static void SetTextureCacheMaxSize(size_t size);
|
||||
|
||||
/** Call glDeleteTextures for all textures (including those for text)
|
||||
This should be called while the gl-context is still valid. Its purpose
|
||||
is to free up gl resources. Note that if a bitmap or text is drawn after
|
||||
this call, new caches will be created.
|
||||
*/
|
||||
static void DeleteAllTextures();
|
||||
|
||||
/** Forget all textures without calling delete (including those for text).
|
||||
This should be called if the gl-context has changed, and the texture
|
||||
IDs that have been cached are no longer valid.
|
||||
*/
|
||||
static void AbandonAllTextures();
|
||||
|
||||
private:
|
||||
SkIPoint fViewportSize;
|
||||
|
||||
// need to disallow this guy
|
||||
virtual SkDevice* setBitmapDevice(const SkBitmap& bitmap) {
|
||||
sk_throw();
|
||||
return NULL;
|
||||
static size_t GetTextureCacheMaxCount() {
|
||||
return SkGLDevice::GetTextureCacheMaxCount();
|
||||
}
|
||||
static void SetTextureCacheMaxCount(size_t count) {
|
||||
SkGLDevice::SetTextureCacheMaxCount(count);
|
||||
}
|
||||
|
||||
typedef SkCanvas INHERITED;
|
||||
static size_t GetTextureCacheMaxSize() {
|
||||
return SkGLDevice::GetTextureCacheMaxSize();
|
||||
}
|
||||
static void SetTextureCacheMaxSize(size_t size) {
|
||||
SkGLDevice::SetTextureCacheMaxSize(size);
|
||||
}
|
||||
|
||||
static void DeleteAllTextures() {
|
||||
SkGLDevice::DeleteAllTextures();
|
||||
}
|
||||
|
||||
static void AbandonAllTextures() {
|
||||
SkGLDevice::AbandonAllTextures();
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -404,8 +404,21 @@ SkDevice* SkCanvas::init(SkDevice* device) {
|
||||
return this->setDevice(device);
|
||||
}
|
||||
|
||||
SkCanvas::SkCanvas(SkDeviceFactory* factory)
|
||||
: fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)),
|
||||
fDeviceFactory(factory) {
|
||||
inc_canvas();
|
||||
|
||||
SkSafeRef(factory);
|
||||
if (!factory)
|
||||
fDeviceFactory = SkNEW(SkRasterDeviceFactory);
|
||||
|
||||
this->init(NULL);
|
||||
}
|
||||
|
||||
SkCanvas::SkCanvas(SkDevice* device)
|
||||
: fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) {
|
||||
: fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)),
|
||||
fDeviceFactory(device->getDeviceFactory()) {
|
||||
inc_canvas();
|
||||
|
||||
this->init(device);
|
||||
@ -415,7 +428,9 @@ SkCanvas::SkCanvas(const SkBitmap& bitmap)
|
||||
: fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) {
|
||||
inc_canvas();
|
||||
|
||||
this->init(SkNEW_ARGS(SkDevice, (bitmap)))->unref();
|
||||
SkDevice* device = SkNEW_ARGS(SkDevice, (bitmap));
|
||||
fDeviceFactory = device->getDeviceFactory();
|
||||
this->init(device)->unref();
|
||||
}
|
||||
|
||||
SkCanvas::~SkCanvas() {
|
||||
@ -423,7 +438,8 @@ SkCanvas::~SkCanvas() {
|
||||
this->restoreToCount(1); // restore everything but the last
|
||||
this->internalRestore(); // restore the last, since we're going away
|
||||
|
||||
fBounder->safeUnref();
|
||||
SkSafeUnref(fBounder);
|
||||
SkSafeUnref(fDeviceFactory);
|
||||
|
||||
dec_canvas();
|
||||
}
|
||||
@ -521,11 +537,21 @@ SkDevice* SkCanvas::setBitmapDevice(const SkBitmap& bitmap) {
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool SkCanvas::getViewport(SkIPoint* size) const {
|
||||
if ((fDeviceFactory->getDeviceCapabilities()
|
||||
& SkDeviceFactory::kGL_Capability) == 0)
|
||||
return false;
|
||||
if (size)
|
||||
size->set(getDevice()->width(), getDevice()->height());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SkCanvas::setViewport(int width, int height) {
|
||||
if ((fDeviceFactory->getDeviceCapabilities()
|
||||
& SkDeviceFactory::kGL_Capability) == 0)
|
||||
return false;
|
||||
this->setDevice(createDevice(SkBitmap::kARGB_8888_Config, width, height,
|
||||
false, false))->unref();
|
||||
return true;
|
||||
}
|
||||
|
||||
void SkCanvas::updateDeviceCMCache() {
|
||||
@ -1004,18 +1030,9 @@ const SkRegion& SkCanvas::getTotalClip() const {
|
||||
|
||||
SkDevice* SkCanvas::createDevice(SkBitmap::Config config, int width,
|
||||
int height, bool isOpaque, bool isForLayer) {
|
||||
SkBitmap bitmap;
|
||||
|
||||
bitmap.setConfig(config, width, height);
|
||||
bitmap.setIsOpaque(isOpaque);
|
||||
|
||||
// should this happen in the device subclass?
|
||||
bitmap.allocPixels();
|
||||
if (!bitmap.isOpaque()) {
|
||||
bitmap.eraseARGB(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
return SkNEW_ARGS(SkDevice, (bitmap));
|
||||
return fDeviceFactory->newDevice(config, width, height, isOpaque,
|
||||
isForLayer);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -107,4 +107,16 @@ void SkDevice::drawDevice(const SkDraw& draw, SkDevice* device,
|
||||
draw.drawSprite(device->accessBitmap(false), x, y, paint);
|
||||
}
|
||||
|
||||
SkDevice* SkRasterDeviceFactory::newDevice(SkBitmap::Config config, int width,
|
||||
int height, bool isOpaque,
|
||||
bool isForLayer) {
|
||||
SkBitmap bitmap;
|
||||
bitmap.setConfig(config, width, height);
|
||||
bitmap.setIsOpaque(isOpaque);
|
||||
|
||||
bitmap.allocPixels();
|
||||
if (!bitmap.isOpaque())
|
||||
bitmap.eraseARGB(0, 0, 0, 0);
|
||||
|
||||
return SkNEW_ARGS(SkDevice, (bitmap));
|
||||
}
|
||||
|
@ -1,180 +0,0 @@
|
||||
#include "SkGLCanvas.h"
|
||||
#include "SkGLDevice.h"
|
||||
#include "SkBlitter.h"
|
||||
#include "SkDraw.h"
|
||||
#include "SkDrawProcs.h"
|
||||
#include "SkGL.h"
|
||||
#include "SkGlyphCache.h"
|
||||
#include "SkTemplates.h"
|
||||
#include "SkUtils.h"
|
||||
#include "SkXfermode.h"
|
||||
|
||||
#ifdef SK_GL_DEVICE_FBO
|
||||
#define USE_FBO_DEVICE
|
||||
#include "SkGLDevice_FBO.h"
|
||||
#else
|
||||
#define USE_SWLAYER_DEVICE
|
||||
#include "SkGLDevice_SWLayer.h"
|
||||
#endif
|
||||
|
||||
// maximum number of entries in our texture cache (before purging)
|
||||
#define kTexCountMax_Default 256
|
||||
// maximum number of bytes used (by gl) for the texture cache (before purging)
|
||||
#define kTexSizeMax_Default (4 * 1024 * 1024)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SkGLCanvas::SkGLCanvas() {
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
|
||||
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
||||
|
||||
fViewportSize.set(0, 0);
|
||||
}
|
||||
|
||||
SkGLCanvas::~SkGLCanvas() {
|
||||
// call this now, while our override of restore() is in effect
|
||||
this->restoreToCount(1);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool SkGLCanvas::getViewport(SkIPoint* size) const {
|
||||
if (size) {
|
||||
*size = fViewportSize;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SkGLCanvas::setViewport(int width, int height) {
|
||||
fViewportSize.set(width, height);
|
||||
|
||||
const bool isOpaque = false; // should this be a parameter to setViewport?
|
||||
const bool isForLayer = false; // viewport is the base layer
|
||||
SkDevice* device = this->createDevice(SkBitmap::kARGB_8888_Config, width,
|
||||
height, isOpaque, isForLayer);
|
||||
this->setDevice(device)->unref();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
SkDevice* SkGLCanvas::createDevice(SkBitmap::Config, int width, int height,
|
||||
bool isOpaque, bool isForLayer) {
|
||||
SkBitmap bitmap;
|
||||
|
||||
bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height);
|
||||
bitmap.setIsOpaque(isOpaque);
|
||||
|
||||
#ifdef USE_FBO_DEVICE
|
||||
return SkNEW_ARGS(SkGLDevice_FBO, (bitmap, isForLayer));
|
||||
#elif defined(USE_SWLAYER_DEVICE)
|
||||
if (isForLayer) {
|
||||
bitmap.allocPixels();
|
||||
if (!bitmap.isOpaque()) {
|
||||
bitmap.eraseColor(0);
|
||||
}
|
||||
return SkNEW_ARGS(SkGLDevice_SWLayer, (bitmap));
|
||||
} else {
|
||||
return SkNEW_ARGS(SkGLDevice, (bitmap, isForLayer));
|
||||
}
|
||||
#else
|
||||
return SkNEW_ARGS(SkGLDevice, (bitmap, isForLayer));
|
||||
#endif
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "SkTextureCache.h"
|
||||
#include "SkThread.h"
|
||||
|
||||
static SkMutex gTextureCacheMutex;
|
||||
static SkTextureCache gTextureCache(kTexCountMax_Default, kTexSizeMax_Default);
|
||||
|
||||
SkGLDevice::TexCache* SkGLDevice::LockTexCache(const SkBitmap& bitmap,
|
||||
GLuint* name, SkPoint* size) {
|
||||
SkAutoMutexAcquire amc(gTextureCacheMutex);
|
||||
|
||||
SkTextureCache::Entry* entry = gTextureCache.lock(bitmap);
|
||||
if (NULL != entry) {
|
||||
if (name) {
|
||||
*name = entry->name();
|
||||
}
|
||||
if (size) {
|
||||
*size = entry->texSize();
|
||||
}
|
||||
}
|
||||
return (TexCache*)entry;
|
||||
}
|
||||
|
||||
void SkGLDevice::UnlockTexCache(TexCache* cache) {
|
||||
SkAutoMutexAcquire amc(gTextureCacheMutex);
|
||||
gTextureCache.unlock((SkTextureCache::Entry*)cache);
|
||||
}
|
||||
|
||||
// public exposure of texture cache settings
|
||||
|
||||
size_t SkGLCanvas::GetTextureCacheMaxCount() {
|
||||
SkAutoMutexAcquire amc(gTextureCacheMutex);
|
||||
return gTextureCache.getMaxCount();
|
||||
}
|
||||
|
||||
size_t SkGLCanvas::GetTextureCacheMaxSize() {
|
||||
SkAutoMutexAcquire amc(gTextureCacheMutex);
|
||||
return gTextureCache.getMaxSize();
|
||||
}
|
||||
|
||||
void SkGLCanvas::SetTextureCacheMaxCount(size_t count) {
|
||||
SkAutoMutexAcquire amc(gTextureCacheMutex);
|
||||
gTextureCache.setMaxCount(count);
|
||||
}
|
||||
|
||||
void SkGLCanvas::SetTextureCacheMaxSize(size_t size) {
|
||||
SkAutoMutexAcquire amc(gTextureCacheMutex);
|
||||
gTextureCache.setMaxSize(size);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "SkGLTextCache.h"
|
||||
|
||||
static bool deleteCachesProc(SkGlyphCache* cache, void* texturesAreValid) {
|
||||
void* auxData;
|
||||
if (cache->getAuxProcData(SkGLDevice::GlyphCacheAuxProc, &auxData)) {
|
||||
bool valid = texturesAreValid != NULL;
|
||||
SkGLTextCache* textCache = static_cast<SkGLTextCache*>(auxData);
|
||||
// call this before delete, in case valid is false
|
||||
textCache->deleteAllStrikes(valid);
|
||||
// now free the memory for the cache itself
|
||||
SkDELETE(textCache);
|
||||
// now remove the entry in the glyphcache (does not call the proc)
|
||||
cache->removeAuxProc(SkGLDevice::GlyphCacheAuxProc);
|
||||
}
|
||||
return false; // keep going
|
||||
}
|
||||
|
||||
void SkGLCanvas::DeleteAllTextures() {
|
||||
// free the textures in our cache
|
||||
|
||||
gTextureCacheMutex.acquire();
|
||||
gTextureCache.deleteAllCaches(true);
|
||||
gTextureCacheMutex.release();
|
||||
|
||||
// now free the textures in the font cache
|
||||
|
||||
SkGlyphCache::VisitAllCaches(deleteCachesProc, reinterpret_cast<void*>(true));
|
||||
}
|
||||
|
||||
void SkGLCanvas::AbandonAllTextures() {
|
||||
// abandon the textures in our cache
|
||||
|
||||
gTextureCacheMutex.acquire();
|
||||
gTextureCache.deleteAllCaches(false);
|
||||
gTextureCacheMutex.release();
|
||||
|
||||
// abandon the textures in the font cache
|
||||
|
||||
SkGlyphCache::VisitAllCaches(deleteCachesProc, reinterpret_cast<void*>(false));
|
||||
}
|
||||
|
@ -4,6 +4,19 @@
|
||||
#include "SkRegion.h"
|
||||
#include "SkThread.h"
|
||||
|
||||
#ifdef SK_GL_DEVICE_FBO
|
||||
#define USE_FBO_DEVICE
|
||||
#include "SkGLDevice_FBO.h"
|
||||
#else
|
||||
#define USE_SWLAYER_DEVICE
|
||||
#include "SkGLDevice_SWLayer.h"
|
||||
#endif
|
||||
|
||||
// maximum number of entries in our texture cache (before purging)
|
||||
#define kTexCountMax_Default 256
|
||||
// maximum number of bytes used (by gl) for the texture cache (before purging)
|
||||
#define kTexSizeMax_Default (4 * 1024 * 1024)
|
||||
|
||||
static void TRACE_DRAW(const char func[], SkGLDevice* device,
|
||||
const SkDraw& draw) {
|
||||
// SkDebugf("--- <%s> %p %p\n", func, canvas, draw.fDevice);
|
||||
@ -69,8 +82,39 @@ private:
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SkDevice* SkGLDeviceFactory::newDevice(SkBitmap::Config config, int width,
|
||||
int height, bool isOpaque,
|
||||
bool isForLayer) {
|
||||
SkBitmap bitmap;
|
||||
|
||||
bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height);
|
||||
bitmap.setIsOpaque(isOpaque);
|
||||
|
||||
#ifdef USE_FBO_DEVICE
|
||||
return SkNEW_ARGS(SkGLDevice_FBO, (bitmap, isForLayer));
|
||||
#elif defined(USE_SWLAYER_DEVICE)
|
||||
if (isForLayer) {
|
||||
bitmap.allocPixels();
|
||||
if (!bitmap.isOpaque()) {
|
||||
bitmap.eraseColor(0);
|
||||
}
|
||||
return SkNEW_ARGS(SkGLDevice_SWLayer, (bitmap));
|
||||
} else {
|
||||
return SkNEW_ARGS(SkGLDevice, (bitmap, isForLayer));
|
||||
}
|
||||
#else
|
||||
return SkNEW_ARGS(SkGLDevice, (bitmap, isForLayer));
|
||||
#endif
|
||||
}
|
||||
|
||||
SkGLDevice::SkGLDevice(const SkBitmap& bitmap, bool offscreen)
|
||||
: SkDevice(bitmap), fClipIter(bitmap.height()) {
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
|
||||
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
||||
|
||||
fDrawProcs = NULL;
|
||||
}
|
||||
|
||||
@ -811,3 +855,99 @@ void SkGLDevice::drawTextOnPath(const SkDraw& draw, const void* text,
|
||||
SkGL_unimpl("drawTextOnPath");
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "SkTextureCache.h"
|
||||
#include "SkThread.h"
|
||||
|
||||
static SkMutex gTextureCacheMutex;
|
||||
static SkTextureCache gTextureCache(kTexCountMax_Default, kTexSizeMax_Default);
|
||||
|
||||
SkGLDevice::TexCache* SkGLDevice::LockTexCache(const SkBitmap& bitmap,
|
||||
GLuint* name, SkPoint* size) {
|
||||
SkAutoMutexAcquire amc(gTextureCacheMutex);
|
||||
|
||||
SkTextureCache::Entry* entry = gTextureCache.lock(bitmap);
|
||||
if (NULL != entry) {
|
||||
if (name) {
|
||||
*name = entry->name();
|
||||
}
|
||||
if (size) {
|
||||
*size = entry->texSize();
|
||||
}
|
||||
}
|
||||
return (TexCache*)entry;
|
||||
}
|
||||
|
||||
void SkGLDevice::UnlockTexCache(TexCache* cache) {
|
||||
SkAutoMutexAcquire amc(gTextureCacheMutex);
|
||||
gTextureCache.unlock((SkTextureCache::Entry*)cache);
|
||||
}
|
||||
|
||||
// public exposure of texture cache settings
|
||||
|
||||
size_t SkGLDevice::GetTextureCacheMaxCount() {
|
||||
SkAutoMutexAcquire amc(gTextureCacheMutex);
|
||||
return gTextureCache.getMaxCount();
|
||||
}
|
||||
|
||||
size_t SkGLDevice::GetTextureCacheMaxSize() {
|
||||
SkAutoMutexAcquire amc(gTextureCacheMutex);
|
||||
return gTextureCache.getMaxSize();
|
||||
}
|
||||
|
||||
void SkGLDevice::SetTextureCacheMaxCount(size_t count) {
|
||||
SkAutoMutexAcquire amc(gTextureCacheMutex);
|
||||
gTextureCache.setMaxCount(count);
|
||||
}
|
||||
|
||||
void SkGLDevice::SetTextureCacheMaxSize(size_t size) {
|
||||
SkAutoMutexAcquire amc(gTextureCacheMutex);
|
||||
gTextureCache.setMaxSize(size);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "SkGLTextCache.h"
|
||||
|
||||
static bool deleteCachesProc(SkGlyphCache* cache, void* texturesAreValid) {
|
||||
void* auxData;
|
||||
if (cache->getAuxProcData(SkGLDevice::GlyphCacheAuxProc, &auxData)) {
|
||||
bool valid = texturesAreValid != NULL;
|
||||
SkGLTextCache* textCache = static_cast<SkGLTextCache*>(auxData);
|
||||
// call this before delete, in case valid is false
|
||||
textCache->deleteAllStrikes(valid);
|
||||
// now free the memory for the cache itself
|
||||
SkDELETE(textCache);
|
||||
// now remove the entry in the glyphcache (does not call the proc)
|
||||
cache->removeAuxProc(SkGLDevice::GlyphCacheAuxProc);
|
||||
}
|
||||
return false; // keep going
|
||||
}
|
||||
|
||||
void SkGLDevice::DeleteAllTextures() {
|
||||
// free the textures in our cache
|
||||
|
||||
gTextureCacheMutex.acquire();
|
||||
gTextureCache.deleteAllCaches(true);
|
||||
gTextureCacheMutex.release();
|
||||
|
||||
// now free the textures in the font cache
|
||||
|
||||
SkGlyphCache::VisitAllCaches(deleteCachesProc, reinterpret_cast<void*>(true)
|
||||
);
|
||||
}
|
||||
|
||||
void SkGLDevice::AbandonAllTextures() {
|
||||
// abandon the textures in our cache
|
||||
|
||||
gTextureCacheMutex.acquire();
|
||||
gTextureCache.deleteAllCaches(false);
|
||||
gTextureCacheMutex.release();
|
||||
|
||||
// abandon the textures in the font cache
|
||||
|
||||
SkGlyphCache::VisitAllCaches(deleteCachesProc, reinterpret_cast<void*>(false
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,19 @@
|
||||
#include "SkGL.h"
|
||||
#include "SkRegion.h"
|
||||
|
||||
#ifdef SK_BUILD_FOR_MAC
|
||||
#include <OpenGL/gl.h>
|
||||
#elif defined(ANDROID)
|
||||
#include <GLES/gl.h>
|
||||
#endif
|
||||
|
||||
class SkGLDeviceFactory : public SkDeviceFactory {
|
||||
public:
|
||||
virtual SkDevice* newDevice(SkBitmap::Config config, int width, int height,
|
||||
bool isOpaque, bool isForLayer);
|
||||
virtual uint32_t getDeviceCapabilities() { return kGL_Capability; }
|
||||
};
|
||||
|
||||
struct SkGLDrawProcs;
|
||||
|
||||
class SkGLDevice : public SkDevice {
|
||||
@ -12,6 +25,10 @@ public:
|
||||
SkGLDevice(const SkBitmap& bitmap, bool offscreen);
|
||||
virtual ~SkGLDevice();
|
||||
|
||||
virtual SkDeviceFactory* getDeviceFactory() {
|
||||
return SkNEW(SkGLDeviceFactory);
|
||||
}
|
||||
|
||||
// used to identify GLTextCache data in the glyphcache
|
||||
static void GlyphCacheAuxProc(void* data);
|
||||
|
||||
@ -63,6 +80,27 @@ public:
|
||||
virtual void drawDevice(const SkDraw&, SkDevice*, int x, int y,
|
||||
const SkPaint&);
|
||||
|
||||
// settings for the global texture cache
|
||||
|
||||
static size_t GetTextureCacheMaxCount();
|
||||
static void SetTextureCacheMaxCount(size_t count);
|
||||
|
||||
static size_t GetTextureCacheMaxSize();
|
||||
static void SetTextureCacheMaxSize(size_t size);
|
||||
|
||||
/** Call glDeleteTextures for all textures (including those for text)
|
||||
This should be called while the gl-context is still valid. Its purpose
|
||||
is to free up gl resources. Note that if a bitmap or text is drawn after
|
||||
this call, new caches will be created.
|
||||
*/
|
||||
static void DeleteAllTextures();
|
||||
|
||||
/** Forget all textures without calling delete (including those for text).
|
||||
This should be called if the gl-context has changed, and the texture
|
||||
IDs that have been cached are no longer valid.
|
||||
*/
|
||||
static void AbandonAllTextures();
|
||||
|
||||
protected:
|
||||
/** Return the current glmatrix, from a previous call to setMatrixClip */
|
||||
const SkMatrix& matrix() const { return fMatrix; }
|
||||
|
@ -26,7 +26,6 @@
|
||||
0001FB87110E35E500C1D647 /* AGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0001FB86110E35E500C1D647 /* AGL.framework */; };
|
||||
0001FB8A110E35FA00C1D647 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0001FB89110E35FA00C1D647 /* OpenGL.framework */; };
|
||||
0001FB94110E362F00C1D647 /* SkGL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0001FB8D110E362F00C1D647 /* SkGL.cpp */; };
|
||||
0001FB95110E362F00C1D647 /* SkGLCanvas.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0001FB8E110E362F00C1D647 /* SkGLCanvas.cpp */; };
|
||||
0001FB96110E362F00C1D647 /* SkGLDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0001FB8F110E362F00C1D647 /* SkGLDevice.cpp */; };
|
||||
0001FB97110E362F00C1D647 /* SkGLDevice_FBO.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0001FB90110E362F00C1D647 /* SkGLDevice_FBO.cpp */; };
|
||||
0001FB98110E362F00C1D647 /* SkGLState.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0001FB91110E362F00C1D647 /* SkGLState.cpp */; };
|
||||
@ -99,7 +98,6 @@
|
||||
27005D5F10095B2B00E275B6 /* SampleCircle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0041CE200F00A12400695E8C /* SampleCircle.cpp */; };
|
||||
27433F1E11A1874A0045AD84 /* SampleSVG.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 27CAAB9B119B32670017B155 /* SampleSVG.cpp */; };
|
||||
27433F3311A18EA60045AD84 /* SampleTextEffects.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 007A7CAD0F01658C00A2D6EE /* SampleTextEffects.cpp */; };
|
||||
27433F4911A1D24E0045AD84 /* SampleMessages.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 27433F4811A1D24E0045AD84 /* SampleMessages.cpp */; };
|
||||
275E801611AAC2FF0051C03A /* SampleShapes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 003145310FB9B48F00B10956 /* SampleShapes.cpp */; };
|
||||
275E802311AAC3330051C03A /* SampleVertices.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 007A7CB10F01658C00A2D6EE /* SampleVertices.cpp */; };
|
||||
2762F66D0FCCCABE002BD8B4 /* SkFlipPixelRef.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2762F66B0FCCCABE002BD8B4 /* SkFlipPixelRef.cpp */; };
|
||||
@ -219,7 +217,6 @@
|
||||
0001FB86110E35E500C1D647 /* AGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AGL.framework; path = /System/Library/Frameworks/AGL.framework; sourceTree = "<absolute>"; };
|
||||
0001FB89110E35FA00C1D647 /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = /System/Library/Frameworks/OpenGL.framework; sourceTree = "<absolute>"; };
|
||||
0001FB8D110E362F00C1D647 /* SkGL.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkGL.cpp; path = ../../src/gl/SkGL.cpp; sourceTree = SOURCE_ROOT; };
|
||||
0001FB8E110E362F00C1D647 /* SkGLCanvas.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkGLCanvas.cpp; path = ../../src/gl/SkGLCanvas.cpp; sourceTree = SOURCE_ROOT; };
|
||||
0001FB8F110E362F00C1D647 /* SkGLDevice.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkGLDevice.cpp; path = ../../src/gl/SkGLDevice.cpp; sourceTree = SOURCE_ROOT; };
|
||||
0001FB90110E362F00C1D647 /* SkGLDevice_FBO.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkGLDevice_FBO.cpp; path = ../../src/gl/SkGLDevice_FBO.cpp; sourceTree = SOURCE_ROOT; };
|
||||
0001FB91110E362F00C1D647 /* SkGLState.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkGLState.cpp; path = ../../src/gl/SkGLState.cpp; sourceTree = SOURCE_ROOT; };
|
||||
@ -307,7 +304,6 @@
|
||||
0867D6ABFE840B52C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||
1870340FFE93FCAF11CA0CD7 /* English */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = English; path = English.lproj/main.nib; sourceTree = "<group>"; };
|
||||
20286C33FDCF999611CA2CEA /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = /System/Library/Frameworks/Carbon.framework; sourceTree = "<absolute>"; };
|
||||
27433F4811A1D24E0045AD84 /* SampleMessages.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SampleMessages.cpp; path = ../../tetrark/SampleMessages.cpp; sourceTree = SOURCE_ROOT; };
|
||||
2762F66B0FCCCABE002BD8B4 /* SkFlipPixelRef.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkFlipPixelRef.cpp; path = ../../src/images/SkFlipPixelRef.cpp; sourceTree = SOURCE_ROOT; };
|
||||
2762F66C0FCCCABE002BD8B4 /* SkPageFlipper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkPageFlipper.cpp; path = ../../src/images/SkPageFlipper.cpp; sourceTree = SOURCE_ROOT; };
|
||||
2762F6740FCCCB01002BD8B4 /* SampleAll.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SampleAll.cpp; path = ../../samplecode/SampleAll.cpp; sourceTree = SOURCE_ROOT; };
|
||||
@ -507,7 +503,6 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
0001FB8D110E362F00C1D647 /* SkGL.cpp */,
|
||||
0001FB8E110E362F00C1D647 /* SkGLCanvas.cpp */,
|
||||
0001FB8F110E362F00C1D647 /* SkGLDevice.cpp */,
|
||||
0001FB90110E362F00C1D647 /* SkGLDevice_FBO.cpp */,
|
||||
0001FB91110E362F00C1D647 /* SkGLState.cpp */,
|
||||
@ -581,7 +576,6 @@
|
||||
00EB4592104DBB18002B413E /* ForthTests.cpp */,
|
||||
00BB289A104781D00057BF7E /* SampleForth.cpp */,
|
||||
00003C620EFC22A8000FF73A /* SampleApp.cpp */,
|
||||
27433F4811A1D24E0045AD84 /* SampleMessages.cpp */,
|
||||
2762F66A0FCCCAA2002BD8B4 /* images */,
|
||||
00003C6A0EFC22AD000FF73A /* views */,
|
||||
00281C7B1083CFB700BCCB06 /* xml */,
|
||||
@ -890,7 +884,6 @@
|
||||
0061BCD910D951AA0079EBE5 /* SkTextBox.cpp in Sources */,
|
||||
0001FB78110E33CC00C1D647 /* SampleTestGL.cpp in Sources */,
|
||||
0001FB94110E362F00C1D647 /* SkGL.cpp in Sources */,
|
||||
0001FB95110E362F00C1D647 /* SkGLCanvas.cpp in Sources */,
|
||||
0001FB96110E362F00C1D647 /* SkGLDevice.cpp in Sources */,
|
||||
0001FB97110E362F00C1D647 /* SkGLDevice_FBO.cpp in Sources */,
|
||||
0001FB98110E362F00C1D647 /* SkGLState.cpp in Sources */,
|
||||
@ -929,7 +922,6 @@
|
||||
27CAAB96119B321A0017B155 /* SkXMLWriter.cpp in Sources */,
|
||||
27433F1E11A1874A0045AD84 /* SampleSVG.cpp in Sources */,
|
||||
27433F3311A18EA60045AD84 /* SampleTextEffects.cpp in Sources */,
|
||||
27433F4911A1D24E0045AD84 /* SampleMessages.cpp in Sources */,
|
||||
275E801611AAC2FF0051C03A /* SampleShapes.cpp in Sources */,
|
||||
275E802311AAC3330051C03A /* SampleVertices.cpp in Sources */,
|
||||
27D0F3C311BD2012001B8EBE /* SampleText.cpp in Sources */,
|
||||
|
Loading…
Reference in New Issue
Block a user