1 #include "SkGLCanvas.h" 2 #include "SkGLDevice.h" 3 #include "SkBlitter.h" 4 #include "SkDraw.h" 5 #include "SkDrawProcs.h" 6 #include "SkGL.h" 7 #include "SkGlyphCache.h" 8 #include "SkTemplates.h" 9 #include "SkUtils.h" 10 #include "SkXfermode.h" 11 12 #ifdef SK_GL_DEVICE_FBO 13 #define USE_FBO_DEVICE 14 #include "SkGLDevice_FBO.h" 15 #else 16 #define USE_SWLAYER_DEVICE 17 #include "SkGLDevice_SWLayer.h" 18 #endif 19 20 // maximum number of entries in our texture cache (before purging) 21 #define kTexCountMax_Default 256 22 // maximum number of bytes used (by gl) for the texture cache (before purging) 23 #define kTexSizeMax_Default (4 * 1024 * 1024) 24 25 /////////////////////////////////////////////////////////////////////////////// 26 27 SkGLCanvas::SkGLCanvas() { 28 glEnable(GL_TEXTURE_2D); 29 glEnable(GL_SCISSOR_TEST); 30 glEnableClientState(GL_VERTEX_ARRAY); 31 32 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); 33 34 fViewportSize.set(0, 0); 35 } 36 37 SkGLCanvas::~SkGLCanvas() { 38 // call this now, while our override of restore() is in effect 39 this->restoreToCount(1); 40 } 41 42 /////////////////////////////////////////////////////////////////////////////// 43 44 bool SkGLCanvas::getViewport(SkIPoint* size) const { 45 if (size) { 46 *size = fViewportSize; 47 } 48 return true; 49 } 50 51 bool SkGLCanvas::setViewport(int width, int height) { 52 fViewportSize.set(width, height); 53 54 const bool isOpaque = false; // should this be a parameter to setViewport? 55 const bool isForLayer = false; // viewport is the base layer 56 SkDevice* device = this->createDevice(SkBitmap::kARGB_8888_Config, width, 57 height, isOpaque, isForLayer); 58 this->setDevice(device)->unref(); 59 60 return true; 61 } 62 63 SkDevice* SkGLCanvas::createDevice(SkBitmap::Config, int width, int height, 64 bool isOpaque, bool isForLayer) { 65 SkBitmap bitmap; 66 67 bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height); 68 bitmap.setIsOpaque(isOpaque); 69 70 #ifdef USE_FBO_DEVICE 71 return SkNEW_ARGS(SkGLDevice_FBO, (bitmap, isForLayer)); 72 #elif defined(USE_SWLAYER_DEVICE) 73 if (isForLayer) { 74 bitmap.allocPixels(); 75 if (!bitmap.isOpaque()) { 76 bitmap.eraseColor(0); 77 } 78 return SkNEW_ARGS(SkGLDevice_SWLayer, (bitmap)); 79 } else { 80 return SkNEW_ARGS(SkGLDevice, (bitmap, isForLayer)); 81 } 82 #else 83 return SkNEW_ARGS(SkGLDevice, (bitmap, isForLayer)); 84 #endif 85 } 86 87 /////////////////////////////////////////////////////////////////////////////// 88 89 #include "SkTextureCache.h" 90 #include "SkThread.h" 91 92 static SkMutex gTextureCacheMutex; 93 static SkTextureCache gTextureCache(kTexCountMax_Default, kTexSizeMax_Default); 94 95 SkGLDevice::TexCache* SkGLDevice::LockTexCache(const SkBitmap& bitmap, 96 GLuint* name, SkPoint* size) { 97 SkAutoMutexAcquire amc(gTextureCacheMutex); 98 99 SkTextureCache::Entry* entry = gTextureCache.lock(bitmap); 100 if (NULL != entry) { 101 if (name) { 102 *name = entry->name(); 103 } 104 if (size) { 105 *size = entry->texSize(); 106 } 107 } 108 return (TexCache*)entry; 109 } 110 111 void SkGLDevice::UnlockTexCache(TexCache* cache) { 112 SkAutoMutexAcquire amc(gTextureCacheMutex); 113 gTextureCache.unlock((SkTextureCache::Entry*)cache); 114 } 115 116 // public exposure of texture cache settings 117 118 size_t SkGLCanvas::GetTextureCacheMaxCount() { 119 SkAutoMutexAcquire amc(gTextureCacheMutex); 120 return gTextureCache.getMaxCount(); 121 } 122 123 size_t SkGLCanvas::GetTextureCacheMaxSize() { 124 SkAutoMutexAcquire amc(gTextureCacheMutex); 125 return gTextureCache.getMaxSize(); 126 } 127 128 void SkGLCanvas::SetTextureCacheMaxCount(size_t count) { 129 SkAutoMutexAcquire amc(gTextureCacheMutex); 130 gTextureCache.setMaxCount(count); 131 } 132 133 void SkGLCanvas::SetTextureCacheMaxSize(size_t size) { 134 SkAutoMutexAcquire amc(gTextureCacheMutex); 135 gTextureCache.setMaxSize(size); 136 } 137 138 /////////////////////////////////////////////////////////////////////////////// 139 140 #include "SkGLTextCache.h" 141 142 static bool deleteCachesProc(SkGlyphCache* cache, void* texturesAreValid) { 143 void* auxData; 144 if (cache->getAuxProcData(SkGLDevice::GlyphCacheAuxProc, &auxData)) { 145 bool valid = texturesAreValid != NULL; 146 SkGLTextCache* textCache = static_cast<SkGLTextCache*>(auxData); 147 // call this before delete, in case valid is false 148 textCache->deleteAllStrikes(valid); 149 // now free the memory for the cache itself 150 SkDELETE(textCache); 151 // now remove the entry in the glyphcache (does not call the proc) 152 cache->removeAuxProc(SkGLDevice::GlyphCacheAuxProc); 153 } 154 return false; // keep going 155 } 156 157 void SkGLCanvas::DeleteAllTextures() { 158 // free the textures in our cache 159 160 gTextureCacheMutex.acquire(); 161 gTextureCache.deleteAllCaches(true); 162 gTextureCacheMutex.release(); 163 164 // now free the textures in the font cache 165 166 SkGlyphCache::VisitAllCaches(deleteCachesProc, reinterpret_cast<void*>(true)); 167 } 168 169 void SkGLCanvas::AbandonAllTextures() { 170 // abandon the textures in our cache 171 172 gTextureCacheMutex.acquire(); 173 gTextureCache.deleteAllCaches(false); 174 gTextureCacheMutex.release(); 175 176 // abandon the textures in the font cache 177 178 SkGlyphCache::VisitAllCaches(deleteCachesProc, reinterpret_cast<void*>(false)); 179 } 180 181