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 /src | |
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
Diffstat (limited to 'src')
-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 |
5 files changed, 223 insertions, 196 deletions
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; } |