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
diff --git a/src/gl/SkGLCanvas.cpp b/src/gl/SkGLCanvas.cpp
deleted file mode 100644
index f7bc96d..0000000
--- 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 d839498..ad4377c 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 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
+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 @@
     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 0fc9e47..61916c1 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 @@
     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 @@
     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; }