X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=Source%2FWebCore%2Fplatform%2Fgraphics%2Fandroid%2FImageTexture.cpp;h=23e38999ff011133225f41523b768cf868ae4207;hb=54e75f0875a8376c1119b019431921bc58295b79;hp=96f77137a94f4ca954aebc40bc5908758a0df361;hpb=ed03bc998bd1c1a64a99ee631f3bc31466590bf1;p=android-x86%2Fexternal-webkit.git diff --git a/Source/WebCore/platform/graphics/android/ImageTexture.cpp b/Source/WebCore/platform/graphics/android/ImageTexture.cpp index 96f77137a..23e38999f 100644 --- a/Source/WebCore/platform/graphics/android/ImageTexture.cpp +++ b/Source/WebCore/platform/graphics/android/ImageTexture.cpp @@ -27,8 +27,11 @@ #include "ImageTexture.h" #include "ImagesManager.h" +#include "LayerAndroid.h" #include "SkDevice.h" +#include "SkPicture.h" #include "TilesManager.h" +#include "TiledTexture.h" #include #include @@ -51,96 +54,201 @@ namespace WebCore { -ImageTexture::ImageTexture(SkBitmapRef* img) - : m_imageRef(img) - , m_image(0) - , m_textureId(0) - , m_refCount(0) +// CRC computation adapted from Tools/DumpRenderTree/CyclicRedundancyCheck.cpp +static void makeCrcTable(unsigned crcTable[256]) +{ + for (unsigned i = 0; i < 256; i++) { + unsigned c = i; + for (int k = 0; k < 8; k++) { + if (c & 1) + c = -306674912 ^ ((c >> 1) & 0x7fffffff); + else + c = c >> 1; + } + crcTable[i] = c; + } +} + +unsigned computeCrc(uint8_t* buffer, size_t size) +{ + static unsigned crcTable[256]; + static bool crcTableComputed = false; + if (!crcTableComputed) { + makeCrcTable(crcTable); + crcTableComputed = true; + } + + unsigned crc = 0xffffffffL; + for (size_t i = 0; i < size; ++i) + crc = crcTable[(crc ^ buffer[i]) & 0xff] ^ ((crc >> 8) & 0x00ffffffL); + return crc ^ 0xffffffffL; +} + +ImageTexture::ImageTexture(SkBitmap* bmp, unsigned crc) + : m_image(bmp) + , m_texture(0) + , m_layer(0) + , m_picture(0) + , m_crc(crc) { #ifdef DEBUG_COUNT ClassTracker::instance()->increment("ImageTexture"); #endif - if (!m_imageRef) + if (!m_image) return; - SkBitmap* bitmap = &m_imageRef->bitmap(); - m_image = new SkBitmap(); + // NOTE: This constructor is called on the webcore thread + + // Create a picture containing the image (needed for TiledTexture) + m_picture = new SkPicture(); + SkCanvas* pcanvas = m_picture->beginRecording(m_image->width(), m_image->height()); + pcanvas->clear(SkColorSetARGBInline(0, 0, 0, 0)); + pcanvas->drawBitmap(*m_image, 0, 0); + m_picture->endRecording(); +} + +ImageTexture::~ImageTexture() +{ +#ifdef DEBUG_COUNT + ClassTracker::instance()->decrement("ImageTexture"); +#endif + delete m_image; + delete m_texture; + SkSafeUnref(m_picture); +} + +SkBitmap* ImageTexture::convertBitmap(SkBitmap* bitmap) +{ + SkBitmap* img = new SkBitmap(); int w = bitmap->width(); int h = bitmap->height(); - m_image->setConfig(SkBitmap::kARGB_8888_Config, w, h); - m_image->allocPixels(); - SkDevice* device = new SkDevice(NULL, *m_image, false); + + // Create a copy of the image + img->setConfig(SkBitmap::kARGB_8888_Config, w, h); + img->allocPixels(); + SkDevice* device = new SkDevice(NULL, *img, false); SkCanvas canvas; canvas.setDevice(device); device->unref(); SkRect dest; dest.set(0, 0, w, h); - m_image->setIsOpaque(false); - m_image->eraseARGB(0, 0, 0, 0); + img->setIsOpaque(false); + img->eraseARGB(0, 0, 0, 0); canvas.drawBitmapRect(*bitmap, 0, dest); + + return img; } -ImageTexture::~ImageTexture() +unsigned ImageTexture::computeCRC(const SkBitmap* bitmap) { -#ifdef DEBUG_COUNT - ClassTracker::instance()->decrement("ImageTexture"); -#endif - delete m_image; + if (!bitmap) + return 0; + bitmap->lockPixels(); + uint8_t* img = static_cast(bitmap->getPixels()); + unsigned crc = computeCrc(img, bitmap->getSize()); + bitmap->unlockPixels(); + return crc; } -void ImageTexture::prepareGL() +bool ImageTexture::equalsCRC(unsigned crc) { - if (m_textureId) - return; - - ImagesManager::instance()->scheduleTextureUpload(this); + return m_crc == crc; } -void ImageTexture::uploadGLTexture() +int ImageTexture::nbTextures() { - if (m_textureId) - return; - - glGenTextures(1, &m_textureId); - GLUtils::createTextureWithBitmap(m_textureId, *m_image); + if (!hasContentToShow()) + return 0; + if (!m_texture) + return 0; + + // TODO: take in account the visible clip (need to maintain + // a list of the clients layer, etc.) + IntRect visibleArea(0, 0, m_image->width(), m_image->height()); + int nbTextures = m_texture->nbTextures(visibleArea, 1.0); + XLOG("ImageTexture %p, %d x %d needs %d textures", + this, m_image->width(), m_image->height(), + nbTextures); + return nbTextures; } -void ImageTexture::drawGL(LayerAndroid* layer) +bool ImageTexture::hasContentToShow() { - if (!layer) - return; - if (!m_textureId) - return; + // Don't display 1x1 image -- no need to allocate a full texture for this if (!m_image) - return; + return false; + if (m_image->width() == 1 && m_image->height() == 1) + return false; + return true; +} - SkRect rect; - rect.fLeft = 0; - rect.fTop = 0; - rect.fRight = layer->getSize().width(); - rect.fBottom = layer->getSize().height(); - TilesManager::instance()->shader()->drawLayerQuad(*layer->drawTransform(), - rect, m_textureId, - layer->drawOpacity(), true); +bool ImageTexture::prepareGL(GLWebViewState* state) +{ + if (!hasContentToShow()) + return false; + + if (!m_texture && m_picture) { + m_texture = new TiledTexture(this); + SkRegion region; + region.setRect(0, 0, m_image->width(), m_image->height()); + m_texture->update(region, m_picture); + } + + if (!m_texture) + return false; + + IntRect visibleArea(0, 0, m_image->width(), m_image->height()); + m_texture->prepare(state, 1.0, true, true, visibleArea); + if (m_texture->ready()) { + m_texture->swapTiles(); + return false; + } + return true; } -void ImageTexture::drawCanvas(SkCanvas* canvas, SkRect& rect) +const TransformationMatrix* ImageTexture::transform() { - canvas->drawBitmapRect(*m_image, 0, rect); + if (!m_layer) + return 0; + + FloatPoint p(0, 0); + p = m_layer->drawTransform()->mapPoint(p); + IntRect layerArea = m_layer->unclippedArea(); + float scaleW = static_cast(layerArea.width()) / static_cast(m_image->width()); + float scaleH = static_cast(layerArea.height()) / static_cast(m_image->height()); + TransformationMatrix d = *(m_layer->drawTransform()); + TransformationMatrix m; + m.scaleNonUniform(scaleW, scaleH); + m_layerMatrix = d.multiply(m); + return &m_layerMatrix; } -void ImageTexture::release() +float ImageTexture::opacity() { - if (m_refCount >= 1) - m_refCount--; - if (!m_refCount) - deleteTexture(); + if (!m_layer) + return 1.0; + return m_layer->drawOpacity(); } -void ImageTexture::deleteTexture() +void ImageTexture::drawGL(LayerAndroid* layer) +{ + if (!layer) + return; + if (!hasContentToShow()) + return; + + // TiledTexture::draw() will call us back to know the + // transform and opacity, so we need to set m_layer + m_layer = layer; + if (m_texture) + m_texture->draw(); + m_layer = 0; +} + +void ImageTexture::drawCanvas(SkCanvas* canvas, SkRect& rect) { - if (m_textureId) - glDeleteTextures(1, &m_textureId); + if (canvas && m_image) + canvas->drawBitmapRect(*m_image, 0, rect); } } // namespace WebCore