summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/platform/graphics/android/ImageTexture.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/platform/graphics/android/ImageTexture.cpp')
-rw-r--r--Source/WebCore/platform/graphics/android/ImageTexture.cpp214
1 files changed, 161 insertions, 53 deletions
diff --git a/Source/WebCore/platform/graphics/android/ImageTexture.cpp b/Source/WebCore/platform/graphics/android/ImageTexture.cpp
index 96f7713..23e3899 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 <cutils/log.h>
#include <wtf/CurrentTime.h>
@@ -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<uint8_t*>(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<float>(layerArea.width()) / static_cast<float>(m_image->width());
+ float scaleH = static_cast<float>(layerArea.height()) / static_cast<float>(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