diff options
Diffstat (limited to 'WebCore/platform/graphics')
27 files changed, 943 insertions, 220 deletions
diff --git a/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.cpp b/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.cpp index 7bfbc4e..12e0436 100644 --- a/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.cpp +++ b/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.cpp @@ -25,10 +25,11 @@ #include "config.h" #include "BackedDoubleBufferedTexture.h" + #include "BaseTile.h" #include "DeleteTextureOperation.h" -#include "TilesManager.h" #include "GLUtils.h" +#include "TilesManager.h" #define LOG_NDEBUG 1 #define LOG_TAG "BackedDoubleBufferedTexture.cpp" @@ -61,7 +62,7 @@ BackedDoubleBufferedTexture::~BackedDoubleBufferedTexture() void BackedDoubleBufferedTexture::destroyTextures(SharedTexture** textures) { int x = 0; - while (textures[x] != 0) { + while (textures[x]) { // We need to delete the source texture and EGLImage in the texture // generation thread. In theory we should be able to delete the EGLImage // from either thread, but it currently throws an error if not deleted @@ -121,6 +122,11 @@ bool BackedDoubleBufferedTexture::acquire(TextureOwner* owner) if (m_owner == owner) return true; + return setOwner(owner); +} + +bool BackedDoubleBufferedTexture::setOwner(TextureOwner* owner) +{ // if the writable texture is busy (i.e. currently being written to) then we // can't change the owner out from underneath that texture android::Mutex::Autolock lock(m_busyLock); @@ -139,9 +145,4 @@ void BackedDoubleBufferedTexture::release(TextureOwner* owner) m_owner = 0; } -void BackedDoubleBufferedTexture::release() -{ - m_owner = 0; -} - } // namespace WebCore diff --git a/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.h b/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.h index 4ffdc07..844715d 100644 --- a/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.h +++ b/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.h @@ -53,7 +53,7 @@ public: // updates the texture with current bitmap and releases (and if needed also // swaps) the texture. - void producerUpdate(TextureInfo* textureInfo); + virtual void producerUpdate(TextureInfo* textureInfo); // The level can be one of the following values: // * -1 for an unused texture. @@ -68,7 +68,9 @@ public: // returns false if ownership cannot be transferred because the tile is busy bool acquire(TextureOwner* owner); void release(TextureOwner* owner); - void release(); + + // set the texture owner if not busy. Return false if busy, true otherwise. + bool setOwner(TextureOwner* owner); // private member accessor functions TextureOwner* owner() { return m_owner; } // only used by the consumer thread diff --git a/WebCore/platform/graphics/android/BaseLayerAndroid.cpp b/WebCore/platform/graphics/android/BaseLayerAndroid.cpp index 996b272..040f63e 100644 --- a/WebCore/platform/graphics/android/BaseLayerAndroid.cpp +++ b/WebCore/platform/graphics/android/BaseLayerAndroid.cpp @@ -75,6 +75,9 @@ BaseLayerAndroid::BaseLayerAndroid() BaseLayerAndroid::~BaseLayerAndroid() { +#if USE(ACCELERATED_COMPOSITING) + TilesManager::instance()->removeOperationsForBaseLayer(this); +#endif m_content.clear(); #ifdef DEBUG_COUNT gBaseLayerAndroidCount--; @@ -256,6 +259,33 @@ bool BaseLayerAndroid::drawGL(IntRect& viewRect, SkRect& visibleRect, ret = drawBasePictureInGL(visibleRect, scale); + if (countChildren() >= 1) { + LayerAndroid* compositedRoot = static_cast<LayerAndroid*>(getChild(0)); + TransformationMatrix ident; + compositedRoot->updateFixedLayersPositions(visibleRect); + compositedRoot->updateGLPositions(ident, 1); + SkMatrix matrix; + matrix.setTranslate(left, top); + + // At this point, the previous LayerAndroid* root has been destroyed, + // which will have removed the layers as owners of the textures. + // Let's now do a pass to reserve the textures for the current tree; + // it will only reserve existing textures, not create them on demand. +#ifdef DEBUG + TilesManager::instance()->printLayersTextures("reserve"); +#endif + compositedRoot->reserveGLTextures(); + // Now that we marked the textures being used, we delete the unnecessary + // ones to make space... + TilesManager::instance()->cleanupLayersTextures(); + // Finally do another pass to create new textures if needed + compositedRoot->createGLTextures(); + + if (compositedRoot->drawGL(matrix)) + ret = true; + } + glDisable(GL_SCISSOR_TEST); + glBindBuffer(GL_ARRAY_BUFFER, 0); m_previousVisible = visibleRect; diff --git a/WebCore/platform/graphics/android/BaseTile.cpp b/WebCore/platform/graphics/android/BaseTile.cpp index 5701486..789cbe0 100644 --- a/WebCore/platform/graphics/android/BaseTile.cpp +++ b/WebCore/platform/graphics/android/BaseTile.cpp @@ -168,8 +168,12 @@ void BaseTile::draw(float transparency, SkRect& rect) } // Early return if set to un-usable in purpose! - if (!m_usable) { - XLOG("early return at BaseTile::draw b/c tile set to unusable !"); + m_atomicSync.lock(); + bool usable = m_usable; + bool isTexturePainted = m_lastPaintedPicture; + m_atomicSync.unlock(); + if (!usable || !isTexturePainted) { + XLOG("early return at BaseTile::draw b/c tile set to unusable or not painted !"); return; } @@ -180,13 +184,8 @@ void BaseTile::draw(float transparency, SkRect& rect) return; } - m_atomicSync.lock(); - bool isTexturePainted = m_lastPaintedPicture; - m_atomicSync.unlock(); - - if (isTexturePainted) - TilesManager::instance()->shader()->drawQuad(rect, textureInfo->m_textureId, - transparency); + TilesManager::instance()->shader()->drawQuad(rect, textureInfo->m_textureId, + transparency); m_texture->consumerRelease(); } diff --git a/WebCore/platform/graphics/android/GLUtils.cpp b/WebCore/platform/graphics/android/GLUtils.cpp index 739dafc..2200d05 100644 --- a/WebCore/platform/graphics/android/GLUtils.cpp +++ b/WebCore/platform/graphics/android/GLUtils.cpp @@ -45,7 +45,8 @@ using namespace android; // Matrix utilities ///////////////////////////////////////////////////////////////////////////////////////// -void GLUtils::toGLMatrix(GLfloat* flattened, const TransformationMatrix& m) { +void GLUtils::toGLMatrix(GLfloat* flattened, const TransformationMatrix& m) +{ flattened[0] = m.m11(); // scaleX flattened[1] = m.m12(); // skewY flattened[2] = m.m13(); @@ -64,7 +65,8 @@ void GLUtils::toGLMatrix(GLfloat* flattened, const TransformationMatrix& m) { flattened[15] = m.m44(); // persp2 } -void GLUtils::toSkMatrix(SkMatrix& matrix, const TransformationMatrix& m) { +void GLUtils::toSkMatrix(SkMatrix& matrix, const TransformationMatrix& m) +{ matrix[0] = m.m11(); // scaleX matrix[1] = m.m21(); // skewX matrix[2] = m.m41(); // transX @@ -77,7 +79,8 @@ void GLUtils::toSkMatrix(SkMatrix& matrix, const TransformationMatrix& m) { } void GLUtils::setOrthographicMatrix(TransformationMatrix& ortho, float left, float top, - float right, float bottom, float nearZ, float farZ) { + float right, float bottom, float nearZ, float farZ) +{ float deltaX = right - left; float deltaY = top - bottom; float deltaZ = farZ - nearZ; @@ -96,19 +99,19 @@ void GLUtils::setOrthographicMatrix(TransformationMatrix& ortho, float left, flo // GL & EGL error checks ///////////////////////////////////////////////////////////////////////////////////////// -void GLUtils::checkEglError(const char* op, EGLBoolean returnVal) { - if (returnVal != EGL_TRUE) { +void GLUtils::checkEglError(const char* op, EGLBoolean returnVal) +{ + if (returnVal != EGL_TRUE) XLOG("EGL ERROR - %s() returned %d\n", op, returnVal); - } else { + else XLOG("EGL OK - %s() returned %d\n", op, returnVal); - } - for (EGLint error = eglGetError(); error != EGL_SUCCESS; error = eglGetError()) { + for (EGLint error = eglGetError(); error != EGL_SUCCESS; error = eglGetError()) XLOG("after %s() eglError (0x%x)\n", op, error); - } } -bool GLUtils::checkGlError(const char* op) { +bool GLUtils::checkGlError(const char* op) +{ bool ret = false; for (GLint error = glGetError(); error; error = glGetError()) { XLOG("GL ERROR - after %s() glError (0x%x)\n", op, error); @@ -117,7 +120,8 @@ bool GLUtils::checkGlError(const char* op) { return ret; } -bool GLUtils::checkGlErrorOn(void* p, const char* op) { +bool GLUtils::checkGlErrorOn(void* p, const char* op) +{ bool ret = false; for (GLint error = glGetError(); error; error = glGetError()) { XLOG("GL ERROR on %x - after %s() glError (0x%x)\n", p, op, error); @@ -130,17 +134,19 @@ bool GLUtils::checkGlErrorOn(void* p, const char* op) { // GL & EGL extension checks ///////////////////////////////////////////////////////////////////////////////////////// -bool GLUtils::isEGLImageSupported() { +bool GLUtils::isEGLImageSupported() +{ const char* eglExtensions = eglQueryString(eglGetCurrentDisplay(), EGL_EXTENSIONS); const char* glExtensions = reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)); - return eglExtensions && glExtensions && - strstr(eglExtensions, "EGL_KHR_image_base") && - strstr(eglExtensions, "EGL_KHR_gl_texture_2D_image") && - strstr(glExtensions, "GL_OES_EGL_image"); + return eglExtensions && glExtensions + && strstr(eglExtensions, "EGL_KHR_image_base") + && strstr(eglExtensions, "EGL_KHR_gl_texture_2D_image") + && strstr(glExtensions, "GL_OES_EGL_image"); } -bool GLUtils::isEGLFenceSyncSupported() { +bool GLUtils::isEGLFenceSyncSupported() +{ const char* eglExtensions = eglQueryString(eglGetCurrentDisplay(), EGL_EXTENSIONS); return eglExtensions && strstr(eglExtensions, "EGL_KHR_fence_sync"); } @@ -151,39 +157,40 @@ bool GLUtils::isEGLFenceSyncSupported() { static GLenum getInternalFormat(SkBitmap::Config config) { - switch(config) { - case SkBitmap::kA8_Config: - return GL_ALPHA; - case SkBitmap::kARGB_4444_Config: - return GL_RGBA; - case SkBitmap::kARGB_8888_Config: - return GL_RGBA; - case SkBitmap::kRGB_565_Config: - return GL_RGB; - default: - return -1; + switch (config) { + case SkBitmap::kA8_Config: + return GL_ALPHA; + case SkBitmap::kARGB_4444_Config: + return GL_RGBA; + case SkBitmap::kARGB_8888_Config: + return GL_RGBA; + case SkBitmap::kRGB_565_Config: + return GL_RGB; + default: + return -1; } } static GLenum getType(SkBitmap::Config config) { - switch(config) { - case SkBitmap::kA8_Config: - return GL_UNSIGNED_BYTE; - case SkBitmap::kARGB_4444_Config: - return GL_UNSIGNED_SHORT_4_4_4_4; - case SkBitmap::kARGB_8888_Config: - return GL_UNSIGNED_BYTE; - case SkBitmap::kIndex8_Config: - return -1; // No type for compressed data. - case SkBitmap::kRGB_565_Config: - return GL_UNSIGNED_SHORT_5_6_5; - default: - return -1; + switch (config) { + case SkBitmap::kA8_Config: + return GL_UNSIGNED_BYTE; + case SkBitmap::kARGB_4444_Config: + return GL_UNSIGNED_SHORT_4_4_4_4; + case SkBitmap::kARGB_8888_Config: + return GL_UNSIGNED_BYTE; + case SkBitmap::kIndex8_Config: + return -1; // No type for compressed data. + case SkBitmap::kRGB_565_Config: + return GL_UNSIGNED_SHORT_5_6_5; + default: + return -1; } } -static EGLConfig defaultPbufferConfig(EGLDisplay display) { +static EGLConfig defaultPbufferConfig(EGLDisplay display) +{ EGLConfig config; EGLint numConfigs; @@ -195,15 +202,15 @@ static EGLConfig defaultPbufferConfig(EGLDisplay display) { eglChooseConfig(display, configAttribs, &config, 1, &numConfigs); GLUtils::checkEglError("eglPbufferConfig"); - if(numConfigs != 1) { + if (numConfigs != 1) LOGI("eglPbufferConfig failed (%d)\n", numConfigs); - } return config; } static EGLSurface createPbufferSurface(EGLDisplay display, const EGLConfig& config, - EGLint* errorCode) { + EGLint* errorCode) +{ const EGLint attribList[] = { EGL_WIDTH, 1, EGL_HEIGHT, 1, @@ -222,7 +229,8 @@ static EGLSurface createPbufferSurface(EGLDisplay display, const EGLConfig& conf return surface; } -EGLContext GLUtils::createBackgroundContext(EGLContext sharedContext) { +EGLContext GLUtils::createBackgroundContext(EGLContext sharedContext) +{ checkEglError("<init>"); EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); checkEglError("eglGetDisplay"); @@ -246,8 +254,8 @@ EGLContext GLUtils::createBackgroundContext(EGLContext sharedContext) { EGLint surfaceConfigId; EGLBoolean success = eglGetConfigAttrib(display, config, EGL_CONFIG_ID, &surfaceConfigId); - EGLint context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; - EGLContext context = eglCreateContext(display, config, sharedContext, context_attribs); + EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; + EGLContext context = eglCreateContext(display, config, sharedContext, contextAttribs); checkEglError("eglCreateContext"); if (context == EGL_NO_CONTEXT) { XLOG("eglCreateContext failed\n"); @@ -264,13 +272,15 @@ EGLContext GLUtils::createBackgroundContext(EGLContext sharedContext) { return context; } -void GLUtils::deleteTexture(GLuint* texture) { +void GLUtils::deleteTexture(GLuint* texture) +{ glDeleteTextures(1, texture); GLUtils::checkGlError("glDeleteTexture"); *texture = 0; } -GLuint GLUtils::createSampleTexture() { +GLuint GLUtils::createSampleTexture() +{ GLuint texture; glGenTextures(1, &texture); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); @@ -289,7 +299,8 @@ GLuint GLUtils::createSampleTexture() { return texture; } -void GLUtils::createTextureWithBitmap(GLuint texture, SkBitmap& bitmap, GLint filter) { +void GLUtils::createTextureWithBitmap(GLuint texture, SkBitmap& bitmap, GLint filter) +{ glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glBindTexture(GL_TEXTURE_2D, texture); GLUtils::checkGlError("glBindTexture"); @@ -305,7 +316,8 @@ void GLUtils::createTextureWithBitmap(GLuint texture, SkBitmap& bitmap, GLint fi glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); } -void GLUtils::updateTextureWithBitmap(GLuint texture, SkBitmap& bitmap, GLint filter) { +void GLUtils::updateTextureWithBitmap(GLuint texture, SkBitmap& bitmap, GLint filter) +{ glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glBindTexture(GL_TEXTURE_2D, texture); GLUtils::checkGlError("glBindTexture"); @@ -321,7 +333,8 @@ void GLUtils::updateTextureWithBitmap(GLuint texture, SkBitmap& bitmap, GLint fi glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); } -void GLUtils::createEGLImageFromTexture(GLuint texture, EGLImageKHR* image) { +void GLUtils::createEGLImageFromTexture(GLuint texture, EGLImageKHR* image) +{ EGLClientBuffer buffer = reinterpret_cast<EGLClientBuffer>(texture); static const EGLint attr[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE }; *image = eglCreateImageKHR(eglGetCurrentDisplay(), eglGetCurrentContext(), @@ -329,7 +342,8 @@ void GLUtils::createEGLImageFromTexture(GLuint texture, EGLImageKHR* image) { GLUtils::checkEglError("eglCreateImage", (*image != EGL_NO_IMAGE_KHR)); } -void GLUtils::createTextureFromEGLImage(GLuint texture, EGLImageKHR image, GLint filter) { +void GLUtils::createTextureFromEGLImage(GLuint texture, EGLImageKHR image, GLint filter) +{ glBindTexture(GL_TEXTURE_2D, texture); GLUtils::checkGlError("glBindTexture"); glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)image); diff --git a/WebCore/platform/graphics/android/GLUtils.h b/WebCore/platform/graphics/android/GLUtils.h index 1b2e823..3e7b800 100644 --- a/WebCore/platform/graphics/android/GLUtils.h +++ b/WebCore/platform/graphics/android/GLUtils.h @@ -23,50 +23,50 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef GLUTILS_H_ -#define GLUTILS_H_ +#ifndef GLUtils_h +#define GLUtils_h #if USE(ACCELERATED_COMPOSITING) -#include <GLES2/gl2.h> -#include <GLES2/gl2ext.h> -#include <EGL/egl.h> -#include <EGL/eglext.h> #include "SkBitmap.h" #include "SkMatrix.h" #include "TransformationMatrix.h" +#include <EGL/egl.h> +#include <EGL/eglext.h> +#include <GLES2/gl2.h> +#include <GLES2/gl2ext.h> namespace WebCore { class GLUtils { public: - // Matrix utilities - static void toGLMatrix(GLfloat* flattened, const TransformationMatrix& matrix); - static void toSkMatrix(SkMatrix& skmatrix, const TransformationMatrix& matrix); - static void setOrthographicMatrix(TransformationMatrix& ortho, float left, float top, - float right, float bottom, float nearZ, float farZ); + // Matrix utilities + static void toGLMatrix(GLfloat* flattened, const TransformationMatrix& matrix); + static void toSkMatrix(SkMatrix& skmatrix, const TransformationMatrix& matrix); + static void setOrthographicMatrix(TransformationMatrix& ortho, float left, float top, + float right, float bottom, float nearZ, float farZ); - // GL & EGL error checks - static void checkEglError(const char* op, EGLBoolean returnVal = EGL_TRUE); - static bool checkGlErrorOn(void* p, const char* op); - static bool checkGlError(const char* op); + // GL & EGL error checks + static void checkEglError(const char* op, EGLBoolean returnVal = EGL_TRUE); + static bool checkGlErrorOn(void* p, const char* op); + static bool checkGlError(const char* op); - // GL & EGL extension checks - static bool isEGLImageSupported(); - static bool isEGLFenceSyncSupported(); + // GL & EGL extension checks + static bool isEGLImageSupported(); + static bool isEGLFenceSyncSupported(); - // Texture utilities - static EGLContext createBackgroundContext(EGLContext sharedContext); - static void deleteTexture(GLuint* texture); - static GLuint createSampleTexture(); - static void createTextureWithBitmap(GLuint texture, SkBitmap& bitmap, GLint filter = GL_LINEAR); - static void updateTextureWithBitmap(GLuint texture, SkBitmap& bitmap, GLint filter = GL_LINEAR); - static void createEGLImageFromTexture(GLuint texture, EGLImageKHR* image); - static void createTextureFromEGLImage(GLuint texture, EGLImageKHR image, GLint filter = GL_LINEAR); + // Texture utilities + static EGLContext createBackgroundContext(EGLContext sharedContext); + static void deleteTexture(GLuint* texture); + static GLuint createSampleTexture(); + static void createTextureWithBitmap(GLuint texture, SkBitmap& bitmap, GLint filter = GL_LINEAR); + static void updateTextureWithBitmap(GLuint texture, SkBitmap& bitmap, GLint filter = GL_LINEAR); + static void createEGLImageFromTexture(GLuint texture, EGLImageKHR* image); + static void createTextureFromEGLImage(GLuint texture, EGLImageKHR image, GLint filter = GL_LINEAR); }; } // namespace WebCore #endif // USE(ACCELERATED_COMPOSITING) -#endif // GLUTILS_H_ +#endif // GLUtils_h diff --git a/WebCore/platform/graphics/android/GLWebViewState.h b/WebCore/platform/graphics/android/GLWebViewState.h index 698eb4a..3b6f1d1 100644 --- a/WebCore/platform/graphics/android/GLWebViewState.h +++ b/WebCore/platform/graphics/android/GLWebViewState.h @@ -170,7 +170,7 @@ public: unsigned int paintBaseLayerContent(SkCanvas* canvas); void setBaseLayer(BaseLayerAndroid* layer, const IntRect& rect); - void setExtra(BaseLayerAndroid* , SkPicture& , const IntRect& ); + void setExtra(BaseLayerAndroid*, SkPicture&, const IntRect&); void scheduleUpdate(const double& currentTime, const SkIRect& viewport, float scale); TiledPage* frontPage(); diff --git a/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp b/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp index 5d1c86a..1efbecc 100644 --- a/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp +++ b/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp @@ -276,12 +276,23 @@ void GraphicsLayerAndroid::setPosition(const FloatPoint& point) askForSync(); } +void GraphicsLayerAndroid::setPreserves3D(bool preserves3D) +{ + if (preserves3D == m_preserves3D) + return; + + GraphicsLayer::setPreserves3D(preserves3D); + m_contentLayer->setPreserves3D(preserves3D); + askForSync(); +} + void GraphicsLayerAndroid::setAnchorPoint(const FloatPoint3D& point) { if (point == m_anchorPoint) return; GraphicsLayer::setAnchorPoint(point); m_contentLayer->setAnchorPoint(point.x(), point.y()); + m_contentLayer->setAnchorPointZ(point.z()); askForSync(); } @@ -303,7 +314,6 @@ void GraphicsLayerAndroid::setTransform(const TransformationMatrix& t) GraphicsLayer::setTransform(t); m_contentLayer->setTransform(t); - askForSync(); } @@ -314,6 +324,7 @@ void GraphicsLayerAndroid::setChildrenTransform(const TransformationMatrix& t) LOG("(%x) setChildrenTransform", this); GraphicsLayer::setChildrenTransform(t); + m_contentLayer->setChildrenTransform(t); for (unsigned int i = 0; i < m_children.size(); i++) { GraphicsLayer* layer = m_children[i]; layer->setTransform(t); @@ -523,6 +534,7 @@ bool GraphicsLayerAndroid::repaint() m_contentLayer->getSize().width(), m_contentLayer->getSize().height()); + m_contentLayer->needsRepaint(); m_needsRepaint = false; m_invalidatedRects.clear(); @@ -549,6 +561,14 @@ bool GraphicsLayerAndroid::paintContext(SkPicture* context, void GraphicsLayerAndroid::setNeedsDisplayInRect(const FloatRect& rect) { + for (unsigned int i = 0; i < m_children.size(); i++) { + GraphicsLayer* layer = m_children[i]; + if (layer) { + FloatRect childrenRect = m_transform.mapRect(rect); + layer->setNeedsDisplayInRect(childrenRect); + } + } + if (!m_haveImage && !drawsContent()) { LOG("(%x) setNeedsDisplay(%.2f,%.2f,%.2f,%.2f) doesn't have content, bypass...", this, rect.x(), rect.y(), rect.width(), rect.height()); @@ -565,8 +585,8 @@ void GraphicsLayerAndroid::setNeedsDisplayInRect(const FloatRect& rect) } #ifdef LAYER_DEBUG - LOG("(%x) setNeedsDisplayInRect(%d) - (%.2f, %.2f, %.2f, %.2f)", this, - m_needsRepaint, rect.x(), rect.y(), rect.width(), rect.height()); + LOG("(%x) layer %d setNeedsDisplayInRect(%d) - (%.2f, %.2f, %.2f, %.2f)", this, + m_contentLayer->uniqueId(), m_needsRepaint, rect.x(), rect.y(), rect.width(), rect.height()); #endif if (addInval) { diff --git a/WebCore/platform/graphics/android/GraphicsLayerAndroid.h b/WebCore/platform/graphics/android/GraphicsLayerAndroid.h index 1e17f47..a243d65 100644 --- a/WebCore/platform/graphics/android/GraphicsLayerAndroid.h +++ b/WebCore/platform/graphics/android/GraphicsLayerAndroid.h @@ -55,6 +55,7 @@ public: virtual void removeFromParent(); virtual void setPosition(const FloatPoint&); + virtual void setPreserves3D(bool b); virtual void setAnchorPoint(const FloatPoint3D&); virtual void setSize(const FloatSize&); diff --git a/WebCore/platform/graphics/android/LayerAndroid.cpp b/WebCore/platform/graphics/android/LayerAndroid.cpp index b71f525..69822b5 100644 --- a/WebCore/platform/graphics/android/LayerAndroid.cpp +++ b/WebCore/platform/graphics/android/LayerAndroid.cpp @@ -6,17 +6,34 @@ #include "AndroidAnimation.h" #include "DrawExtra.h" #include "GLUtils.h" +#include "PaintLayerOperation.h" #include "ParseCanvas.h" #include "SkBitmapRef.h" #include "SkBounder.h" #include "SkDrawFilter.h" #include "SkPaint.h" #include "SkPicture.h" +#include "TilesManager.h" #include <wtf/CurrentTime.h> #define LAYER_DEBUG // Add diagonals for debugging #undef LAYER_DEBUG +#ifdef DEBUG + +#include <cutils/log.h> +#include <wtf/text/CString.h> + +#undef XLOG +#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "LayerAndroid", __VA_ARGS__) + +#else + +#undef XLOG +#define XLOG(...) + +#endif // DEBUG + namespace WebCore { static int gDebugLayerAndroidInstances; @@ -51,13 +68,20 @@ LayerAndroid::LayerAndroid(bool isRootLayer) : SkLayer(), m_isRootLayer(isRootLayer), m_haveClip(false), m_isFixed(false), + m_preserves3D(false), + m_anchorPointZ(0), m_recordingPicture(0), m_contentsImage(0), m_extra(0), - m_uniqueId(++gUniqueId) + m_uniqueId(++gUniqueId), + m_texture(0), + m_pictureUsed(0) { m_backgroundColor = 0; + m_preserves3D = false; + m_dirty = false; + gDebugLayerAndroidInstances++; } @@ -65,7 +89,8 @@ LayerAndroid::LayerAndroid(const LayerAndroid& layer) : SkLayer(layer), m_isRootLayer(layer.m_isRootLayer), m_haveClip(layer.m_haveClip), m_extra(0), // deliberately not copied - m_uniqueId(layer.m_uniqueId) + m_uniqueId(layer.m_uniqueId), + m_texture(0) { m_isFixed = layer.m_isFixed; m_contentsImage = layer.m_contentsImage; @@ -87,6 +112,13 @@ LayerAndroid::LayerAndroid(const LayerAndroid& layer) : SkLayer(layer), m_recordingPicture = layer.m_recordingPicture; SkSafeRef(m_recordingPicture); + m_preserves3D = layer.m_preserves3D; + m_anchorPointZ = layer.m_anchorPointZ; + m_drawTransform = layer.m_drawTransform; + m_childrenTransform = layer.m_childrenTransform; + m_dirty = layer.m_dirty; + m_pictureUsed = layer.m_pictureUsed; + for (int i = 0; i < layer.countChildren(); i++) addChild(layer.getChild(i)->copy())->unref(); @@ -104,15 +136,19 @@ LayerAndroid::LayerAndroid(SkPicture* picture) : SkLayer(), m_recordingPicture(picture), m_contentsImage(0), m_extra(0), - m_uniqueId(-1) + m_uniqueId(-1), + m_texture(0) { m_backgroundColor = 0; + m_dirty = false; SkSafeRef(m_recordingPicture); gDebugLayerAndroidInstances++; } LayerAndroid::~LayerAndroid() { + if (m_texture) + m_texture->release(this); removeChildren(); m_contentsImage->safeUnref(); m_recordingPicture->safeUnref(); @@ -158,6 +194,8 @@ bool LayerAndroid::evaluateAnimations(double time) const void LayerAndroid::addAnimation(PassRefPtr<AndroidAnimation> anim) { + if (m_animations.get(anim->name())) + removeAnimation(anim->name()); m_animations.add(anim->name(), anim); } @@ -316,10 +354,11 @@ public: bool drewText() { return m_findCheck.drewText(); } - void setBest(const LayerAndroid* best) { + void setBest(const LayerAndroid* best, int x, int y) + { m_best = best; - m_bestX = m_x; - m_bestY = m_y; + m_bestX = x; + m_bestY = y; } int x() const { return m_x; } int y() const { return m_y; } @@ -354,12 +393,14 @@ void LayerAndroid::findInner(LayerAndroid::FindState& state) const for (int i = 0; i < countChildren(); i++) getChild(i)->findInner(state); // Move back into the parent coordinates. + int testX = state.x(); + int testY = state.y(); state.setLocation(x + localBounds.fLeft, y + localBounds.fTop); if (!m_recordingPicture) return; - if (!state.drew(m_recordingPicture, localBounds)) + if (!contentIsScrollable() && !state.drew(m_recordingPicture, localBounds)) return; - state.setBest(this); // set last match (presumably on top) + state.setBest(this, testX, testY); // set last match (presumably on top) } const LayerAndroid* LayerAndroid::find(int* xPtr, int* yPtr, SkPicture* root) const @@ -414,13 +455,12 @@ void LayerAndroid::updateFixedLayersPositions(const SkRect& viewport) void LayerAndroid::updatePositions() { // apply the viewport to us - SkMatrix matrix; if (!m_isFixed) { // turn our fields into a matrix. // // TODO: this should happen in the caller, and we should remove these // fields from our subclass - matrix.reset(); + SkMatrix matrix; GLUtils::toSkMatrix(matrix, m_transform); this->setMatrix(matrix); } @@ -431,30 +471,214 @@ void LayerAndroid::updatePositions() this->getChild(i)->updatePositions(); } +void LayerAndroid::updateGLPositions(const TransformationMatrix& parentMatrix, float opacity) +{ + IntSize bounds(getSize().width(), getSize().height()); + FloatPoint anchorPoint(getAnchorPoint().fX, getAnchorPoint().fY); + FloatPoint position(getPosition().fX, getPosition().fY); + float centerOffsetX = (0.5f - anchorPoint.x()) * bounds.width(); + float centerOffsetY = (0.5f - anchorPoint.y()) * bounds.height(); + float originX = anchorPoint.x() * bounds.width(); + float originY = anchorPoint.y() * bounds.height(); + TransformationMatrix localMatrix = parentMatrix; + localMatrix.translate3d(originX + position.x(), + originY + position.y(), + anchorPointZ()); + FloatPoint p(0, 0); + p = localMatrix.mapPoint(p); + p = m_transform.mapPoint(p); + + localMatrix.multLeft(m_transform); + localMatrix.translate3d(-originX, + -originY, + -anchorPointZ()); + p = localMatrix.mapPoint(p); + + setDrawTransform(localMatrix); + opacity *= getOpacity(); + setDrawOpacity(opacity); + + int count = this->countChildren(); + if (!count) + return; + + // Flatten to 2D if the layer doesn't preserve 3D. + if (!preserves3D()) { + localMatrix.setM13(0); + localMatrix.setM23(0); + localMatrix.setM31(0); + localMatrix.setM32(0); + localMatrix.setM33(1); + localMatrix.setM34(0); + localMatrix.setM43(0); + } + // now apply it to our children + + if (!m_childrenTransform.isIdentity()) { + localMatrix.translate(getSize().width() * 0.5f, getSize().height() * 0.5f); + localMatrix.multLeft(m_childrenTransform); + localMatrix.translate(-getSize().width() * 0.5f, -getSize().height() * 0.5f); + } + for (int i = 0; i < count; i++) + this->getChild(i)->updateGLPositions(localMatrix, opacity); +} + void LayerAndroid::setContentsImage(SkBitmapRef* img) { SkRefCnt_SafeAssign(m_contentsImage, img); } -void LayerAndroid::onDraw(SkCanvas* canvas, SkScalar opacity) +bool LayerAndroid::needsTexture() { - if (m_haveClip) { - SkRect r; - r.set(0, 0, getSize().width(), getSize().height()); - canvas->clipRect(r); + return !m_isRootLayer && prepareContext() && m_recordingPicture->width() && m_recordingPicture->height(); +} + +void LayerAndroid::reserveGLTextures() +{ + int count = this->countChildren(); + for (int i = 0; i < count; i++) + this->getChild(i)->reserveGLTextures(); + + if (needsTexture()) { + LayerTexture* texture; + texture = TilesManager::instance()->getExistingTextureForLayer(this); + // SMP flush + android::AutoMutex lock(m_atomicSync); + m_texture = texture; + } +} + +void LayerAndroid::createGLTextures() +{ + int count = this->countChildren(); + for (int i = 0; i < count; i++) + this->getChild(i)->createGLTextures(); + + if (needsTexture() && !m_texture) { + LayerTexture* texture; + texture = TilesManager::instance()->createTextureForLayer(this); + // SMP flush + keep dirty bit in sync + android::AutoMutex lock(m_atomicSync); + m_texture = texture; + m_dirty = true; + } + + checkForObsolescence(); +} + +void LayerAndroid::checkForObsolescence() +{ + m_atomicSync.lock(); + if (!m_texture) { + m_atomicSync.unlock(); return; } - if (!prepareContext()) + if (!m_pictureUsed || m_texture->pictureUsed() != m_pictureUsed) { + XLOG("We mark layer %d as dirty because: m_pictureUsed(%d == 0?), texture picture used %x", + uniqueId(), m_pictureUsed, m_texture->pictureUsed()); + m_texture->setPictureUsed(m_pictureUsed); + m_dirty = true; + } + + if (!m_texture->isReady()) + m_dirty = true; + + bool dirty = m_dirty; + m_atomicSync.unlock(); + + if (!dirty) return; - // we just have this save/restore for opacity... - SkAutoCanvasRestore restore(canvas, true); + XLOG("We schedule a paint for layer %d, because isReady %d or m_dirty %d", + uniqueId(), m_texture->isReady(), m_dirty); + PaintLayerOperation* operation = new PaintLayerOperation(this); + TilesManager::instance()->scheduleOperation(operation); +} - int canvasOpacity = SkScalarRound(opacity * 255); - if (canvasOpacity < 255) - canvas->setDrawFilter(new OpacityDrawFilter(canvasOpacity)); +static inline bool compareLayerZ(const LayerAndroid* a, const LayerAndroid* b) +{ + const TransformationMatrix& transformA = a->drawTransform(); + const TransformationMatrix& transformB = b->drawTransform(); + + return transformA.m43() < transformB.m43(); +} + +bool LayerAndroid::drawGL(SkMatrix& matrix) +{ + if (prepareContext() && m_texture) { + TextureInfo* textureInfo = m_texture->consumerLock(); + if (textureInfo && m_texture->isReady()) { + SkRect rect; + rect.set(0, 0, getSize().width(), getSize().height()); + TransformationMatrix m = drawTransform(); + TilesManager::instance()->shader()->drawLayerQuad(m, rect, + textureInfo->m_textureId, + m_drawOpacity); + } + m_texture->consumerRelease(); + } + + bool askPaint = false; + int count = this->countChildren(); + if (count > 0) { + Vector <LayerAndroid*> sublayers; + for (int i = 0; i < count; i++) + sublayers.append(this->getChild(i)); + + // now we sort for the transparency + std::stable_sort(sublayers.begin(), sublayers.end(), compareLayerZ); + for (int i = 0; i < count; i++) { + LayerAndroid* layer = sublayers[i]; + askPaint |= layer->drawGL(matrix); + } + } + + return askPaint; +} + +// This is called from the texture generation thread +void LayerAndroid::paintBitmapGL() +{ + XLOG("LayerAndroid paintBitmapGL (layer %d)", uniqueId()); + // We acquire the values below atomically. This ensures that we are reading + // values correctly across cores. Further, once we have these values they + // can be updated by other threads without consequence. + m_atomicSync.lock(); + LayerTexture* texture = m_texture; + m_atomicSync.unlock(); + + if (!texture) { + XLOG("Layer %d doesn't have a texture!", uniqueId()); + return; + } + + texture->producerAcquireContext(); + TextureInfo* textureInfo = texture->producerLock(); + + // at this point we can safely check the ownership (if the texture got + // transferred to another BaseTile under us) + if (texture->owner() != this) { + texture->producerRelease(); + return; + } + + XLOG("LayerAndroid %d paintBitmapGL WE ARE PAINTING", uniqueId()); + SkCanvas* canvas = texture->canvas(); + canvas->drawARGB(0, 0, 0, 0, SkXfermode::kClear_Mode); + contentDraw(canvas); + + XLOG("LayerAndroid %d paintBitmapGL PAINTING DONE, updating the texture", uniqueId()); + m_atomicSync.lock(); + m_dirty = false; + m_atomicSync.unlock(); + texture->producerUpdate(textureInfo); + XLOG("LayerAndroid %d paintBitmapGL UPDATING DONE", uniqueId()); +} + +void LayerAndroid::contentDraw(SkCanvas* canvas) +{ if (m_contentsImage) { SkRect dest; dest.set(0, 0, getSize().width(), getSize().height()); @@ -488,6 +712,28 @@ void LayerAndroid::onDraw(SkCanvas* canvas, SkScalar opacity) #endif } +void LayerAndroid::onDraw(SkCanvas* canvas, SkScalar opacity) +{ + if (m_haveClip) { + SkRect r; + r.set(0, 0, getSize().width(), getSize().height()); + canvas->clipRect(r); + return; + } + + if (!prepareContext()) + return; + + // we just have this save/restore for opacity... + SkAutoCanvasRestore restore(canvas, true); + + int canvasOpacity = SkScalarRound(opacity * 255); + if (canvasOpacity < 255) + canvas->setDrawFilter(new OpacityDrawFilter(canvasOpacity)); + + contentDraw(canvas); +} + SkPicture* LayerAndroid::recordContext() { if (prepareContext(true)) diff --git a/WebCore/platform/graphics/android/LayerAndroid.h b/WebCore/platform/graphics/android/LayerAndroid.h index 1269a1d..3d1c5af 100644 --- a/WebCore/platform/graphics/android/LayerAndroid.h +++ b/WebCore/platform/graphics/android/LayerAndroid.h @@ -19,9 +19,13 @@ #if USE(ACCELERATED_COMPOSITING) +#include "FloatPoint.h" +#include "FloatPoint3D.h" +#include "LayerTexture.h" #include "RefPtr.h" #include "SkColor.h" #include "SkLayer.h" +#include "TextureOwner.h" #include "TransformationMatrix.h" #include <wtf/HashMap.h> @@ -76,8 +80,11 @@ struct SkLength { namespace WebCore { class AndroidAnimation; +class BackedDoubleBufferedTexture; +class LayerAndroidFindState; +class TiledPage; -class LayerAndroid : public SkLayer { +class LayerAndroid : public SkLayer, public TextureOwner { public: LayerAndroid(bool isRootLayer); @@ -85,11 +92,39 @@ public: LayerAndroid(SkPicture*); virtual ~LayerAndroid(); + // TextureOwner methods + virtual void removeTexture() + { + android::AutoMutex lock(m_atomicSync); + m_texture = 0; + } + virtual TiledPage* page() { return 0; } + static int instancesCount(); void setTransform(const TransformationMatrix& matrix) { m_transform = matrix; } FloatPoint translation() const; SkRect bounds() const; + // called on the root layer + void reserveGLTextures(); + void createGLTextures(); + + bool needsTexture(); + void checkForObsolescence(); + + bool drawGL(SkMatrix&); + void paintBitmapGL(); + void updateGLPositions(const TransformationMatrix& parentMatrix, float opacity); + void setDrawOpacity(float opacity) { m_drawOpacity = opacity; } + + bool preserves3D() { return m_preserves3D; } + void setPreserves3D(bool value) { m_preserves3D = value; } + void setAnchorPointZ(float z) { m_anchorPointZ = z; } + float anchorPointZ() { return m_anchorPointZ; } + void setDrawTransform(const TransformationMatrix& transform) { m_drawTransform = transform; } + const TransformationMatrix& drawTransform() const { return m_drawTransform; } + void setChildrenTransform(const TransformationMatrix& t) { m_childrenTransform = t; } + void setFixedPosition(SkLength left, // CSS left property SkLength top, // CSS top property SkLength right, // CSS right property @@ -177,12 +212,17 @@ public: m_recordingPicture and m_contentsImage. */ void setContentsImage(SkBitmapRef* img); + bool hasContentsImage() { return m_contentsImage; } void bounds(SkRect*) const; virtual bool contentIsScrollable() const { return false; } virtual LayerAndroid* copy() const { return new LayerAndroid(*this); } + void needsRepaint() { m_pictureUsed++; } + unsigned int pictureUsed() { return m_pictureUsed; } + void contentDraw(SkCanvas*); + protected: virtual void onDraw(SkCanvas*, SkScalar opacity); @@ -216,6 +256,12 @@ private: SkColor m_backgroundColor; + bool m_preserves3D; + float m_anchorPointZ; + float m_drawOpacity; + TransformationMatrix m_drawTransform; + TransformationMatrix m_childrenTransform; + // Note that m_recordingPicture and m_contentsImage are mutually exclusive; // m_recordingPicture is used when WebKit is asked to paint the layer's // content, while m_contentsImage contains an image that we directly @@ -231,6 +277,17 @@ private: DrawExtra* m_extra; int m_uniqueId; + // GL textures management + LayerTexture* m_texture; + // used to signal that the tile is out-of-date and needs to be redrawn + bool m_dirty; + unsigned int m_pictureUsed; + + // This mutex serves two purposes. (1) It ensures that certain operations + // happen atomically and (2) it makes sure those operations are synchronized + // across all threads and cores. + android::Mutex m_atomicSync; + typedef SkLayer INHERITED; }; diff --git a/WebCore/platform/graphics/android/LayerTexture.cpp b/WebCore/platform/graphics/android/LayerTexture.cpp new file mode 100644 index 0000000..294c3d3 --- /dev/null +++ b/WebCore/platform/graphics/android/LayerTexture.cpp @@ -0,0 +1,51 @@ +/* + * Copyright 2010, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "LayerTexture.h" + +#define DOUBLE_BUFFERED_TEXTURE_MINIMUM_ACCESS 3 + +void LayerTexture::producerUpdate(TextureInfo* textureInfo) +{ + update(); + BackedDoubleBufferedTexture::producerUpdate(textureInfo); +} + +void LayerTexture::update() +{ + // FIXME: fix the double buffered texture class instead of doing this + // this is a stop gap measure and should be removed. + // Right now we have to update the textures 3 times (one create, two + // updates) before we can be sure to have a non-corrupted texture + // to display. + if (m_textureUpdates < DOUBLE_BUFFERED_TEXTURE_MINIMUM_ACCESS) + m_textureUpdates++; +} + +bool LayerTexture::isReady() +{ + return m_textureUpdates == DOUBLE_BUFFERED_TEXTURE_MINIMUM_ACCESS; +} diff --git a/WebCore/platform/graphics/android/LayerTexture.h b/WebCore/platform/graphics/android/LayerTexture.h new file mode 100644 index 0000000..959978f --- /dev/null +++ b/WebCore/platform/graphics/android/LayerTexture.h @@ -0,0 +1,61 @@ +/* + * Copyright 2010, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef LayerTexture_h +#define LayerTexture_h + +#include "BackedDoubleBufferedTexture.h" + +namespace WebCore { + +class LayerTexture : public BackedDoubleBufferedTexture { + public: + LayerTexture(uint32_t w, uint32_t h, + SkBitmap::Config config = SkBitmap::kARGB_8888_Config) + : BackedDoubleBufferedTexture(w, h, config) + , m_id(0) + , m_pictureUsed(0) + , m_textureUpdates(0) + {} + + int id() { return m_id; } + void setId(int id) { m_id = id; } + + unsigned int pictureUsed() { return m_pictureUsed; } + void setPictureUsed(unsigned pictureUsed) { m_pictureUsed = pictureUsed; } + bool isReady(); + virtual void producerUpdate(TextureInfo* textureInfo); + + private: + void update(); + + int m_id; + unsigned int m_pictureUsed; + unsigned int m_textureUpdates; +}; + +} // namespace WebCore + +#endif // LayerTexture_h diff --git a/WebCore/platform/graphics/android/MediaPlayerPrivateAndroid.h b/WebCore/platform/graphics/android/MediaPlayerPrivateAndroid.h index 49aafec..e8e29bf 100644 --- a/WebCore/platform/graphics/android/MediaPlayerPrivateAndroid.h +++ b/WebCore/platform/graphics/android/MediaPlayerPrivateAndroid.h @@ -115,7 +115,7 @@ protected: MediaPlayer::ReadyState m_readyState; MediaPlayer::NetworkState m_networkState; - SkBitmap* m_poster; // not owned + SkBitmap* m_poster; // not owned String m_posterUrl; IntSize m_naturalSize; @@ -124,7 +124,7 @@ protected: bool m_isVisible; }; -} // namespace WebCore +} // namespace WebCore #endif diff --git a/WebCore/platform/graphics/android/PaintLayerOperation.cpp b/WebCore/platform/graphics/android/PaintLayerOperation.cpp new file mode 100644 index 0000000..a3ef148 --- /dev/null +++ b/WebCore/platform/graphics/android/PaintLayerOperation.cpp @@ -0,0 +1,61 @@ +/* + * Copyright 2010, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "PaintLayerOperation.h" + +#include "LayerAndroid.h" + +bool PaintLayerOperation::operator==(const QueuedOperation* operation) +{ + if (operation->type() != type()) + return false; + const PaintLayerOperation* op = static_cast<const PaintLayerOperation*>(operation); + return op->m_layer == m_layer; +} + +void PaintLayerOperation::run() +{ + if (m_layer) + m_layer->paintBitmapGL(); +} + +SkLayer* PaintLayerOperation::baseLayer() +{ + if (!m_layer) + return 0; + + return m_layer->getRootLayer(); +} + +bool PaintLayerFilter::check(QueuedOperation* operation) +{ + if (operation->type() == QueuedOperation::PaintLayer) { + PaintLayerOperation* op = static_cast<PaintLayerOperation*>(operation); + if (op->baseLayer() == m_baseLayer) + return true; + } + return false; +} diff --git a/WebCore/platform/graphics/android/PaintLayerOperation.h b/WebCore/platform/graphics/android/PaintLayerOperation.h new file mode 100644 index 0000000..d393ac5 --- /dev/null +++ b/WebCore/platform/graphics/android/PaintLayerOperation.h @@ -0,0 +1,62 @@ +/* + * Copyright 2010, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef PaintLayerOperation_h +#define PaintLayerOperation_h + +#include "QueuedOperation.h" + +class SkLayer; + +namespace WebCore { + +class LayerAndroid; + +class PaintLayerOperation : public QueuedOperation { + public: + PaintLayerOperation(LayerAndroid* layer) + : QueuedOperation(QueuedOperation::PaintLayer, 0) + , m_layer(layer) {} + virtual ~PaintLayerOperation() {} + virtual bool operator==(const QueuedOperation* operation); + virtual void run(); + SkLayer* baseLayer(); + + private: + LayerAndroid* m_layer; +}; + +class PaintLayerFilter : public OperationFilter { + public: + PaintLayerFilter(SkLayer* layer) : m_baseLayer(layer) {} + virtual bool check(QueuedOperation* operation); + + private: + SkLayer* m_baseLayer; +}; + +} + +#endif // PaintLayerOperation_h diff --git a/WebCore/platform/graphics/android/QueuedOperation.h b/WebCore/platform/graphics/android/QueuedOperation.h index 7472db7..089483d 100644 --- a/WebCore/platform/graphics/android/QueuedOperation.h +++ b/WebCore/platform/graphics/android/QueuedOperation.h @@ -32,7 +32,7 @@ namespace WebCore { class QueuedOperation { public: - enum OperationType { Undefined, PaintTileSet, DeleteTexture }; + enum OperationType { Undefined, PaintTileSet, PaintLayer, DeleteTexture }; QueuedOperation(OperationType type, TiledPage* page) : m_type(type) , m_page(page) {} @@ -46,15 +46,13 @@ class QueuedOperation { TiledPage* m_page; }; -class OperationFilter -{ +class OperationFilter { public: - virtual ~OperationFilter() {} - virtual bool check(QueuedOperation* operation) = 0; + virtual ~OperationFilter() {} + virtual bool check(QueuedOperation* operation) = 0; }; -class PageFilter : public OperationFilter -{ +class PageFilter : public OperationFilter { public: PageFilter(TiledPage* page) : m_page(page) {} virtual bool check(QueuedOperation* operation) diff --git a/WebCore/platform/graphics/android/ScrollableLayerAndroid.cpp b/WebCore/platform/graphics/android/ScrollableLayerAndroid.cpp index 7b40b8d..ca8f03c 100644 --- a/WebCore/platform/graphics/android/ScrollableLayerAndroid.cpp +++ b/WebCore/platform/graphics/android/ScrollableLayerAndroid.cpp @@ -5,10 +5,11 @@ namespace WebCore { -bool ScrollableLayerAndroid::scrollTo(int x, int y) { +bool ScrollableLayerAndroid::scrollTo(int x, int y) +{ SkIRect scrollBounds; getScrollRect(&scrollBounds); - if (scrollBounds.fRight == 0 && scrollBounds.fBottom == 0) + if (!scrollBounds.fRight && !scrollBounds.fBottom) return false; SkScalar newX = SkScalarPin(x, 0, scrollBounds.fRight); @@ -24,7 +25,8 @@ bool ScrollableLayerAndroid::scrollTo(int x, int y) { return true; } -void ScrollableLayerAndroid::getScrollRect(SkIRect* out) const { +void ScrollableLayerAndroid::getScrollRect(SkIRect* out) const +{ const SkPoint& pos = getPosition(); out->fLeft = m_scrollLimits.fLeft - pos.fX; out->fTop = m_scrollLimits.fTop - pos.fY; diff --git a/WebCore/platform/graphics/android/ScrollableLayerAndroid.h b/WebCore/platform/graphics/android/ScrollableLayerAndroid.h index 25f9900..697fe74 100644 --- a/WebCore/platform/graphics/android/ScrollableLayerAndroid.h +++ b/WebCore/platform/graphics/android/ScrollableLayerAndroid.h @@ -32,7 +32,8 @@ public: : LayerAndroid(layer) , m_scrollLimits(layer.m_scrollLimits) {} ScrollableLayerAndroid(const LayerAndroid& layer) - : LayerAndroid(layer) { + : LayerAndroid(layer) + { m_scrollLimits.setEmpty(); } virtual ~ScrollableLayerAndroid() {}; @@ -51,7 +52,8 @@ public: // fBottom = maxY void getScrollRect(SkIRect* out) const; - void setScrollLimits(float x, float y, float width, float height) { + void setScrollLimits(float x, float y, float width, float height) + { m_scrollLimits.set(x, y, x + width, y + height); } @@ -63,4 +65,4 @@ private: #endif // USE(ACCELERATED_COMPOSITING) -#endif // LayerAndroid_h +#endif // LayerAndroid_h diff --git a/WebCore/platform/graphics/android/ShaderProgram.cpp b/WebCore/platform/graphics/android/ShaderProgram.cpp index 2195bd4..ac6375d 100644 --- a/WebCore/platform/graphics/android/ShaderProgram.cpp +++ b/WebCore/platform/graphics/android/ShaderProgram.cpp @@ -28,9 +28,9 @@ #if USE(ACCELERATED_COMPOSITING) -#include <GLES2/gl2.h> #include "GLUtils.h" +#include <GLES2/gl2.h> #include <cutils/log.h> #include <wtf/CurrentTime.h> #include <wtf/text/CString.h> @@ -59,10 +59,11 @@ static const char gFragmentShader[] = " gl_FragColor.a *= alpha; " "}\n"; -GLuint ShaderProgram::loadShader(GLenum shaderType, const char* pSource) { +GLuint ShaderProgram::loadShader(GLenum shaderType, const char* pSource) +{ GLuint shader = glCreateShader(shaderType); if (shader) { - glShaderSource(shader, 1, &pSource, NULL); + glShaderSource(shader, 1, &pSource, 0); glCompileShader(shader); GLint compiled = 0; glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); @@ -72,7 +73,7 @@ GLuint ShaderProgram::loadShader(GLenum shaderType, const char* pSource) { if (infoLen) { char* buf = (char*) malloc(infoLen); if (buf) { - glGetShaderInfoLog(shader, infoLen, NULL, buf); + glGetShaderInfoLog(shader, infoLen, 0, buf); XLOG("could not compile shader %d:\n%s\n", shaderType, buf); free(buf); } @@ -84,16 +85,15 @@ GLuint ShaderProgram::loadShader(GLenum shaderType, const char* pSource) { return shader; } -GLuint ShaderProgram::createProgram(const char* pVertexSource, const char* pFragmentSource) { +GLuint ShaderProgram::createProgram(const char* pVertexSource, const char* pFragmentSource) +{ GLuint vertexShader = loadShader(GL_VERTEX_SHADER, pVertexSource); - if (!vertexShader) { + if (!vertexShader) return 0; - } GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pFragmentSource); - if (!pixelShader) { + if (!pixelShader) return 0; - } GLuint program = glCreateProgram(); if (program) { @@ -110,7 +110,7 @@ GLuint ShaderProgram::createProgram(const char* pVertexSource, const char* pFrag if (bufLength) { char* buf = (char*) malloc(bufLength); if (buf) { - glGetProgramInfoLog(program, bufLength, NULL, buf); + glGetProgramInfoLog(program, bufLength, 0, buf); XLOG("could not link program:\n%s\n", buf); free(buf); } @@ -122,7 +122,8 @@ GLuint ShaderProgram::createProgram(const char* pVertexSource, const char* pFrag return program; } -ShaderProgram::ShaderProgram() { +ShaderProgram::ShaderProgram() +{ m_program = createProgram(gVertexShader, gFragmentShader); m_hProjectionMatrix = glGetUniformLocation(m_program, "projectionMatrix"); @@ -130,10 +131,10 @@ ShaderProgram::ShaderProgram() { m_hTexSampler = glGetUniformLocation(m_program, "s_texture"); const GLfloat coord[] = { - 0.0f, 0.0f, //C - 1.0f, 0.0f, //D - 0.0f, 1.0f, //A - 1.0f, 1.0f //B + 0.0f, 0.0f, // C + 1.0f, 0.0f, // D + 0.0f, 1.0f, // A + 1.0f, 1.0f // B }; glGenBuffers(1, m_textureBuffer); @@ -145,14 +146,16 @@ ShaderProgram::ShaderProgram() { // Drawing ///////////////////////////////////////////////////////////////////////////////////////// -void ShaderProgram::setViewport(SkRect& viewport) { +void ShaderProgram::setViewport(SkRect& viewport) +{ TransformationMatrix ortho; GLUtils::setOrthographicMatrix(ortho, viewport.fLeft, viewport.fTop, viewport.fRight, viewport.fBottom, -1000, 1000); m_projectionMatrix = ortho; } -void ShaderProgram::setProjectionMatrix(SkRect& geometry) { +void ShaderProgram::setProjectionMatrix(SkRect& geometry) +{ TransformationMatrix translate; translate.translate3d(geometry.fLeft, geometry.fTop, 0.0); TransformationMatrix scale; @@ -167,7 +170,8 @@ void ShaderProgram::setProjectionMatrix(SkRect& geometry) { glUniformMatrix4fv(m_hProjectionMatrix, 1, GL_FALSE, projectionMatrix); } -void ShaderProgram::drawQuad(SkRect& geometry, int textureId, float opacity) { +void ShaderProgram::drawQuad(SkRect& geometry, int textureId, float opacity) +{ setProjectionMatrix(geometry); glActiveTexture(GL_TEXTURE0); @@ -185,7 +189,8 @@ void ShaderProgram::drawQuad(SkRect& geometry, int textureId, float opacity) { } void ShaderProgram::drawLayerQuad(const TransformationMatrix& drawMatrix, - SkRect& geometry, int textureId, float opacity) { + SkRect& geometry, int textureId, float opacity) +{ TransformationMatrix renderMatrix = drawMatrix; renderMatrix.scale3d(geometry.width(), geometry.height(), 1); diff --git a/WebCore/platform/graphics/android/ShaderProgram.h b/WebCore/platform/graphics/android/ShaderProgram.h index 93a6d4c..785b42d 100644 --- a/WebCore/platform/graphics/android/ShaderProgram.h +++ b/WebCore/platform/graphics/android/ShaderProgram.h @@ -14,48 +14,48 @@ * limitations under the License. */ -#ifndef SHADERPROGRAM_H_ -#define SHADERPROGRAM_H_ +#ifndef ShaderProgram_h +#define ShaderProgram_h #if USE(ACCELERATED_COMPOSITING) -#include <GLES2/gl2.h> #include "SkRect.h" #include "TransformationMatrix.h" +#include <GLES2/gl2.h> namespace WebCore { class ShaderProgram { public: - ShaderProgram(); - int projectionMatrix() { return m_hProjectionMatrix; } - int alpha() { return m_hAlpha; } - int textureSampler() { return m_hTexSampler; } - int program() { return m_program; } - - // Drawing - void setViewport(SkRect& viewport); - void drawQuad(SkRect& geometry, int textureId, float opacity); - void drawLayerQuad(const TransformationMatrix& drawMatrix, + ShaderProgram(); + int projectionMatrix() { return m_hProjectionMatrix; } + int alpha() { return m_hAlpha; } + int textureSampler() { return m_hTexSampler; } + int program() { return m_program; } + + // Drawing + void setViewport(SkRect& viewport); + void drawQuad(SkRect& geometry, int textureId, float opacity); + void drawLayerQuad(const TransformationMatrix& drawMatrix, SkRect& geometry, int textureId, float opacity); private: - GLuint loadShader(GLenum shaderType, const char* pSource); - GLuint createProgram(const char* vertexSource, const char* fragmentSource); - void setProjectionMatrix(SkRect& geometry); + GLuint loadShader(GLenum shaderType, const char* pSource); + GLuint createProgram(const char* vertexSource, const char* fragmentSource); + void setProjectionMatrix(SkRect& geometry); - int m_program; + int m_program; - TransformationMatrix m_projectionMatrix; - GLuint m_textureBuffer[1]; + TransformationMatrix m_projectionMatrix; + GLuint m_textureBuffer[1]; - // uniforms - int m_hProjectionMatrix; - int m_hAlpha; - int m_hTexSampler; + // uniforms + int m_hProjectionMatrix; + int m_hAlpha; + int m_hTexSampler; }; } // namespace WebCore #endif // USE(ACCELERATED_COMPOSITING) -#endif // SHADERPROGRAM_H_ +#endif // ShaderProgram_h diff --git a/WebCore/platform/graphics/android/SharedTexture.cpp b/WebCore/platform/graphics/android/SharedTexture.cpp index 16ec97f..76d6da0 100644 --- a/WebCore/platform/graphics/android/SharedTexture.cpp +++ b/WebCore/platform/graphics/android/SharedTexture.cpp @@ -25,6 +25,7 @@ #include "config.h" #include "SharedTexture.h" + #include "GLUtils.h" #define LOG_NDEBUG 1 @@ -33,30 +34,35 @@ namespace WebCore { -TextureInfo::TextureInfo() { +TextureInfo::TextureInfo() +{ m_textureId = GL_NO_TEXTURE; m_width = 0; m_height = 0; m_internalFormat = 0; } -bool TextureInfo::equalsAttributes(const TextureInfo* otherTexture) { - return otherTexture->m_width == m_width && - otherTexture->m_height == m_height && - otherTexture->m_internalFormat == m_internalFormat; +bool TextureInfo::equalsAttributes(const TextureInfo* otherTexture) +{ + return otherTexture->m_width == m_width + && otherTexture->m_height == m_height + && otherTexture->m_internalFormat == m_internalFormat; } -void TextureInfo::copyAttributes(const TextureInfo* sourceTexture) { +void TextureInfo::copyAttributes(const TextureInfo* sourceTexture) +{ m_width = sourceTexture->m_width; m_height = sourceTexture->m_height; m_internalFormat = sourceTexture->m_internalFormat; } -bool TextureInfo::operator==(const TextureInfo& otherTexture) { +bool TextureInfo::operator==(const TextureInfo& otherTexture) +{ return otherTexture.m_textureId == m_textureId && equalsAttributes(&otherTexture); } -SharedTexture::SharedTexture() { +SharedTexture::SharedTexture() +{ m_display = eglGetCurrentDisplay(); m_eglImage = EGL_NO_IMAGE_KHR; m_isNewImage = true; @@ -64,7 +70,7 @@ SharedTexture::SharedTexture() { m_supportsEGLImage = GLUtils::isEGLImageSupported(); m_supportsEGLFenceSyncKHR = GLUtils::isEGLFenceSyncSupported(); - //TODO temporarily disable fence sync until nvidia implementation is complete + // TODO temporarily disable fence sync until nvidia implementation is complete m_supportsEGLFenceSyncKHR = false; LOGI("imageEGL: %d syncKHR: %d", m_supportsEGLImage, m_supportsEGLFenceSyncKHR); @@ -74,28 +80,29 @@ SharedTexture::SharedTexture() { // terminated all providers. If EGLImages are used, the deletion of the // source texture and EGLImage is the responsibility of the caller. In the case // of double buffered textures this is handled in the onDestroy(...) method. -SharedTexture::~SharedTexture() { - if (m_supportsEGLImage) { +SharedTexture::~SharedTexture() +{ + if (m_supportsEGLImage) GLUtils::deleteTexture(&m_targetTexture.m_textureId); - } else { + else GLUtils::deleteTexture(&m_sourceTexture.m_textureId); - } } -void SharedTexture::initSourceTexture() { +void SharedTexture::initSourceTexture() +{ glGenTextures(1, &m_sourceTexture.m_textureId); } -TextureInfo* SharedTexture::lockSource() { +TextureInfo* SharedTexture::lockSource() +{ m_lock.lock(); if (m_supportsEGLFenceSyncKHR && m_syncObject != EGL_NO_SYNC_KHR) { EGLint status = eglClientWaitSyncKHR(m_display, m_syncObject, 0, 1000000); - if (status == EGL_TIMEOUT_EXPIRED_KHR) { + if (status == EGL_TIMEOUT_EXPIRED_KHR) LOGE("Sync timeout for shared texture (%d)", m_sourceTexture.m_textureId); - } eglDestroySyncKHR(m_display, m_syncObject); m_syncObject = EGL_NO_SYNC_KHR; @@ -104,8 +111,8 @@ TextureInfo* SharedTexture::lockSource() { return &m_sourceTexture; } -void SharedTexture::releaseSource() { - +void SharedTexture::releaseSource() +{ if (m_supportsEGLImage) { // delete the existing image if needed if (!m_sourceTexture.equalsAttributes(&m_targetTexture)) { @@ -138,19 +145,20 @@ void SharedTexture::releaseSource() { m_lock.unlock(); } -TextureInfo* SharedTexture::lockTarget() { +TextureInfo* SharedTexture::lockTarget() +{ m_lock.lock(); - if ((!m_supportsEGLImage && m_targetTexture.m_textureId == GL_NO_TEXTURE) || - (m_supportsEGLImage && m_eglImage == EGL_NO_IMAGE_KHR)) { + if ((!m_supportsEGLImage && m_targetTexture.m_textureId == GL_NO_TEXTURE) + || (m_supportsEGLImage && m_eglImage == EGL_NO_IMAGE_KHR)) { m_lock.unlock(); return 0; } if (m_supportsEGLImage && (m_isNewImage || m_targetTexture.m_textureId == GL_NO_TEXTURE)) { - if (m_targetTexture.m_textureId == GL_NO_TEXTURE) { + if (m_targetTexture.m_textureId == GL_NO_TEXTURE) glGenTextures(1, &m_targetTexture.m_textureId); - } + GLUtils::createTextureFromEGLImage(m_targetTexture.m_textureId, m_eglImage); LOGV("Generating Consumer Texture from 0x%x", m_eglImage); m_isNewImage = false; @@ -159,13 +167,13 @@ TextureInfo* SharedTexture::lockTarget() { return &m_targetTexture; } -void SharedTexture::releaseTarget() { +void SharedTexture::releaseTarget() +{ if (m_supportsEGLFenceSyncKHR) { - if (m_syncObject != EGL_NO_SYNC_KHR) { + if (m_syncObject != EGL_NO_SYNC_KHR) eglDestroySyncKHR(m_display, m_syncObject); - } - m_syncObject = eglCreateSyncKHR(m_display, EGL_SYNC_FENCE_KHR, NULL); + m_syncObject = eglCreateSyncKHR(m_display, EGL_SYNC_FENCE_KHR, 0); } else { // TODO the flush currently prevents the screen from getting partial // updates but the only way to guarantee this is to call glFinish. Until diff --git a/WebCore/platform/graphics/android/SharedTexture.h b/WebCore/platform/graphics/android/SharedTexture.h index 581ad77..e654c5c 100644 --- a/WebCore/platform/graphics/android/SharedTexture.h +++ b/WebCore/platform/graphics/android/SharedTexture.h @@ -23,14 +23,14 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef SharedTexture__DEFINED -#define SharedTexture__DEFINED +#ifndef SharedTexture_h +#define SharedTexture_h -#include <utils/threads.h> -#include <GLES2/gl2.h> -#include <GLES2/gl2ext.h> #include <EGL/egl.h> #include <EGL/eglext.h> +#include <GLES2/gl2.h> +#include <GLES2/gl2ext.h> +#include <utils/threads.h> namespace WebCore { @@ -132,4 +132,4 @@ private: } // namespace WebCore -#endif // SharedTexture__DEFINED +#endif // SharedTexture_h diff --git a/WebCore/platform/graphics/android/TexturesGenerator.cpp b/WebCore/platform/graphics/android/TexturesGenerator.cpp index 234c7f9..289665d 100644 --- a/WebCore/platform/graphics/android/TexturesGenerator.cpp +++ b/WebCore/platform/graphics/android/TexturesGenerator.cpp @@ -28,7 +28,9 @@ #if USE(ACCELERATED_COMPOSITING) +#include "BaseLayerAndroid.h" #include "GLUtils.h" +#include "PaintLayerOperation.h" #include "TilesManager.h" #ifdef DEBUG @@ -76,6 +78,11 @@ void TexturesGenerator::removeOperationsForPage(TiledPage* page) removeOperationsForFilter(new PageFilter(page)); } +void TexturesGenerator::removeOperationsForBaseLayer(BaseLayerAndroid* layer) +{ + removeOperationsForFilter(new PaintLayerFilter(layer)); +} + void TexturesGenerator::removeOperationsForFilter(OperationFilter* filter) { mRequestedOperationsLock.lock(); diff --git a/WebCore/platform/graphics/android/TexturesGenerator.h b/WebCore/platform/graphics/android/TexturesGenerator.h index 84dbeab..0e40e4a 100644 --- a/WebCore/platform/graphics/android/TexturesGenerator.h +++ b/WebCore/platform/graphics/android/TexturesGenerator.h @@ -37,6 +37,9 @@ namespace WebCore { using namespace android; +class BaseLayerAndroid; +class LayerAndroid; + class TexturesGenerator : public Thread { public: TexturesGenerator() : Thread() @@ -46,6 +49,7 @@ public: virtual status_t readyToRun(); void removeOperationsForPage(TiledPage* page); + void removeOperationsForBaseLayer(BaseLayerAndroid* layer); void removeOperationsForFilter(OperationFilter* filter); void scheduleOperation(QueuedOperation* operation); diff --git a/WebCore/platform/graphics/android/TilesManager.cpp b/WebCore/platform/graphics/android/TilesManager.cpp index 38dd282..3e174d1 100644 --- a/WebCore/platform/graphics/android/TilesManager.cpp +++ b/WebCore/platform/graphics/android/TilesManager.cpp @@ -30,6 +30,7 @@ #include "BaseTile.h" #include "SkCanvas.h" +#include "SkDevice.h" #include "SkPaint.h" #include <cutils/atomic.h> @@ -59,20 +60,27 @@ #define TILE_WIDTH 300 #define TILE_HEIGHT 300 +// Define a maximum amount of ram used by layers +#define MAX_LAYERS_ALLOCATION 20971520 // 20Mb +#define BYTES_PER_PIXEL 4 // 8888 config + namespace WebCore { TilesManager::TilesManager() - : m_generatorReady(false) + : m_layersMemoryUsage(0) + , m_generatorReady(false) { + XLOG("TilesManager ctor"); m_textures.reserveCapacity(MAX_TEXTURE_ALLOCATION); for (int i = 0; i < MAX_TEXTURE_ALLOCATION; i++) { BackedDoubleBufferedTexture* texture = new BackedDoubleBufferedTexture( tileWidth(), tileHeight()); // the atomic load ensures that the texture has been fully initialized // before we pass a pointer for other threads to operate on - m_textures.append( - (BackedDoubleBufferedTexture*)android_atomic_acquire_load((int32_t*)&texture)); + m_textures.append(reinterpret_cast<BackedDoubleBufferedTexture*>( + android_atomic_acquire_load(reinterpret_cast<int32_t*>(&texture)))); } + XLOG("TilesManager ctor"); m_pixmapsGenerationThread = new TexturesGenerator(); m_pixmapsGenerationThread->run("TexturesGenerator"); @@ -86,6 +94,7 @@ void TilesManager::enableTextures() BackedDoubleBufferedTexture* texture = m_textures[i]; texture->producerAcquireContext(); } + XLOG("enableTextures"); } void TilesManager::printTextures() @@ -217,6 +226,74 @@ BackedDoubleBufferedTexture* TilesManager::getAvailableTexture(BaseTile* owner) return 0; } +LayerTexture* TilesManager::getExistingTextureForLayer(LayerAndroid* layer) +{ + android::Mutex::Autolock lock(m_texturesLock); + for (unsigned int i = 0; i< m_layersTextures.size(); i++) { + if (m_layersTextures[i]->id() != layer->uniqueId()) + continue; + if (layer->getSize() != m_layersTextures[i]->getSize()) + continue; + + XLOG("return layer %d (%x) for tile %d (%x)", + i, m_layersTextures[i], + layer->uniqueId(), layer); + + if (m_layersTextures[i]->acquire(layer)) + return m_layersTextures[i]; + } + return 0; +} + +void TilesManager::printLayersTextures(const char* s) +{ +#ifdef DEBUG + for (unsigned int i = 0; i< m_layersTextures.size(); i++) { + XLOG("[%d] %s, texture %x for layer %d, owner: %x", i, s, m_layersTextures[i], + m_layersTextures[i]->id(), m_layersTextures[i]->owner()); + } +#endif +} + +void TilesManager::cleanupLayersTextures(bool forceCleanup) +{ + android::Mutex::Autolock lock(m_texturesLock); +#ifdef DEBUG + printLayersTextures("cleanup"); +#endif + for (unsigned int i = 0; i< m_layersTextures.size(); i++) { + LayerTexture* texture = m_layersTextures[i]; + + if (forceCleanup) + texture->setOwner(0); + + if (!texture->owner()) { + m_layersMemoryUsage -= (int) texture->getSize().fWidth + * (int) texture->getSize().fHeight * BYTES_PER_PIXEL; + m_layersTextures.remove(i); + delete texture; + } + } +} + +LayerTexture* TilesManager::createTextureForLayer(LayerAndroid* layer) +{ + int w = layer->getWidth(); + int h = layer->getHeight(); + int size = w * h * BYTES_PER_PIXEL; + + if (m_layersMemoryUsage + size > MAX_LAYERS_ALLOCATION) + cleanupLayersTextures(true); + + android::Mutex::Autolock lock(m_texturesLock); + LayerTexture* texture = new LayerTexture(w, h); + texture->setId(layer->uniqueId()); + m_layersTextures.append(texture); + texture->acquire(layer); + m_layersMemoryUsage += size; + return texture; +} + int TilesManager::maxTextureCount() { return MAX_TEXTURE_ALLOCATION; diff --git a/WebCore/platform/graphics/android/TilesManager.h b/WebCore/platform/graphics/android/TilesManager.h index f855738..e69db4c 100644 --- a/WebCore/platform/graphics/android/TilesManager.h +++ b/WebCore/platform/graphics/android/TilesManager.h @@ -30,6 +30,8 @@ #include "BackedDoubleBufferedTexture.h" #include "BaseTile.h" +#include "LayerAndroid.h" +#include "LayerTexture.h" #include "ShaderProgram.h" #include "TexturesGenerator.h" #include "TiledPage.h" @@ -48,6 +50,11 @@ public: m_pixmapsGenerationThread->removeOperationsForPage(page); } + void removeOperationsForBaseLayer(BaseLayerAndroid* layer) + { + m_pixmapsGenerationThread->removeOperationsForBaseLayer(layer); + } + void scheduleOperation(QueuedOperation* operation) { m_pixmapsGenerationThread->scheduleOperation(operation); @@ -57,6 +64,11 @@ public: BackedDoubleBufferedTexture* getAvailableTexture(BaseTile* owner); + void printLayersTextures(const char* s); + void cleanupLayersTextures(bool forceCleanup = false); + LayerTexture* getExistingTextureForLayer(LayerAndroid* layer); + LayerTexture* createTextureForLayer(LayerAndroid* layer); + void markGeneratorAsReady() { android::Mutex::Autolock lock(m_generatorLock); @@ -84,6 +96,9 @@ private: } Vector<BackedDoubleBufferedTexture*> m_textures; + Vector<LayerTexture*> m_layersTextures; + + unsigned int m_layersMemoryUsage; bool m_generatorReady; |