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
SkGLCanvas()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
~SkGLCanvas()37 SkGLCanvas::~SkGLCanvas() {
38 // call this now, while our override of restore() is in effect
39 this->restoreToCount(1);
40 }
41
42 ///////////////////////////////////////////////////////////////////////////////
43
getViewport(SkIPoint * size) const44 bool SkGLCanvas::getViewport(SkIPoint* size) const {
45 if (size) {
46 *size = fViewportSize;
47 }
48 return true;
49 }
50
setViewport(int width,int height)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
createDevice(SkBitmap::Config,int width,int height,bool isOpaque,bool isForLayer)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
LockTexCache(const SkBitmap & bitmap,GLuint * name,SkPoint * size)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
UnlockTexCache(TexCache * cache)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
GetTextureCacheMaxCount()118 size_t SkGLCanvas::GetTextureCacheMaxCount() {
119 SkAutoMutexAcquire amc(gTextureCacheMutex);
120 return gTextureCache.getMaxCount();
121 }
122
GetTextureCacheMaxSize()123 size_t SkGLCanvas::GetTextureCacheMaxSize() {
124 SkAutoMutexAcquire amc(gTextureCacheMutex);
125 return gTextureCache.getMaxSize();
126 }
127
SetTextureCacheMaxCount(size_t count)128 void SkGLCanvas::SetTextureCacheMaxCount(size_t count) {
129 SkAutoMutexAcquire amc(gTextureCacheMutex);
130 gTextureCache.setMaxCount(count);
131 }
132
SetTextureCacheMaxSize(size_t size)133 void SkGLCanvas::SetTextureCacheMaxSize(size_t size) {
134 SkAutoMutexAcquire amc(gTextureCacheMutex);
135 gTextureCache.setMaxSize(size);
136 }
137
138 ///////////////////////////////////////////////////////////////////////////////
139
140 #include "SkGLTextCache.h"
141
deleteCachesProc(SkGlyphCache * cache,void * texturesAreValid)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
DeleteAllTextures()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
AbandonAllTextures()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