diff options
author | vandebo@chromium.org <vandebo@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2010-10-13 22:13:05 +0000 |
---|---|---|
committer | vandebo@chromium.org <vandebo@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2010-10-13 22:13:05 +0000 |
commit | 8d84fac294682647694b0d2d8a87ac2bd19b6aab (patch) | |
tree | 2bfd3dea3c5c79bf42003ce620a51069526f28f0 | |
parent | 60eaa398ebdded0fb7957724c170baabef811e17 (diff) |
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
-rw-r--r-- | include/core/SkCanvas.h | 47 | ||||
-rw-r--r-- | include/core/SkDevice.h | 42 | ||||
-rw-r--r-- | include/utils/SkGLCanvas.h | 69 | ||||
-rw-r--r-- | src/core/SkCanvas.cpp | 49 | ||||
-rw-r--r-- | src/core/SkDevice.cpp | 12 | ||||
-rw-r--r-- | src/gl/SkGLCanvas.cpp | 180 | ||||
-rw-r--r-- | src/gl/SkGLDevice.cpp | 140 | ||||
-rw-r--r-- | src/gl/SkGLDevice.h | 38 | ||||
-rw-r--r-- | xcode/sampleapp/SampleApp.xcodeproj/project.pbxproj | 8 |
9 files changed, 307 insertions, 278 deletions
diff --git a/include/core/SkCanvas.h b/include/core/SkCanvas.h index 0ccc2dd999..6d995b8b55 100644 --- a/include/core/SkCanvas.h +++ b/include/core/SkCanvas.h @@ -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); @@ -88,15 +97,16 @@ public: device, its reference count is decremented. The new device is returned. */ 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); /////////////////////////////////////////////////////////////////////////// - + enum SaveFlags { /** save the matrix state, restoring it on restore() */ kMatrix_SaveFlag = 0x01, @@ -749,6 +759,7 @@ private: SkBounder* fBounder; SkDevice* fLastDeviceToGainFocus; + SkDeviceFactory* fDeviceFactory; void prepareForDeviceDraw(SkDevice*); diff --git a/include/core/SkDevice.h b/include/core/SkDevice.h index 4d678c6a40..b7a9cbcb3a 100644 --- a/include/core/SkDevice.h +++ b/include/core/SkDevice.h @@ -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(); } diff --git a/include/utils/SkGLCanvas.h b/include/utils/SkGLCanvas.h index 40fc52d556..87c81ff5a2 100644 --- a/include/utils/SkGLCanvas.h +++ b/include/utils/SkGLCanvas.h @@ -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(); - - // 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); + SkGLCanvas() : SkCanvas(SkNEW(SkGLDeviceFactory)) {} - 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(); + static size_t GetTextureCacheMaxCount() { + return SkGLDevice::GetTextureCacheMaxCount(); + } + static void SetTextureCacheMaxCount(size_t count) { + SkGLDevice::SetTextureCacheMaxCount(count); + } -private: - SkIPoint fViewportSize; + static size_t GetTextureCacheMaxSize() { + return SkGLDevice::GetTextureCacheMaxSize(); + } + static void SetTextureCacheMaxSize(size_t size) { + SkGLDevice::SetTextureCacheMaxSize(size); + } - // need to disallow this guy - virtual SkDevice* setBitmapDevice(const SkBitmap& bitmap) { - sk_throw(); - return NULL; + static void DeleteAllTextures() { + SkGLDevice::DeleteAllTextures(); } - typedef SkCanvas INHERITED; + static void AbandonAllTextures() { + SkGLDevice::AbandonAllTextures(); + } }; #endif diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp index 61998ec632..7cda41e7d9 100644 --- a/src/core/SkCanvas.cpp +++ b/src/core/SkCanvas.cpp @@ -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 { - return false; + 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) { - return false; + 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); } ////////////////////////////////////////////////////////////////////////////// diff --git a/src/core/SkDevice.cpp b/src/core/SkDevice.cpp index 139174da30..fa43aa254d 100644 --- a/src/core/SkDevice.cpp +++ b/src/core/SkDevice.cpp @@ -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)); +} diff --git a/src/gl/SkGLCanvas.cpp b/src/gl/SkGLCanvas.cpp deleted file mode 100644 index f7bc96d9e3..0000000000 --- a/src/gl/SkGLCanvas.cpp +++ /dev/null @@ -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)); -} - diff --git a/src/gl/SkGLDevice.cpp b/src/gl/SkGLDevice.cpp index d839498dec..ad4377c618 100644 --- a/src/gl/SkGLDevice.cpp +++ b/src/gl/SkGLDevice.cpp @@ -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 +)); +} + diff --git a/src/gl/SkGLDevice.h b/src/gl/SkGLDevice.h index 0fc9e47941..61916c1c5c 100644 --- a/src/gl/SkGLDevice.h +++ b/src/gl/SkGLDevice.h @@ -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; } diff --git a/xcode/sampleapp/SampleApp.xcodeproj/project.pbxproj b/xcode/sampleapp/SampleApp.xcodeproj/project.pbxproj index 911486d700..72b7187bca 100644 --- a/xcode/sampleapp/SampleApp.xcodeproj/project.pbxproj +++ b/xcode/sampleapp/SampleApp.xcodeproj/project.pbxproj @@ -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 */, |