aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
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 /src
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
Diffstat (limited to 'src')
-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
5 files changed, 223 insertions, 196 deletions
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; }