aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar vandebo@chromium.org <vandebo@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2010-10-13 22:13:05 +0000
committerGravatar vandebo@chromium.org <vandebo@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2010-10-13 22:13:05 +0000
commit8d84fac294682647694b0d2d8a87ac2bd19b6aab (patch)
tree2bfd3dea3c5c79bf42003ce620a51069526f28f0
parent60eaa398ebdded0fb7957724c170baabef811e17 (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
-rw-r--r--include/core/SkCanvas.h47
-rw-r--r--include/core/SkDevice.h42
-rw-r--r--include/utils/SkGLCanvas.h69
-rw-r--r--src/core/SkCanvas.cpp49
-rw-r--r--src/core/SkDevice.cpp12
-rw-r--r--src/gl/SkGLCanvas.cpp180
-rw-r--r--src/gl/SkGLDevice.cpp140
-rw-r--r--src/gl/SkGLDevice.h38
-rw-r--r--xcode/sampleapp/SampleApp.xcodeproj/project.pbxproj8
9 files changed, 307 insertions, 278 deletions
diff --git a/include/core/SkCanvas.h b/include/core/SkCanvas.h
index 0ccc2dd999..6d995b8b55 100644
--- a/include/core/SkCanvas.h
+++ b/include/core/SkCanvas.h
@@ -29,6 +29,7 @@
class SkBounder;
class SkDevice;
+class SkDeviceFactory;
class SkDraw;
class SkDrawFilter;
class SkPicture;
@@ -51,29 +52,37 @@ class SkShape;
*/
class SkCanvas : public SkRefCnt {
public:
- /** Construct a canvas with the specified bitmap to draw into.
+ /** Construct a canvas with the given device factory.
+ @param factory Specify the factory for generating additional devices.
+ The factory may be null, in which case SkDeviceFactory
+ will be used.
+ */
+ explicit SkCanvas(SkDeviceFactory* factory = NULL);
+
+ /** Construct a canvas with the specified device to draw into. The device
+ factory will be retrieved from the passed device.
+ @param device Specifies a device for the canvas to draw into.
+ */
+ explicit SkCanvas(SkDevice* device);
+
+ /** Deprecated - Construct a canvas with the specified bitmap to draw into.
@param bitmap Specifies a bitmap for the canvas to draw into. Its
structure are copied to the canvas.
*/
explicit SkCanvas(const SkBitmap& bitmap);
- /** Construct a canvas with the specified device to draw into.
- @param device Specifies a device for the canvas to draw into. The
- device may be null.
- */
- explicit SkCanvas(SkDevice* device = NULL);
virtual ~SkCanvas();
///////////////////////////////////////////////////////////////////////////
- /** If this subclass of SkCanvas supports GL viewports, return true and set
- size (if not null) to the size of the viewport. If it is not supported,
- ignore vp and return false.
+ /** If the Device supports GL viewports, return true and set size (if not
+ null) to the size of the viewport. If it is not supported, ignore size
+ and return false.
*/
virtual bool getViewport(SkIPoint* size) const;
-
- /** If this subclass of SkCanvas supports GL viewports, return true and set
- the viewport to the specified x and y dimensions. If it is not
- supported, ignore x and y and return false.
+
+ /** If the Device supports GL viewports, return true and set the viewport
+ to the specified x and y dimensions. If it is not supported, ignore x
+ and y and return false.
*/
virtual bool setViewport(int x, int y);
@@ -88,15 +97,16 @@ public:
device, its reference count is decremented. The new device is returned.
*/
SkDevice* setDevice(SkDevice* device);
-
- /** Specify a bitmap for the canvas to draw into. This is a help method for
- setDevice(), and it creates a device for the bitmap by calling
- createDevice(). The structure of the bitmap is copied into the device.
+
+ /** Deprecated - Specify a bitmap for the canvas to draw into. This is a
+ helper method for setDevice(), and it creates a device for the bitmap by
+ calling createDevice(). The structure of the bitmap is copied into the
+ device.
*/
virtual SkDevice* setBitmapDevice(const SkBitmap& bitmap);
///////////////////////////////////////////////////////////////////////////
-
+
enum SaveFlags {
/** save the matrix state, restoring it on restore() */
kMatrix_SaveFlag = 0x01,
@@ -749,6 +759,7 @@ private:
SkBounder* fBounder;
SkDevice* fLastDeviceToGainFocus;
+ SkDeviceFactory* fDeviceFactory;
void prepareForDeviceDraw(SkDevice*);
diff --git a/include/core/SkDevice.h b/include/core/SkDevice.h
index 4d678c6a40..b7a9cbcb3a 100644
--- a/include/core/SkDevice.h
+++ b/include/core/SkDevice.h
@@ -22,26 +22,52 @@
#include "SkCanvas.h"
#include "SkColor.h"
+class SkDevice;
class SkDraw;
struct SkIRect;
class SkMatrix;
class SkRegion;
+/** \class SkDeviceFactory
+
+ Devices that extend SkDevice should also provide a SkDeviceFactory class
+ to pass into SkCanvas. Doing so will eliminate the need to extend
+ SkCanvas as well.
+*/
+class SkDeviceFactory : public SkRefCnt {
+public:
+ virtual SkDevice* newDevice(SkBitmap::Config config, int width, int height,
+ bool isOpaque, bool isForLayer) = 0;
+
+ enum Capabilities {
+ kGL_Capability = 0x1, //!< mask to indicate this device supports GL
+ kAll_Capabilities = 0x1
+ };
+ virtual uint32_t getDeviceCapabilities() = 0;
+};
+
+class SkRasterDeviceFactory : public SkDeviceFactory {
+public:
+ virtual SkDevice* newDevice(SkBitmap::Config config, int width, int height,
+ bool isOpaque, bool isForLayer);
+ virtual uint32_t getDeviceCapabilities() { return 0; }
+};
+
class SkDevice : public SkRefCnt {
public:
SkDevice();
- /** Construct a new device, extracting the width/height/config/isOpaque values from
- the bitmap. If transferPixelOwnership is true, and the bitmap claims to own its
- own pixels (getOwnsPixels() == true), then transfer this responsibility to the
- device, and call setOwnsPixels(false) on the bitmap.
-
- Subclasses may override the destructor, which is virtual, even though this class
- doesn't have one. SkRefCnt does.
-
+ /** Construct a new device, extracting the width/height/config/isOpaque
+ values from the bitmap. Subclasses may override the destructor, which
+ is virtual, even though this class doesn't have one. SkRefCnt does.
+
@param bitmap A copy of this bitmap is made and stored in the device
*/
SkDevice(const SkBitmap& bitmap);
+ virtual SkDeviceFactory* getDeviceFactory() {
+ return SkNEW(SkRasterDeviceFactory);
+ }
+
/** Return the width of the device (in pixels).
*/
int width() const { return fBitmap.width(); }
diff --git a/include/utils/SkGLCanvas.h b/include/utils/SkGLCanvas.h
index 40fc52d556..87c81ff5a2 100644
--- a/include/utils/SkGLCanvas.h
+++ b/include/utils/SkGLCanvas.h
@@ -18,62 +18,35 @@
#define SkGLCanvas_DEFINED
#include "SkCanvas.h"
+#include "SkGLDevice.h"
-#ifdef SK_BUILD_FOR_MAC
- #include <OpenGL/gl.h>
-#elif defined(ANDROID)
- #include <GLES/gl.h>
-#endif
-
-class SkGLDevice;
-class SkGLClipIter;
-
+// Deprecated. You should now use SkGLDevice and SkGLDeviceFactory with
+// SkCanvas.
class SkGLCanvas : public SkCanvas {
public:
- // notice, we do NOT allow the SkCanvas(bitmap) constructor, since that
- // does not create a SkGLDevice, which we require
- SkGLCanvas();
- virtual ~SkGLCanvas();
-
- // overrides from SkCanvas
-
- virtual bool getViewport(SkIPoint*) const;
- virtual bool setViewport(int width, int height);
-
- virtual SkDevice* createDevice(SkBitmap::Config, int width, int height,
- bool isOpaque, bool isForLayer);
-
- // settings for the global texture cache
-
- static size_t GetTextureCacheMaxCount();
- static void SetTextureCacheMaxCount(size_t count);
+ SkGLCanvas() : SkCanvas(SkNEW(SkGLDeviceFactory)) {}
- 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();
+ static size_t GetTextureCacheMaxCount() {
+ return SkGLDevice::GetTextureCacheMaxCount();
+ }
+ static void SetTextureCacheMaxCount(size_t count) {
+ SkGLDevice::SetTextureCacheMaxCount(count);
+ }
-private:
- SkIPoint fViewportSize;
+ static size_t GetTextureCacheMaxSize() {
+ return SkGLDevice::GetTextureCacheMaxSize();
+ }
+ static void SetTextureCacheMaxSize(size_t size) {
+ SkGLDevice::SetTextureCacheMaxSize(size);
+ }
- // need to disallow this guy
- virtual SkDevice* setBitmapDevice(const SkBitmap& bitmap) {
- sk_throw();
- return NULL;
+ static void DeleteAllTextures() {
+ SkGLDevice::DeleteAllTextures();
}
- typedef SkCanvas INHERITED;
+ static void AbandonAllTextures() {
+ SkGLDevice::AbandonAllTextures();
+ }
};
#endif
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; }
diff --git a/xcode/sampleapp/SampleApp.xcodeproj/project.pbxproj b/xcode/sampleapp/SampleApp.xcodeproj/project.pbxproj
index 911486d700..72b7187bca 100644
--- a/xcode/sampleapp/SampleApp.xcodeproj/project.pbxproj
+++ b/xcode/sampleapp/SampleApp.xcodeproj/project.pbxproj
@@ -26,7 +26,6 @@
0001FB87110E35E500C1D647 /* AGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0001FB86110E35E500C1D647 /* AGL.framework */; };
0001FB8A110E35FA00C1D647 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0001FB89110E35FA00C1D647 /* OpenGL.framework */; };
0001FB94110E362F00C1D647 /* SkGL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0001FB8D110E362F00C1D647 /* SkGL.cpp */; };
- 0001FB95110E362F00C1D647 /* SkGLCanvas.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0001FB8E110E362F00C1D647 /* SkGLCanvas.cpp */; };
0001FB96110E362F00C1D647 /* SkGLDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0001FB8F110E362F00C1D647 /* SkGLDevice.cpp */; };
0001FB97110E362F00C1D647 /* SkGLDevice_FBO.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0001FB90110E362F00C1D647 /* SkGLDevice_FBO.cpp */; };
0001FB98110E362F00C1D647 /* SkGLState.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0001FB91110E362F00C1D647 /* SkGLState.cpp */; };
@@ -99,7 +98,6 @@
27005D5F10095B2B00E275B6 /* SampleCircle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0041CE200F00A12400695E8C /* SampleCircle.cpp */; };
27433F1E11A1874A0045AD84 /* SampleSVG.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 27CAAB9B119B32670017B155 /* SampleSVG.cpp */; };
27433F3311A18EA60045AD84 /* SampleTextEffects.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 007A7CAD0F01658C00A2D6EE /* SampleTextEffects.cpp */; };
- 27433F4911A1D24E0045AD84 /* SampleMessages.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 27433F4811A1D24E0045AD84 /* SampleMessages.cpp */; };
275E801611AAC2FF0051C03A /* SampleShapes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 003145310FB9B48F00B10956 /* SampleShapes.cpp */; };
275E802311AAC3330051C03A /* SampleVertices.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 007A7CB10F01658C00A2D6EE /* SampleVertices.cpp */; };
2762F66D0FCCCABE002BD8B4 /* SkFlipPixelRef.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2762F66B0FCCCABE002BD8B4 /* SkFlipPixelRef.cpp */; };
@@ -219,7 +217,6 @@
0001FB86110E35E500C1D647 /* AGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AGL.framework; path = /System/Library/Frameworks/AGL.framework; sourceTree = "<absolute>"; };
0001FB89110E35FA00C1D647 /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = /System/Library/Frameworks/OpenGL.framework; sourceTree = "<absolute>"; };
0001FB8D110E362F00C1D647 /* SkGL.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkGL.cpp; path = ../../src/gl/SkGL.cpp; sourceTree = SOURCE_ROOT; };
- 0001FB8E110E362F00C1D647 /* SkGLCanvas.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkGLCanvas.cpp; path = ../../src/gl/SkGLCanvas.cpp; sourceTree = SOURCE_ROOT; };
0001FB8F110E362F00C1D647 /* SkGLDevice.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkGLDevice.cpp; path = ../../src/gl/SkGLDevice.cpp; sourceTree = SOURCE_ROOT; };
0001FB90110E362F00C1D647 /* SkGLDevice_FBO.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkGLDevice_FBO.cpp; path = ../../src/gl/SkGLDevice_FBO.cpp; sourceTree = SOURCE_ROOT; };
0001FB91110E362F00C1D647 /* SkGLState.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkGLState.cpp; path = ../../src/gl/SkGLState.cpp; sourceTree = SOURCE_ROOT; };
@@ -307,7 +304,6 @@
0867D6ABFE840B52C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; };
1870340FFE93FCAF11CA0CD7 /* English */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = English; path = English.lproj/main.nib; sourceTree = "<group>"; };
20286C33FDCF999611CA2CEA /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = /System/Library/Frameworks/Carbon.framework; sourceTree = "<absolute>"; };
- 27433F4811A1D24E0045AD84 /* SampleMessages.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SampleMessages.cpp; path = ../../tetrark/SampleMessages.cpp; sourceTree = SOURCE_ROOT; };
2762F66B0FCCCABE002BD8B4 /* SkFlipPixelRef.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkFlipPixelRef.cpp; path = ../../src/images/SkFlipPixelRef.cpp; sourceTree = SOURCE_ROOT; };
2762F66C0FCCCABE002BD8B4 /* SkPageFlipper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkPageFlipper.cpp; path = ../../src/images/SkPageFlipper.cpp; sourceTree = SOURCE_ROOT; };
2762F6740FCCCB01002BD8B4 /* SampleAll.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SampleAll.cpp; path = ../../samplecode/SampleAll.cpp; sourceTree = SOURCE_ROOT; };
@@ -507,7 +503,6 @@
isa = PBXGroup;
children = (
0001FB8D110E362F00C1D647 /* SkGL.cpp */,
- 0001FB8E110E362F00C1D647 /* SkGLCanvas.cpp */,
0001FB8F110E362F00C1D647 /* SkGLDevice.cpp */,
0001FB90110E362F00C1D647 /* SkGLDevice_FBO.cpp */,
0001FB91110E362F00C1D647 /* SkGLState.cpp */,
@@ -581,7 +576,6 @@
00EB4592104DBB18002B413E /* ForthTests.cpp */,
00BB289A104781D00057BF7E /* SampleForth.cpp */,
00003C620EFC22A8000FF73A /* SampleApp.cpp */,
- 27433F4811A1D24E0045AD84 /* SampleMessages.cpp */,
2762F66A0FCCCAA2002BD8B4 /* images */,
00003C6A0EFC22AD000FF73A /* views */,
00281C7B1083CFB700BCCB06 /* xml */,
@@ -890,7 +884,6 @@
0061BCD910D951AA0079EBE5 /* SkTextBox.cpp in Sources */,
0001FB78110E33CC00C1D647 /* SampleTestGL.cpp in Sources */,
0001FB94110E362F00C1D647 /* SkGL.cpp in Sources */,
- 0001FB95110E362F00C1D647 /* SkGLCanvas.cpp in Sources */,
0001FB96110E362F00C1D647 /* SkGLDevice.cpp in Sources */,
0001FB97110E362F00C1D647 /* SkGLDevice_FBO.cpp in Sources */,
0001FB98110E362F00C1D647 /* SkGLState.cpp in Sources */,
@@ -929,7 +922,6 @@
27CAAB96119B321A0017B155 /* SkXMLWriter.cpp in Sources */,
27433F1E11A1874A0045AD84 /* SampleSVG.cpp in Sources */,
27433F3311A18EA60045AD84 /* SampleTextEffects.cpp in Sources */,
- 27433F4911A1D24E0045AD84 /* SampleMessages.cpp in Sources */,
275E801611AAC2FF0051C03A /* SampleShapes.cpp in Sources */,
275E802311AAC3330051C03A /* SampleVertices.cpp in Sources */,
27D0F3C311BD2012001B8EBE /* SampleText.cpp in Sources */,