diff options
Diffstat (limited to 'Source')
4 files changed, 75 insertions, 38 deletions
diff --git a/Source/WebCore/platform/graphics/android/CanvasLayer.cpp b/Source/WebCore/platform/graphics/android/CanvasLayer.cpp index 52bdaaa..fea429f 100644 --- a/Source/WebCore/platform/graphics/android/CanvasLayer.cpp +++ b/Source/WebCore/platform/graphics/android/CanvasLayer.cpp @@ -70,30 +70,36 @@ CanvasLayer::CanvasLayer(const CanvasLayer& layer) // We are making a copy for the UI, sync the interesting bits m_contentRect = layer.contentRect(); m_offsetFromRenderer = layer.offsetFromRenderer(); - m_texture->setSize(m_contentRect.size()); bool previousState = m_texture->hasValidTexture(); - // Attempt to upload to a surface texture - if (!m_texture->uploadImageBuffer(layer.m_canvas->buffer())) { - // Blargh, no surface texture - fall back to software + if (!previousState && layer.m_dirtyCanvas.isEmpty()) { + // We were previously in software and don't have anything new to draw, + // so stay in software m_bitmap = layer.bitmap(); SkSafeRef(m_bitmap); - // Merge the canvas invals with the layer's invals to repaint the needed - // tiles. - SkRegion::Iterator iter(layer.m_dirtyCanvas); - const IntPoint& offset = m_contentRect.location(); - for (; !iter.done(); iter.next()) { - SkIRect diff = iter.rect(); - diff.fLeft += offset.x(); - diff.fRight += offset.x(); - diff.fTop += offset.y(); - diff.fBottom += offset.y(); - m_dirtyRegion.op(diff, SkRegion::kUnion_Op); + } else { + // Attempt to upload to a surface texture + if (!m_texture->uploadImageBuffer(layer.m_canvas->buffer())) { + // Blargh, no surface texture or ImageBuffer - fall back to software + m_bitmap = layer.bitmap(); + SkSafeRef(m_bitmap); + // Merge the canvas invals with the layer's invals to repaint the needed + // tiles. + SkRegion::Iterator iter(layer.m_dirtyCanvas); + const IntPoint& offset = m_contentRect.location(); + for (; !iter.done(); iter.next()) { + SkIRect diff = iter.rect(); + diff.fLeft += offset.x(); + diff.fRight += offset.x(); + diff.fTop += offset.y(); + diff.fBottom += offset.y(); + m_dirtyRegion.op(diff, SkRegion::kUnion_Op); + } + } + if (previousState != m_texture->hasValidTexture()) { + // Need to do a full inval of the canvas content as we are mode switching + m_dirtyRegion.op(m_contentRect.x(), m_contentRect.y(), + m_contentRect.maxX(), m_contentRect.maxY(), SkRegion::kUnion_Op); } - } - if (previousState != m_texture->hasValidTexture()) { - // Need to do a full inval of the canvas content as we are mode switching - m_dirtyRegion.op(m_contentRect.x(), m_contentRect.y(), - m_contentRect.maxX(), m_contentRect.maxY(), SkRegion::kUnion_Op); } } @@ -111,17 +117,26 @@ void CanvasLayer::init() void CanvasLayer::canvasChanged(HTMLCanvasElement*, const FloatRect& changedRect) { - SkIRect irect = SkIRect::MakeXYWH(changedRect.x(), changedRect.y(), - changedRect.width(), changedRect.height()); - m_dirtyCanvas.op(irect, SkRegion::kUnion_Op); + if (!m_texture->hasValidTexture()) { + // We only need to track invals if we aren't using a SurfaceTexture. + // If we drop out of hwa, we will do a full inval anyway + SkIRect irect = SkIRect::MakeXYWH(changedRect.x(), changedRect.y(), + changedRect.width(), changedRect.height()); + m_dirtyCanvas.op(irect, SkRegion::kUnion_Op); + } owningLayer()->compositor()->scheduleLayerFlush(); } void CanvasLayer::canvasResized(HTMLCanvasElement*) { const IntSize& size = m_canvas->size(); - SkIRect irect = SkIRect::MakeWH(size.width(), size.height()); - m_dirtyCanvas.op(irect, SkRegion::kUnion_Op); + m_dirtyCanvas.setRect(0, 0, size.width(), size.height()); + // If we are smaller than one tile, don't bother using a surface texture + if (size.width() <= TilesManager::layerTileWidth() + && size.height() <= TilesManager::layerTileHeight()) + m_texture->setSize(IntSize()); + else + m_texture->setSize(size); } void CanvasLayer::canvasDestroyed(HTMLCanvasElement*) @@ -146,6 +161,12 @@ SkBitmapRef* CanvasLayer::bitmap() const IntRect CanvasLayer::contentRect() const { + if (!m_canvas + || !m_canvas->renderer() + || !m_canvas->renderer()->style() + || !m_canvas->inDocument() + || m_canvas->renderer()->style()->visibility() != VISIBLE) + return IntRect(); return m_canvas->renderBox()->contentBoxRect(); } diff --git a/Source/WebCore/platform/graphics/android/CanvasTexture.cpp b/Source/WebCore/platform/graphics/android/CanvasTexture.cpp index ca520fd..e4b2bc6 100644 --- a/Source/WebCore/platform/graphics/android/CanvasTexture.cpp +++ b/Source/WebCore/platform/graphics/android/CanvasTexture.cpp @@ -72,7 +72,7 @@ bool CanvasTexture::setHwAccelerated(bool hwAccelerated) m_useHwAcceleration = hwAccelerated; if (!m_ANW.get()) return false; - destroySurfaceTexture(); + destroySurfaceTextureLocked(); return true; } @@ -87,15 +87,15 @@ void CanvasTexture::setSize(const IntSize& size) return; m_size = size; if (m_ANW.get()) { - if (!useSurfaceTexture()) { - m_ANW.clear(); - m_surfaceTexture->abandon(); - m_surfaceTexture.clear(); - } else { + if (useSurfaceTexture()) { int result = native_window_set_buffers_dimensions(m_ANW.get(), m_size.width(), m_size.height()); GLUtils::checkSurfaceTextureError("native_window_set_buffers_dimensions", result); + if (result != NO_ERROR) + m_useHwAcceleration = false; // On error, drop out of HWA } + if (!useSurfaceTexture()) + destroySurfaceTextureLocked(); } } @@ -112,9 +112,16 @@ SurfaceTextureClient* CanvasTexture::nativeWindow() m_ANW = new android::SurfaceTextureClient(m_surfaceTexture); int result = native_window_set_buffers_format(m_ANW.get(), HAL_PIXEL_FORMAT_RGBA_8888); GLUtils::checkSurfaceTextureError("native_window_set_buffers_format", result); - result = native_window_set_buffers_dimensions(m_ANW.get(), - m_size.width(), m_size.height()); - GLUtils::checkSurfaceTextureError("native_window_set_buffers_dimensions", result); + if (result == NO_ERROR) { + result = native_window_set_buffers_dimensions(m_ANW.get(), + m_size.width(), m_size.height()); + GLUtils::checkSurfaceTextureError("native_window_set_buffers_dimensions", result); + } + if (result != NO_ERROR) { + m_useHwAcceleration = false; + destroySurfaceTextureLocked(); + return 0; + } return m_ANW.get(); } @@ -124,11 +131,15 @@ bool CanvasTexture::uploadImageBuffer(ImageBuffer* imageBuffer) SurfaceTextureClient* anw = nativeWindow(); if (!anw) return false; + // Size mismatch, early abort (will fall back to software) + if (imageBuffer->size() != m_size) + return false; GraphicsContext* gc = imageBuffer ? imageBuffer->context() : 0; if (!gc) return false; const SkBitmap& bitmap = android_gc2canvas(gc)->getDevice()->accessBitmap(false); - GLUtils::updateSharedSurfaceTextureWithBitmap(anw, bitmap); + if (!GLUtils::updateSharedSurfaceTextureWithBitmap(anw, bitmap)) + return false; m_hasValidTexture = true; return true; } @@ -174,7 +185,7 @@ bool CanvasTexture::updateTexImage() * Called by both threads ********************************************/ -void CanvasTexture::destroySurfaceTexture() +void CanvasTexture::destroySurfaceTextureLocked() { if (m_ANW.get()) { m_ANW.clear(); diff --git a/Source/WebCore/platform/graphics/android/CanvasTexture.h b/Source/WebCore/platform/graphics/android/CanvasTexture.h index 8875af7..98962a0 100644 --- a/Source/WebCore/platform/graphics/android/CanvasTexture.h +++ b/Source/WebCore/platform/graphics/android/CanvasTexture.h @@ -69,7 +69,7 @@ private: /******************************************** * Called by both threads ********************************************/ - void destroySurfaceTexture(); + void destroySurfaceTextureLocked(); /******************************************** * Called by WebKit thread diff --git a/Source/WebCore/platform/graphics/android/GLUtils.cpp b/Source/WebCore/platform/graphics/android/GLUtils.cpp index 9c5a079..fb69deb 100644 --- a/Source/WebCore/platform/graphics/android/GLUtils.cpp +++ b/Source/WebCore/platform/graphics/android/GLUtils.cpp @@ -525,8 +525,13 @@ bool GLUtils::updateSharedSurfaceTextureWithBitmap(ANativeWindow* anw, const SkB ANativeWindow_Buffer buffer; if (ANativeWindow_lock(anw, &buffer, 0)) return false; - if (buffer.width < bitmap.width() || buffer.height < bitmap.height()) + if (buffer.width < bitmap.width() || buffer.height < bitmap.height()) { + ALOGW("bitmap (%dx%d) too large for buffer (%dx%d)!", + bitmap.width(), bitmap.height(), + buffer.width, buffer.height); + ANativeWindow_unlockAndPost(anw); return false; + } uint8_t* img = (uint8_t*)buffer.bits; int row; int bpp = 4; // Now we only deal with RGBA8888 format. |