| #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)); |
| } |
| |