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