C++程序  |  181行  |  5.22 KB

#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));
}