diff options
Diffstat (limited to 'Source/WebCore')
199 files changed, 5841 insertions, 6423 deletions
diff --git a/Source/WebCore/Android.derived.jscbindings.mk b/Source/WebCore/Android.derived.jscbindings.mk deleted file mode 100644 index d859b15..0000000 --- a/Source/WebCore/Android.derived.jscbindings.mk +++ /dev/null @@ -1,752 +0,0 @@ - -## -## Copyright 2009, 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. -## - -# lookup tables for old-style JavaScript bindings -create_hash_table := $(LOCAL_PATH)/../JavaScriptCore/create_hash_table - -GEN := $(addprefix $(intermediates)/, \ - bindings/js/JSDOMWindowBase.lut.h \ - ) -$(GEN): PRIVATE_CUSTOM_TOOL = perl $(create_hash_table) $< > $@ -$(GEN): $(intermediates)/bindings/js/%.lut.h: $(LOCAL_PATH)/bindings/js/%.cpp $(create_hash_table) - $(transform-generated-source) -LOCAL_GENERATED_SOURCES += $(GEN) - - -GEN := $(intermediates)/bindings/js/JSHTMLInputElementBaseTable.cpp -$(GEN): PRIVATE_CUSTOM_TOOL = perl $(create_hash_table) $< > $@ -$(GEN): $(intermediates)/bindings/js/%Table.cpp: $(LOCAL_PATH)/bindings/js/%.cpp $(create_hash_table) - $(transform-generated-source) -$(intermediates)/bindings/js/JSHTMLInputElementBase.o : $(GEN) - -# lookup tables for old-style JavaScript bindings -js_binding_scripts := $(addprefix $(LOCAL_PATH)/,\ - bindings/scripts/CodeGenerator.pm \ - bindings/scripts/IDLParser.pm \ - bindings/scripts/IDLStructure.pm \ - bindings/scripts/generate-bindings.pl \ - ) - -FEATURE_DEFINES := ENABLE_ORIENTATION_EVENTS=1 ENABLE_TOUCH_EVENTS=1 ENABLE_DATABASE=1 ENABLE_OFFLINE_WEB_APPLICATIONS=1 ENABLE_DOM_STORAGE=1 ENABLE_VIDEO=1 ENABLE_GEOLOCATION=1 ENABLE_CONNECTION=1 ENABLE_APPLICATION_INSTALLED=1 ENABLE_XPATH=1 ENABLE_XSLT=1 ENABLE_DEVICE_ORIENTATION=1 ENABLE_FILE_READER=1 ENABLE_BLOB=1 ENABLE_WEB_TIMING=1 - -ifeq ($(ENABLE_SVG), true) - FEATURE_DEFINES += ENABLE_SVG=1 -endif - -# CSS -GEN := \ - $(intermediates)/css/JSCSSCharsetRule.h \ - $(intermediates)/css/JSCSSFontFaceRule.h \ - $(intermediates)/css/JSCSSImportRule.h \ - $(intermediates)/css/JSCSSMediaRule.h \ - $(intermediates)/css/JSCSSPageRule.h \ - $(intermediates)/css/JSCSSPrimitiveValue.h \ - $(intermediates)/css/JSCSSRule.h \ - $(intermediates)/css/JSCSSRuleList.h \ - $(intermediates)/css/JSCSSStyleDeclaration.h \ - $(intermediates)/css/JSCSSStyleRule.h \ - $(intermediates)/css/JSCSSStyleSheet.h \ - $(intermediates)/css/JSCSSValue.h \ - $(intermediates)/css/JSCSSValueList.h \ - $(intermediates)/css/JSCounter.h \ - $(intermediates)/css/JSMediaList.h \ - $(intermediates)/css/JSMediaQueryList.h \ - $(intermediates)/css/JSRGBColor.h \ - $(intermediates)/css/JSRect.h \ - $(intermediates)/css/JSStyleMedia.h \ - $(intermediates)/css/JSStyleSheet.h \ - $(intermediates)/css/JSStyleSheetList.h \ - $(intermediates)/css/JSWebKitCSSKeyframeRule.h \ - $(intermediates)/css/JSWebKitCSSKeyframesRule.h \ - $(intermediates)/css/JSWebKitCSSMatrix.h \ - $(intermediates)/css/JSWebKitCSSTransformValue.h -$(GEN): PRIVATE_PATH := $(LOCAL_PATH) -$(GEN): PRIVATE_CUSTOM_TOOL = perl -I$(PRIVATE_PATH)/bindings/scripts $(PRIVATE_PATH)/bindings/scripts/generate-bindings.pl --defines "$(FEATURE_DEFINES) LANGUAGE_JAVASCRIPT" --generator JS --include dom --include html --outputdir $(dir $@) $< -$(GEN): $(intermediates)/css/JS%.h : $(LOCAL_PATH)/css/%.idl $(js_binding_scripts) - $(transform-generated-source) -LOCAL_GENERATED_SOURCES += $(GEN) $(GEN:%.h=%.cpp) - - -# We also need the .cpp files, which are generated as side effects of the -# above rules. Specifying this explicitly makes -j2 work. -$(patsubst %.h,%.cpp,$(GEN)): $(intermediates)/css/%.cpp : $(intermediates)/css/%.h - -# DOM -GEN := \ - $(intermediates)/dom/JSAttr.h \ - $(intermediates)/dom/JSBeforeLoadEvent.h \ - $(intermediates)/dom/JSCDATASection.h \ - $(intermediates)/dom/JSCharacterData.h \ - $(intermediates)/dom/JSClientRect.h \ - $(intermediates)/dom/JSClientRectList.h \ - $(intermediates)/dom/JSClipboard.h \ - $(intermediates)/dom/JSComment.h \ - $(intermediates)/dom/JSCustomEvent.h \ - $(intermediates)/dom/JSCompositionEvent.h \ - $(intermediates)/dom/JSDOMCoreException.h \ - $(intermediates)/dom/JSDOMImplementation.h \ - $(intermediates)/dom/JSDOMStringList.h \ - $(intermediates)/dom/JSDOMStringMap.h \ - $(intermediates)/dom/JSDataTransferItems.h \ - $(intermediates)/dom/JSDeviceMotionEvent.h \ - $(intermediates)/dom/JSDeviceOrientationEvent.h \ - $(intermediates)/dom/JSDocument.h \ - $(intermediates)/dom/JSDocumentFragment.h \ - $(intermediates)/dom/JSDocumentType.h \ - $(intermediates)/dom/JSElement.h \ - $(intermediates)/dom/JSEntity.h \ - $(intermediates)/dom/JSEntityReference.h \ - $(intermediates)/dom/JSErrorEvent.h \ - $(intermediates)/dom/JSEvent.h \ - $(intermediates)/dom/JSEventException.h \ - $(intermediates)/dom/JSHashChangeEvent.h \ - $(intermediates)/dom/JSKeyboardEvent.h \ - $(intermediates)/dom/JSMessageChannel.h \ - $(intermediates)/dom/JSMessageEvent.h \ - $(intermediates)/dom/JSMessagePort.h \ - $(intermediates)/dom/JSMouseEvent.h \ - $(intermediates)/dom/JSMutationEvent.h \ - $(intermediates)/dom/JSNamedNodeMap.h \ - $(intermediates)/dom/JSNode.h \ - $(intermediates)/dom/JSNodeFilter.h \ - $(intermediates)/dom/JSNodeIterator.h \ - $(intermediates)/dom/JSNodeList.h \ - $(intermediates)/dom/JSNotation.h \ - $(intermediates)/dom/JSOverflowEvent.h \ - $(intermediates)/dom/JSPageTransitionEvent.h \ - $(intermediates)/dom/JSPopStateEvent.h \ - $(intermediates)/dom/JSProcessingInstruction.h \ - $(intermediates)/dom/JSProgressEvent.h \ - $(intermediates)/dom/JSRange.h \ - $(intermediates)/dom/JSRangeException.h \ - $(intermediates)/dom/JSText.h \ - $(intermediates)/dom/JSTextEvent.h \ - $(intermediates)/dom/JSTouch.h \ - $(intermediates)/dom/JSTouchEvent.h \ - $(intermediates)/dom/JSTouchList.h \ - $(intermediates)/dom/JSTreeWalker.h \ - $(intermediates)/dom/JSUIEvent.h \ - $(intermediates)/dom/JSWebKitAnimationEvent.h \ - $(intermediates)/dom/JSWebKitTransitionEvent.h \ - $(intermediates)/dom/JSWheelEvent.h -$(GEN): PRIVATE_PATH := $(LOCAL_PATH) -$(GEN): PRIVATE_CUSTOM_TOOL = perl -I$(PRIVATE_PATH)/bindings/scripts $(PRIVATE_PATH)/bindings/scripts/generate-bindings.pl --defines "$(FEATURE_DEFINES) LANGUAGE_JAVASCRIPT" --generator JS --include dom --include html --outputdir $(dir $@) $< -$(GEN): $(intermediates)/dom/JS%.h : $(LOCAL_PATH)/dom/%.idl $(js_binding_scripts) - $(transform-generated-source) -LOCAL_GENERATED_SOURCES += $(GEN) $(GEN:%.h=%.cpp) - -# We also need the .cpp files, which are generated as side effects of the -# above rules. Specifying this explicitly makes -j2 work. -$(patsubst %.h,%.cpp,$(GEN)): $(intermediates)/dom/%.cpp : $(intermediates)/dom/%.h - -# Fileapi -GEN := \ - $(intermediates)/fileapi/JSBlob.h \ - $(intermediates)/fileapi/JSDOMFileSystem.h \ - $(intermediates)/fileapi/JSDOMFileSystemSync.h \ - $(intermediates)/fileapi/JSDirectoryEntry.h \ - $(intermediates)/fileapi/JSDirectoryEntrySync.h \ - $(intermediates)/fileapi/JSDirectoryReader.h \ - $(intermediates)/fileapi/JSDirectoryReaderSync.h \ - $(intermediates)/fileapi/JSEntriesCallback.h \ - $(intermediates)/fileapi/JSEntry.h \ - $(intermediates)/fileapi/JSEntryArray.h \ - $(intermediates)/fileapi/JSEntryArraySync.h \ - $(intermediates)/fileapi/JSEntryCallback.h \ - $(intermediates)/fileapi/JSEntrySync.h \ - $(intermediates)/fileapi/JSErrorCallback.h \ - $(intermediates)/fileapi/JSFile.h \ - $(intermediates)/fileapi/JSFileCallback.h \ - $(intermediates)/fileapi/JSFileEntry.h \ - $(intermediates)/fileapi/JSFileEntrySync.h \ - $(intermediates)/fileapi/JSFileError.h \ - $(intermediates)/fileapi/JSFileException.h \ - $(intermediates)/fileapi/JSFileList.h \ - $(intermediates)/fileapi/JSFileReader.h \ - $(intermediates)/fileapi/JSFileReaderSync.h \ - $(intermediates)/fileapi/JSFileSystemCallback.h \ - $(intermediates)/fileapi/JSFileWriter.h \ - $(intermediates)/fileapi/JSFileWriterCallback.h \ - $(intermediates)/fileapi/JSMetadata.h \ - $(intermediates)/fileapi/JSMetadataCallback.h \ - $(intermediates)/fileapi/JSWebKitBlobBuilder.h \ - $(intermediates)/fileapi/JSWebKitFlags.h - -$(GEN): PRIVATE_PATH := $(LOCAL_PATH) -$(GEN): PRIVATE_CUSTOM_TOOL = perl -I$(PRIVATE_PATH)/bindings/scripts $(PRIVATE_PATH)/bindings/scripts/generate-bindings.pl --defines "$(FEATURE_DEFINES) LANGUAGE_JAVASCRIPT" --generator JS --include dom --include html --include fileapi --outputdir $(dir $@) $< -$(GEN): $(intermediates)/fileapi/JS%.h : $(LOCAL_PATH)/fileapi/%.idl $(js_binding_scripts) - $(transform-generated-source) -LOCAL_GENERATED_SOURCES += $(GEN) $(GEN:%.h=%.cpp) - -# We also need the .cpp files, which are generated as side effects of the -# above rules. Specifying this explicitly makes -j2 work. -$(patsubst %.h,%.cpp,$(GEN)): $(intermediates)/fileapi/%.cpp : $(intermediates)/fileapi/%.h - -# HTML -GEN := \ - $(intermediates)/html/JSDOMFormData.h \ - $(intermediates)/html/JSDOMSettableTokenList.h \ - $(intermediates)/html/JSDOMTokenList.h \ - $(intermediates)/html/JSDOMURL.h \ - $(intermediates)/html/JSDataGridColumn.h \ - $(intermediates)/html/JSDataGridColumnList.h \ - $(intermediates)/html/JSHTMLAllCollection.h \ - $(intermediates)/html/JSHTMLAnchorElement.h \ - $(intermediates)/html/JSHTMLAppletElement.h \ - $(intermediates)/html/JSHTMLAreaElement.h \ - $(intermediates)/html/JSHTMLAudioElement.h \ - $(intermediates)/html/JSHTMLBRElement.h \ - $(intermediates)/html/JSHTMLBaseElement.h \ - $(intermediates)/html/JSHTMLBaseFontElement.h \ - $(intermediates)/html/JSHTMLBlockquoteElement.h \ - $(intermediates)/html/JSHTMLBodyElement.h \ - $(intermediates)/html/JSHTMLButtonElement.h \ - $(intermediates)/html/JSHTMLCanvasElement.h \ - $(intermediates)/html/JSHTMLCollection.h \ - $(intermediates)/html/JSHTMLDataGridElement.h \ - $(intermediates)/html/JSHTMLDataGridCellElement.h \ - $(intermediates)/html/JSHTMLDataGridColElement.h \ - $(intermediates)/html/JSHTMLDataGridRowElement.h \ - $(intermediates)/html/JSHTMLDataListElement.h \ - $(intermediates)/html/JSHTMLDetailsElement.h \ - $(intermediates)/html/JSHTMLDListElement.h \ - $(intermediates)/html/JSHTMLDirectoryElement.h \ - $(intermediates)/html/JSHTMLDivElement.h \ - $(intermediates)/html/JSHTMLDocument.h \ - $(intermediates)/html/JSHTMLElement.h \ - $(intermediates)/html/JSHTMLEmbedElement.h \ - $(intermediates)/html/JSHTMLFieldSetElement.h \ - $(intermediates)/html/JSHTMLFontElement.h \ - $(intermediates)/html/JSHTMLFormElement.h \ - $(intermediates)/html/JSHTMLFrameElement.h \ - $(intermediates)/html/JSHTMLFrameSetElement.h \ - $(intermediates)/html/JSHTMLHRElement.h \ - $(intermediates)/html/JSHTMLHeadElement.h \ - $(intermediates)/html/JSHTMLHeadingElement.h \ - $(intermediates)/html/JSHTMLHtmlElement.h \ - $(intermediates)/html/JSHTMLIFrameElement.h \ - $(intermediates)/html/JSHTMLImageElement.h \ - $(intermediates)/html/JSHTMLInputElement.h \ - $(intermediates)/html/JSHTMLIsIndexElement.h \ - $(intermediates)/html/JSHTMLKeygenElement.h \ - $(intermediates)/html/JSHTMLLIElement.h \ - $(intermediates)/html/JSHTMLLabelElement.h \ - $(intermediates)/html/JSHTMLLegendElement.h \ - $(intermediates)/html/JSHTMLLinkElement.h \ - $(intermediates)/html/JSHTMLMapElement.h \ - $(intermediates)/html/JSHTMLMarqueeElement.h \ - $(intermediates)/html/JSHTMLMediaElement.h \ - $(intermediates)/html/JSHTMLMenuElement.h \ - $(intermediates)/html/JSHTMLMetaElement.h \ - $(intermediates)/html/JSHTMLMeterElement.h \ - $(intermediates)/html/JSHTMLModElement.h \ - $(intermediates)/html/JSHTMLOListElement.h \ - $(intermediates)/html/JSHTMLObjectElement.h \ - $(intermediates)/html/JSHTMLOptGroupElement.h \ - $(intermediates)/html/JSHTMLOptionElement.h \ - $(intermediates)/html/JSHTMLOptionsCollection.h \ - $(intermediates)/html/JSHTMLOutputElement.h \ - $(intermediates)/html/JSHTMLParagraphElement.h \ - $(intermediates)/html/JSHTMLParamElement.h \ - $(intermediates)/html/JSHTMLPreElement.h \ - $(intermediates)/html/JSHTMLProgressElement.h \ - $(intermediates)/html/JSHTMLQuoteElement.h \ - $(intermediates)/html/JSHTMLScriptElement.h \ - $(intermediates)/html/JSHTMLSelectElement.h \ - $(intermediates)/html/JSHTMLSourceElement.h \ - $(intermediates)/html/JSHTMLStyleElement.h \ - $(intermediates)/html/JSHTMLTableCaptionElement.h \ - $(intermediates)/html/JSHTMLTableCellElement.h \ - $(intermediates)/html/JSHTMLTableColElement.h \ - $(intermediates)/html/JSHTMLTableElement.h \ - $(intermediates)/html/JSHTMLTableRowElement.h \ - $(intermediates)/html/JSHTMLTableSectionElement.h \ - $(intermediates)/html/JSHTMLTextAreaElement.h \ - $(intermediates)/html/JSHTMLTitleElement.h \ - $(intermediates)/html/JSHTMLUListElement.h \ - $(intermediates)/html/JSHTMLVideoElement.h \ - $(intermediates)/html/JSImageData.h \ - $(intermediates)/html/JSMediaError.h \ - $(intermediates)/html/JSTextMetrics.h \ - $(intermediates)/html/JSTimeRanges.h \ - $(intermediates)/html/JSValidityState.h \ - $(intermediates)/html/JSVoidCallback.h - - -$(GEN): PRIVATE_PATH := $(LOCAL_PATH) -$(GEN): PRIVATE_CUSTOM_TOOL = perl -I$(PRIVATE_PATH)/bindings/scripts $(PRIVATE_PATH)/bindings/scripts/generate-bindings.pl --defines "$(FEATURE_DEFINES) LANGUAGE_JAVASCRIPT" --generator JS --include dom --include html --outputdir $(dir $@) $< -$(GEN): $(intermediates)/html/JS%.h : $(LOCAL_PATH)/html/%.idl $(js_binding_scripts) - $(transform-generated-source) -LOCAL_GENERATED_SOURCES += $(GEN) $(GEN:%.h=%.cpp) - -# We also need the .cpp files, which are generated as side effects of the -# above rules. Specifying this explicitly makes -j2 work. -$(patsubst %.h,%.cpp,$(GEN)): $(intermediates)/html/%.cpp : $(intermediates)/html/%.h - -# Canvas -GEN := \ - $(intermediates)/html/canvas/JSArrayBuffer.h \ - $(intermediates)/html/canvas/JSArrayBufferView.h \ - $(intermediates)/html/canvas/JSCanvasGradient.h \ - $(intermediates)/html/canvas/JSCanvasPattern.h \ - $(intermediates)/html/canvas/JSCanvasRenderingContext.h \ - $(intermediates)/html/canvas/JSCanvasRenderingContext2D.h \ - $(intermediates)/html/canvas/JSDataView.h \ - $(intermediates)/html/canvas/JSFloat32Array.h \ - $(intermediates)/html/canvas/JSInt8Array.h \ - $(intermediates)/html/canvas/JSInt16Array.h \ - $(intermediates)/html/canvas/JSInt32Array.h \ - $(intermediates)/html/canvas/JSOESTextureFloat.h \ - $(intermediates)/html/canvas/JSOESVertexArrayObject.h \ - $(intermediates)/html/canvas/JSUint8Array.h \ - $(intermediates)/html/canvas/JSUint16Array.h \ - $(intermediates)/html/canvas/JSUint32Array.h \ - $(intermediates)/html/canvas/JSWebGLActiveInfo.h \ - $(intermediates)/html/canvas/JSWebGLBuffer.h \ - $(intermediates)/html/canvas/JSWebGLFramebuffer.h \ - $(intermediates)/html/canvas/JSWebGLProgram.h \ - $(intermediates)/html/canvas/JSWebGLRenderbuffer.h \ - $(intermediates)/html/canvas/JSWebGLRenderingContext.h \ - $(intermediates)/html/canvas/JSWebGLShader.h \ - $(intermediates)/html/canvas/JSWebGLTexture.h \ - $(intermediates)/html/canvas/JSWebGLUniformLocation.h \ - $(intermediates)/html/canvas/JSWebGLVertexArrayObjectOES.h - -$(GEN): PRIVATE_PATH := $(LOCAL_PATH) -$(GEN): PRIVATE_CUSTOM_TOOL = perl -I$(PRIVATE_PATH)/bindings/scripts $(PRIVATE_PATH)/bindings/scripts/generate-bindings.pl --defines "$(FEATURE_DEFINES) LANGUAGE_JAVASCRIPT" --generator JS --include dom --include html --outputdir $(dir $@) $< -$(GEN): $(intermediates)/html/canvas/JS%.h : $(LOCAL_PATH)/html/canvas/%.idl $(js_binding_scripts) - $(transform-generated-source) -LOCAL_GENERATED_SOURCES += $(GEN) $(GEN:%.h=%.cpp) - -# We also need the .cpp files, which are generated as side effects of the -# above rules. Specifying this explicitly makes -j2 work. -$(patsubst %.h,%.cpp,$(GEN)): $(intermediates)/html/canvas/%.cpp : $(intermediates)/html/canvas/%.h - -# Appcache -GEN := \ - $(intermediates)/loader/appcache/JSDOMApplicationCache.h - -$(GEN): PRIVATE_PATH := $(LOCAL_PATH) -$(GEN): PRIVATE_CUSTOM_TOOL = perl -I$(PRIVATE_PATH)/bindings/scripts $(PRIVATE_PATH)/bindings/scripts/generate-bindings.pl --defines "$(FEATURE_DEFINES) LANGUAGE_JAVASCRIPT" --generator JS --include dom --include html --outputdir $(dir $@) $< -$(GEN): $(intermediates)/loader/appcache/JS%.h : $(LOCAL_PATH)/loader/appcache/%.idl $(js_binding_scripts) - $(transform-generated-source) -LOCAL_GENERATED_SOURCES += $(GEN) $(GEN:%.h=%.cpp) - -# We also need the .cpp files, which are generated as side effects of the -# above rules. Specifying this explicitly makes -j2 work. -$(patsubst %.h,%.cpp,$(GEN)): $(intermediates)/loader/appcache/%.cpp : $(intermediates)/loader/appcache/%.h - -# page -GEN := \ - $(intermediates)/page/JSBarInfo.h \ - $(intermediates)/page/JSConnection.h \ - $(intermediates)/page/JSConsole.h \ - $(intermediates)/page/JSCoordinates.h \ - $(intermediates)/page/JSCrypto.h \ - $(intermediates)/page/JSDOMSelection.h \ - $(intermediates)/page/JSDOMWindow.h \ - $(intermediates)/page/JSEventSource.h \ - $(intermediates)/page/JSGeolocation.h \ - $(intermediates)/page/JSGeoposition.h \ - $(intermediates)/page/JSHistory.h \ - $(intermediates)/page/JSLocation.h \ - $(intermediates)/page/JSMemoryInfo.h \ - $(intermediates)/page/JSNavigator.h \ - $(intermediates)/page/JSNavigatorUserMediaError.h \ - $(intermediates)/page/JSNavigatorUserMediaErrorCallback.h \ - $(intermediates)/page/JSNavigatorUserMediaSuccessCallback.h \ - $(intermediates)/page/JSPerformance.h \ - $(intermediates)/page/JSPerformanceNavigation.h \ - $(intermediates)/page/JSPerformanceTiming.h \ - $(intermediates)/page/JSPositionError.h \ - $(intermediates)/page/JSScreen.h \ - $(intermediates)/page/JSSpeechInputEvent.h \ - $(intermediates)/page/JSWebKitAnimation.h \ - $(intermediates)/page/JSWebKitAnimationList.h \ - $(intermediates)/page/JSWebKitPoint.h \ - $(intermediates)/page/JSWorkerNavigator.h - -$(GEN): PRIVATE_PATH := $(LOCAL_PATH) -$(GEN): PRIVATE_CUSTOM_TOOL = perl -I$(PRIVATE_PATH)/bindings/scripts $(PRIVATE_PATH)/bindings/scripts/generate-bindings.pl --defines "$(FEATURE_DEFINES) LANGUAGE_JAVASCRIPT" --generator JS --include dom --include html --outputdir $(dir $@) $< -$(GEN): $(intermediates)/page/JS%.h : $(LOCAL_PATH)/page/%.idl $(js_binding_scripts) - $(transform-generated-source) -LOCAL_GENERATED_SOURCES += $(GEN) $(GEN:%.h=%.cpp) - -# We also need the .cpp files, which are generated as side effects of the -# above rules. Specifying this explicitly makes -j2 work. -$(patsubst %.h,%.cpp,$(GEN)): $(intermediates)/page/%.cpp : $(intermediates)/page/%.h - -GEN := \ - $(intermediates)/plugins/JSDOMMimeType.h \ - $(intermediates)/plugins/JSDOMMimeTypeArray.h \ - $(intermediates)/plugins/JSDOMPlugin.h \ - $(intermediates)/plugins/JSDOMPluginArray.h - -$(GEN): PRIVATE_PATH := $(LOCAL_PATH) -$(GEN): PRIVATE_CUSTOM_TOOL = perl -I$(PRIVATE_PATH)/bindings/scripts $(PRIVATE_PATH)/bindings/scripts/generate-bindings.pl --defines "$(FEATURE_DEFINES) LANGUAGE_JAVASCRIPT" --generator JS --include dom --include html --outputdir $(dir $@) $< -$(GEN): $(intermediates)/plugins/JS%.h : $(LOCAL_PATH)/plugins/%.idl $(js_binding_scripts) - $(transform-generated-source) -LOCAL_GENERATED_SOURCES += $(GEN) $(GEN:%.h=%.cpp) - -# We also need the .cpp files, which are generated as side effects of the -# above rules. Specifying this explicitly makes -j2 work. -$(patsubst %.h,%.cpp,$(GEN)): $(intermediates)/plugins/%.cpp : $(intermediates)/plugins/%.h - -# Database -GEN := \ - $(intermediates)/storage/JSDatabase.h \ - $(intermediates)/storage/JSDatabaseCallback.h \ - $(intermediates)/storage/JSDatabaseSync.h \ - $(intermediates)/storage/JSSQLError.h \ - $(intermediates)/storage/JSSQLException.h \ - $(intermediates)/storage/JSSQLResultSet.h \ - $(intermediates)/storage/JSSQLResultSetRowList.h \ - $(intermediates)/storage/JSSQLStatementCallback.h \ - $(intermediates)/storage/JSSQLStatementErrorCallback.h \ - $(intermediates)/storage/JSSQLTransaction.h \ - $(intermediates)/storage/JSSQLTransactionCallback.h \ - $(intermediates)/storage/JSSQLTransactionSync.h \ - $(intermediates)/storage/JSSQLTransactionSyncCallback.h \ - $(intermediates)/storage/JSSQLTransactionErrorCallback.h - -$(GEN): PRIVATE_PATH := $(LOCAL_PATH) -$(GEN): PRIVATE_CUSTOM_TOOL = perl -I$(PRIVATE_PATH)/bindings/scripts $(PRIVATE_PATH)/bindings/scripts/generate-bindings.pl --defines "$(FEATURE_DEFINES) LANGUAGE_JAVASCRIPT" --generator JS --include dom --include html --include storage --outputdir $(dir $@) $< -$(GEN): $(intermediates)/storage/JS%.h : $(LOCAL_PATH)/storage/%.idl $(js_binding_scripts) - $(transform-generated-source) -LOCAL_GENERATED_SOURCES += $(GEN) $(GEN:%.h=%.cpp) - -# We also need the .cpp files, which are generated as side effects of the -# above rules. Specifying this explicitly makes -j2 work. -$(patsubst %.h,%.cpp,$(GEN)): $(intermediates)/storage/%.cpp : $(intermediates)/storage/%.h - -# DOM Storage -GEN := \ - $(intermediates)/storage/JSStorage.h \ - $(intermediates)/storage/JSStorageEvent.h - -$(GEN): PRIVATE_PATH := $(LOCAL_PATH) -$(GEN): PRIVATE_CUSTOM_TOOL = perl -I$(PRIVATE_PATH)/bindings/scripts $(PRIVATE_PATH)/bindings/scripts/generate-bindings.pl --defines "$(FEATURE_DEFINES) LANGUAGE_JAVASCRIPT" --generator JS --include dom --include html --outputdir $(dir $@) $< -$(GEN): $(intermediates)/storage/JS%.h : $(LOCAL_PATH)/storage/%.idl $(js_binding_scripts) - $(transform-generated-source) -LOCAL_GENERATED_SOURCES += $(GEN) $(GEN:%.h=%.cpp) - -# We also need the .cpp files, which are generated as side effects of the -# above rules. Specifying this explicitly makes -j2 work. -$(patsubst %.h,%.cpp,$(GEN)): $(intermediates)/storage/%.cpp : $(intermediates)/storage/%.h - -# Indexed Database -GEN := \ - $(intermediates)/storage/JSIDBAny.h \ - $(intermediates)/storage/JSIDBCursor.h \ - $(intermediates)/storage/JSIDBCursorWithValue.h \ - $(intermediates)/storage/JSIDBDatabaseError.h \ - $(intermediates)/storage/JSIDBDatabaseException.h \ - $(intermediates)/storage/JSIDBDatabase.h \ - $(intermediates)/storage/JSIDBFactory.h \ - $(intermediates)/storage/JSIDBIndex.h \ - $(intermediates)/storage/JSIDBKey.h \ - $(intermediates)/storage/JSIDBKeyRange.h \ - $(intermediates)/storage/JSIDBObjectStore.h \ - $(intermediates)/storage/JSIDBRequest.h \ - $(intermediates)/storage/JSIDBTransaction.h \ - $(intermediates)/storage/JSIDBVersionChangeEvent.h \ - $(intermediates)/storage/JSIDBVersionChangeRequest.h - -$(GEN): PRIVATE_PATH := $(LOCAL_PATH) -$(GEN): PRIVATE_CUSTOM_TOOL = perl -I$(PRIVATE_PATH)/bindings/scripts $(PRIVATE_PATH)/bindings/scripts/generate-bindings.pl --defines "$(FEATURE_DEFINES) LANGUAGE_JAVASCRIPT" --generator JS --include dom --include html --include storage --outputdir $(dir $@) $< -$(GEN): $(intermediates)/storage/JS%.h : $(LOCAL_PATH)/storage/%.idl $(js_binding_scripts) - $(transform-generated-source) -LOCAL_GENERATED_SOURCES += $(GEN) $(GEN:%.h=%.cpp) - -# We also need the .cpp files, which are generated as side effects of the -# above rules. Specifying this explicitly makes -j2 work. -$(patsubst %.h,%.cpp,$(GEN)): $(intermediates)/storage/%.cpp : $(intermediates)/storage/%.h - -# SVG -ifeq ($(ENABLE_SVG), true) -GEN := \ - $(intermediates)/svg/JSSVGAElement.h \ - $(intermediates)/svg/JSSVGAltGlyphElement.h \ - $(intermediates)/svg/JSSVGAngle.h \ - $(intermediates)/svg/JSSVGAnimateColorElement.h \ - $(intermediates)/svg/JSSVGAnimateElement.h \ - $(intermediates)/svg/JSSVGAnimateTransformElement.h \ - $(intermediates)/svg/JSSVGAnimatedAngle.h \ - $(intermediates)/svg/JSSVGAnimatedBoolean.h \ - $(intermediates)/svg/JSSVGAnimatedEnumeration.h \ - $(intermediates)/svg/JSSVGAnimatedInteger.h \ - $(intermediates)/svg/JSSVGAnimatedLength.h \ - $(intermediates)/svg/JSSVGAnimatedLengthList.h \ - $(intermediates)/svg/JSSVGAnimatedNumber.h \ - $(intermediates)/svg/JSSVGAnimatedNumberList.h \ - $(intermediates)/svg/JSSVGAnimatedPreserveAspectRatio.h \ - $(intermediates)/svg/JSSVGAnimatedRect.h \ - $(intermediates)/svg/JSSVGAnimatedString.h \ - $(intermediates)/svg/JSSVGAnimatedTransformList.h \ - $(intermediates)/svg/JSSVGAnimationElement.h \ - $(intermediates)/svg/JSSVGCircleElement.h \ - $(intermediates)/svg/JSSVGClipPathElement.h \ - $(intermediates)/svg/JSSVGColor.h \ - $(intermediates)/svg/JSSVGComponentTransferFunctionElement.h \ - $(intermediates)/svg/JSSVGCursorElement.h \ - $(intermediates)/svg/JSSVGDefsElement.h \ - $(intermediates)/svg/JSSVGDescElement.h \ - $(intermediates)/svg/JSSVGDocument.h \ - $(intermediates)/svg/JSSVGElement.h \ - $(intermediates)/svg/JSSVGElementInstance.h \ - $(intermediates)/svg/JSSVGElementInstanceList.h \ - $(intermediates)/svg/JSSVGEllipseElement.h \ - $(intermediates)/svg/JSSVGException.h \ - $(intermediates)/svg/JSSVGFEBlendElement.h \ - $(intermediates)/svg/JSSVGFEColorMatrixElement.h \ - $(intermediates)/svg/JSSVGFEComponentTransferElement.h \ - $(intermediates)/svg/JSSVGFECompositeElement.h \ - $(intermediates)/svg/JSSVGFEConvolveMatrixElement.h \ - $(intermediates)/svg/JSSVGFEDiffuseLightingElement.h \ - $(intermediates)/svg/JSSVGFEDisplacementMapElement.h \ - $(intermediates)/svg/JSSVGFEDistantLightElement.h \ - $(intermediates)/svg/JSSVGFEFloodElement.h \ - $(intermediates)/svg/JSSVGFEFuncAElement.h \ - $(intermediates)/svg/JSSVGFEFuncBElement.h \ - $(intermediates)/svg/JSSVGFEFuncGElement.h \ - $(intermediates)/svg/JSSVGFEFuncRElement.h \ - $(intermediates)/svg/JSSVGFEGaussianBlurElement.h \ - $(intermediates)/svg/JSSVGFEImageElement.h \ - $(intermediates)/svg/JSSVGFEMergeElement.h \ - $(intermediates)/svg/JSSVGFEMergeNodeElement.h \ - $(intermediates)/svg/JSSVGFEOffsetElement.h \ - $(intermediates)/svg/JSSVGFEPointLightElement.h \ - $(intermediates)/svg/JSSVGFESpecularLightingElement.h \ - $(intermediates)/svg/JSSVGFESpotLightElement.h \ - $(intermediates)/svg/JSSVGFETileElement.h \ - $(intermediates)/svg/JSSVGFETurbulenceElement.h \ - $(intermediates)/svg/JSSVGFilterElement.h \ - $(intermediates)/svg/JSSVGFontElement.h \ - $(intermediates)/svg/JSSVGFontFaceElement.h \ - $(intermediates)/svg/JSSVGFontFaceFormatElement.h \ - $(intermediates)/svg/JSSVGFontFaceNameElement.h \ - $(intermediates)/svg/JSSVGFontFaceSrcElement.h \ - $(intermediates)/svg/JSSVGFontFaceUriElement.h \ - $(intermediates)/svg/JSSVGForeignObjectElement.h \ - $(intermediates)/svg/JSSVGGElement.h \ - $(intermediates)/svg/JSSVGGlyphElement.h \ - $(intermediates)/svg/JSSVGGradientElement.h \ - $(intermediates)/svg/JSSVGHKernElement.h \ - $(intermediates)/svg/JSSVGImageElement.h \ - $(intermediates)/svg/JSSVGLength.h \ - $(intermediates)/svg/JSSVGLengthList.h \ - $(intermediates)/svg/JSSVGLineElement.h \ - $(intermediates)/svg/JSSVGLinearGradientElement.h \ - $(intermediates)/svg/JSSVGMarkerElement.h \ - $(intermediates)/svg/JSSVGMaskElement.h \ - $(intermediates)/svg/JSSVGMatrix.h \ - $(intermediates)/svg/JSSVGMetadataElement.h \ - $(intermediates)/svg/JSSVGMissingGlyphElement.h \ - $(intermediates)/svg/JSSVGNumber.h \ - $(intermediates)/svg/JSSVGNumberList.h \ - $(intermediates)/svg/JSSVGPaint.h \ - $(intermediates)/svg/JSSVGPathElement.h \ - $(intermediates)/svg/JSSVGPathSeg.h \ - $(intermediates)/svg/JSSVGPathSegArcAbs.h \ - $(intermediates)/svg/JSSVGPathSegArcRel.h \ - $(intermediates)/svg/JSSVGPathSegClosePath.h \ - $(intermediates)/svg/JSSVGPathSegCurvetoCubicAbs.h \ - $(intermediates)/svg/JSSVGPathSegCurvetoCubicRel.h \ - $(intermediates)/svg/JSSVGPathSegCurvetoCubicSmoothAbs.h \ - $(intermediates)/svg/JSSVGPathSegCurvetoCubicSmoothRel.h \ - $(intermediates)/svg/JSSVGPathSegCurvetoQuadraticAbs.h \ - $(intermediates)/svg/JSSVGPathSegCurvetoQuadraticRel.h \ - $(intermediates)/svg/JSSVGPathSegCurvetoQuadraticSmoothAbs.h \ - $(intermediates)/svg/JSSVGPathSegCurvetoQuadraticSmoothRel.h \ - $(intermediates)/svg/JSSVGPathSegLinetoAbs.h \ - $(intermediates)/svg/JSSVGPathSegLinetoHorizontalAbs.h \ - $(intermediates)/svg/JSSVGPathSegLinetoHorizontalRel.h \ - $(intermediates)/svg/JSSVGPathSegLinetoRel.h \ - $(intermediates)/svg/JSSVGPathSegLinetoVerticalAbs.h \ - $(intermediates)/svg/JSSVGPathSegLinetoVerticalRel.h \ - $(intermediates)/svg/JSSVGPathSegList.h \ - $(intermediates)/svg/JSSVGPathSegMovetoAbs.h \ - $(intermediates)/svg/JSSVGPathSegMovetoRel.h \ - $(intermediates)/svg/JSSVGPatternElement.h \ - $(intermediates)/svg/JSSVGPoint.h \ - $(intermediates)/svg/JSSVGPointList.h \ - $(intermediates)/svg/JSSVGPolygonElement.h \ - $(intermediates)/svg/JSSVGPolylineElement.h \ - $(intermediates)/svg/JSSVGPreserveAspectRatio.h \ - $(intermediates)/svg/JSSVGRadialGradientElement.h \ - $(intermediates)/svg/JSSVGRect.h \ - $(intermediates)/svg/JSSVGRectElement.h \ - $(intermediates)/svg/JSSVGRenderingIntent.h \ - $(intermediates)/svg/JSSVGSVGElement.h \ - $(intermediates)/svg/JSSVGScriptElement.h \ - $(intermediates)/svg/JSSVGSetElement.h \ - $(intermediates)/svg/JSSVGStopElement.h \ - $(intermediates)/svg/JSSVGStringList.h \ - $(intermediates)/svg/JSSVGStyleElement.h \ - $(intermediates)/svg/JSSVGSwitchElement.h \ - $(intermediates)/svg/JSSVGSymbolElement.h \ - $(intermediates)/svg/JSSVGTRefElement.h \ - $(intermediates)/svg/JSSVGTSpanElement.h \ - $(intermediates)/svg/JSSVGTextContentElement.h \ - $(intermediates)/svg/JSSVGTextElement.h \ - $(intermediates)/svg/JSSVGTextPathElement.h \ - $(intermediates)/svg/JSSVGTextPositioningElement.h \ - $(intermediates)/svg/JSSVGTitleElement.h \ - $(intermediates)/svg/JSSVGTransform.h \ - $(intermediates)/svg/JSSVGTransformList.h \ - $(intermediates)/svg/JSSVGUnitTypes.h \ - $(intermediates)/svg/JSSVGUseElement.h \ - $(intermediates)/svg/JSSVGViewElement.h \ - $(intermediates)/svg/JSSVGVKernElement.h \ - $(intermediates)/svg/JSSVGZoomEvent.h -$(GEN): PRIVATE_PATH := $(LOCAL_PATH) -$(GEN): PRIVATE_CUSTOM_TOOL = perl -I$(PRIVATE_PATH)/bindings/scripts $(PRIVATE_PATH)/bindings/scripts/generate-bindings.pl --defines "$(FEATURE_DEFINES) LANGUAGE_JAVASCRIPT" --generator JS --include external/webkit/Source/WebCore/dom --include external/webkit/Source/WebCore/html --include external/webkit/Source/WebCore/svg --outputdir $(dir $@) $< -$(GEN): $(intermediates)/svg/JS%.h : $(LOCAL_PATH)/svg/%.idl $(js_binding_scripts) - $(transform-generated-source) -LOCAL_GENERATED_SOURCES += $(GEN) $(GEN:%.h=%.cpp) - -# We also need the .cpp files, which are generated as side effects of the -# above rules. Specifying this explicitly makes -j2 work. -$(patsubst %.h,%.cpp,$(GEN)): $(intermediates)/svg/%.cpp : $(intermediates)/svg/%.h -endif - -# Workers -GEN := \ - $(intermediates)/workers/JSAbstractWorker.h \ - $(intermediates)/workers/JSDedicatedWorkerContext.h \ - $(intermediates)/workers/JSSharedWorker.h \ - $(intermediates)/workers/JSSharedWorkerContext.h \ - $(intermediates)/workers/JSWorker.h \ - $(intermediates)/workers/JSWorkerContext.h \ - $(intermediates)/workers/JSWorkerLocation.h - -$(GEN): PRIVATE_PATH := $(LOCAL_PATH) -$(GEN): PRIVATE_CUSTOM_TOOL = perl -I$(PRIVATE_PATH)/bindings/scripts $(PRIVATE_PATH)/bindings/scripts/generate-bindings.pl --defines "$(FEATURE_DEFINES) LANGUAGE_JAVASCRIPT" --generator JS --include dom --include html --outputdir $(dir $@) $< -$(GEN): $(intermediates)/workers/JS%.h : $(LOCAL_PATH)/workers/%.idl $(js_binding_scripts) - $(transform-generated-source) -LOCAL_GENERATED_SOURCES += $(GEN) $(GEN:%.h=%.cpp) - -# We also need the .cpp files, which are generated as side effects of the -# above rules. Specifying this explicitly makes -j2 work. -$(patsubst %.h,%.cpp,$(GEN)): $(intermediates)/workers/%.cpp : $(intermediates)/workers/%.h - -# XML -GEN := \ - $(intermediates)/xml/JSDOMParser.h \ - $(intermediates)/xml/JSXMLHttpRequest.h \ - $(intermediates)/xml/JSXMLHttpRequestException.h \ - $(intermediates)/xml/JSXMLHttpRequestProgressEvent.h \ - $(intermediates)/xml/JSXMLHttpRequestUpload.h \ - $(intermediates)/xml/JSXMLSerializer.h \ - $(intermediates)/xml/JSXPathException.h \ - $(intermediates)/xml/JSXPathExpression.h \ - $(intermediates)/xml/JSXPathEvaluator.h \ - $(intermediates)/xml/JSXPathNSResolver.h \ - $(intermediates)/xml/JSXPathResult.h \ - $(intermediates)/xml/JSXSLTProcessor.h -$(GEN): PRIVATE_PATH := $(LOCAL_PATH) -$(GEN): PRIVATE_CUSTOM_TOOL = perl -I$(PRIVATE_PATH)/bindings/scripts $(PRIVATE_PATH)/bindings/scripts/generate-bindings.pl --defines "$(FEATURE_DEFINES) LANGUAGE_JAVASCRIPT" --generator JS --include dom --include html --outputdir $(dir $@) $< -$(GEN): $(intermediates)/xml/JS%.h : $(LOCAL_PATH)/xml/%.idl $(js_binding_scripts) - $(transform-generated-source) -LOCAL_GENERATED_SOURCES += $(GEN) $(GEN:%.h=%.cpp) - -# We also need the .cpp files, which are generated as side effects of the -# above rules. Specifying this explicitly makes -j2 work. -$(patsubst %.h,%.cpp,$(GEN)): $(intermediates)/xml/%.cpp : $(intermediates)/xml/%.h -#end - -# Inspector -# These headers are required even when Inspector is disabled. -# Note that Inspector.idl should not be processed using the JS generator. -GEN := \ - $(intermediates)/inspector/JSScriptProfile.h - -$(GEN): PRIVATE_PATH := $(LOCAL_PATH) -$(GEN): PRIVATE_CUSTOM_TOOL = perl -I$(PRIVATE_PATH)/bindings/scripts $(PRIVATE_PATH)/bindings/scripts/generate-bindings.pl --defines "$(FEATURE_DEFINES) LANGUAGE_JAVASCRIPT" --generator JS --include dom --include html --outputdir $(dir $@) $< -$(GEN): $(intermediates)/inspector/JS%.h : $(LOCAL_PATH)/inspector/%.idl $(js_binding_scripts) - $(transform-generated-source) -LOCAL_GENERATED_SOURCES += $(GEN) $(GEN:%.h=%.cpp) - -# We also need the .cpp files, which are generated as side effects of the -# above rules. Specifying this explicitly makes -j2 work. -$(patsubst %.h,%.cpp,$(GEN)): $(intermediates)/inspector/%.cpp : $(intermediates)/inspector/%.h - -# WebAudio -# These headers are required even when WebAudio is disabled -GEN := \ - $(intermediates)/webaudio/JSAudioContext.h \ - $(intermediates)/webaudio/JSAudioPannerNode.h - -$(GEN): PRIVATE_PATH := $(LOCAL_PATH) -$(GEN): PRIVATE_CUSTOM_TOOL = perl -I$(PRIVATE_PATH)/bindings/scripts $(PRIVATE_PATH)/bindings/scripts/generate-bindings.pl --defines "$(FEATURE_DEFINES) LANGUAGE_JAVASCRIPT" --generator JS --include dom --include html --outputdir $(dir $@) $< -$(GEN): $(intermediates)/webaudio/JS%.h : $(LOCAL_PATH)/webaudio/%.idl $(js_binding_scripts) - $(transform-generated-source) -LOCAL_GENERATED_SOURCES += $(GEN) $(GEN:%.h=%.cpp) - -# We also need the .cpp files, which are generated as side effects of the -# above rules. Specifying this explicitly makes -j2 work. -$(patsubst %.h,%.cpp,$(GEN)): $(intermediates)/webaudio/%.cpp : $(intermediates)/webaudio/%.h - -# HTML tag and attribute names - -GEN:= $(intermediates)/HTMLNames.cpp $(intermediates)/HTMLNames.h $(intermediates)/HTMLElementFactory.cpp $(intermediates)/HTMLElementFactory.h $(intermediates)/JSHTMLElementWrapperFactory.cpp $(intermediates)/JSHTMLElementWrapperFactory.h -$(GEN): PRIVATE_PATH := $(LOCAL_PATH) -$(GEN): PRIVATE_CUSTOM_TOOL = perl -I $(PRIVATE_PATH)/bindings/scripts $< --tags $(PRIVATE_PATH)/html/HTMLTagNames.in --attrs $(PRIVATE_PATH)/html/HTMLAttributeNames.in --extraDefines "$(FEATURE_DEFINES)" --factory --wrapperFactory --output $(dir $@) -$(GEN): $(LOCAL_PATH)/dom/make_names.pl $(LOCAL_PATH)/html/HTMLTagNames.in $(LOCAL_PATH)/html/HTMLAttributeNames.in - $(transform-generated-source) -LOCAL_GENERATED_SOURCES += $(GEN) - -# SVG tag and attribute names - -# Note that if SVG is not used, we still need the headers and SVGNames.cpp as -# the HTML5 parser still requires these. The factory .cpp files are also -# generated in this case, but since these are not needed, they are excluded -# from GEN so that they don't get compiled. -ifeq ($(ENABLE_SVG), true) -GEN:= $(intermediates)/SVGNames.cpp $(intermediates)/SVGNames.h $(intermediates)/SVGElementFactory.cpp $(intermediates)/SVGElementFactory.h $(intermediates)/JSSVGElementWrapperFactory.cpp $(intermediates)/JSSVGElementWrapperFactory.h -else -GEN:= $(intermediates)/SVGNames.h $(intermediates)/SVGNames.cpp $(intermediates)/SVGElementFactory.h $(intermediates)/JSSVGElementWrapperFactory.h -endif -SVG_FLAGS:=ENABLE_SVG_ANIMATION=1 ENABLE_SVG_AS_IMAGE=1 ENABLE_SVG_FILTERS=1 ENABLE_SVG_FONTS=1 ENABLE_SVG_FOREIGN_OBJECT=1 ENABLE_SVG_USE=1 -$(GEN): PRIVATE_PATH := $(LOCAL_PATH) -$(GEN): PRIVATE_CUSTOM_TOOL = perl -I $(PRIVATE_PATH)/bindings/scripts $< --tags $(PRIVATE_PATH)/svg/svgtags.in --attrs $(PRIVATE_PATH)/svg/svgattrs.in --extraDefines "$(SVG_FLAGS)" --factory --wrapperFactory --output $(dir $@) -$(GEN): $(LOCAL_PATH)/dom/make_names.pl $(LOCAL_PATH)/svg/svgtags.in $(LOCAL_PATH)/svg/svgattrs.in - $(transform-generated-source) -LOCAL_GENERATED_SOURCES += $(GEN) - -# MathML tag and attribute names - -# Note that MathML is never used but we still need the headers and -# MathMLames.cpp as the HTML5 parser still requires these. The factory -# .cpp files are also generated in this case, but since these are not -# needed, they are excluded from GEN so that they don't get compiled. -GEN:= $(intermediates)/MathMLNames.h $(intermediates)/MathMLNames.cpp $(intermediates)/MathMLElementFactory.h $(intermediates)/JSMathMLElementWrapperFactory.h -$(GEN): PRIVATE_PATH := $(LOCAL_PATH) -$(GEN): PRIVATE_CUSTOM_TOOL = perl -I $(PRIVATE_PATH)/bindings/scripts $< --tags $(PRIVATE_PATH)/mathml/mathtags.in --attrs $(PRIVATE_PATH)/mathml/mathattrs.in --factory --wrapperFactory --output $(dir $@) -$(GEN): $(LOCAL_PATH)/dom/make_names.pl $(LOCAL_PATH)/mathml/mathtags.in $(LOCAL_PATH)/mathml/mathattrs.in - $(transform-generated-source) -LOCAL_GENERATED_SOURCES += $(GEN) - diff --git a/Source/WebCore/Android.derived.v8bindings.mk b/Source/WebCore/Android.derived.v8bindings.mk index 992cc40..546cefe 100644 --- a/Source/WebCore/Android.derived.v8bindings.mk +++ b/Source/WebCore/Android.derived.v8bindings.mk @@ -301,6 +301,7 @@ GEN := \ $(intermediates)/bindings/V8CanvasRenderingContext2D.h \ $(intermediates)/bindings/V8DataView.h \ $(intermediates)/bindings/V8Float32Array.h \ + $(intermediates)/bindings/V8Float64Array.h \ $(intermediates)/bindings/V8Int8Array.h \ $(intermediates)/bindings/V8Int16Array.h \ $(intermediates)/bindings/V8Int32Array.h \ diff --git a/Source/WebCore/Android.jscbindings.mk b/Source/WebCore/Android.jscbindings.mk deleted file mode 100644 index bdd6d92..0000000 --- a/Source/WebCore/Android.jscbindings.mk +++ /dev/null @@ -1,240 +0,0 @@ -## -## Copyright 2009, 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. -## - -BINDING_C_INCLUDES := \ - $(LOCAL_PATH)/bindings/js \ - $(LOCAL_PATH)/bindings/js/specialization \ - $(LOCAL_PATH)/bridge \ - $(LOCAL_PATH)/bridge/c \ - $(LOCAL_PATH)/bridge/jni \ - $(LOCAL_PATH)/bridge/jni/jsc \ - $(LOCAL_PATH)/bridge/jsc \ - \ - $(JAVASCRIPTCORE_PATH)/API \ - $(JAVASCRIPTCORE_PATH)/assembler \ - $(JAVASCRIPTCORE_PATH)/bytecode \ - $(JAVASCRIPTCORE_PATH)/bytecompiler \ - $(JAVASCRIPTCORE_PATH)/debugger \ - $(JAVASCRIPTCORE_PATH)/parser \ - $(JAVASCRIPTCORE_PATH)/jit \ - $(JAVASCRIPTCORE_PATH)/interpreter \ - $(JAVASCRIPTCORE_PATH)/profiler \ - $(JAVASCRIPTCORE_PATH)/runtime \ - $(JAVASCRIPTCORE_PATH)/yarr \ - $(JAVASCRIPTCORE_PATH)/ForwardingHeaders \ - \ - $(WEBCORE_INTERMEDIATES_PATH)/bindings/js \ - $(WEBCORE_INTERMEDIATES_PATH)/dom \ - $(WEBCORE_INTERMEDIATES_PATH)/fileapi \ - $(WEBCORE_INTERMEDIATES_PATH)/html/canvas \ - $(WEBCORE_INTERMEDIATES_PATH)/inspector \ - $(WEBCORE_INTERMEDIATES_PATH)/loader/appcache \ - $(WEBCORE_INTERMEDIATES_PATH)/page \ - $(WEBCORE_INTERMEDIATES_PATH)/plugins \ - $(WEBCORE_INTERMEDIATES_PATH)/storage \ - $(WEBCORE_INTERMEDIATES_PATH)/svg \ - $(WEBCORE_INTERMEDIATES_PATH)/webaudio \ - $(WEBCORE_INTERMEDIATES_PATH)/workers \ - $(WEBCORE_INTERMEDIATES_PATH)/xml - -LOCAL_SRC_FILES += \ - bindings/js/CallbackFunction.cpp \ - bindings/js/DOMObjectHashTableMap.cpp \ - bindings/js/DOMWrapperWorld.cpp \ - bindings/js/GCController.cpp \ - bindings/js/IDBBindingUtilities.cpp \ - bindings/js/JSArrayBufferCustom.cpp \ - bindings/js/JSAttrCustom.cpp \ - bindings/js/JSAudioBufferSourceNodeCustom.cpp \ - bindings/js/JSAudioConstructor.cpp \ - bindings/js/JSCDATASectionCustom.cpp \ - bindings/js/JSCSSFontFaceRuleCustom.cpp \ - bindings/js/JSCSSImportRuleCustom.cpp \ - bindings/js/JSCSSMediaRuleCustom.cpp \ - bindings/js/JSCSSPageRuleCustom.cpp \ - bindings/js/JSCSSRuleCustom.cpp \ - bindings/js/JSCSSRuleListCustom.cpp \ - bindings/js/JSCSSStyleDeclarationCustom.cpp \ - bindings/js/JSCSSStyleRuleCustom.cpp \ - bindings/js/JSCSSValueCustom.cpp \ - bindings/js/JSCallbackData.cpp \ - bindings/js/JSCanvasRenderingContext2DCustom.cpp \ - bindings/js/JSCanvasRenderingContextCustom.cpp \ - bindings/js/JSClipboardCustom.cpp \ - bindings/js/JSConsoleCustom.cpp \ - bindings/js/JSConvolverNodeCustom.cpp \ - bindings/js/JSCoordinatesCustom.cpp \ - bindings/js/JSCustomApplicationInstalledCallback.cpp \ - bindings/js/JSCustomPositionCallback.cpp \ - bindings/js/JSCustomPositionErrorCallback.cpp \ - bindings/js/JSCustomSQLStatementErrorCallback.cpp \ - bindings/js/JSCustomVoidCallback.cpp \ - bindings/js/JSDOMApplicationCacheCustom.cpp \ - bindings/js/JSDOMBinding.cpp \ - bindings/js/JSDOMFormDataCustom.cpp \ - bindings/js/JSDOMGlobalObject.cpp \ - bindings/js/JSDOMImplementationCustom.cpp \ - bindings/js/JSDOMMimeTypeArrayCustom.cpp \ - bindings/js/JSDOMPluginArrayCustom.cpp \ - bindings/js/JSDOMPluginCustom.cpp \ - bindings/js/JSDOMStringMapCustom.cpp \ - bindings/js/JSDOMWindowBase.cpp \ - bindings/js/JSDOMWindowCustom.cpp \ - bindings/js/JSDOMWindowShell.cpp \ - bindings/js/JSDOMWrapper.cpp \ - bindings/js/JSDataGridColumnListCustom.cpp \ - bindings/js/JSDataGridDataSource.cpp \ - bindings/js/JSDataViewCustom.cpp \ - bindings/js/JSDedicatedWorkerContextCustom.cpp \ - bindings/js/JSDesktopNotificationsCustom.cpp \ - bindings/js/JSDeviceMotionEventCustom.cpp \ - bindings/js/JSDeviceOrientationEventCustom.cpp \ - bindings/js/JSDirectoryEntrySyncCustom.cpp \ - bindings/js/JSDocumentCustom.cpp \ - bindings/js/JSElementCustom.cpp \ - bindings/js/JSEntrySyncCustom.cpp \ - bindings/js/JSErrorHandler.cpp \ - bindings/js/JSEventCustom.cpp \ - bindings/js/JSEventListener.cpp \ - bindings/js/JSEventTarget.cpp \ - bindings/js/JSExceptionBase.cpp \ - bindings/js/JSFloat32ArrayCustom.cpp \ - bindings/js/JSFileReaderCustom.cpp \ - bindings/js/JSGeolocationCustom.cpp \ - bindings/js/JSHTMLAllCollectionCustom.cpp \ - bindings/js/JSHTMLAppletElementCustom.cpp \ - bindings/js/JSHTMLCanvasElementCustom.cpp \ - bindings/js/JSHTMLCollectionCustom.cpp \ - bindings/js/JSHTMLDataGridElementCustom.cpp \ - bindings/js/JSHTMLDocumentCustom.cpp \ - bindings/js/JSHTMLElementCustom.cpp \ - bindings/js/JSHTMLEmbedElementCustom.cpp \ - bindings/js/JSHTMLFormElementCustom.cpp \ - bindings/js/JSHTMLFrameElementCustom.cpp \ - bindings/js/JSHTMLFrameSetElementCustom.cpp \ - bindings/js/JSHTMLInputElementCustom.cpp \ - bindings/js/JSHTMLLinkElementCustom.cpp \ - bindings/js/JSHTMLObjectElementCustom.cpp \ - bindings/js/JSHTMLOptionsCollectionCustom.cpp \ - bindings/js/JSHTMLOutputElementCustom.cpp \ - bindings/js/JSHTMLSelectElementCustom.cpp \ - bindings/js/JSHTMLStyleElementCustom.cpp \ - bindings/js/JSHistoryCustom.cpp \ - bindings/js/JSIDBAnyCustom.cpp \ - bindings/js/JSIDBKeyCustom.cpp \ - bindings/js/JSImageConstructor.cpp \ - bindings/js/JSImageDataCustom.cpp \ - bindings/js/JSInt16ArrayCustom.cpp \ - bindings/js/JSInt32ArrayCustom.cpp \ - bindings/js/JSInt8ArrayCustom.cpp \ - bindings/js/JSJavaScriptAudioNodeCustom.cpp \ - bindings/js/JSLazyEventListener.cpp \ - bindings/js/JSLocationCustom.cpp \ - bindings/js/JSMainThreadExecState.cpp \ - bindings/js/JSMemoryInfoCustom.cpp \ - bindings/js/JSMessageChannelCustom.cpp \ - bindings/js/JSMessageEventCustom.cpp \ - bindings/js/JSMessagePortCustom.cpp \ - bindings/js/JSNamedNodeMapCustom.cpp \ - bindings/js/JSNavigatorCustom.cpp \ - bindings/js/JSNodeCustom.cpp \ - bindings/js/JSNodeFilterCondition.cpp \ - bindings/js/JSNodeFilterCustom.cpp \ - bindings/js/JSNodeIteratorCustom.cpp \ - bindings/js/JSNodeListCustom.cpp \ - bindings/js/JSOptionConstructor.cpp \ - bindings/js/JSPluginElementFunctions.cpp \ - bindings/js/JSProcessingInstructionCustom.cpp \ - bindings/js/JSSQLResultSetRowListCustom.cpp \ - bindings/js/JSSQLTransactionCustom.cpp \ - bindings/js/JSSQLTransactionSyncCustom.cpp \ - bindings/js/JSSVGElementInstanceCustom.cpp \ - bindings/js/JSSVGLengthCustom.cpp \ - bindings/js/JSSVGPathSegCustom.cpp \ - bindings/js/JSSharedWorkerCustom.cpp \ - bindings/js/JSStorageCustom.cpp \ - bindings/js/JSStyleSheetCustom.cpp \ - bindings/js/JSStyleSheetListCustom.cpp \ - bindings/js/JSTextCustom.cpp \ - bindings/js/JSTouchCustom.cpp \ - bindings/js/JSTouchListCustom.cpp \ - bindings/js/JSTreeWalkerCustom.cpp \ - bindings/js/JSUint16ArrayCustom.cpp \ - bindings/js/JSUint32ArrayCustom.cpp \ - bindings/js/JSUint8ArrayCustom.cpp \ - bindings/js/JSWebKitAnimationCustom.cpp \ - bindings/js/JSWebKitAnimationListCustom.cpp \ - bindings/js/JSWebKitCSSKeyframeRuleCustom.cpp \ - bindings/js/JSWebKitCSSKeyframesRuleCustom.cpp \ - bindings/js/JSWebKitCSSMatrixCustom.cpp \ - bindings/js/JSWebKitPointCustom.cpp \ - bindings/js/JSWorkerContextBase.cpp \ - bindings/js/JSWorkerContextCustom.cpp \ - bindings/js/JSWorkerCustom.cpp \ - bindings/js/JSXMLHttpRequestCustom.cpp \ - bindings/js/JSXMLHttpRequestUploadCustom.cpp \ - bindings/js/JSXSLTProcessorCustom.cpp \ - bindings/js/ScheduledAction.cpp \ - bindings/js/ScriptCachedFrameData.cpp \ - bindings/js/ScriptCallStackFactory.cpp \ - bindings/js/ScriptController.cpp \ - bindings/js/ScriptControllerAndroid.cpp \ - bindings/js/ScriptEventListener.cpp \ - bindings/js/ScriptFunctionCall.cpp \ - bindings/js/ScriptObject.cpp \ - bindings/js/ScriptProfile.cpp \ - bindings/js/ScriptState.cpp \ - bindings/js/ScriptValue.cpp \ - bindings/js/SerializedScriptValue.cpp \ - bindings/js/WorkerScriptController.cpp \ - \ - bindings/ScriptControllerBase.cpp \ - \ - bridge/IdentifierRep.cpp \ - bridge/NP_jsobject.cpp \ - bridge/c/CRuntimeObject.cpp \ - bridge/c/c_class.cpp \ - bridge/c/c_instance.cpp \ - bridge/c/c_runtime.cpp \ - bridge/c/c_utility.cpp \ - bridge/jni/JNIUtility.cpp \ - bridge/jni/JavaMethodJobject.cpp \ - bridge/jni/JobjectWrapper.cpp \ - bridge/jni/jsc/JNIUtilityPrivate.cpp \ - bridge/jni/jsc/JavaArrayJSC.cpp \ - bridge/jni/jsc/JavaClassJSC.cpp \ - bridge/jni/jsc/JavaFieldJSC.cpp \ - bridge/jni/jsc/JavaInstanceJSC.cpp \ - bridge/jni/jsc/JavaRuntimeObject.cpp \ - bridge/jsc/BridgeJSC.cpp \ - bridge/npruntime.cpp \ - bridge/runtime_array.cpp \ - bridge/runtime_method.cpp \ - bridge/runtime_object.cpp \ - bridge/runtime_root.cpp - -# For XPath. -LOCAL_SRC_FILES += \ - bindings/js/JSCustomXPathNSResolver.cpp diff --git a/Source/WebCore/Android.mk b/Source/WebCore/Android.mk index 6542931..816b163 100644 --- a/Source/WebCore/Android.mk +++ b/Source/WebCore/Android.mk @@ -124,6 +124,7 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \ dom/DOMImplementation.cpp \ dom/DOMStringList.cpp \ dom/DOMStringMap.cpp \ + dom/DOMTextContentWalker.cpp \ dom/DatasetDOMStringMap.cpp \ dom/DecodedDataDocumentParser.cpp \ dom/DeviceMotionController.cpp \ @@ -378,6 +379,7 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \ html/canvas/CanvasStyle.cpp \ html/canvas/DataView.cpp \ html/canvas/Float32Array.cpp \ + html/canvas/Float64Array.cpp \ html/canvas/Int16Array.cpp \ html/canvas/Int32Array.cpp \ html/canvas/Int8Array.cpp \ @@ -638,7 +640,8 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \ platform/graphics/android/BaseTileTexture.cpp \ platform/graphics/android/BitmapAllocatorAndroid.cpp \ platform/graphics/android/ClassTracker.cpp \ - platform/graphics/android/DoubleBufferedTexture.cpp \ + platform/graphics/android/DumpLayer.cpp \ + platform/graphics/android/FixedPositioning.cpp \ platform/graphics/android/FontAndroid.cpp \ platform/graphics/android/FontCacheAndroid.cpp \ platform/graphics/android/FontCustomPlatformData.cpp \ @@ -653,26 +656,30 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \ platform/graphics/android/GradientAndroid.cpp \ platform/graphics/android/GraphicsContextAndroid.cpp \ platform/graphics/android/GraphicsLayerAndroid.cpp \ + platform/graphics/android/IFrameContentLayerAndroid.cpp \ + platform/graphics/android/IFrameLayerAndroid.cpp \ platform/graphics/android/ImageAndroid.cpp \ platform/graphics/android/ImageBufferAndroid.cpp \ platform/graphics/android/ImageSourceAndroid.cpp \ platform/graphics/android/ImagesManager.cpp \ platform/graphics/android/ImageTexture.cpp \ + platform/graphics/android/InspectorCanvas.cpp \ platform/graphics/android/Layer.cpp \ platform/graphics/android/LayerAndroid.cpp \ + platform/graphics/android/LayerGroup.cpp \ platform/graphics/android/MediaLayer.cpp \ platform/graphics/android/MediaTexture.cpp \ platform/graphics/android/PaintTileOperation.cpp \ - platform/graphics/android/PaintedSurface.cpp \ platform/graphics/android/PathAndroid.cpp \ platform/graphics/android/PatternAndroid.cpp \ + platform/graphics/android/PictureLayerContent.cpp \ + platform/graphics/android/PictureSetLayerContent.cpp \ platform/graphics/android/PlatformGraphicsContext.cpp \ platform/graphics/android/PerformanceMonitor.cpp \ platform/graphics/android/RasterRenderer.cpp \ platform/graphics/android/ScrollableLayerAndroid.cpp \ platform/graphics/android/SharedBufferStream.cpp \ platform/graphics/android/ShaderProgram.cpp \ - platform/graphics/android/SharedTexture.cpp \ platform/graphics/android/TextureInfo.cpp \ platform/graphics/android/TexturesGenerator.cpp \ platform/graphics/android/TilesManager.cpp \ @@ -680,12 +687,12 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \ platform/graphics/android/TiledPage.cpp \ platform/graphics/android/TiledTexture.cpp \ platform/graphics/android/TransferQueue.cpp \ - platform/graphics/android/TreeManager.cpp \ + platform/graphics/android/SurfaceCollection.cpp \ + platform/graphics/android/SurfaceCollectionManager.cpp \ platform/graphics/android/VerticalTextMap.cpp \ platform/graphics/android/VideoLayerAndroid.cpp \ platform/graphics/android/VideoLayerManager.cpp \ platform/graphics/android/ZoomManager.cpp \ - platform/graphics/android/android_graphics.cpp \ ifeq ($(ENABLE_SVG), true) LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \ @@ -811,6 +818,7 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \ plugins/DOMPluginArray.cpp \ plugins/PluginData.cpp \ plugins/PluginDatabase.cpp \ + plugins/PluginDebug.cpp \ plugins/PluginMainThreadScheduler.cpp \ plugins/PluginPackage.cpp \ plugins/PluginStream.cpp \ diff --git a/Source/WebCore/Android.v8bindings.mk b/Source/WebCore/Android.v8bindings.mk index 283a212..7858ef3 100644 --- a/Source/WebCore/Android.v8bindings.mk +++ b/Source/WebCore/Android.v8bindings.mk @@ -130,6 +130,7 @@ LOCAL_SRC_FILES += \ bindings/v8/custom/V8EventSourceConstructor.cpp \ bindings/v8/custom/V8FileReaderCustom.cpp \ bindings/v8/custom/V8Float32ArrayCustom.cpp \ + bindings/v8/custom/V8Float64ArrayCustom.cpp \ bindings/v8/custom/V8GeolocationCustom.cpp \ bindings/v8/custom/V8HistoryCustom.cpp \ bindings/v8/custom/V8HTMLAllCollectionCustom.cpp \ diff --git a/Source/WebCore/DerivedSources.cpp b/Source/WebCore/DerivedSources.cpp index 3bba78c..45a425c 100644 --- a/Source/WebCore/DerivedSources.cpp +++ b/Source/WebCore/DerivedSources.cpp @@ -130,6 +130,7 @@ #include "JSFileWriterSync.cpp" #include "JSWebKitFlags.cpp" #include "JSFloat32Array.cpp" +#include "JSFloat64Array.cpp" #include "JSGeolocation.cpp" #include "JSGeoposition.cpp" #include "JSHashChangeEvent.cpp" diff --git a/Source/WebCore/bindings/js/JSBindingsAllInOne.cpp b/Source/WebCore/bindings/js/JSBindingsAllInOne.cpp index a457ce8..82367b2 100644 --- a/Source/WebCore/bindings/js/JSBindingsAllInOne.cpp +++ b/Source/WebCore/bindings/js/JSBindingsAllInOne.cpp @@ -81,6 +81,7 @@ #include "JSEventTarget.cpp" #include "JSExceptionBase.cpp" #include "JSFloat32ArrayCustom.cpp" +#include "JSFloat64ArrayCustom.cpp" #include "JSGeolocationCustom.cpp" #include "JSHTMLAllCollectionCustom.cpp" #include "JSHTMLAppletElementCustom.cpp" diff --git a/Source/WebCore/bindings/js/JSDOMWindowCustom.cpp b/Source/WebCore/bindings/js/JSDOMWindowCustom.cpp index 4bde9e5..938be96 100644 --- a/Source/WebCore/bindings/js/JSDOMWindowCustom.cpp +++ b/Source/WebCore/bindings/js/JSDOMWindowCustom.cpp @@ -31,6 +31,7 @@ #include "JSEventListener.h" #include "JSEventSource.h" #include "JSFloat32Array.h" +#include "JSFloat64Array.h" #include "JSHTMLCollection.h" #include "JSHistory.h" #include "JSImageConstructor.h" @@ -569,6 +570,11 @@ JSValue JSDOMWindow::float32Array(ExecState* exec) const return getDOMConstructor<JSFloat32ArrayConstructor>(exec, this); } +JSValue JSDOMWindow::float64Array(ExecState* exec) const +{ + return getDOMConstructor<JSFloat64ArrayConstructor>(exec, this); +} + JSValue JSDOMWindow::dataView(ExecState* exec) const { return getDOMConstructor<JSDataViewConstructor>(exec, this); diff --git a/Source/WebCore/bindings/js/JSFloat64ArrayCustom.cpp b/Source/WebCore/bindings/js/JSFloat64ArrayCustom.cpp new file mode 100644 index 0000000..446b0ec --- /dev/null +++ b/Source/WebCore/bindings/js/JSFloat64ArrayCustom.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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 APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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 "JSFloat64Array.h" + +#include "Float64Array.h" +#include "JSArrayBufferViewHelper.h" + +using namespace JSC; + +namespace WebCore { + +void JSFloat64Array::indexSetter(JSC::ExecState* exec, unsigned index, JSC::JSValue value) +{ + impl()->set(index, value.toNumber(exec)); +} + +JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, Float64Array* object) +{ + return toJSArrayBufferView<JSFloat64Array>(exec, globalObject, object); +} + +JSC::JSValue JSFloat64Array::set(JSC::ExecState* exec) +{ + return setWebGLArrayHelper(exec, impl(), toFloat64Array); +} + +EncodedJSValue JSC_HOST_CALL JSFloat64ArrayConstructor::constructJSFloat64Array(ExecState* exec) +{ + JSFloat64ArrayConstructor* jsConstructor = static_cast<JSFloat64ArrayConstructor*>(exec->callee()); + RefPtr<Float64Array> array = constructArrayBufferView<Float64Array, double>(exec); + if (!array.get()) + // Exception has already been thrown. + return JSValue::encode(JSValue()); + return JSValue::encode(asObject(toJS(exec, jsConstructor->globalObject(), array.get()))); +} + +} // namespace WebCore diff --git a/Source/WebCore/bindings/v8/V8DOMWindowShell.cpp b/Source/WebCore/bindings/v8/V8DOMWindowShell.cpp index e025008..c3a0cbb 100644 --- a/Source/WebCore/bindings/v8/V8DOMWindowShell.cpp +++ b/Source/WebCore/bindings/v8/V8DOMWindowShell.cpp @@ -76,10 +76,6 @@ #include <wtf/UnusedParam.h> #include <wtf/text/CString.h> -#ifdef ANDROID_INSTRUMENT -#include "TimeCounter.h" -#endif - namespace WebCore { static void handleFatalErrorInV8() @@ -283,10 +279,6 @@ bool V8DOMWindowShell::initContextIfNeeded() if (!m_context.IsEmpty()) return false; -#ifdef ANDROID_INSTRUMENT - android::TimeCounter::start(android::TimeCounter::JavaScriptInitTimeCounter); -#endif - // Create a handle scope for all local handles. v8::HandleScope handleScope; @@ -352,10 +344,6 @@ bool V8DOMWindowShell::initContextIfNeeded() // we do isolated worlds the WebCore way. m_frame->loader()->dispatchDidClearWindowObjectInWorld(0); -#ifdef ANDROID_INSTRUMENT - android::TimeCounter::record(android::TimeCounter::JavaScriptInitTimeCounter, __FUNCTION__); -#endif - return true; } diff --git a/Source/WebCore/bindings/v8/V8Proxy.cpp b/Source/WebCore/bindings/v8/V8Proxy.cpp index ca57fa8..d90cf1c 100644 --- a/Source/WebCore/bindings/v8/V8Proxy.cpp +++ b/Source/WebCore/bindings/v8/V8Proxy.cpp @@ -83,14 +83,6 @@ #include <wtf/UnusedParam.h> #include <wtf/text/StringConcatenate.h> -#ifdef ANDROID_INSTRUMENT -#include "TimeCounter.h" -#endif - -#if PLATFORM(ANDROID) -#include <wtf/text/CString.h> -#endif - namespace WebCore { // Static list of registered extensions @@ -209,16 +201,6 @@ V8Proxy::~V8Proxy() } v8::Handle<v8::Script> V8Proxy::compileScript(v8::Handle<v8::String> code, const String& fileName, const TextPosition0& scriptStartPosition, v8::ScriptData* scriptData) -#ifdef ANDROID_INSTRUMENT -{ - android::TimeCounter::start(android::TimeCounter::JavaScriptParseTimeCounter); - v8::Handle<v8::Script> script = compileScriptInternal(code, fileName, scriptStartPosition, scriptData); - android::TimeCounter::record(android::TimeCounter::JavaScriptParseTimeCounter, __FUNCTION__); - return script; -} - -v8::Handle<v8::Script> V8Proxy::compileScriptInternal(v8::Handle<v8::String> code, const String& fileName, const TextPosition0& scriptStartPosition, v8::ScriptData* scriptData) -#endif { const uint16_t* fileNameString = fromWebCoreString(fileName); v8::Handle<v8::String> name = v8::String::New(fileNameString, fileName.length()); @@ -398,16 +380,6 @@ v8::Local<v8::Value> V8Proxy::evaluate(const ScriptSourceCode& source, Node* nod } v8::Local<v8::Value> V8Proxy::runScript(v8::Handle<v8::Script> script, bool isInlineCode) -#ifdef ANDROID_INSTRUMENT -{ - android::TimeCounter::start(android::TimeCounter::JavaScriptExecuteTimeCounter); - v8::Local<v8::Value> result = runScriptInternal(script, isInlineCode); - android::TimeCounter::record(android::TimeCounter::JavaScriptExecuteTimeCounter, __FUNCTION__); - return result; -} - -v8::Local<v8::Value> V8Proxy::runScriptInternal(v8::Handle<v8::Script> script, bool isInlineCode) -#endif { if (script.IsEmpty()) return notHandledByInterceptor(); @@ -472,9 +444,6 @@ v8::Local<v8::Value> V8Proxy::runScriptInternal(v8::Handle<v8::Script> script, b v8::Local<v8::Value> V8Proxy::callFunction(v8::Handle<v8::Function> function, v8::Handle<v8::Object> receiver, int argc, v8::Handle<v8::Value> args[]) { -#ifdef ANDROID_INSTRUMENT - android::TimeCounter::start(android::TimeCounter::JavaScriptExecuteTimeCounter); -#endif V8GCController::checkMemoryUsage(); v8::Local<v8::Value> result; { @@ -521,9 +490,6 @@ v8::Local<v8::Value> V8Proxy::callFunction(v8::Handle<v8::Function> function, v8 if (v8::V8::IsDead()) handleFatalErrorInV8(); -#ifdef ANDROID_INSTRUMENT - android::TimeCounter::record(android::TimeCounter::JavaScriptExecuteTimeCounter, __FUNCTION__); -#endif return result; } diff --git a/Source/WebCore/bindings/v8/V8Proxy.h b/Source/WebCore/bindings/v8/V8Proxy.h index fc52b19..777815b 100644 --- a/Source/WebCore/bindings/v8/V8Proxy.h +++ b/Source/WebCore/bindings/v8/V8Proxy.h @@ -171,10 +171,6 @@ namespace WebCore { // Run an already compiled script. v8::Local<v8::Value> runScript(v8::Handle<v8::Script>, bool isInlineCode); -#ifdef ANDROID_INSTRUMENT - v8::Local<v8::Value> runScriptInternal(v8::Handle<v8::Script> script, bool inline_code); -#endif - // Call the function with the given receiver and arguments. v8::Local<v8::Value> callFunction(v8::Handle<v8::Function>, v8::Handle<v8::Object>, int argc, v8::Handle<v8::Value> argv[]); @@ -244,10 +240,6 @@ namespace WebCore { static v8::Handle<v8::Script> compileScript(v8::Handle<v8::String> code, const String& fileName, const TextPosition0& scriptStartPosition, v8::ScriptData* = 0); -#ifdef ANDROID_INSTRUMENT - static v8::Handle<v8::Script> compileScriptInternal(v8::Handle<v8::String> code, const String& fileName, int baseLine, v8::ScriptData* scriptData); -#endif - // If the exception code is different from zero, a DOM exception is // schedule to be thrown. static void setDOMException(int exceptionCode); diff --git a/Source/WebCore/bindings/v8/custom/V8Float64ArrayCustom.cpp b/Source/WebCore/bindings/v8/custom/V8Float64ArrayCustom.cpp new file mode 100644 index 0000000..429e962 --- /dev/null +++ b/Source/WebCore/bindings/v8/custom/V8Float64ArrayCustom.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2011 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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 APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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 "Float64Array.h" + +#include "ArrayBuffer.h" +#include "V8ArrayBuffer.h" +#include "V8ArrayBufferViewCustom.h" +#include "V8Binding.h" +#include "V8Float64Array.h" +#include "V8Proxy.h" + +namespace WebCore { + +v8::Handle<v8::Value> V8Float64Array::constructorCallback(const v8::Arguments& args) +{ + INC_STATS("DOM.Float64Array.Contructor"); + + return constructWebGLArray<Float64Array, double>(args, &info, v8::kExternalDoubleArray); +} + +v8::Handle<v8::Value> V8Float64Array::setCallback(const v8::Arguments& args) +{ + INC_STATS("DOM.Float64Array.set()"); + return setWebGLArrayHelper<Float64Array, V8Float64Array>(args); +} + +v8::Handle<v8::Value> toV8(Float64Array* impl) +{ + if (!impl) + return v8::Null(); + v8::Handle<v8::Object> wrapper = V8Float64Array::wrap(impl); + if (!wrapper.IsEmpty()) + wrapper->SetIndexedPropertiesToExternalArrayData(impl->baseAddress(), v8::kExternalDoubleArray, impl->length()); + return wrapper; +} + +} // namespace WebCore diff --git a/Source/WebCore/bridge/jni/JavaMethodJobject.cpp b/Source/WebCore/bridge/jni/JavaMethodJobject.cpp index 01a0b5b..f93e197 100644 --- a/Source/WebCore/bridge/jni/JavaMethodJobject.cpp +++ b/Source/WebCore/bridge/jni/JavaMethodJobject.cpp @@ -131,9 +131,9 @@ const char* JavaMethodJobject::signature() const else { signatureBuilder.append(signatureFromJavaType(type)); if (type == JavaTypeObject -#if USE(V8) +// ANDROID || type == JavaTypeString -#endif +// ANDROID ) { appendClassName(signatureBuilder, javaClassName.data()); signatureBuilder.append(';'); @@ -148,9 +148,9 @@ const char* JavaMethodJobject::signature() const else { signatureBuilder.append(signatureFromJavaType(m_returnType)); if (m_returnType == JavaTypeObject -#if USE(V8) +// ANDROID || m_returnType == JavaTypeString -#endif +// ANDROID ) { appendClassName(signatureBuilder, returnType); signatureBuilder.append(';'); diff --git a/Source/WebCore/bridge/jni/v8/JNIUtilityPrivate.cpp b/Source/WebCore/bridge/jni/v8/JNIUtilityPrivate.cpp index 42efaac..15b4bda 100644 --- a/Source/WebCore/bridge/jni/v8/JNIUtilityPrivate.cpp +++ b/Source/WebCore/bridge/jni/v8/JNIUtilityPrivate.cpp @@ -72,11 +72,16 @@ JavaValue convertNPVariantToJavaValue(NPVariant value, const String& javaClass) break; } - jsize length = 0; - if (NPVARIANT_IS_INT32(npvLength)) - length = static_cast<jsize>(NPVARIANT_TO_INT32(npvLength)); - else if (NPVARIANT_IS_DOUBLE(npvLength)) - length = static_cast<jsize>(NPVARIANT_TO_DOUBLE(npvLength)); + // Convert to null if the length property is not a number. + if (!NPVARIANT_IS_INT32(npvLength) && !NPVARIANT_IS_DOUBLE(npvLength)) + break; + + // Convert to null if the length property is out of bounds. + double doubleLength = NPVARIANT_IS_INT32(npvLength) ? NPVARIANT_TO_INT32(npvLength) : NPVARIANT_TO_DOUBLE(npvLength); + if (doubleLength < 0.0 || doubleLength > INT32_MAX) + break; + + jsize length = static_cast<jsize>(doubleLength); if (!strcmp(javaClassName.data(), "[Ljava.lang.String;")) { // Match JSC behavior by only allowing Object arrays if they are Strings. @@ -85,7 +90,7 @@ JavaValue convertNPVariantToJavaValue(NPVariant value, const String& javaClass) for (jsize i = 0; i < length; i++) { NPVariant npvValue; _NPN_GetProperty(0, object, _NPN_GetIntIdentifier(i), &npvValue); - if(NPVARIANT_IS_STRING(npvValue)) { + if (NPVARIANT_IS_STRING(npvValue)) { NPString str = NPVARIANT_TO_STRING(npvValue); env->SetObjectArrayElement(static_cast<jobjectArray>(javaArray), i, env->NewStringUTF(str.UTF8Characters)); } @@ -100,11 +105,10 @@ JavaValue convertNPVariantToJavaValue(NPVariant value, const String& javaClass) NPVariant npvValue; _NPN_GetProperty(0, object, _NPN_GetIntIdentifier(i), &npvValue); jbyte bVal = 0; - if (NPVARIANT_IS_INT32(npvValue)) { + if (NPVARIANT_IS_INT32(npvValue)) bVal = static_cast<jbyte>(NPVARIANT_TO_INT32(npvValue)); - } else if (NPVARIANT_IS_DOUBLE(npvValue)) { + else if (NPVARIANT_IS_DOUBLE(npvValue)) bVal = static_cast<jbyte>(NPVARIANT_TO_DOUBLE(npvValue)); - } env->SetByteArrayRegion(static_cast<jbyteArray>(javaArray), i, 1, &bVal); } } else if (!strcmp(javaClassName.data(), "[C")) { @@ -115,12 +119,8 @@ JavaValue convertNPVariantToJavaValue(NPVariant value, const String& javaClass) NPVariant npvValue; _NPN_GetProperty(0, object, _NPN_GetIntIdentifier(i), &npvValue); jchar cVal = 0; - if (NPVARIANT_IS_INT32(npvValue)) { + if (NPVARIANT_IS_INT32(npvValue)) cVal = static_cast<jchar>(NPVARIANT_TO_INT32(npvValue)); - } else if (NPVARIANT_IS_STRING(npvValue)) { - NPString str = NPVARIANT_TO_STRING(npvValue); - cVal = str.UTF8Characters[0]; - } env->SetCharArrayRegion(static_cast<jcharArray>(javaArray), i, 1, &cVal); } } else if (!strcmp(javaClassName.data(), "[D")) { @@ -155,11 +155,10 @@ JavaValue convertNPVariantToJavaValue(NPVariant value, const String& javaClass) NPVariant npvValue; _NPN_GetProperty(0, object, _NPN_GetIntIdentifier(i), &npvValue); jint iVal = 0; - if (NPVARIANT_IS_INT32(npvValue)) { + if (NPVARIANT_IS_INT32(npvValue)) iVal = NPVARIANT_TO_INT32(npvValue); - } else if (NPVARIANT_IS_DOUBLE(npvValue)) { + else if (NPVARIANT_IS_DOUBLE(npvValue)) iVal = static_cast<jint>(NPVARIANT_TO_DOUBLE(npvValue)); - } env->SetIntArrayRegion(static_cast<jintArray>(javaArray), i, 1, &iVal); } } else if (!strcmp(javaClassName.data(), "[J")) { @@ -170,11 +169,10 @@ JavaValue convertNPVariantToJavaValue(NPVariant value, const String& javaClass) NPVariant npvValue; _NPN_GetProperty(0, object, _NPN_GetIntIdentifier(i), &npvValue); jlong jVal = 0; - if (NPVARIANT_IS_INT32(npvValue)) { + if (NPVARIANT_IS_INT32(npvValue)) jVal = static_cast<jlong>(NPVARIANT_TO_INT32(npvValue)); - } else if (NPVARIANT_IS_DOUBLE(npvValue)) { + else if (NPVARIANT_IS_DOUBLE(npvValue)) jVal = static_cast<jlong>(NPVARIANT_TO_DOUBLE(npvValue)); - } env->SetLongArrayRegion(static_cast<jlongArray>(javaArray), i, 1, &jVal); } } else if (!strcmp(javaClassName.data(), "[S")) { @@ -185,11 +183,10 @@ JavaValue convertNPVariantToJavaValue(NPVariant value, const String& javaClass) NPVariant npvValue; _NPN_GetProperty(0, object, _NPN_GetIntIdentifier(i), &npvValue); jshort sVal = 0; - if (NPVARIANT_IS_INT32(npvValue)) { + if (NPVARIANT_IS_INT32(npvValue)) sVal = static_cast<jshort>(NPVARIANT_TO_INT32(npvValue)); - } else if (NPVARIANT_IS_DOUBLE(npvValue)) { + else if (NPVARIANT_IS_DOUBLE(npvValue)) sVal = static_cast<jshort>(NPVARIANT_TO_DOUBLE(npvValue)); - } env->SetShortArrayRegion(static_cast<jshortArray>(javaArray), i, 1, &sVal); } } else if (!strcmp(javaClassName.data(), "[Z")) { diff --git a/Source/WebCore/bridge/jni/v8/JavaValueV8.h b/Source/WebCore/bridge/jni/v8/JavaValueV8.h index 3e1c623..c6ff315 100644 --- a/Source/WebCore/bridge/jni/v8/JavaValueV8.h +++ b/Source/WebCore/bridge/jni/v8/JavaValueV8.h @@ -49,7 +49,18 @@ class JavaInstance; // currently used only with V8. // See https://bugs.webkit.org/show_bug.cgi?id=57023. struct JavaValue { - JavaValue() : m_type(JavaTypeInvalid) {} +// ANDROID + JavaValue() + : m_type(JavaTypeInvalid) + , m_booleanValue(false) + , m_byteValue(0) + , m_charValue(0) + , m_shortValue(0) + , m_intValue(0) + , m_longValue(0) + , m_floatValue(0.0) + , m_doubleValue(0.0) {} +// ANDROID JavaType m_type; // We don't use a union because we want to be able to ref-count some of the diff --git a/Source/WebCore/css/AndroidCSSPropertyNames.in b/Source/WebCore/css/AndroidCSSPropertyNames.in index ef67d6b..be751da 100644 --- a/Source/WebCore/css/AndroidCSSPropertyNames.in +++ b/Source/WebCore/css/AndroidCSSPropertyNames.in @@ -21,14 +21,5 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # --webkit-ring --webkit-ring-fill-color --webkit-ring-inner-width --webkit-ring-outer-width --webkit-ring-outset --webkit-ring-pressed-inner-color --webkit-ring-pressed-outer-color --webkit-ring-radius --webkit-ring-selected-inner-color --webkit-ring-selected-outer-color + -webkit-tap-highlight-color diff --git a/Source/WebCore/css/CSSComputedStyleDeclaration.cpp b/Source/WebCore/css/CSSComputedStyleDeclaration.cpp index 4c0571d..4922109 100644 --- a/Source/WebCore/css/CSSComputedStyleDeclaration.cpp +++ b/Source/WebCore/css/CSSComputedStyleDeclaration.cpp @@ -291,18 +291,6 @@ static const int computedProperties[] = { CSSPropertyWebkitSvgShadow, CSSPropertyVectorEffect #endif -#ifdef ANDROID_CSS_RING - , - CSSPropertyWebkitRingFillColor, - CSSPropertyWebkitRingInnerWidth, - CSSPropertyWebkitRingOuterWidth, - CSSPropertyWebkitRingOutset, - CSSPropertyWebkitRingPressedInnerColor, - CSSPropertyWebkitRingPressedOuterColor, - CSSPropertyWebkitRingRadius, - CSSPropertyWebkitRingSelectedInnerColor, - CSSPropertyWebkitRingSelectedOuterColor -#endif #ifdef ANDROID_CSS_TAP_HIGHLIGHT_COLOR , CSSPropertyWebkitTapHighlightColor @@ -1818,29 +1806,6 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(int proper case CSSPropertyWebkitTransformOriginZ: case CSSPropertyWebkitTransition: break; -#ifdef ANDROID_CSS_RING - case CSSPropertyWebkitRing: - // shorthand property currently not supported see bug 13658 - break; - case CSSPropertyWebkitRingFillColor: - return primitiveValueCache->createColorValue(style->ringFillColor().rgb()); - case CSSPropertyWebkitRingInnerWidth: - return primitiveValueCache->createValue(style->ringInnerWidth()); - case CSSPropertyWebkitRingOuterWidth: - return primitiveValueCache->createValue(style->ringOuterWidth()); - case CSSPropertyWebkitRingOutset: - return primitiveValueCache->createValue(style->ringOutset()); - case CSSPropertyWebkitRingPressedInnerColor: - return primitiveValueCache->createColorValue(style->ringPressedInnerColor().rgb()); - case CSSPropertyWebkitRingPressedOuterColor: - return primitiveValueCache->createColorValue(style->ringPressedOuterColor().rgb()); - case CSSPropertyWebkitRingRadius: - return primitiveValueCache->createValue(style->ringRadius()); - case CSSPropertyWebkitRingSelectedInnerColor: - return primitiveValueCache->createColorValue(style->ringSelectedInnerColor().rgb()); - case CSSPropertyWebkitRingSelectedOuterColor: - return primitiveValueCache->createColorValue(style->ringSelectedOuterColor().rgb()); -#endif #ifdef ANDROID_CSS_TAP_HIGHLIGHT_COLOR case CSSPropertyWebkitTapHighlightColor: return primitiveValueCache->createColorValue(style->tapHighlightColor().rgb()); diff --git a/Source/WebCore/css/CSSImportRule.cpp b/Source/WebCore/css/CSSImportRule.cpp index 09e313e..81ade39 100644 --- a/Source/WebCore/css/CSSImportRule.cpp +++ b/Source/WebCore/css/CSSImportRule.cpp @@ -170,26 +170,4 @@ void CSSImportRule::addSubresourceStyleURLs(ListHashSet<KURL>& urls) addSubresourceURL(urls, m_styleSheet->baseURL()); } -#ifdef ANDROID_INSTRUMENT -void* CSSImportRule::operator new(size_t size) -{ - return StyleBase::operator new(size); -} - -void* CSSImportRule::operator new[](size_t size) -{ - return StyleBase::operator new[](size); -} - -void CSSImportRule::operator delete(void* p, size_t size) -{ - StyleBase::operator delete(p, size); -} - -void CSSImportRule::operator delete[](void* p, size_t size) -{ - StyleBase::operator delete[](p, size); -} -#endif - } // namespace WebCore diff --git a/Source/WebCore/css/CSSImportRule.h b/Source/WebCore/css/CSSImportRule.h index 3f44f5b..ad4e97d 100644 --- a/Source/WebCore/css/CSSImportRule.h +++ b/Source/WebCore/css/CSSImportRule.h @@ -66,14 +66,6 @@ private: // from CachedResourceClient virtual void setCSSStyleSheet(const String& href, const KURL& baseURL, const String& charset, const CachedCSSStyleSheet*); -#ifdef ANDROID_INSTRUMENT - // Overridden to resolve the ambiguous - void* operator new(size_t size); - void* operator new[](size_t size); - void operator delete(void* p, size_t size); - void operator delete[](void* p, size_t size); -#endif - String m_strHref; RefPtr<MediaList> m_lstMedia; RefPtr<CSSStyleSheet> m_styleSheet; diff --git a/Source/WebCore/css/CSSMutableStyleDeclaration.cpp b/Source/WebCore/css/CSSMutableStyleDeclaration.cpp index ba3332d..ece418a 100644 --- a/Source/WebCore/css/CSSMutableStyleDeclaration.cpp +++ b/Source/WebCore/css/CSSMutableStyleDeclaration.cpp @@ -261,20 +261,6 @@ String CSSMutableStyleDeclaration::getPropertyValue(int propertyID) const return value->cssText(); } #endif -#ifdef ANDROID_CSS_RING - case CSSPropertyWebkitRing: { - const int properties[9] = { CSSPropertyWebkitRingFillColor, - CSSPropertyWebkitRingInnerWidth, - CSSPropertyWebkitRingOuterWidth, - CSSPropertyWebkitRingOutset, - CSSPropertyWebkitRingPressedInnerColor, - CSSPropertyWebkitRingPressedOuterColor, - CSSPropertyWebkitRingRadius, - CSSPropertyWebkitRingSelectedInnerColor, - CSSPropertyWebkitRingSelectedOuterColor }; - return getLayeredShorthandValue(properties, 9); - } -#endif } return String(); } diff --git a/Source/WebCore/css/CSSParser.cpp b/Source/WebCore/css/CSSParser.cpp index 831e438..b78a6d0 100644 --- a/Source/WebCore/css/CSSParser.cpp +++ b/Source/WebCore/css/CSSParser.cpp @@ -92,10 +92,6 @@ extern int cssyyparse(void* parser); using namespace std; using namespace WTF; -#ifdef ANDROID_INSTRUMENT -#include "TimeCounter.h" -#endif - namespace WebCore { static const unsigned INVALID_NUM_PARSED_PROPERTIES = UINT_MAX; @@ -230,9 +226,6 @@ void CSSParser::setupParser(const char* prefix, const String& string, const char void CSSParser::parseSheet(CSSStyleSheet* sheet, const String& string, int startLineNumber, StyleRuleRangeMap* ruleRangeMap) { -#ifdef ANDROID_INSTRUMENT - android::TimeCounter::start(android::TimeCounter::CSSParseTimeCounter); -#endif setStyleSheet(sheet); m_defaultNamespace = starAtom; // Reset the default namespace. m_ruleRangeMap = ruleRangeMap; @@ -247,37 +240,22 @@ void CSSParser::parseSheet(CSSStyleSheet* sheet, const String& string, int start m_ruleRangeMap = 0; m_currentRuleData = 0; m_rule = 0; -#ifdef ANDROID_INSTRUMENT - android::TimeCounter::record(android::TimeCounter::CSSParseTimeCounter, __FUNCTION__); -#endif } PassRefPtr<CSSRule> CSSParser::parseRule(CSSStyleSheet* sheet, const String& string) { -#ifdef ANDROID_INSTRUMENT - android::TimeCounter::start(android::TimeCounter::CSSParseTimeCounter); -#endif setStyleSheet(sheet); m_allowNamespaceDeclarations = false; setupParser("@-webkit-rule{", string, "} "); cssyyparse(this); -#ifdef ANDROID_INSTRUMENT - android::TimeCounter::record(android::TimeCounter::CSSParseTimeCounter, __FUNCTION__); -#endif return m_rule.release(); } PassRefPtr<CSSRule> CSSParser::parseKeyframeRule(CSSStyleSheet *sheet, const String &string) { -#ifdef ANDROID_INSTRUMENT - android::TimeCounter::start(android::TimeCounter::CSSParseTimeCounter); -#endif setStyleSheet(sheet); setupParser("@-webkit-keyframe-rule{ ", string, "} "); cssyyparse(this); -#ifdef ANDROID_INSTRUMENT - android::TimeCounter::record(android::TimeCounter::CSSParseTimeCounter, __FUNCTION__); -#endif return m_keyframe.release(); } @@ -440,9 +418,6 @@ bool CSSParser::parseValue(CSSMutableStyleDeclaration* declaration, int property bool CSSParser::parseValue(CSSMutableStyleDeclaration* declaration, int propertyId, const String& string, bool important) { -#ifdef ANDROID_INSTRUMENT - android::TimeCounter::start(android::TimeCounter::CSSParseTimeCounter); -#endif ASSERT(!declaration->stylesheet() || declaration->stylesheet()->isCSSStyleSheet()); setStyleSheet(static_cast<CSSStyleSheet*>(declaration->stylesheet())); @@ -464,9 +439,6 @@ bool CSSParser::parseValue(CSSMutableStyleDeclaration* declaration, int property clearProperties(); } -#ifdef ANDROID_INSTRUMENT - android::TimeCounter::record(android::TimeCounter::CSSParseTimeCounter, __FUNCTION__); -#endif return ok; } @@ -499,9 +471,6 @@ bool CSSParser::parseColor(RGBA32& color, const String& string, bool strict) bool CSSParser::parseColor(CSSMutableStyleDeclaration* declaration, const String& string) { -#ifdef ANDROID_INSTRUMENT - android::TimeCounter::start(android::TimeCounter::CSSParseTimeCounter); -#endif ASSERT(!declaration->stylesheet() || declaration->stylesheet()->isCSSStyleSheet()); setStyleSheet(static_cast<CSSStyleSheet*>(declaration->stylesheet())); @@ -509,9 +478,6 @@ bool CSSParser::parseColor(CSSMutableStyleDeclaration* declaration, const String cssyyparse(this); m_rule = 0; -#ifdef ANDROID_INSTRUMENT - android::TimeCounter::record(android::TimeCounter::CSSParseTimeCounter, __FUNCTION__); -#endif return (m_numParsedProperties && m_parsedProperties[0]->m_id == CSSPropertyColor); } @@ -533,9 +499,6 @@ bool CSSParser::parseSystemColor(RGBA32& color, const String& string, Document* void CSSParser::parseSelector(const String& string, Document* doc, CSSSelectorList& selectorList) { -#ifdef ANDROID_INSTRUMENT - android::TimeCounter::start(android::TimeCounter::CSSParseTimeCounter); -#endif RefPtr<CSSStyleSheet> dummyStyleSheet = CSSStyleSheet::create(doc); setStyleSheet(dummyStyleSheet.get()); @@ -549,18 +512,10 @@ void CSSParser::parseSelector(const String& string, Document* doc, CSSSelectorLi // The style sheet will be deleted right away, so it won't outlive the document. ASSERT(dummyStyleSheet->hasOneRef()); - -#ifdef ANDROID_INSTRUMENT - android::TimeCounter::record(android::TimeCounter::CSSParseTimeCounter, __FUNCTION__); -#endif } bool CSSParser::parseDeclaration(CSSMutableStyleDeclaration* declaration, const String& string, RefPtr<CSSStyleSourceData>* styleSourceData) { -#ifdef ANDROID_INSTRUMENT - android::TimeCounter::start(android::TimeCounter::CSSParseTimeCounter); -#endif - // Length of the "@-webkit-decls{" prefix. static const unsigned prefixLength = 15; @@ -599,9 +554,6 @@ bool CSSParser::parseDeclaration(CSSMutableStyleDeclaration* declaration, const m_currentRuleData = 0; m_inStyleRuleOrDeclaration = false; } -#ifdef ANDROID_INSTRUMENT - android::TimeCounter::record(android::TimeCounter::CSSParseTimeCounter, __FUNCTION__); -#endif return ok; } @@ -610,9 +562,6 @@ bool CSSParser::parseMediaQuery(MediaList* queries, const String& string) if (string.isEmpty()) return true; -#ifdef ANDROID_INSTRUMENT - android::TimeCounter::start(android::TimeCounter::CSSParseTimeCounter); -#endif ASSERT(!m_mediaQuery); // can't use { because tokenizer state switches from mediaquery to initial state when it sees { token. @@ -626,9 +575,6 @@ bool CSSParser::parseMediaQuery(MediaList* queries, const String& string) queries->appendMediaQuery(m_mediaQuery.release()); } -#ifdef ANDROID_INSTRUMENT - android::TimeCounter::record(android::TimeCounter::CSSParseTimeCounter, __FUNCTION__); -#endif return ok; } @@ -2016,7 +1962,6 @@ bool CSSParser::parseValue(int propId, bool important) case CSSPropertyTextOverline: case CSSPropertyTextUnderline: return false; - #if ENABLE(WCSS) case CSSPropertyWapInputFormat: validPrimitive = true; @@ -2063,36 +2008,6 @@ bool CSSParser::parseValue(int propId, bool important) return parseLineBoxContain(important); break; -#ifdef ANDROID_CSS_RING - case CSSPropertyWebkitRing: - { - const int properties[9] = { CSSPropertyWebkitRingFillColor, - CSSPropertyWebkitRingInnerWidth, - CSSPropertyWebkitRingOuterWidth, - CSSPropertyWebkitRingOutset, - CSSPropertyWebkitRingPressedInnerColor, - CSSPropertyWebkitRingPressedOuterColor, - CSSPropertyWebkitRingRadius, - CSSPropertyWebkitRingSelectedInnerColor, - CSSPropertyWebkitRingSelectedOuterColor }; - return parseShorthand(propId, properties, 9, important); - } - case CSSPropertyWebkitRingFillColor: - case CSSPropertyWebkitRingPressedInnerColor: - case CSSPropertyWebkitRingPressedOuterColor: - case CSSPropertyWebkitRingSelectedInnerColor: - case CSSPropertyWebkitRingSelectedOuterColor: - parsedValue = parseColor(); - if (parsedValue) - m_valueList->next(); - break; - case CSSPropertyWebkitRingInnerWidth: - case CSSPropertyWebkitRingOuterWidth: - case CSSPropertyWebkitRingOutset: - case CSSPropertyWebkitRingRadius: - validPrimitive = validUnit(value, FLength | FNonNeg, m_strict); - break; -#endif #ifdef ANDROID_CSS_TAP_HIGHLIGHT_COLOR case CSSPropertyWebkitTapHighlightColor: parsedValue = parseColor(); diff --git a/Source/WebCore/css/CSSPropertyNames.in b/Source/WebCore/css/CSSPropertyNames.in index a62d2f3..395b7cf 100644 --- a/Source/WebCore/css/CSSPropertyNames.in +++ b/Source/WebCore/css/CSSPropertyNames.in @@ -306,3 +306,4 @@ z-index -webkit-user-drag -webkit-user-modify -webkit-user-select +-webkit-overflow-scrolling diff --git a/Source/WebCore/css/CSSStyleDeclaration.cpp b/Source/WebCore/css/CSSStyleDeclaration.cpp index 1c465e5..d4acc2a 100644 --- a/Source/WebCore/css/CSSStyleDeclaration.cpp +++ b/Source/WebCore/css/CSSStyleDeclaration.cpp @@ -27,6 +27,7 @@ #include "CSSPropertyNames.h" #include "CSSRule.h" #include <wtf/ASCIICType.h> +#include <wtf/text/CString.h> using namespace WTF; diff --git a/Source/WebCore/css/CSSStyleSelector.cpp b/Source/WebCore/css/CSSStyleSelector.cpp index b79f2dc..0b6fd35 100644 --- a/Source/WebCore/css/CSSStyleSelector.cpp +++ b/Source/WebCore/css/CSSStyleSelector.cpp @@ -6054,138 +6054,6 @@ void CSSStyleSelector::applyProperty(int id, CSSValue *value) ASSERT_NOT_REACHED(); return; -#ifdef ANDROID_CSS_RING - case CSSPropertyWebkitRing: - if (valueType != CSSValue::CSS_INHERIT || !m_parentNode) return; - m_style->setRingFillColor(m_parentStyle->ringFillColor()); - m_style->setRingInnerWidth(m_parentStyle->ringInnerWidth()); - m_style->setRingOuterWidth(m_parentStyle->ringOuterWidth()); - m_style->setRingOutset(m_parentStyle->ringOutset()); - m_style->setRingPressedInnerColor(m_parentStyle->ringPressedInnerColor()); - m_style->setRingPressedOuterColor(m_parentStyle->ringPressedOuterColor()); - m_style->setRingRadius(m_parentStyle->ringRadius()); - m_style->setRingSelectedInnerColor(m_parentStyle->ringSelectedInnerColor()); - m_style->setRingSelectedOuterColor(m_parentStyle->ringSelectedOuterColor()); - return; - case CSSPropertyWebkitRingFillColor: { - HANDLE_INHERIT_AND_INITIAL(ringFillColor, RingFillColor); - if (!primitiveValue) - break; - Color col = getColorFromPrimitiveValue(primitiveValue).blendWithWhite(); - m_style->setRingFillColor(col); - return; - } - case CSSPropertyWebkitRingInnerWidth: { - HANDLE_INHERIT_AND_INITIAL(ringInnerWidth, RingInnerWidth) - if (!primitiveValue) - break; - Length l; - int type = primitiveValue->primitiveType(); - if (CSSPrimitiveValue::isUnitTypeLength(type)) { - // width can be specified with fractional px - // scale by 16 here (and unscale in android_graphics) to keep - // 4 bits of fraction - RefPtr<CSSPrimitiveValue> scaledValue = CSSPrimitiveValue::create( - primitiveValue->getFloatValue() * 16, - (CSSPrimitiveValue::UnitTypes) type); - l = Length(scaledValue->computeLengthIntForLength(style(), - m_rootElementStyle, zoomFactor), Fixed); - scaledValue.release(); - } else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) - l = Length(primitiveValue->getDoubleValue(), Percent); - else - return; - m_style->setRingInnerWidth(l); - return; - } - case CSSPropertyWebkitRingOuterWidth: { - HANDLE_INHERIT_AND_INITIAL(ringOuterWidth, RingOuterWidth) - if (!primitiveValue) - break; - Length l; - int type = primitiveValue->primitiveType(); - if (CSSPrimitiveValue::isUnitTypeLength(type)) { - // width can be specified with fractional px - // scale by 16 here (and unscale in android_graphics) to keep - // 4 bits of fraction - RefPtr<CSSPrimitiveValue> scaledValue = CSSPrimitiveValue::create( - primitiveValue->getFloatValue() * 16, - (CSSPrimitiveValue::UnitTypes) type); - l = Length(scaledValue->computeLengthIntForLength(style(), - m_rootElementStyle, zoomFactor), Fixed); - scaledValue.release(); - } else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) - l = Length(primitiveValue->getDoubleValue(), Percent); - else - return; - m_style->setRingOuterWidth(l); - return; - } - case CSSPropertyWebkitRingOutset: { - HANDLE_INHERIT_AND_INITIAL(ringOutset, RingOutset) - if (!primitiveValue) - break; - Length l; - int type = primitiveValue->primitiveType(); - if (CSSPrimitiveValue::isUnitTypeLength(type)) - l = Length(primitiveValue->computeLengthIntForLength(style(), - m_rootElementStyle, zoomFactor), Fixed); - else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) - l = Length(primitiveValue->getDoubleValue(), Percent); - else - return; - m_style->setRingOutset(l); - return; - } - case CSSPropertyWebkitRingPressedInnerColor: { - HANDLE_INHERIT_AND_INITIAL(ringPressedInnerColor, RingPressedInnerColor); - if (!primitiveValue) - break; - Color col = getColorFromPrimitiveValue(primitiveValue).blendWithWhite(); - m_style->setRingPressedInnerColor(col); - return; - } - case CSSPropertyWebkitRingPressedOuterColor: { - HANDLE_INHERIT_AND_INITIAL(ringPressedOuterColor, RingPressedOuterColor); - if (!primitiveValue) - break; - Color col = getColorFromPrimitiveValue(primitiveValue).blendWithWhite(); - m_style->setRingPressedOuterColor(col); - return; - } - case CSSPropertyWebkitRingRadius: { - HANDLE_INHERIT_AND_INITIAL(ringRadius, RingRadius) - if (!primitiveValue) - break; - Length l; - int type = primitiveValue->primitiveType(); - if (CSSPrimitiveValue::isUnitTypeLength(type)) - l = Length(primitiveValue->computeLengthIntForLength(style(), - m_rootElementStyle, zoomFactor), Fixed); - else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) - l = Length(primitiveValue->getDoubleValue(), Percent); - else - return; - m_style->setRingRadius(l); - return; - } - case CSSPropertyWebkitRingSelectedInnerColor: { - HANDLE_INHERIT_AND_INITIAL(ringSelectedInnerColor, RingSelectedInnerColor); - if (!primitiveValue) - break; - Color col = getColorFromPrimitiveValue(primitiveValue).blendWithWhite(); - m_style->setRingSelectedInnerColor(col); - return; - } - case CSSPropertyWebkitRingSelectedOuterColor: { - HANDLE_INHERIT_AND_INITIAL(ringSelectedOuterColor, RingSelectedOuterColor); - if (!primitiveValue) - break; - Color col = getColorFromPrimitiveValue(primitiveValue).blendWithWhite(); - m_style->setRingSelectedOuterColor(col); - return; - } -#endif #ifdef ANDROID_CSS_TAP_HIGHLIGHT_COLOR case CSSPropertyWebkitTapHighlightColor: { HANDLE_INHERIT_AND_INITIAL(tapHighlightColor, TapHighlightColor); diff --git a/Source/WebCore/css/CSSValueKeywords.in b/Source/WebCore/css/CSSValueKeywords.in index 6dac06f..5b6e5b0 100644 --- a/Source/WebCore/css/CSSValueKeywords.in +++ b/Source/WebCore/css/CSSValueKeywords.in @@ -756,6 +756,10 @@ windowed manual # auto +# -webkit-overflow-scrolling +# auto +touch + # -webkit-writing-mode # SVG compatibility lr diff --git a/Source/WebCore/css/StyleBase.cpp b/Source/WebCore/css/StyleBase.cpp index 5d9d79d..93dbda0 100644 --- a/Source/WebCore/css/StyleBase.cpp +++ b/Source/WebCore/css/StyleBase.cpp @@ -65,37 +65,4 @@ KURL StyleBase::baseURL() const return sheet->ownerNode()->document()->baseURL(); } -#ifdef ANDROID_INSTRUMENT -static size_t styleSize = 0; - -void* StyleBase::operator new(size_t size) -{ - styleSize += size; - return ::operator new(size); -} - -void* StyleBase::operator new[](size_t size) -{ - styleSize += size; - return ::operator new[](size); -} - -void StyleBase::operator delete(void* p, size_t size) -{ - styleSize -= size; - ::operator delete(p); -} - -void StyleBase::operator delete[](void* p, size_t size) -{ - styleSize -= size; - ::operator delete[](p); -} - -size_t StyleBase::reportStyleSize() -{ - return styleSize; -} -#endif - } diff --git a/Source/WebCore/css/StyleBase.h b/Source/WebCore/css/StyleBase.h index 94efa01..63c671e 100644 --- a/Source/WebCore/css/StyleBase.h +++ b/Source/WebCore/css/StyleBase.h @@ -72,18 +72,6 @@ namespace WebCore { StyleSheet* stylesheet(); -#ifdef ANDROID_INSTRUMENT - // Overridden to prevent the normal new from being called. - void* operator new(size_t size); - void* operator new[](size_t size); - - // Overridden to prevent the normal delete from being called. - void operator delete(void* p, size_t size); - void operator delete[](void* p, size_t size); - - static size_t reportStyleSize(); -#endif - protected: StyleBase(StyleBase* parent) : m_parent(parent) diff --git a/Source/WebCore/css/mediaControlsAndroid.css b/Source/WebCore/css/mediaControlsAndroid.css index 77f8b08..614c92f 100644 --- a/Source/WebCore/css/mediaControlsAndroid.css +++ b/Source/WebCore/css/mediaControlsAndroid.css @@ -49,10 +49,7 @@ video:-webkit-full-page-media::-webkit-media-controls-panel { } audio::-webkit-media-controls-mute-button, video::-webkit-media-controls-mute-button { - -webkit-appearance: media-mute-button; - display: -webkit-box; - width: 48px; - height: 48px; + display: none; } audio::-webkit-media-controls-play-button, video::-webkit-media-controls-play-button { diff --git a/Source/WebCore/dom/DOMTextContentWalker.cpp b/Source/WebCore/dom/DOMTextContentWalker.cpp new file mode 100644 index 0000000..5e77db1 --- /dev/null +++ b/Source/WebCore/dom/DOMTextContentWalker.cpp @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2011 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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 APPLE INC. AND ITS CONTRIBUTORS ``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 APPLE INC. OR ITS 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 "DOMTextContentWalker.h" + +#if OS(ANDROID) + +#include "Range.h" +#include "TextIterator.h" +#include "VisiblePosition.h" +#include "VisibleSelection.h" +#include "visible_units.h" + +namespace WebCore { + +static PassRefPtr<Range> getRange(const Position& start, const Position& end) +{ + return VisibleSelection(start.parentAnchoredEquivalent(), end.parentAnchoredEquivalent(), DOWNSTREAM).firstRange(); +} + +DOMTextContentWalker::DOMTextContentWalker(const VisiblePosition& position, unsigned maxLength) + : m_hitOffsetInContent(0) +{ + const unsigned halfMaxLength = maxLength / 2; + RefPtr<Range> forwardRange = makeRange(position, endOfDocument(position)); + if (!forwardRange) + return; + CharacterIterator forwardChar(forwardRange.get(), TextIteratorStopsOnFormControls); + forwardChar.advance(maxLength - halfMaxLength); + + // No forward contents, started inside form control. + if (getRange(position.deepEquivalent(), forwardChar.range()->startPosition())->text().length() == 0) + return; + + RefPtr<Range> backwardsRange = makeRange(startOfDocument(position), position); + if (!backwardsRange) + return; + BackwardsCharacterIterator backwardsChar(backwardsRange.get(), TextIteratorStopsOnFormControls); + backwardsChar.advance(halfMaxLength); + + m_hitOffsetInContent = getRange(backwardsChar.range()->endPosition(), position.deepEquivalent())->text().length(); + m_contentRange = getRange(backwardsChar.range()->endPosition(), forwardChar.range()->startPosition()); +} + +PassRefPtr<Range> DOMTextContentWalker::contentOffsetsToRange(unsigned startInContent, unsigned endInContent) +{ + if (startInContent >= endInContent || endInContent > content().length()) + return 0; + + CharacterIterator iterator(m_contentRange.get()); + iterator.advance(startInContent); + + Position start = iterator.range()->startPosition(); + iterator.advance(endInContent - startInContent); + Position end = iterator.range()->startPosition(); + return getRange(start, end); +} + +String DOMTextContentWalker::content() const +{ + if (m_contentRange) + return m_contentRange->text(); + return String(); +} + +unsigned DOMTextContentWalker::hitOffsetInContent() const +{ + return m_hitOffsetInContent; +} + +} // namespace WebCore + +#endif // OS(ANDROID) diff --git a/Source/WebCore/dom/DOMTextContentWalker.h b/Source/WebCore/dom/DOMTextContentWalker.h new file mode 100644 index 0000000..0d4259b --- /dev/null +++ b/Source/WebCore/dom/DOMTextContentWalker.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2011 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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 APPLE INC. AND ITS CONTRIBUTORS ``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 APPLE INC. OR ITS 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 DOMTextContentWalker_h +#define DOMTextContentWalker_h + +#if OS(ANDROID) + +#include "PlatformString.h" + +namespace WebCore { + +class Range; +class VisiblePosition; + +// Explore the DOM tree to find the text contents up to a limit +// around a position in a given text node. +class DOMTextContentWalker { + WTF_MAKE_NONCOPYABLE(DOMTextContentWalker); +public: + DOMTextContentWalker(const VisiblePosition& position, unsigned maxLength); + + String content() const; + unsigned hitOffsetInContent() const; + + // Convert start/end positions in the content text string into a text range. + PassRefPtr<Range> contentOffsetsToRange(unsigned startInContent, unsigned endInContent); + +private: + RefPtr<Range> m_contentRange; + size_t m_hitOffsetInContent; +}; + +} // namespace WebCore + +#endif // OS(ANDROID) + +#endif // DOMTextContentWalker_h + diff --git a/Source/WebCore/dom/Document.cpp b/Source/WebCore/dom/Document.cpp index 6e21dc3..1b5f55b 100644 --- a/Source/WebCore/dom/Document.cpp +++ b/Source/WebCore/dom/Document.cpp @@ -189,15 +189,6 @@ #include "Settings.h" #endif -#ifdef ANDROID_RESET_SELECTION -#include "CacheBuilder.h" -#include "HTMLTextAreaElement.h" -#endif - -#ifdef ANDROID_INSTRUMENT -#include "TimeCounter.h" -#endif - #if ENABLE(TOUCH_EVENTS) #if USE(V8) #include "RuntimeEnabledFeatures.h" @@ -1475,10 +1466,6 @@ void Document::recalcStyle(StyleChange change) frameView->beginDeferredRepaints(); } -#ifdef ANDROID_INSTRUMENT - android::TimeCounter::start(android::TimeCounter::CalculateStyleTimeCounter); -#endif - ASSERT(!renderer() || renderArena()); if (!renderer() || !renderArena()) goto bail_out; @@ -1500,10 +1487,6 @@ void Document::recalcStyle(StyleChange change) if (change >= Inherit || n->childNeedsStyleRecalc() || n->needsStyleRecalc()) n->recalcStyle(change); -#ifdef ANDROID_INSTRUMENT - android::TimeCounter::record(android::TimeCounter::CalculateStyleTimeCounter, __FUNCTION__); -#endif - #if USE(ACCELERATED_COMPOSITING) if (view()) { bool layoutPending = view()->layoutPending() || renderer()->needsLayout(); @@ -2729,8 +2712,8 @@ void Document::processArguments(const String& features, void* data, ArgumentsCal #ifdef ANDROID_META_SUPPORT if (frame()) frame()->settings()->setMetadataSettings(keyString, valueString); -#endif if (callback && data) +#endif callback(keyString, valueString, this, data); } } diff --git a/Source/WebCore/dom/Node.cpp b/Source/WebCore/dom/Node.cpp index 1fd4b92..0967ef5 100644 --- a/Source/WebCore/dom/Node.cpp +++ b/Source/WebCore/dom/Node.cpp @@ -2498,39 +2498,6 @@ Node* Node::enclosingLinkEventParentOrSelf() return 0; } -#ifdef ANDROID_INSTRUMENT -static size_t nodeSize = 0; - -void* Node::operator new(size_t size) -{ - nodeSize += size; - return ::operator new(size); -} - -void* Node::operator new[](size_t size) -{ - nodeSize += size; - return ::operator new[](size); -} - -void Node::operator delete(void* p, size_t size) -{ - nodeSize -= size; - ::operator delete(p); -} - -void Node::operator delete[](void* p, size_t size) -{ - nodeSize -= size; - ::operator delete[](p); -} - -size_t Node::reportDOMNodesSize() -{ - return nodeSize; -} -#endif - // -------- ScriptExecutionContext* Node::scriptExecutionContext() const diff --git a/Source/WebCore/dom/Node.h b/Source/WebCore/dom/Node.h index 1fe30ad..08b1921 100644 --- a/Source/WebCore/dom/Node.h +++ b/Source/WebCore/dom/Node.h @@ -528,18 +528,6 @@ public: unsigned short compareDocumentPosition(Node*); -#ifdef ANDROID_INSTRUMENT - // Overridden to prevent the normal new from being called. - void* operator new(size_t size); - void* operator new[](size_t size); - - // Overridden to prevent the normal delete from being called. - void operator delete(void* p, size_t size); - void operator delete[](void* p, size_t size); - - static size_t reportDOMNodesSize(); -#endif - virtual Node* toNode() { return this; } virtual InputElement* toInputElement(); diff --git a/Source/WebCore/dom/ProcessingInstruction.cpp b/Source/WebCore/dom/ProcessingInstruction.cpp index 7135644..30111d8 100644 --- a/Source/WebCore/dom/ProcessingInstruction.cpp +++ b/Source/WebCore/dom/ProcessingInstruction.cpp @@ -297,26 +297,4 @@ void ProcessingInstruction::finishParsingChildren() ContainerNode::finishParsingChildren(); } -#ifdef ANDROID_INSTRUMENT -void* ProcessingInstruction::operator new(size_t size) -{ - return Node::operator new(size); -} - -void* ProcessingInstruction::operator new[](size_t size) -{ - return Node::operator new[](size); -} - -void ProcessingInstruction::operator delete(void* p, size_t size) -{ - Node::operator delete(p, size); -} - -void ProcessingInstruction::operator delete[](void* p, size_t size) -{ - Node::operator delete[](p, size); -} -#endif - } // namespace diff --git a/Source/WebCore/dom/ProcessingInstruction.h b/Source/WebCore/dom/ProcessingInstruction.h index fd98566..1be8710 100644 --- a/Source/WebCore/dom/ProcessingInstruction.h +++ b/Source/WebCore/dom/ProcessingInstruction.h @@ -56,14 +56,6 @@ public: private: ProcessingInstruction(Document*, const String& target, const String& data); -#ifdef ANDROID_INSTRUMENT - // Overridden to resolve the ambiguous - void* operator new(size_t size); - void* operator new[](size_t size); - void operator delete(void* p, size_t size); - void operator delete[](void* p, size_t size); -#endif - virtual String nodeName() const; virtual NodeType nodeType() const; virtual String nodeValue() const; diff --git a/Source/WebCore/dom/Text.cpp b/Source/WebCore/dom/Text.cpp index 906e421..c4ea0a6 100644 --- a/Source/WebCore/dom/Text.cpp +++ b/Source/WebCore/dom/Text.cpp @@ -31,6 +31,8 @@ #include "SVGNames.h" #endif +#include <wtf/text/CString.h> + #if ENABLE(WML) #include "WMLDocument.h" #include "WMLVariables.h" diff --git a/Source/WebCore/editing/InsertIntoTextNodeCommand.cpp b/Source/WebCore/editing/InsertIntoTextNodeCommand.cpp index b1a455b..bd6fb60 100644 --- a/Source/WebCore/editing/InsertIntoTextNodeCommand.cpp +++ b/Source/WebCore/editing/InsertIntoTextNodeCommand.cpp @@ -28,6 +28,8 @@ #include "AXObjectCache.h" #include "Text.h" +#include "RenderText.h" +#include "Settings.h" namespace WebCore { @@ -46,7 +48,13 @@ void InsertIntoTextNodeCommand::doApply() { if (!m_node->rendererIsEditable()) return; - + + if (document()->settings() && document()->settings()->passwordEchoEnabled()) { + RenderText* renderText = toRenderText(m_node->renderer()); + if (renderText && renderText->isSecure()) + renderText->momentarilyRevealLastTypedCharacter(m_offset + m_text.length() - 1); + } + ExceptionCode ec; m_node->insertData(m_offset, m_text, ec); diff --git a/Source/WebCore/editing/SelectionController.cpp b/Source/WebCore/editing/SelectionController.cpp index c5a33d3..acae6bf 100644 --- a/Source/WebCore/editing/SelectionController.cpp +++ b/Source/WebCore/editing/SelectionController.cpp @@ -1217,10 +1217,6 @@ void SelectionController::invalidateCaretRect() void SelectionController::paintCaret(GraphicsContext* context, int tx, int ty, const IntRect& clipRect) { -#ifdef ANDROID_ALLOW_TURNING_OFF_CARET - if (m_frame && !android::WebViewCore::getWebViewCore(m_frame->view())->shouldPaintCaret()) - return; -#endif #if ENABLE(TEXT_CARET) if (!m_caretVisible) return; @@ -1592,6 +1588,10 @@ void SelectionController::updateAppearance() // We need to update style in case the node containing the selection is made display:none. m_frame->document()->updateStyleIfNeeded(); +#if PLATFORM(ANDROID) + return; +#endif + RenderView* view = m_frame->contentRenderer(); if (!view) return; diff --git a/Source/WebCore/editing/TextIterator.cpp b/Source/WebCore/editing/TextIterator.cpp index c3be277..3aa68af 100644 --- a/Source/WebCore/editing/TextIterator.cpp +++ b/Source/WebCore/editing/TextIterator.cpp @@ -239,6 +239,20 @@ static void setUpFullyClippedStack(BitStack& stack, Node* node) ASSERT(stack.size() == 1 + depthCrossingShadowBoundaries(node)); } +#if OS(ANDROID) +static bool checkFormControlElement(Node* startNode) +{ + Node* node = startNode; + while (node) { + if (node->isElementNode() && static_cast<Element*>(node)->isFormControlElement()) + return true; + node = node->parentNode(); + } + return false; +} +#endif + + // -------- TextIterator::TextIterator() @@ -258,6 +272,10 @@ TextIterator::TextIterator() , m_handledFirstLetter(false) , m_ignoresStyleVisibility(false) , m_emitsObjectReplacementCharacters(false) +#if OS(ANDROID) + , m_stopsOnFormControls(false) + , m_shouldStop(false) +#endif { } @@ -277,6 +295,10 @@ TextIterator::TextIterator(const Range* r, TextIteratorBehavior behavior) , m_handledFirstLetter(false) , m_ignoresStyleVisibility(behavior & TextIteratorIgnoresStyleVisibility) , m_emitsObjectReplacementCharacters(behavior & TextIteratorEmitsObjectReplacementCharacters) +#if OS(ANDROID) + , m_stopsOnFormControls(behavior & TextIteratorStopsOnFormControls) + , m_shouldStop(false) +#endif { if (!r) return; @@ -334,8 +356,21 @@ TextIterator::~TextIterator() { } +bool TextIterator::atEnd() const +{ +#if OS(ANDROID) + return !m_positionNode || m_shouldStop; +#else + return !m_positionNode; +#endif +} + void TextIterator::advance() { +#if OS(ANDROID) + if (m_shouldStop) + return; +#endif // reset the run information m_positionNode = 0; m_textLength = 0; @@ -368,6 +403,10 @@ void TextIterator::advance() } while (m_node && m_node != m_pastEndNode) { +#if OS(ANDROID) + if (!m_shouldStop && m_stopsOnFormControls && checkFormControlElement(m_node)) + m_shouldStop = true; +#endif // if the range ends at offset 0 of an element, represent the // position, but not the content, of that element e.g. if the // node is a blockflow element, emit a newline that @@ -1034,6 +1073,10 @@ SimplifiedBackwardsTextIterator::SimplifiedBackwardsTextIterator() : m_behavior(TextIteratorDefaultBehavior) , m_node(0) , m_positionNode(0) +#if OS(ANDROID) + , m_stopsOnFormControls(false) + , m_shouldStop(false) +#endif { } @@ -1041,8 +1084,16 @@ SimplifiedBackwardsTextIterator::SimplifiedBackwardsTextIterator(const Range* r, : m_behavior(behavior) , m_node(0) , m_positionNode(0) +#if OS(ANDROID) + , m_stopsOnFormControls(behavior & TextIteratorStopsOnFormControls) + , m_shouldStop(false) +#endif { +#if OS(ANDROID) + ASSERT(m_behavior == TextIteratorDefaultBehavior || m_behavior == TextIteratorStopsOnFormControls); +#else ASSERT(m_behavior == TextIteratorDefaultBehavior); +#endif if (!r) return; @@ -1091,10 +1142,30 @@ SimplifiedBackwardsTextIterator::SimplifiedBackwardsTextIterator(const Range* r, advance(); } +bool SimplifiedBackwardsTextIterator::atEnd() const +{ +#if OS(ANDROID) + return !m_positionNode || m_shouldStop; +#else + return !m_positionNode; +#endif +} + void SimplifiedBackwardsTextIterator::advance() { ASSERT(m_positionNode); +#if OS(ANDROID) + if (m_shouldStop) + return; + + // Prevent changing the iterator position if a form control element was found and advance should stop on it. + if (m_stopsOnFormControls && checkFormControlElement(m_node)) { + m_shouldStop = true; + return; + } +#endif + m_positionNode = 0; m_textLength = 0; diff --git a/Source/WebCore/editing/TextIterator.h b/Source/WebCore/editing/TextIterator.h index 9fe4ceb..c4fc264 100644 --- a/Source/WebCore/editing/TextIterator.h +++ b/Source/WebCore/editing/TextIterator.h @@ -42,7 +42,10 @@ enum TextIteratorBehavior { TextIteratorEntersTextControls = 1 << 1, TextIteratorEmitsTextsWithoutTranscoding = 1 << 2, TextIteratorIgnoresStyleVisibility = 1 << 3, - TextIteratorEmitsObjectReplacementCharacters = 1 << 4 + TextIteratorEmitsObjectReplacementCharacters = 1 << 4, +#if OS(ANDROID) + TextIteratorStopsOnFormControls = 1 << 6 +#endif }; // FIXME: Can't really answer this question correctly without knowing the white-space mode. @@ -88,7 +91,7 @@ public: ~TextIterator(); explicit TextIterator(const Range*, TextIteratorBehavior = TextIteratorDefaultBehavior); - bool atEnd() const { return !m_positionNode; } + bool atEnd() const; void advance(); int length() const { return m_textLength; } @@ -182,6 +185,12 @@ private: bool m_ignoresStyleVisibility; // Used when emitting the special 0xFFFC character is required. bool m_emitsObjectReplacementCharacters; +#if OS(ANDROID) + // Used when the iteration should stop if form controls are reached. + bool m_stopsOnFormControls; + // Used when m_stopsOnFormControls is set to determine if the iterator should keep advancing. + bool m_shouldStop; +#endif }; // Iterates through the DOM range, returning all the text, and 0-length boundaries @@ -192,7 +201,7 @@ public: SimplifiedBackwardsTextIterator(); explicit SimplifiedBackwardsTextIterator(const Range*, TextIteratorBehavior = TextIteratorDefaultBehavior); - bool atEnd() const { return !m_positionNode; } + bool atEnd() const; void advance(); int length() const { return m_textLength; } @@ -240,6 +249,13 @@ private: // Whether m_node has advanced beyond the iteration range (i.e. m_startNode). bool m_havePassedStartNode; + +#if OS(ANDROID) + // Used when the iteration should stop if form controls are reached. + bool m_stopsOnFormControls; + // Used when m_stopsOnFormControls is set to determine if the iterator should keep advancing. + bool m_shouldStop; +#endif }; // Builds on the text iterator, adding a character position so we can walk one diff --git a/Source/WebCore/html/HTMLAnchorElement.cpp b/Source/WebCore/html/HTMLAnchorElement.cpp index 60f5b4a..4636f20 100644 --- a/Source/WebCore/html/HTMLAnchorElement.cpp +++ b/Source/WebCore/html/HTMLAnchorElement.cpp @@ -531,7 +531,11 @@ bool HTMLAnchorElement::treatLinkAsLiveForEventType(EventType eventType) const bool isEnterKeyKeydownEvent(Event* event) { +#if OS(ANDROID) + return event->type() == eventNames().keyupEvent && event->isKeyboardEvent() && static_cast<KeyboardEvent*>(event)->keyIdentifier() == "Enter"; +#else return event->type() == eventNames().keydownEvent && event->isKeyboardEvent() && static_cast<KeyboardEvent*>(event)->keyIdentifier() == "Enter"; +#endif } bool isMiddleMouseButtonEvent(Event* event) diff --git a/Source/WebCore/html/HTMLCanvasElement.h b/Source/WebCore/html/HTMLCanvasElement.h index 9eab209..207c384 100644 --- a/Source/WebCore/html/HTMLCanvasElement.h +++ b/Source/WebCore/html/HTMLCanvasElement.h @@ -128,22 +128,6 @@ public: void makeRenderingResultsAvailable(); -#ifdef ANDROID_INSTRUMENT - void* operator new(size_t size) { - return HTMLElement::operator new(size); - } - void* operator new[](size_t size) { - return HTMLElement::operator new[](size); - } - - void operator delete(void* p, size_t size) { - HTMLElement::operator delete(p, size); - } - void operator delete[](void* p, size_t size) { - HTMLElement::operator delete[](p, size); - } -#endif - private: HTMLCanvasElement(const QualifiedName&, Document*); diff --git a/Source/WebCore/html/HTMLDocument.cpp b/Source/WebCore/html/HTMLDocument.cpp index dd41514..a1be93d 100644 --- a/Source/WebCore/html/HTMLDocument.cpp +++ b/Source/WebCore/html/HTMLDocument.cpp @@ -438,26 +438,4 @@ bool HTMLDocument::isFrameSet() const return bodyElement && bodyElement->hasTagName(framesetTag); } -#ifdef ANDROID_INSTRUMENT -void* HTMLDocument::operator new(size_t size) -{ - return Node::operator new(size); -} - -void* HTMLDocument::operator new[](size_t size) -{ - return Node::operator new[](size); -} - -void HTMLDocument::operator delete(void* p, size_t size) -{ - Node::operator delete(p, size); -} - -void HTMLDocument::operator delete[](void* p, size_t size) -{ - Node::operator delete[](p, size); -} -#endif - } diff --git a/Source/WebCore/html/HTMLDocument.h b/Source/WebCore/html/HTMLDocument.h index 3310b71..d39f392 100644 --- a/Source/WebCore/html/HTMLDocument.h +++ b/Source/WebCore/html/HTMLDocument.h @@ -82,14 +82,6 @@ public: protected: HTMLDocument(Frame*, const KURL&); -#ifdef ANDROID_INSTRUMENT - // Overridden to resolve the ambiguous - void* operator new(size_t size); - void* operator new[](size_t size); - void operator delete(void* p, size_t size); - void operator delete[](void* p, size_t size); -#endif - private: virtual PassRefPtr<Element> createElement(const AtomicString& tagName, ExceptionCode&); diff --git a/Source/WebCore/html/HTMLLinkElement.cpp b/Source/WebCore/html/HTMLLinkElement.cpp index 7cbf38b..4673109 100644 --- a/Source/WebCore/html/HTMLLinkElement.cpp +++ b/Source/WebCore/html/HTMLLinkElement.cpp @@ -504,28 +504,6 @@ void HTMLLinkElement::addSubresourceAttributeURLs(ListHashSet<KURL>& urls) const styleSheet->addSubresourceStyleURLs(urls); } -#ifdef ANDROID_INSTRUMENT -void* HTMLLinkElement::operator new(size_t size) -{ - return Node::operator new(size); -} - -void* HTMLLinkElement::operator new[](size_t size) -{ - return Node::operator new[](size); -} - -void HTMLLinkElement::operator delete(void* p, size_t size) -{ - Node::operator delete(p, size); -} - -void HTMLLinkElement::operator delete[](void* p, size_t size) -{ - Node::operator delete[](p, size); -} -#endif - void HTMLLinkElement::addPendingSheet(PendingSheetType type) { if (type <= m_pendingSheetType) diff --git a/Source/WebCore/html/HTMLLinkElement.h b/Source/WebCore/html/HTMLLinkElement.h index f602d38..1a6eba9 100644 --- a/Source/WebCore/html/HTMLLinkElement.h +++ b/Source/WebCore/html/HTMLLinkElement.h @@ -120,14 +120,6 @@ private: void addPendingSheet(PendingSheetType); void removePendingSheet(); -#ifdef ANDROID_INSTRUMENT - // Overridden to resolve the ambiguous - void* operator new(size_t size); - void* operator new[](size_t size); - void operator delete(void* p, size_t size); - void operator delete[](void* p, size_t size); -#endif - private: HTMLLinkElement(const QualifiedName&, Document*, bool createdByParser); diff --git a/Source/WebCore/html/HTMLMediaElement.cpp b/Source/WebCore/html/HTMLMediaElement.cpp index 023e8d2..5cd2ddd 100644 --- a/Source/WebCore/html/HTMLMediaElement.cpp +++ b/Source/WebCore/html/HTMLMediaElement.cpp @@ -178,6 +178,7 @@ HTMLMediaElement::HTMLMediaElement(const QualifiedName& tagName, Document* docum , m_completelyLoaded(false) #if PLATFORM(ANDROID) , m_lastTouch(0) + , m_userGestureInitiated(false) #endif { LOG(Media, "HTMLMediaElement::HTMLMediaElement"); @@ -187,8 +188,8 @@ HTMLMediaElement::HTMLMediaElement(const QualifiedName& tagName, Document* docum #if PLATFORM(ANDROID) && ENABLE(TOUCH_EVENTS) // Enable the Media Element to listen to all the touch events document->addListenerTypeIfNeeded(eventNames().touchstartEvent); + m_restrictions |= RequireUserGestureForRateChangeRestriction; #endif - } HTMLMediaElement::~HTMLMediaElement() @@ -515,6 +516,9 @@ void HTMLMediaElement::load(bool isUserGesture, ExceptionCode& ec) ec = INVALID_STATE_ERR; else { m_loadInitiatedByUserGesture = isUserGesture; +#if PLATFORM(ANDROID) + m_userGestureInitiated |= isUserGesture; +#endif prepareForLoad(); loadInternal(); } @@ -1417,9 +1421,19 @@ void HTMLMediaElement::play(bool isUserGesture) { LOG(Media, "HTMLMediaElement::play(isUserGesture : %s)", boolString(isUserGesture)); - if (m_restrictions & RequireUserGestureForRateChangeRestriction && !isUserGesture) + if (m_restrictions & RequireUserGestureForRateChangeRestriction && !isUserGesture +#if PLATFORM(ANDROID) + && !m_userGestureInitiated +#endif + ) return; +#if PLATFORM(ANDROID) + // B/c we set the restriction to require gesture for rate change for + // Android, when we don't early return, we can safely set this to true. + m_userGestureInitiated = true; +#endif + Document* doc = document(); Settings* settings = doc->settings(); if (settings && settings->needsSiteSpecificQuirks() && m_dispatchingCanPlayEvent && !m_loadInitiatedByUserGesture) { @@ -1466,9 +1480,17 @@ void HTMLMediaElement::pause(bool isUserGesture) { LOG(Media, "HTMLMediaElement::pause(isUserGesture : %s)", boolString(isUserGesture)); - if (m_restrictions & RequireUserGestureForRateChangeRestriction && !isUserGesture) + if (m_restrictions & RequireUserGestureForRateChangeRestriction && !isUserGesture +#if PLATFORM(ANDROID) + && !m_userGestureInitiated +#endif + ) return; - +#if PLATFORM(ANDROID) + // B/c we set the restriction to require gesture for rate change for + // Android, when we don't early return, we can safely set this to true. + m_userGestureInitiated = true; +#endif pauseInternal(); } @@ -2402,6 +2424,15 @@ void HTMLMediaElement::defaultEventHandler(Event* event) } #endif +#if PLATFORM(ANDROID) + // It is really hard to hit the play/pause button on mobile devices. + // This allows user to click the video area to toggle play/pause state. + if (event->type() == eventNames().clickEvent + && !hasEventListeners(eventNames().clickEvent)) { + m_userGestureInitiated = processingUserGesture(); + togglePlayState(); + } +#endif HTMLElement::defaultEventHandler(event); #endif } diff --git a/Source/WebCore/html/HTMLMediaElement.h b/Source/WebCore/html/HTMLMediaElement.h index 987cf87..2144ea1 100644 --- a/Source/WebCore/html/HTMLMediaElement.h +++ b/Source/WebCore/html/HTMLMediaElement.h @@ -420,6 +420,10 @@ private: #if PLATFORM(ANDROID) double m_lastTouch; + // When user gesture invoke load, play or pause, this turns to be true. + // After this becomes true, we ignore the user gesture requirement for play + // and pause. + bool m_userGestureInitiated; #endif }; diff --git a/Source/WebCore/html/canvas/ArrayBufferView.h b/Source/WebCore/html/canvas/ArrayBufferView.h index 701abbc..d06fc8d 100644 --- a/Source/WebCore/html/canvas/ArrayBufferView.h +++ b/Source/WebCore/html/canvas/ArrayBufferView.h @@ -46,6 +46,7 @@ class ArrayBufferView : public RefCounted<ArrayBufferView> { virtual bool isIntArray() const { return false; } virtual bool isUnsignedIntArray() const { return false; } virtual bool isFloatArray() const { return false; } + virtual bool isDoubleArray() const { return false; } virtual bool isDataView() const { return false; } PassRefPtr<ArrayBuffer> buffer() const diff --git a/Source/WebCore/html/canvas/Float64Array.cpp b/Source/WebCore/html/canvas/Float64Array.cpp new file mode 100644 index 0000000..2dcb373 --- /dev/null +++ b/Source/WebCore/html/canvas/Float64Array.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * Copyright (C) 2011 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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 APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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 "Float64Array.h" + +namespace WebCore { + +PassRefPtr<Float64Array> Float64Array::create(unsigned length) +{ + return TypedArrayBase<double>::create<Float64Array>(length); +} + +PassRefPtr<Float64Array> Float64Array::create(const double* array, unsigned length) +{ + return TypedArrayBase<double>::create<Float64Array>(array, length); +} + +PassRefPtr<Float64Array> Float64Array::create(PassRefPtr<ArrayBuffer> buffer, unsigned byteOffset, unsigned length) +{ + return TypedArrayBase<double>::create<Float64Array>(buffer, byteOffset, length); +} + +Float64Array::Float64Array(PassRefPtr<ArrayBuffer> buffer, unsigned byteOffset, unsigned length) + : TypedArrayBase<double>(buffer, byteOffset, length) +{ +} + +PassRefPtr<Float64Array> Float64Array::subarray(int start) const +{ + return subarray(start, length()); +} + +PassRefPtr<Float64Array> Float64Array::subarray(int start, int end) const +{ + return subarrayImpl<Float64Array>(start, end); +} + +} diff --git a/Source/WebCore/html/canvas/Float64Array.h b/Source/WebCore/html/canvas/Float64Array.h new file mode 100644 index 0000000..f45a21c --- /dev/null +++ b/Source/WebCore/html/canvas/Float64Array.h @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * Copyright (C) 2011 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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 APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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 Float64Array_h +#define Float64Array_h + +#include "TypedArrayBase.h" +#include <wtf/MathExtras.h> + +namespace WebCore { + +class Float64Array : public TypedArrayBase<double> { +public: + static PassRefPtr<Float64Array> create(unsigned length); + static PassRefPtr<Float64Array> create(const double* array, unsigned length); + static PassRefPtr<Float64Array> create(PassRefPtr<ArrayBuffer>, unsigned byteOffset, unsigned length); + + using TypedArrayBase<double>::set; + + void set(unsigned index, double value) + { + if (index >= TypedArrayBase<double>::m_length) + return; + TypedArrayBase<double>::data()[index] = static_cast<double>(value); + } + + // Invoked by the indexed getter. Does not perform range checks; caller + // is responsible for doing so and returning undefined as necessary. + double item(unsigned index) const + { + ASSERT(index < TypedArrayBase<double>::m_length); + double result = TypedArrayBase<double>::data()[index]; + return result; + } + + PassRefPtr<Float64Array> subarray(int start) const; + PassRefPtr<Float64Array> subarray(int start, int end) const; + +private: + Float64Array(PassRefPtr<ArrayBuffer>, + unsigned byteOffset, + unsigned length); + // Make constructor visible to superclass. + friend class TypedArrayBase<double>; + + // Overridden from ArrayBufferView. + virtual bool isDoubleArray() const { return true; } +}; + +} // namespace WebCore + +#endif // Float64Array_h diff --git a/Source/WebCore/html/canvas/Float64Array.idl b/Source/WebCore/html/canvas/Float64Array.idl new file mode 100644 index 0000000..6057253 --- /dev/null +++ b/Source/WebCore/html/canvas/Float64Array.idl @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * Copyright (C) 2011 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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 APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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. + */ + +module html { + interface [ + CanBeConstructed, + CustomConstructFunction, + V8CustomConstructor, + HasNumericIndexGetter, + HasCustomIndexSetter, + GenerateNativeConverter, + NoStaticTables, + CustomToJS, + DontCheckEnums + ] Float64Array : ArrayBufferView { + const unsigned int BYTES_PER_ELEMENT = 8; + + readonly attribute unsigned long length; + Float64Array subarray(in long start, in [Optional] long end); + + // void set(in Float64Array array, [Optional] in unsigned long offset); + // void set(in sequence<long> array, [Optional] in unsigned long offset); + [Custom] void set(); + }; +} diff --git a/Source/WebCore/html/parser/HTMLDocumentParser.cpp b/Source/WebCore/html/parser/HTMLDocumentParser.cpp index 8f95cc5..46dddf0 100644 --- a/Source/WebCore/html/parser/HTMLDocumentParser.cpp +++ b/Source/WebCore/html/parser/HTMLDocumentParser.cpp @@ -41,10 +41,6 @@ #include "NestingLevelIncrementer.h" #include "Settings.h" -#ifdef ANDROID_INSTRUMENT -#include "TimeCounter.h" -#endif - namespace WebCore { using namespace HTMLNames; @@ -318,10 +314,6 @@ void HTMLDocumentParser::insert(const SegmentedString& source) if (isStopped()) return; -#ifdef ANDROID_INSTRUMENT - android::TimeCounter::start(android::TimeCounter::ParsingTimeCounter); -#endif - // pumpTokenizer can cause this parser to be detached from the Document, // but we need to ensure it isn't deleted yet. RefPtr<HTMLDocumentParser> protect(this); @@ -369,18 +361,12 @@ void HTMLDocumentParser::append(const SegmentedString& source) // We've gotten data off the network in a nested write. // We don't want to consume any more of the input stream now. Do // not worry. We'll consume this data in a less-nested write(). -#ifdef ANDROID_INSTRUMENT - android::TimeCounter::record(android::TimeCounter::ParsingTimeCounter, __FUNCTION__); -#endif return; } pumpTokenizerIfPossible(AllowYield); endIfDelayed(); -#ifdef ANDROID_INSTRUMENT - android::TimeCounter::record(android::TimeCounter::ParsingTimeCounter, __FUNCTION__); -#endif } void HTMLDocumentParser::end() diff --git a/Source/WebCore/loader/FrameLoader.cpp b/Source/WebCore/loader/FrameLoader.cpp index 85b1541..f999fdb 100644 --- a/Source/WebCore/loader/FrameLoader.cpp +++ b/Source/WebCore/loader/FrameLoader.cpp @@ -119,11 +119,6 @@ #include "ArchiveFactory.h" #endif -#ifdef ANDROID_INSTRUMENT -#include "TimeCounter.h" -#include "RenderArena.h" -#endif - namespace WebCore { using namespace HTMLNames; @@ -1114,11 +1109,7 @@ void FrameLoader::handleFallbackContent() } void FrameLoader::provisionalLoadStarted() -{ -#ifdef ANDROID_INSTRUMENT - if (!m_frame->tree()->parent()) - android::TimeCounter::reset(); -#endif +{ if (m_stateMachine.firstLayoutDone()) m_stateMachine.advanceTo(FrameLoaderStateMachine::CommittedFirstRealLoad); m_frame->navigationScheduler()->cancel(true); @@ -2308,7 +2299,7 @@ void FrameLoader::finishedLoadingDocument(DocumentLoader* loader) if (m_stateMachine.creatingInitialEmptyDocument()) return; #endif - + #if !ENABLE(WEB_ARCHIVE) m_client->finishedLoading(loader); #else @@ -2499,12 +2490,6 @@ void FrameLoader::checkLoadCompleteForThisFrame() if (Page* page = m_frame->page()) page->progress()->progressCompleted(m_frame); - -#ifdef ANDROID_INSTRUMENT - if (!m_frame->tree()->parent() && m_frame->document()->renderArena()) - android::TimeCounter::report(m_URL, cache()->getLiveSize(), cache()->getDeadSize(), - m_frame->document()->renderArena()->reportPoolSize()); -#endif return; } diff --git a/Source/WebCore/loader/archive/android/WebArchiveAndroid.cpp b/Source/WebCore/loader/archive/android/WebArchiveAndroid.cpp index 55d7cec..5f60163 100644 --- a/Source/WebCore/loader/archive/android/WebArchiveAndroid.cpp +++ b/Source/WebCore/loader/archive/android/WebArchiveAndroid.cpp @@ -36,6 +36,7 @@ #include <libxml/tree.h> #include <libxml/xmlstring.h> #include <libxml/xmlwriter.h> +#include <utils/Log.h> #include <wtf/text/CString.h> namespace WebCore { @@ -117,7 +118,7 @@ static bool loadArchiveResourceField(xmlNodePtr resourceNode, const xmlChar* fie } } if (!base64Data) { - LOGD("loadArchiveResourceField: Failed to load field."); + ALOGD("loadArchiveResourceField: Failed to load field."); return false; } @@ -125,7 +126,7 @@ static bool loadArchiveResourceField(xmlNodePtr resourceNode, const xmlChar* fie const int result = base64Decode(base64Data, base64Size, *outputData); if (!result) { - LOGD("loadArchiveResourceField: Failed to decode field."); + ALOGD("loadArchiveResourceField: Failed to decode field."); return false; } @@ -165,37 +166,37 @@ static KURL loadArchiveResourceFieldURL(xmlNodePtr resourceNode, const xmlChar* static PassRefPtr<ArchiveResource> loadArchiveResource(xmlNodePtr resourceNode) { if (!xmlStrEqual(resourceNode->name, archiveResourceTag)) { - LOGD("loadArchiveResource: Malformed resource."); + ALOGD("loadArchiveResource: Malformed resource."); return 0; } KURL url = loadArchiveResourceFieldURL(resourceNode, urlFieldTag); if (url.isNull()) { - LOGD("loadArchiveResource: Failed to load resource."); + ALOGD("loadArchiveResource: Failed to load resource."); return 0; } String mimeType = loadArchiveResourceFieldString(resourceNode, mimeFieldTag); if (mimeType.isNull()) { - LOGD("loadArchiveResource: Failed to load resource."); + ALOGD("loadArchiveResource: Failed to load resource."); return 0; } String textEncoding = loadArchiveResourceFieldString(resourceNode, encodingFieldTag); if (textEncoding.isNull()) { - LOGD("loadArchiveResource: Failed to load resource."); + ALOGD("loadArchiveResource: Failed to load resource."); return 0; } String frameName = loadArchiveResourceFieldString(resourceNode, frameFieldTag); if (frameName.isNull()) { - LOGD("loadArchiveResource: Failed to load resource."); + ALOGD("loadArchiveResource: Failed to load resource."); return 0; } PassRefPtr<SharedBuffer> data = loadArchiveResourceFieldBuffer(resourceNode, dataFieldTag); if (!data) { - LOGD("loadArchiveResource: Failed to load resource."); + ALOGD("loadArchiveResource: Failed to load resource."); return 0; } @@ -211,7 +212,7 @@ static PassRefPtr<WebArchiveAndroid> loadArchive(xmlNodePtr archiveNode) Vector<PassRefPtr<Archive> > subframes; if (!xmlStrEqual(archiveNode->name, archiveTag)) { - LOGD("loadArchive: Malformed archive."); + ALOGD("loadArchive: Malformed archive."); return 0; } @@ -227,7 +228,7 @@ static PassRefPtr<WebArchiveAndroid> loadArchive(xmlNodePtr archiveNode) } } if (!mainResource) { - LOGD("loadArchive: Failed to load main resource."); + ALOGD("loadArchive: Failed to load main resource."); return 0; } @@ -240,7 +241,7 @@ static PassRefPtr<WebArchiveAndroid> loadArchive(xmlNodePtr archiveNode) resourceNode = resourceNode->next) { PassRefPtr<ArchiveResource> subresource = loadArchiveResource(resourceNode); if (!subresource) { - LOGD("loadArchive: Failed to load subresource."); + ALOGD("loadArchive: Failed to load subresource."); break; } subresources.append(subresource); @@ -258,7 +259,7 @@ static PassRefPtr<WebArchiveAndroid> loadArchive(xmlNodePtr archiveNode) resourceNode = resourceNode->next) { PassRefPtr<WebArchiveAndroid> subframe = loadArchive(resourceNode); if (!subframe) { - LOGD("loadArchive: Failed to load subframe."); + ALOGD("loadArchive: Failed to load subframe."); break; } subframes.append(subframe); @@ -290,20 +291,20 @@ PassRefPtr<WebArchiveAndroid> WebArchiveAndroid::create(SharedBuffer* buffer) xmlDocPtr doc = xmlReadMemory(buffer->data(), buffer->size(), noBaseUrl, defaultEncoding, noParserOptions); if (!doc) { - LOGD("create: Failed to parse document."); + ALOGD("create: Failed to parse document."); return createArchiveForError(); } xmlNodePtr root = xmlDocGetRootElement(doc); if (!root) { - LOGD("create: Empty document."); + ALOGD("create: Empty document."); xmlFreeDoc(doc); return createArchiveForError(); } RefPtr<WebArchiveAndroid> archive = loadArchive(root); if (!archive) { - LOGD("create: Failed to load archive."); + ALOGD("create: Failed to load archive."); xmlFreeDoc(doc); return createArchiveForError(); } @@ -316,7 +317,7 @@ static bool saveArchiveResourceField(xmlTextWriterPtr writer, const xmlChar* tag { int result = xmlTextWriterStartElement(writer, tag); if (result < 0) { - LOGD("saveArchiveResourceField: Failed to start element."); + ALOGD("saveArchiveResourceField: Failed to start element."); return false; } @@ -324,20 +325,20 @@ static bool saveArchiveResourceField(xmlTextWriterPtr writer, const xmlChar* tag Vector<char> base64Data; base64Encode(data, size, base64Data, false); if (base64Data.isEmpty()) { - LOGD("saveArchiveResourceField: Failed to base64 encode data."); + ALOGD("saveArchiveResourceField: Failed to base64 encode data."); return false; } result = xmlTextWriterWriteRawLen(writer, BAD_CAST base64Data.data(), base64Data.size()); if (result < 0) { - LOGD("saveArchiveResourceField: Failed to write data."); + ALOGD("saveArchiveResourceField: Failed to write data."); return false; } } result = xmlTextWriterEndElement(writer); if (result < 0) { - LOGD("saveArchiveResourceField: Failed to end element."); + ALOGD("saveArchiveResourceField: Failed to end element."); return false; } @@ -360,7 +361,7 @@ static bool saveArchiveResource(xmlTextWriterPtr writer, PassRefPtr<ArchiveResou { int result = xmlTextWriterStartElement(writer, archiveResourceTag); if (result < 0) { - LOGD("saveArchiveResource: Failed to start element."); + ALOGD("saveArchiveResource: Failed to start element."); return false; } @@ -373,7 +374,7 @@ static bool saveArchiveResource(xmlTextWriterPtr writer, PassRefPtr<ArchiveResou result = xmlTextWriterEndElement(writer); if (result < 0) { - LOGD("saveArchiveResource: Failed to end element."); + ALOGD("saveArchiveResource: Failed to end element."); return false; } @@ -384,13 +385,13 @@ static bool saveArchive(xmlTextWriterPtr writer, PassRefPtr<Archive> archive) { int result = xmlTextWriterStartElement(writer, archiveTag); if (result < 0) { - LOGD("saveArchive: Failed to start element."); + ALOGD("saveArchive: Failed to start element."); return false; } result = xmlTextWriterStartElement(writer, mainResourceTag); if (result < 0) { - LOGD("saveArchive: Failed to start element."); + ALOGD("saveArchive: Failed to start element."); return false; } @@ -399,13 +400,13 @@ static bool saveArchive(xmlTextWriterPtr writer, PassRefPtr<Archive> archive) result = xmlTextWriterEndElement(writer); if (result < 0) { - LOGD("saveArchive: Failed to end element."); + ALOGD("saveArchive: Failed to end element."); return false; } result = xmlTextWriterStartElement(writer, subresourcesTag); if (result < 0) { - LOGD("saveArchive: Failed to start element."); + ALOGD("saveArchive: Failed to start element."); return false; } @@ -418,13 +419,13 @@ static bool saveArchive(xmlTextWriterPtr writer, PassRefPtr<Archive> archive) result = xmlTextWriterEndElement(writer); if (result < 0) { - LOGD("saveArchive: Failed to end element."); + ALOGD("saveArchive: Failed to end element."); return false; } result = xmlTextWriterStartElement(writer, subframesTag); if (result < 0) { - LOGD("saveArchive: Failed to start element."); + ALOGD("saveArchive: Failed to start element."); return false; } @@ -437,7 +438,7 @@ static bool saveArchive(xmlTextWriterPtr writer, PassRefPtr<Archive> archive) result = xmlTextWriterEndElement(writer); if (result < 0) { - LOGD("saveArchive: Failed to end element."); + ALOGD("saveArchive: Failed to end element."); return true; } @@ -452,7 +453,7 @@ bool WebArchiveAndroid::saveWebArchive(xmlTextWriterPtr writer) int result = xmlTextWriterStartDocument(writer, defaultXmlVersion, defaultEncoding, defaultStandalone); if (result < 0) { - LOGD("saveWebArchive: Failed to start document."); + ALOGD("saveWebArchive: Failed to start document."); return false; } @@ -461,7 +462,7 @@ bool WebArchiveAndroid::saveWebArchive(xmlTextWriterPtr writer) result = xmlTextWriterEndDocument(writer); if (result< 0) { - LOGD("saveWebArchive: Failed to end document."); + ALOGD("saveWebArchive: Failed to end document."); return false; } diff --git a/Source/WebCore/loader/cache/MemoryCache.h b/Source/WebCore/loader/cache/MemoryCache.h index a092eac..c9b91f9 100644 --- a/Source/WebCore/loader/cache/MemoryCache.h +++ b/Source/WebCore/loader/cache/MemoryCache.h @@ -171,12 +171,6 @@ public: void removeResourcesWithOrigin(SecurityOrigin*); void getOriginsWithCache(SecurityOriginSet& origins); -#ifdef ANDROID_INSTRUMENT - unsigned getLiveSize() { return m_liveSize; } - unsigned getDeadSize() { return m_deadSize; } -#endif - - private: MemoryCache(); ~MemoryCache(); // Not implemented to make sure nobody accidentally calls delete -- WebCore does not delete singletons. diff --git a/Source/WebCore/loader/icon/IconDatabase.cpp b/Source/WebCore/loader/icon/IconDatabase.cpp index 3cefea7..2bb22ec 100644 --- a/Source/WebCore/loader/icon/IconDatabase.cpp +++ b/Source/WebCore/loader/icon/IconDatabase.cpp @@ -73,7 +73,7 @@ static const int updateTimerDelay = 5; static bool checkIntegrityOnOpen = false; -#ifndef NDEBUG +#if !LOG_DISABLED || !ERROR_DISABLED static String urlForLogging(const String& url) { static unsigned urlTruncationLength = 120; @@ -967,7 +967,7 @@ void* IconDatabase::iconDatabaseSyncThread() LOG(IconDatabase, "(THREAD) IconDatabase sync thread started"); -#ifndef NDEBUG +#if !LOG_DISABLED double startTime = currentTime(); #endif @@ -993,7 +993,7 @@ void* IconDatabase::iconDatabaseSyncThread() if (shouldStopThreadActivity()) return syncThreadMainLoop(); -#ifndef NDEBUG +#if !LOG_DISABLED double timeStamp = currentTime(); LOG(IconDatabase, "(THREAD) Open took %.4f seconds", timeStamp - startTime); #endif @@ -1002,7 +1002,7 @@ void* IconDatabase::iconDatabaseSyncThread() if (shouldStopThreadActivity()) return syncThreadMainLoop(); -#ifndef NDEBUG +#if !LOG_DISABLED double newStamp = currentTime(); LOG(IconDatabase, "(THREAD) performOpenInitialization() took %.4f seconds, now %.4f seconds from thread start", newStamp - timeStamp, newStamp - startTime); timeStamp = newStamp; @@ -1025,7 +1025,7 @@ void* IconDatabase::iconDatabaseSyncThread() if (shouldStopThreadActivity()) return syncThreadMainLoop(); -#ifndef NDEBUG +#if !LOG_DISABLED newStamp = currentTime(); LOG(IconDatabase, "(THREAD) performImport() took %.4f seconds, now %.4f seconds from thread start", newStamp - timeStamp, newStamp - startTime); timeStamp = newStamp; @@ -1042,7 +1042,7 @@ void* IconDatabase::iconDatabaseSyncThread() if (shouldStopThreadActivity()) return syncThreadMainLoop(); -#ifndef NDEBUG +#if !LOG_DISABLED newStamp = currentTime(); LOG(IconDatabase, "(THREAD) performURLImport() took %.4f seconds. Entering main loop %.4f seconds from thread start", newStamp - timeStamp, newStamp - startTime); #endif @@ -1358,7 +1358,7 @@ void* IconDatabase::syncThreadMainLoop() while (!m_threadTerminationRequested) { m_syncLock.unlock(); -#ifndef NDEBUG +#if !LOG_DISABLED double timeStamp = currentTime(); #endif LOG(IconDatabase, "(THREAD) Main work loop starting"); @@ -1391,7 +1391,7 @@ void* IconDatabase::syncThreadMainLoop() // has asked to delay pruning static bool prunedUnretainedIcons = false; if (didWrite && !m_privateBrowsingEnabled && !prunedUnretainedIcons && !databaseCleanupCounter) { -#ifndef NDEBUG +#if !LOG_DISABLED double time = currentTime(); #endif LOG(IconDatabase, "(THREAD) Starting pruneUnretainedIcons()"); @@ -1410,7 +1410,7 @@ void* IconDatabase::syncThreadMainLoop() break; } -#ifndef NDEBUG +#if !LOG_DISABLED double newstamp = currentTime(); LOG(IconDatabase, "(THREAD) Main work loop ran for %.4f seconds, %s requested to terminate", newstamp - timeStamp, shouldStopThreadActivity() ? "was" : "was not"); #endif @@ -1458,7 +1458,7 @@ bool IconDatabase::readFromDatabase() { ASSERT_ICON_SYNC_THREAD(); -#ifndef NDEBUG +#if !LOG_DISABLED double timeStamp = currentTime(); #endif @@ -1567,7 +1567,7 @@ bool IconDatabase::writeToDatabase() { ASSERT_ICON_SYNC_THREAD(); -#ifndef NDEBUG +#if !LOG_DISABLED double timeStamp = currentTime(); #endif @@ -1772,7 +1772,7 @@ void* IconDatabase::cleanupSyncThread() { ASSERT_ICON_SYNC_THREAD(); -#ifndef NDEBUG +#if !LOG_DISABLED double timeStamp = currentTime(); #endif @@ -1792,7 +1792,7 @@ void* IconDatabase::cleanupSyncThread() deleteAllPreparedStatements(); m_syncDB.close(); -#ifndef NDEBUG +#if !LOG_DISABLED LOG(IconDatabase, "(THREAD) Final closure took %.4f seconds", currentTime() - timeStamp); #endif diff --git a/Source/WebCore/page/DOMWindow.cpp b/Source/WebCore/page/DOMWindow.cpp index c7f162a..ee2206b 100644 --- a/Source/WebCore/page/DOMWindow.cpp +++ b/Source/WebCore/page/DOMWindow.cpp @@ -1095,11 +1095,7 @@ int DOMWindow::innerHeight() const if (!view) return 0; -#if PLATFORM(ANDROID) - return static_cast<int>(view->actualHeight() / m_frame->pageZoomFactor()); -#else return static_cast<int>(view->height() / m_frame->pageZoomFactor()); -#endif } int DOMWindow::innerWidth() const @@ -1111,11 +1107,7 @@ int DOMWindow::innerWidth() const if (!view) return 0; -#if PLATFORM(ANDROID) - return static_cast<int>(view->actualWidth() / m_frame->pageZoomFactor()); -#else return static_cast<int>(view->width() / m_frame->pageZoomFactor()); -#endif } int DOMWindow::screenX() const @@ -1153,11 +1145,7 @@ int DOMWindow::scrollX() const m_frame->document()->updateLayoutIgnorePendingStylesheets(); -#if PLATFORM(ANDROID) - return static_cast<int>(view->actualScrollX() / m_frame->pageZoomFactor()); -#else return static_cast<int>(view->scrollX() / m_frame->pageZoomFactor()); -#endif } int DOMWindow::scrollY() const @@ -1171,11 +1159,7 @@ int DOMWindow::scrollY() const m_frame->document()->updateLayoutIgnorePendingStylesheets(); -#if PLATFORM(ANDROID) - return static_cast<int>(view->actualScrollY() / m_frame->pageZoomFactor()); -#else return static_cast<int>(view->scrollY() / m_frame->pageZoomFactor()); -#endif } bool DOMWindow::closed() const diff --git a/Source/WebCore/page/DOMWindow.idl b/Source/WebCore/page/DOMWindow.idl index 9f7313c..d5d3413 100644 --- a/Source/WebCore/page/DOMWindow.idl +++ b/Source/WebCore/page/DOMWindow.idl @@ -510,6 +510,7 @@ module window { attribute [JSCCustomGetter] Int32ArrayConstructor Int32Array; // Usable with new operator attribute [JSCCustomGetter] Uint32ArrayConstructor Uint32Array; // Usable with new operator attribute [JSCCustomGetter] Float32ArrayConstructor Float32Array; // Usable with new operator + attribute [JSCCustomGetter] Float64ArrayConstructor Float64Array; // Usable with new operator attribute [JSCCustomGetter] DataViewConstructor DataView; // Usable with new operator attribute [JSCCustomGetter,Conditional=WEB_AUDIO,EnabledAtRuntime] AudioContextConstructor webkitAudioContext; // Usable with new operator diff --git a/Source/WebCore/page/EventHandler.cpp b/Source/WebCore/page/EventHandler.cpp index e77809c..a737754 100644 --- a/Source/WebCore/page/EventHandler.cpp +++ b/Source/WebCore/page/EventHandler.cpp @@ -2415,16 +2415,10 @@ static Node* eventTargetNodeForDocument(Document* doc) if (!doc) return 0; Node* node = doc->focusedNode(); -#if defined(ANDROID_PLUGINS) - if (!node && doc->frame() && doc->frame()->view()) - node = android::WebViewCore::getWebViewCore(doc->frame()->view()) - ->cursorNodeIsPlugin(); -#else if (!node && doc->isPluginDocument()) { PluginDocument* pluginDocument = static_cast<PluginDocument*>(doc); node = pluginDocument->pluginNode(); } -#endif if (!node && doc->isHTMLDocument()) node = doc->body(); if (!node) diff --git a/Source/WebCore/page/Frame.cpp b/Source/WebCore/page/Frame.cpp index 8a1ad69..049f08b 100644 --- a/Source/WebCore/page/Frame.cpp +++ b/Source/WebCore/page/Frame.cpp @@ -113,10 +113,6 @@ #include "WMLNames.h" #endif -#if PLATFORM(ANDROID) -#include "WebViewCore.h" -#endif - using namespace std; namespace WebCore { diff --git a/Source/WebCore/page/FrameView.cpp b/Source/WebCore/page/FrameView.cpp index 49a7d0c..f332074 100644 --- a/Source/WebCore/page/FrameView.cpp +++ b/Source/WebCore/page/FrameView.cpp @@ -62,11 +62,6 @@ #include "TextResourceDecoder.h" #include <wtf/CurrentTime.h> -#ifdef ANDROID_INSTRUMENT -#include "FrameTree.h" -#include "TimeCounter.h" -#endif - #if USE(ACCELERATED_COMPOSITING) #include "RenderLayerCompositor.h" #endif @@ -872,11 +867,6 @@ void FrameView::layout(bool allowSubtree) return; } -#ifdef ANDROID_INSTRUMENT - if (!m_frame->tree() || !m_frame->tree()->parent()) - android::TimeCounter::start(android::TimeCounter::LayoutTimeCounter); -#endif - m_nestedLayoutCount++; if (!m_layoutRoot) { @@ -1014,10 +1004,6 @@ void FrameView::layout(bool allowSubtree) updateDashboardRegions(); #endif -#ifdef ANDROID_INSTRUMENT - if (!m_frame->tree()->parent()) - android::TimeCounter::record(android::TimeCounter::LayoutTimeCounter, __FUNCTION__); -#endif ASSERT(!root->needsLayout()); updateCanBlitOnScrollRecursively(); @@ -1752,11 +1738,6 @@ void FrameView::scheduleRelayout() if (!m_frame->document()->shouldScheduleLayout()) return; -#ifdef ANDROID_FLATTEN_FRAMESET - if (m_frame->ownerRenderer()) - m_frame->ownerRenderer()->setNeedsLayoutAndPrefWidthsRecalc(); -#endif - // When frame flattening is enabled, the contents of the frame affects layout of the parent frames. // Also invalidate parent frame starting from the owner element of this frame. if (m_frame->settings() && m_frame->settings()->frameFlatteningEnabled() && m_frame->ownerRenderer()) { diff --git a/Source/WebCore/page/Settings.cpp b/Source/WebCore/page/Settings.cpp index e2312a9..c26a0fc 100644 --- a/Source/WebCore/page/Settings.cpp +++ b/Source/WebCore/page/Settings.cpp @@ -98,6 +98,7 @@ Settings::Settings(Page* page) #ifdef ANDROID_LAYOUT , m_layoutAlgorithm(kLayoutFitColumnToScreen) #endif + , m_passwordEchoDurationInSeconds(1) , m_isSpatialNavigationEnabled(false) , m_isJavaEnabled(false) , m_loadsImagesAutomatically(false) @@ -192,6 +193,11 @@ Settings::Settings(Page* page) #ifdef ANDROID_PLUGINS , m_pluginsOnDemand(false) #endif +#if OS(SYMBIAN) + , m_passwordEchoEnabled(true) +#else + , m_passwordEchoEnabled(false) +#endif { // A Frame may not have been created yet, so we initialize the AtomicString // hash before trying to use it. diff --git a/Source/WebCore/page/Settings.h b/Source/WebCore/page/Settings.h index 31a5ad9..2bb222d 100644 --- a/Source/WebCore/page/Settings.h +++ b/Source/WebCore/page/Settings.h @@ -458,6 +458,12 @@ namespace WebCore { void setShouldInjectUserScriptsInInitialEmptyDocument(bool flag) { m_shouldInjectUserScriptsInInitialEmptyDocument = flag; } bool shouldInjectUserScriptsInInitialEmptyDocument() { return m_shouldInjectUserScriptsInInitialEmptyDocument; } + void setPasswordEchoEnabled(bool flag) { m_passwordEchoEnabled = flag; } + bool passwordEchoEnabled() const { return m_passwordEchoEnabled; } + + void setPasswordEchoDurationInSeconds(double durationInSeconds) { m_passwordEchoDurationInSeconds = durationInSeconds; } + double passwordEchoDurationInSeconds() const { return m_passwordEchoDurationInSeconds; } + #if ENABLE(WEB_AUTOFILL) void setAutoFillEnabled(bool flag) { m_autoFillEnabled = flag; } bool autoFillEnabled() { return m_autoFillEnabled; } @@ -511,6 +517,8 @@ namespace WebCore { #ifdef ANDROID_LAYOUT LayoutAlgorithm m_layoutAlgorithm; #endif + double m_passwordEchoDurationInSeconds; + bool m_isSpatialNavigationEnabled : 1; bool m_isJavaEnabled : 1; bool m_loadsImagesAutomatically : 1; @@ -617,6 +625,7 @@ namespace WebCore { #ifdef ANDROID_PLUGINS bool m_pluginsOnDemand : 1; #endif + bool m_passwordEchoEnabled : 1; #if USE(SAFARI_THEME) static bool gShouldPaintNativeControls; diff --git a/Source/WebCore/platform/Arena.cpp b/Source/WebCore/platform/Arena.cpp index 231e1b6..33980ed 100644 --- a/Source/WebCore/platform/Arena.cpp +++ b/Source/WebCore/platform/Arena.cpp @@ -255,16 +255,4 @@ void FinishArenaPool(ArenaPool *pool) FreeArenaList(pool, &pool->first, true); } -#ifdef ANDROID_INSTRUMENT -size_t ReportPoolSize(const ArenaPool* pool) -{ - size_t total = 0; - for (const Arena *a = &pool->first; a; a = a->next) - total += (a->limit - a->base); - for (const Arena *fa = arena_freelist; fa; fa = fa->next ) - total += (fa->limit - fa->base); - return total; -} -#endif - } diff --git a/Source/WebCore/platform/Arena.h b/Source/WebCore/platform/Arena.h index e937955..06e09f2 100644 --- a/Source/WebCore/platform/Arena.h +++ b/Source/WebCore/platform/Arena.h @@ -134,10 +134,6 @@ void* ArenaAllocate(ArenaPool *pool, unsigned int nb); fastFree(a); \ (a) = 0; -#ifdef ANDROID_INSTRUMENT -size_t ReportPoolSize(const ArenaPool* pool); -#endif - } #endif diff --git a/Source/WebCore/platform/NotImplemented.h b/Source/WebCore/platform/NotImplemented.h index a71e99c..e9758b0 100644 --- a/Source/WebCore/platform/NotImplemented.h +++ b/Source/WebCore/platform/NotImplemented.h @@ -38,21 +38,7 @@ #define supressNotImplementedWarning() false #endif -#if OS(ANDROID) - -#include <cutils/log.h> -#ifndef LOG_TAG -#define LOG_TAG "WebCore" -#endif -#define notImplemented() do { \ - static bool havePrinted = false; \ - if (!havePrinted && !supressNotImplementedWarning()) { \ - LOGV("%s: notImplemented", __PRETTY_FUNCTION__); \ - havePrinted = true; \ - } \ - } while (0) - -#elif defined(NDEBUG) +#if defined(NDEBUG) #define notImplemented() ((void)0) #else diff --git a/Source/WebCore/platform/ScrollView.cpp b/Source/WebCore/platform/ScrollView.cpp index e79f049..140c8e5 100644 --- a/Source/WebCore/platform/ScrollView.cpp +++ b/Source/WebCore/platform/ScrollView.cpp @@ -27,6 +27,13 @@ #include "ScrollView.h" #include "AXObjectCache.h" +#if PLATFORM(ANDROID) +#include "FrameView.h" +#include "GraphicsLayerAndroid.h" +#include "RenderLayer.h" +#include "RenderLayerBacking.h" +#include "RenderView.h" +#endif #include "GraphicsContext.h" #include "GraphicsLayer.h" #include "HostWindow.h" @@ -301,32 +308,12 @@ void ScrollView::setContentsSize(const IntSize& newSize) } #if PLATFORM(ANDROID) -int ScrollView::actualWidth() const -{ - if (platformWidget()) - return platformActualWidth(); - return width(); -} - -int ScrollView::actualHeight() const -{ - if (platformWidget()) - return platformActualHeight(); - return height(); -} - -int ScrollView::actualScrollX() const -{ - if (platformWidget()) - return platformActualScrollX(); - return scrollX(); -} - -int ScrollView::actualScrollY() const -{ - if (platformWidget()) - return platformActualScrollY(); - return scrollY(); +FrameView* ScrollView::frameView() { + if (this->isFrameView()) { + FrameView* frameView = reinterpret_cast<FrameView*>(this); + return frameView; + } + return 0; } #endif @@ -386,6 +373,26 @@ void ScrollView::scrollTo(const IntSize& newOffset) return; m_scrollOffset = newOffset; +#if PLATFORM(ANDROID) + if (parent()) { + FrameView* frameView = this->frameView(); + // IFrames are composited on a layer, we do not need to repaint them + // when scrolling + if (frameView) { + RenderView* renderer = frameView->frame()->contentRenderer(); + if (renderer) { + RenderLayer* layer = renderer->layer(); + if (layer->backing()) { + GraphicsLayerAndroid* backing = static_cast<GraphicsLayerAndroid*>( + layer->backing()->graphicsLayer()); + backing->updateScrollOffset(); + } + } + return; + } + } +#endif + if (scrollbarsSuppressed()) return; diff --git a/Source/WebCore/platform/ScrollView.h b/Source/WebCore/platform/ScrollView.h index 558aee2..e58d025 100644 --- a/Source/WebCore/platform/ScrollView.h +++ b/Source/WebCore/platform/ScrollView.h @@ -53,6 +53,10 @@ namespace WebCore { class HostWindow; class Scrollbar; +#if PLATFORM(ANDROID) +class FrameView; +#endif + class ScrollView : public Widget, public ScrollableArea { public: ~ScrollView(); @@ -168,10 +172,7 @@ public: virtual void setContentsSize(const IntSize&); #if PLATFORM(ANDROID) - int actualWidth() const; - int actualHeight() const; - int actualScrollX() const; - int actualScrollY() const; + FrameView* frameView(); #endif // Functions for querying the current scrolled position (both as a point, a size, or as individual X and Y values). @@ -400,13 +401,6 @@ private: void platformSetScrollOrigin(const IntPoint&, bool updatePositionAtAll, bool updatePositionSynchronously); -#if PLATFORM(ANDROID) - int platformActualWidth() const; - int platformActualHeight() const; - int platformActualScrollX() const; - int platformActualScrollY() const; -#endif - #if PLATFORM(MAC) && defined __OBJC__ public: NSView* documentView() const; diff --git a/Source/WebCore/platform/android/KeyEventAndroid.cpp b/Source/WebCore/platform/android/KeyEventAndroid.cpp index eaf34a9..dd1f37d 100644 --- a/Source/WebCore/platform/android/KeyEventAndroid.cpp +++ b/Source/WebCore/platform/android/KeyEventAndroid.cpp @@ -33,7 +33,7 @@ #include "NotImplemented.h" #include "WindowsKeyboardCodes.h" -#include <ui/KeycodeLabels.h> +#include <androidfw/KeycodeLabels.h> namespace WebCore { @@ -191,7 +191,7 @@ static String keyIdentifierForAndroidKeyCode(int keyCode) return "U+00007F"; default: char upper[16]; - sprintf(upper, "U+%06X", windowsKeyCodeForKeyEvent(keyCode)); + sprintf(upper, "U+%04X", windowsKeyCodeForKeyEvent(keyCode)); return String(upper); } } diff --git a/Source/WebCore/platform/android/PopupMenuAndroid.cpp b/Source/WebCore/platform/android/PopupMenuAndroid.cpp index f4c351f..a5758bb 100644 --- a/Source/WebCore/platform/android/PopupMenuAndroid.cpp +++ b/Source/WebCore/platform/android/PopupMenuAndroid.cpp @@ -25,10 +25,13 @@ #include "config.h" #include "PopupMenuAndroid.h" +#include "IntRect.h" #include "PopupMenuClient.h" #include "SkTDArray.h" #include "WebViewCore.h" +using namespace WebCore; + class PopupReply : public android::WebCoreReply { public: PopupReply(const IntRect& rect, android::WebViewCore* view, ListPopupMenuClient* client) diff --git a/Source/WebCore/platform/android/RenderThemeAndroid.cpp b/Source/WebCore/platform/android/RenderThemeAndroid.cpp index 93c99a4..ee406c2 100644 --- a/Source/WebCore/platform/android/RenderThemeAndroid.cpp +++ b/Source/WebCore/platform/android/RenderThemeAndroid.cpp @@ -38,10 +38,8 @@ #include "RenderMediaControls.h" #endif #include "RenderSkinAndroid.h" -#include "RenderSkinButton.h" -#include "RenderSkinCombo.h" #include "RenderSkinMediaButton.h" -#include "RenderSkinRadio.h" +#include "RoundedIntRect.h" #include "SkCanvas.h" #include "UserAgentStyleSheets.h" #include "WebCoreFrameBridge.h" @@ -63,6 +61,31 @@ const int listboxPadding = 5; const RGBA32 selectionColor = makeRGB(181, 224, 136); +// Colors copied from the holo resources +const RGBA32 defaultBgColor = makeRGBA(204, 204, 204, 197); +const RGBA32 defaultBgBright = makeRGBA(213, 213, 213, 221); +const RGBA32 defaultBgDark = makeRGBA(92, 92, 92, 160); +const RGBA32 defaultBgMedium = makeRGBA(132, 132, 132, 111); +const RGBA32 defaultFgColor = makeRGBA(101, 101, 101, 225); +const RGBA32 defaultCheckColor = makeRGBA(154, 204, 2, 255); + +const RGBA32 disabledBgColor = makeRGBA(205, 205, 205, 107); +const RGBA32 disabledBgBright = makeRGBA(213, 213, 213, 133); +const RGBA32 disabledBgDark = makeRGBA(92, 92, 92, 96); +const RGBA32 disabledBgMedium = makeRGBA(132, 132, 132, 111); +const RGBA32 disabledFgColor = makeRGBA(148, 148, 148, 137); + +const int paddingButton = 2; +const int cornerButton = 2; + +// scale factors for various resolutions +const float scaleFactor[RenderSkinAndroid::ResolutionCount] = { + 1.0f, // medium res + 1.5f, // high res + 2.0f // extra high res +}; + + static SkCanvas* getCanvasFromInfo(const PaintInfo& info) { return info.context->platformContext()->mCanvas; @@ -158,6 +181,16 @@ Color RenderThemeAndroid::platformInactiveListBoxSelectionForegroundColor() cons return Color(Color::transparent); } +Color RenderThemeAndroid::platformActiveTextSearchHighlightColor() const +{ + return Color(0x00, 0x99, 0xcc, 0x99); // HOLO_DARK +} + +Color RenderThemeAndroid::platformInactiveTextSearchHighlightColor() const +{ + return Color(0x33, 0xb5, 0xe5, 0x66); // HOLO_LIGHT +} + int RenderThemeAndroid::baselinePosition(const RenderObject* obj) const { // From the description of this function in RenderTheme.h: @@ -166,7 +199,7 @@ int RenderThemeAndroid::baselinePosition(const RenderObject* obj) const // controls that need to do this. // // Our checkboxes and radio buttons need to be offset to line up properly. - return RenderTheme::baselinePosition(obj) - 2; + return RenderTheme::baselinePosition(obj) - 8; } void RenderThemeAndroid::addIntrinsicMargins(RenderStyle* style) const @@ -174,10 +207,10 @@ void RenderThemeAndroid::addIntrinsicMargins(RenderStyle* style) const // Cut out the intrinsic margins completely if we end up using a small font size if (style->fontSize() < 11) return; - + // Intrinsic margin value. const int m = 2; - + // FIXME: Using width/height alone and not also dealing with min-width/max-width is flawed. if (style->width().isIntrinsicOrAuto()) { if (style->marginLeft().quirk()) @@ -210,22 +243,11 @@ bool RenderThemeAndroid::supportsFocus(ControlPart appearance) void RenderThemeAndroid::adjustButtonStyle(CSSStyleSelector*, RenderStyle* style, WebCore::Element*) const { - // Code is taken from RenderThemeSafari.cpp - // It makes sure we have enough space for the button text. - const int paddingHoriz = 12; - const int paddingVert = 8; - style->setPaddingLeft(Length(paddingHoriz, Fixed)); - style->setPaddingRight(Length(paddingHoriz, Fixed)); - style->setPaddingTop(Length(paddingVert, Fixed)); - style->setPaddingBottom(Length(paddingVert, Fixed)); - - // Set a min-height so that we can't get smaller than the mini button. - style->setMinHeight(Length(15, Fixed)); } bool RenderThemeAndroid::paintCheckbox(RenderObject* obj, const PaintInfo& info, const IntRect& rect) { - RenderSkinRadio::Draw(getCanvasFromInfo(info), obj->node(), rect, true); + paintRadio(obj, info, rect); return false; } @@ -237,16 +259,50 @@ bool RenderThemeAndroid::paintButton(RenderObject* obj, const PaintInfo& info, c if (formControlElement) { android::WebFrame* webFrame = getWebFrame(node); if (webFrame) { - RenderSkinAndroid* skins = webFrame->renderSkins(); - if (skins) { - RenderSkinAndroid::State state = RenderSkinAndroid::kNormal; - if (!formControlElement->isEnabledFormControl()) - state = RenderSkinAndroid::kDisabled; - skins->renderSkinButton()->draw(getCanvasFromInfo(info), rect, state); + GraphicsContext *context = info.context; + IntRect innerrect = IntRect(rect.x() + paddingButton, rect.y() + paddingButton, + rect.width() - 2 * paddingButton, rect.height() - 2 * paddingButton); + IntSize cornerrect = IntSize(cornerButton, cornerButton); + Color bg, bright, dark, medium; + if (formControlElement->isEnabledFormControl()) { + bg = Color(defaultBgColor); + bright = Color(defaultBgBright); + dark = Color(defaultBgDark); + medium = Color(defaultBgMedium); + } else { + bg = Color(disabledBgColor); + bright = Color(disabledBgBright); + dark = Color(disabledBgDark); + medium = Color(disabledBgMedium); } + context->save(); + context->clip( + IntRect(innerrect.x(), innerrect.y(), innerrect.width(), 1)); + context->fillRoundedRect(innerrect, cornerrect, cornerrect, + cornerrect, cornerrect, bright, context->fillColorSpace()); + context->restore(); + context->save(); + context->clip(IntRect(innerrect.x(), innerrect.y() + innerrect.height() - 1, + innerrect.width(), 1)); + context->fillRoundedRect(innerrect, cornerrect, cornerrect, + cornerrect, cornerrect, dark, context->fillColorSpace()); + context->restore(); + context->save(); + context->clip(IntRect(innerrect.x(), innerrect.y() + 1, innerrect.width(), + innerrect.height() - 2)); + context->fillRoundedRect(innerrect, cornerrect, cornerrect, + cornerrect, cornerrect, bg, context->fillColorSpace()); + context->restore(); + context->setStrokeColor(medium, context->strokeColorSpace()); + context->setStrokeThickness(1.0f); + context->drawLine(IntPoint(innerrect.x(), innerrect.y() + cornerButton), + IntPoint(innerrect.x(), innerrect.y() + innerrect.height() - cornerButton)); + context->drawLine(IntPoint(innerrect.x() + innerrect.width(), innerrect.y() + cornerButton), + IntPoint(innerrect.x() + innerrect.width(), innerrect.y() + innerrect.height() - cornerButton)); } } + // We always return false so we do not request to be redrawn. return false; } @@ -336,7 +392,9 @@ bool RenderThemeAndroid::paintMediaControlsBackground(RenderObject* o, const Pai bool translucent = false; if (o && toParentMediaElement(o) && toParentMediaElement(o)->hasTagName(HTMLNames::videoTag)) translucent = true; - RenderSkinMediaButton::Draw(getCanvasFromInfo(paintInfo), rect, RenderSkinMediaButton::BACKGROUND_SLIDER, translucent); + RenderSkinMediaButton::Draw(getCanvasFromInfo(paintInfo), rect, + RenderSkinMediaButton::BACKGROUND_SLIDER, + translucent, 0, false); return false; } @@ -355,7 +413,9 @@ bool RenderThemeAndroid::paintMediaSliderThumb(RenderObject* o, const PaintInfo& bool translucent = false; if (o && toParentMediaElement(o) && toParentMediaElement(o)->hasTagName(HTMLNames::videoTag)) translucent = true; - RenderSkinMediaButton::Draw(getCanvasFromInfo(paintInfo), rect, RenderSkinMediaButton::SLIDER_THUMB, translucent); + RenderSkinMediaButton::Draw(getCanvasFromInfo(paintInfo), rect, + RenderSkinMediaButton::SLIDER_THUMB, + translucent, 0, false); return false; } @@ -373,7 +433,49 @@ void RenderThemeAndroid::adjustSliderThumbSize(RenderObject* o) const bool RenderThemeAndroid::paintRadio(RenderObject* obj, const PaintInfo& info, const IntRect& rect) { - RenderSkinRadio::Draw(getCanvasFromInfo(info), obj->node(), rect, false); + Node* node = obj->node(); + Element* element = static_cast<Element*>(node); + if (element) { + InputElement* input = element->toInputElement(); + GraphicsContext* context = info.context; + if (!element->isEnabledFormControl()) { + context->setAlpha(0.5f); + } + const IntRect inner = IntRect(rect.x() - 2, rect.y() - 2, rect.width() - 4, rect.height() - 4); + context->setFillColor(Color(defaultBgBright), context->fillColorSpace()); + context->setStrokeColor(Color(defaultBgBright), context->strokeColorSpace()); + context->setStrokeThickness(1.0f); + if (input->isCheckbox()) { + context->drawRect(inner); + } else { + context->drawEllipse(inner); + } + context->setStrokeColor(Color(defaultFgColor), context->strokeColorSpace()); + if (input->isCheckbox()) { + context->drawRect(IntRect(inner.x() + 2, inner.y() + 2, inner.width() -4, inner.height() - 4)); + } else { + context->drawEllipse(IntRect(inner.x() + 2, inner.y() + 2, inner.width() -4, inner.height() - 4)); + } + if (input->isChecked()) { + context->setFillColor(Color(defaultCheckColor), context->fillColorSpace()); + context->setStrokeColor(Color(defaultCheckColor), context->strokeColorSpace()); + if (input->isCheckbox()) { + const float w2 = ((float) rect.width() / 2); + const float cx = ((float) rect.x()); + const float cy = ((float) rect.y()); + context->save(); + // magic numbers due to weird scale in context + context->translate(cx + w2 / 2.2f, cy + w2 / 1.2f); + context->rotate(3.93f); // 225 degrees + context->drawRect(IntRect(0, 0, rect.width() / 4, 2)); + context->rotate(1.57f); // 90 degrees + context->drawRect(IntRect(0, 0, rect.width() / 2, 2)); + context->restore(); + } else { + context->drawEllipse(IntRect(inner.x() + 5, inner.y() + 5, inner.width() - 10, inner.height() - 10)); + } + } + } return false; } @@ -396,7 +498,7 @@ void RenderThemeAndroid::adjustTextFieldStyle(CSSStyleSelector*, RenderStyle* st bool RenderThemeAndroid::paintTextField(RenderObject*, const PaintInfo&, const IntRect&) { - return true; + return true; } void RenderThemeAndroid::adjustTextAreaStyle(CSSStyleSelector*, RenderStyle* style, WebCore::Element*) const @@ -418,25 +520,29 @@ void RenderThemeAndroid::adjustSearchFieldStyle(CSSStyleSelector*, RenderStyle* bool RenderThemeAndroid::paintSearchField(RenderObject*, const PaintInfo&, const IntRect&) { - return true; + return true; } static void adjustMenuListStyleCommon(RenderStyle* style) { // Added to make room for our arrow and make the touch target less cramped. - style->setPaddingLeft(Length(RenderSkinCombo::padding(), Fixed)); - style->setPaddingTop(Length(RenderSkinCombo::padding(), Fixed)); - style->setPaddingBottom(Length(RenderSkinCombo::padding(), Fixed)); - style->setPaddingRight(Length(RenderSkinCombo::extraWidth(), Fixed)); - style->setMinHeight(Length(RenderSkinCombo::minHeight(), Fixed)); + const int padding = (int)(scaleFactor[RenderSkinAndroid::DrawableResolution()] + 0.5f); + style->setPaddingLeft(Length(padding,Fixed)); + style->setPaddingTop(Length(padding, Fixed)); + style->setPaddingBottom(Length(padding, Fixed)); + // allocate height as arrow size + int arrow = std::max(18, style->fontMetrics().height() + 2 * padding); + style->setPaddingRight(Length(arrow, Fixed)); + style->setMinHeight(Length(arrow, Fixed)); + style->setHeight(Length(arrow, Fixed)); } -void RenderThemeAndroid::adjustListboxStyle(CSSStyleSelector*, RenderStyle* style, Element*) const +void RenderThemeAndroid::adjustListboxStyle(CSSStyleSelector*, RenderStyle* style, Element* e) const { adjustMenuListButtonStyle(0, style, 0); } -void RenderThemeAndroid::adjustMenuListStyle(CSSStyleSelector*, RenderStyle* style, Element* e) const +void RenderThemeAndroid::adjustMenuListStyle(CSSStyleSelector*, RenderStyle* style, Element*) const { adjustMenuListStyleCommon(style); addIntrinsicMargins(style); @@ -446,11 +552,55 @@ bool RenderThemeAndroid::paintCombo(RenderObject* obj, const PaintInfo& info, c { if (obj->style() && !obj->style()->visitedDependentColor(CSSPropertyBackgroundColor).alpha()) return true; - return RenderSkinCombo::Draw(getCanvasFromInfo(info), obj->node(), rect.x(), rect.y(), rect.width(), rect.height()); + Node* node = obj->node(); + Element* element = static_cast<Element*>(node); + if (element) { + InputElement* input = element->toInputElement(); + GraphicsContext* context = info.context; + if (!element->isEnabledFormControl()) { + context->setAlpha(0.5f); + } + IntRect bounds = IntRect(rect.x(), rect.y(), rect.width(), rect.height()); + // paint bg color + RenderStyle* style = obj->style(); + context->setFillColor(style->visitedDependentColor(CSSPropertyBackgroundColor), + context->fillColorSpace()); + context->fillRect(FloatRect(bounds)); + // copied form the original RenderSkinCombo: + // If this is an appearance where RenderTheme::paint returns true + // without doing anything, this means that + // RenderBox::PaintBoxDecorationWithSize will end up painting the + // border, so we shouldn't paint a border here. + if (style->appearance() != MenulistButtonPart && + style->appearance() != ListboxPart && + style->appearance() != TextFieldPart && + style->appearance() != TextAreaPart) { + const int arrowSize = bounds.height(); + // dropdown button bg + context->setFillColor(Color(defaultBgColor), context->fillColorSpace()); + context->fillRect(FloatRect(bounds.maxX() - arrowSize + 0.5f, bounds.y() + .5f, + arrowSize - 1, bounds.height() - 1)); + // outline + context->setStrokeThickness(1.0f); + context->setStrokeColor(Color(defaultBgDark), context->strokeColorSpace()); + context->strokeRect(bounds, 1.0f); + // arrow + context->setFillColor(Color(defaultFgColor), context->fillColorSpace()); + Path tri = Path(); + tri.clear(); + const float aw = arrowSize - 10; + FloatPoint br = FloatPoint(bounds.maxX() - 4, bounds.maxY() - 4); + tri.moveTo(br); + tri.addLineTo(FloatPoint(br.x() - aw, br.y())); + tri.addLineTo(FloatPoint(br.x(), br.y() - aw)); + context->fillPath(tri); + } + } + return false; } -bool RenderThemeAndroid::paintMenuList(RenderObject* obj, const PaintInfo& info, const IntRect& rect) -{ +bool RenderThemeAndroid::paintMenuList(RenderObject* obj, const PaintInfo& info, const IntRect& rect) +{ return paintCombo(obj, info, rect); } @@ -461,13 +611,13 @@ void RenderThemeAndroid::adjustMenuListButtonStyle(CSSStyleSelector*, const float baseFontSize = 11.0f; const int baseBorderRadius = 5; float fontScale = style->fontSize() / baseFontSize; - + style->resetPadding(); style->setBorderRadius(IntSize(int(baseBorderRadius + fontScale - 1), int(baseBorderRadius + fontScale - 1))); // FIXME: Round up? const int minHeight = 15; style->setMinHeight(Length(minHeight, Fixed)); - + style->setLineHeight(RenderStyle::initialLineHeight()); // Found these padding numbers by trial and error. const int padding = 4; @@ -476,26 +626,23 @@ void RenderThemeAndroid::adjustMenuListButtonStyle(CSSStyleSelector*, adjustMenuListStyleCommon(style); } -bool RenderThemeAndroid::paintMenuListButton(RenderObject* obj, const PaintInfo& info, const IntRect& rect) +bool RenderThemeAndroid::paintMenuListButton(RenderObject* obj, const PaintInfo& info, const IntRect& rect) { return paintCombo(obj, info, rect); } +Color RenderThemeAndroid::platformFocusRingColor() const +{ + static Color focusRingColor(0x33, 0xB5, 0xE5, 0x66); + return focusRingColor; +} + bool RenderThemeAndroid::supportsFocusRing(const RenderStyle* style) const { - return style->opacity() > 0 - && style->hasAppearance() - && style->appearance() != TextFieldPart - && style->appearance() != SearchFieldPart - && style->appearance() != TextAreaPart - && style->appearance() != CheckboxPart - && style->appearance() != RadioPart - && style->appearance() != PushButtonPart - && style->appearance() != SquareButtonPart - && style->appearance() != ButtonPart - && style->appearance() != ButtonBevelPart - && style->appearance() != MenulistPart - && style->appearance() != MenulistButtonPart; + // Draw the focus ring ourselves unless it is a text area (webkit does borders better) + if (!style || !style->hasAppearance()) + return true; + return style->appearance() != TextFieldPart && style->appearance() != TextAreaPart; } } // namespace WebCore diff --git a/Source/WebCore/platform/android/RenderThemeAndroid.h b/Source/WebCore/platform/android/RenderThemeAndroid.h index e3922a1..ed4d07f 100644 --- a/Source/WebCore/platform/android/RenderThemeAndroid.h +++ b/Source/WebCore/platform/android/RenderThemeAndroid.h @@ -31,10 +31,6 @@ namespace WebCore { -class RenderSkinButton; -class RenderSkinRadio; -class RenderSkinCombo; - struct ThemeData { ThemeData() : m_part(0) @@ -52,7 +48,7 @@ public: ~RenderThemeAndroid(); virtual bool stateChanged(RenderObject*, ControlState) const; - + virtual bool supportsFocusRing(const RenderStyle*) const; // A method asking if the theme's controls actually care about redrawing when hovered. virtual bool supportsHover(const RenderStyle* style) const { return style->affectedByHoverRules(); } @@ -64,12 +60,16 @@ public: virtual Color platformActiveSelectionForegroundColor() const; virtual Color platformInactiveSelectionForegroundColor() const; virtual Color platformTextSearchHighlightColor() const; + virtual Color platformFocusRingColor() const; virtual Color platformActiveListBoxSelectionBackgroundColor() const; virtual Color platformInactiveListBoxSelectionBackgroundColor() const; virtual Color platformActiveListBoxSelectionForegroundColor() const; virtual Color platformInactiveListBoxSelectionForegroundColor() const; + virtual Color platformActiveTextSearchHighlightColor() const; + virtual Color platformInactiveTextSearchHighlightColor() const; + virtual void systemFont(int, WebCore::FontDescription&) const {} virtual int minimumMenuListSize(RenderStyle*) const { return 0; } diff --git a/Source/WebCore/platform/android/ScrollViewAndroid.cpp b/Source/WebCore/platform/android/ScrollViewAndroid.cpp index f29e998..ecaa2b5 100644 --- a/Source/WebCore/platform/android/ScrollViewAndroid.cpp +++ b/Source/WebCore/platform/android/ScrollViewAndroid.cpp @@ -68,38 +68,8 @@ IntSize ScrollView::platformContentsSize() const return m_contentsSize; } -int ScrollView::platformActualWidth() const -{ - if (parent()) - return width(); - return platformWidget()->visibleWidth(); -} - -int ScrollView::platformActualHeight() const -{ - if (parent()) - return height(); - return platformWidget()->visibleHeight(); -} - -int ScrollView::platformActualScrollX() const -{ - if (parent()) - return scrollX(); - return platformWidget()->visibleX(); -} - -int ScrollView::platformActualScrollY() const -{ - if (parent()) - return scrollY(); - return platformWidget()->visibleY(); -} - void ScrollView::platformSetScrollPosition(const WebCore::IntPoint& pt) { - if (parent()) // don't attempt to scroll subframes; they're fully visible - return; PlatformBridge::setScrollPosition(this, m_scrollOrigin.x() + pt.x(), m_scrollOrigin.y() + pt.y()); } diff --git a/Source/WebCore/platform/android/SharedTimerAndroid.cpp b/Source/WebCore/platform/android/SharedTimerAndroid.cpp index e4f3b36..a3f3db5 100644 --- a/Source/WebCore/platform/android/SharedTimerAndroid.cpp +++ b/Source/WebCore/platform/android/SharedTimerAndroid.cpp @@ -51,7 +51,7 @@ void setSharedTimerFireTime(double fireTime) { long long timeInMs = static_cast<long long>((fireTime - WTF::currentTime()) * 1000); - LOGV("setSharedTimerFireTime: in %ld millisec", timeInMs); + ALOGV("setSharedTimerFireTime: in %ld millisec", timeInMs); if (JavaSharedClient::GetTimerClient()) JavaSharedClient::GetTimerClient()->setSharedTimer(timeInMs); } diff --git a/Source/WebCore/platform/android/TemporaryLinkStubs.cpp b/Source/WebCore/platform/android/TemporaryLinkStubs.cpp index ca9f24d..7df3e8c 100644 --- a/Source/WebCore/platform/android/TemporaryLinkStubs.cpp +++ b/Source/WebCore/platform/android/TemporaryLinkStubs.cpp @@ -80,13 +80,6 @@ #include <wtf/MainThread.h> #include <wtf/text/CString.h> -#if USE(JSC) -#include "API/JSClassRef.h" -#include "JNIUtilityPrivate.h" -#include "JavaScriptCallFrame.h" -#include "ScriptDebugServer.h" -#endif - using namespace WebCore; /********************************************************/ @@ -394,18 +387,6 @@ PassRefPtr<SharedBuffer> SharedBuffer::createWithContentsOfFile(const String&) } -#if USE(JSC) -namespace JSC { namespace Bindings { -bool dispatchJNICall(ExecState*, const void* targetAppletView, jobject obj, bool isStatic, JavaType returnType, - jmethodID methodID, jvalue* args, jvalue& result, const char* callingURL, JSValue& exceptionDescription) -{ - notImplemented(); - return false; -} - -} } // namespace Bindings -#endif - char* dirname(const char*) { notImplemented(); diff --git a/Source/WebCore/platform/android/WidgetAndroid.cpp b/Source/WebCore/platform/android/WidgetAndroid.cpp index 10326f9..0f7758d 100644 --- a/Source/WebCore/platform/android/WidgetAndroid.cpp +++ b/Source/WebCore/platform/android/WidgetAndroid.cpp @@ -49,9 +49,7 @@ Widget::~Widget() IntRect Widget::frameRect() const { - if (!platformWidget()) - return m_frame; - return platformWidget()->getBounds(); + return m_frame; } void Widget::setFocus(bool focused) @@ -95,11 +93,6 @@ void Widget::hide() void Widget::setFrameRect(const IntRect& rect) { m_frame = rect; - // platformWidget() is 0 when called from Scrollbar - if (!platformWidget()) - return; - platformWidget()->setLocation(rect.x(), rect.y()); - platformWidget()->setSize(rect.width(), rect.height()); } void Widget::setIsSelected(bool isSelected) diff --git a/Source/WebCore/platform/graphics/Color.h b/Source/WebCore/platform/graphics/Color.h index 02ec005..0fb355b 100644 --- a/Source/WebCore/platform/graphics/Color.h +++ b/Source/WebCore/platform/graphics/Color.h @@ -162,15 +162,8 @@ public: static const RGBA32 lightGray = 0xFFC0C0C0; static const RGBA32 transparent = 0x00000000; -#ifdef ANDROID_CSS_RING - static const RGBA32 ringFill = 0x666699FF; - static const RGBA32 ringPressedInner = 0x006699FF; - static const RGBA32 ringPressedOuter = 0x336699FF; - static const RGBA32 ringSelectedInner = 0xAA6699FF; - static const RGBA32 ringSelectedOuter = 0x336699FF; -#endif #ifdef ANDROID_CSS_TAP_HIGHLIGHT_COLOR - static const RGBA32 tap = 0x4D1A1A1A; + static const RGBA32 tap = 0x6633B5E5; #endif private: diff --git a/Source/WebCore/platform/graphics/GraphicsContext.cpp b/Source/WebCore/platform/graphics/GraphicsContext.cpp index 65cc6df..e032714 100644 --- a/Source/WebCore/platform/graphics/GraphicsContext.cpp +++ b/Source/WebCore/platform/graphics/GraphicsContext.cpp @@ -432,6 +432,7 @@ void GraphicsContext::drawBidiText(const Font& font, const TextRun& run, const F bidiRuns.deleteRuns(); } +#if !PLATFORM(ANDROID) void GraphicsContext::drawHighlightForText(const Font& font, const TextRun& run, const FloatPoint& point, int h, const Color& backgroundColor, ColorSpace colorSpace, int from, int to) { if (paintingDisabled()) @@ -439,6 +440,7 @@ void GraphicsContext::drawHighlightForText(const Font& font, const TextRun& run, fillRect(font.selectionRectForText(run, point, h, from, to), backgroundColor, colorSpace); } +#endif void GraphicsContext::drawImage(Image* image, ColorSpace styleColorSpace, const FloatRect& dest, const FloatRect& src, CompositeOperator op, bool useLowQualityScale) { diff --git a/Source/WebCore/platform/graphics/GraphicsContext.h b/Source/WebCore/platform/graphics/GraphicsContext.h index 2b41c2e..ed43cf0 100644 --- a/Source/WebCore/platform/graphics/GraphicsContext.h +++ b/Source/WebCore/platform/graphics/GraphicsContext.h @@ -382,7 +382,11 @@ namespace WebCore { void drawText(const Font&, const TextRun&, const FloatPoint&, int from = 0, int to = -1); void drawEmphasisMarks(const Font&, const TextRun& , const AtomicString& mark, const FloatPoint&, int from = 0, int to = -1); void drawBidiText(const Font&, const TextRun&, const FloatPoint&); +#if PLATFORM(ANDROID) + void drawHighlightForText(const Font&, const TextRun&, const FloatPoint&, int h, const Color& backgroundColor, ColorSpace, int from = 0, int to = -1, bool isActive = true); +#else void drawHighlightForText(const Font&, const TextRun&, const FloatPoint&, int h, const Color& backgroundColor, ColorSpace, int from = 0, int to = -1); +#endif enum RoundingMode { RoundAllSides, diff --git a/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp index 9c7716c..c9a8b9a 100644 --- a/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp @@ -29,6 +29,7 @@ #if USE(ACCELERATED_COMPOSITING) #include "ClassTracker.h" #include "GLUtils.h" +#include "LayerGroup.h" #include "ShaderProgram.h" #include "SkCanvas.h" #include "TilesManager.h" @@ -67,6 +68,7 @@ using namespace android; BaseLayerAndroid::BaseLayerAndroid() #if USE(ACCELERATED_COMPOSITING) : m_color(Color::white) + , m_content(0) , m_scrollState(NotScrolling) #endif { @@ -77,23 +79,17 @@ BaseLayerAndroid::BaseLayerAndroid() BaseLayerAndroid::~BaseLayerAndroid() { - m_content.clear(); + SkSafeUnref(m_content); #ifdef DEBUG_COUNT ClassTracker::instance()->decrement("BaseLayerAndroid"); #endif } -void BaseLayerAndroid::setContent(const PictureSet& src) +void BaseLayerAndroid::setContent(LayerContent* content) { -#if USE(ACCELERATED_COMPOSITING) - // FIXME: We lock here because we do not want - // to paint and change the m_content concurrently. - // We should instead refactor PictureSet to use - // an atomic refcounting scheme and use atomic operations - // to swap PictureSets. - android::Mutex::Autolock lock(m_drawLock); -#endif - m_content.set(src); + SkSafeRef(content); + SkSafeUnref(m_content); + m_content = content; // FIXME: We cannot set the size of the base layer because it will screw up // the matrix used. We need to fix matrix computation for the base layer // and then we can set the size. @@ -102,17 +98,15 @@ void BaseLayerAndroid::setContent(const PictureSet& src) bool BaseLayerAndroid::drawCanvas(SkCanvas* canvas) { -#if USE(ACCELERATED_COMPOSITING) android::Mutex::Autolock lock(m_drawLock); -#endif - if (!m_content.isEmpty()) - m_content.draw(canvas); + if (m_content && !m_content->isEmpty()) + m_content->draw(canvas); return true; } #if USE(ACCELERATED_COMPOSITING) -void BaseLayerAndroid::prefetchBasePicture(SkRect& viewport, float currentScale, +void BaseLayerAndroid::prefetchBasePicture(const SkRect& viewport, float currentScale, TiledPage* prefetchTiledPage, bool draw) { SkIRect bounds; @@ -131,7 +125,7 @@ void BaseLayerAndroid::prefetchBasePicture(SkRect& viewport, float currentScale, viewport.fTop, viewport.fRight, viewport.fBottom, - scale); + currentScale); bounds.fLeft = static_cast<int>(floorf(viewport.fLeft * invTileWidth)) - PREFETCH_X_DIST; bounds.fTop = static_cast<int>(floorf(viewport.fTop * invTileHeight)) - PREFETCH_Y_DIST; @@ -141,11 +135,11 @@ void BaseLayerAndroid::prefetchBasePicture(SkRect& viewport, float currentScale, XLOG("prefetch rect %d %d %d %d, scale %f, preparing page %p", bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom, - scale * PREFETCH_SCALE, + prefetchScale, prefetchTiledPage); prefetchTiledPage->setScale(prefetchScale); - prefetchTiledPage->updateTileDirtiness(bounds); + prefetchTiledPage->updateTileDirtiness(); prefetchTiledPage->prepare(goingDown, goingLeft, bounds, TiledPage::ExpandedBounds); prefetchTiledPage->swapBuffersIfReady(bounds, @@ -167,20 +161,11 @@ bool BaseLayerAndroid::isReady() return false; } - LayerAndroid* compositedRoot = static_cast<LayerAndroid*>(getChild(0)); - if (compositedRoot) { - XLOG("base layer is ready, how about children?"); - return compositedRoot->isReady(); - } - return true; } void BaseLayerAndroid::swapTiles() { - if (countChildren()) - getChild(0)->swapTiles(); // TODO: move to parent impl - m_state->frontPage()->swapBuffersIfReady(m_state->preZoomBounds(), m_state->zoomManager()->currentScale()); @@ -188,37 +173,22 @@ void BaseLayerAndroid::swapTiles() m_state->zoomManager()->currentScale()); } -void BaseLayerAndroid::setIsDrawing(bool isDrawing) -{ - if (countChildren()) - getChild(0)->setIsDrawing(isDrawing); // TODO: move to parent impl -} - -void BaseLayerAndroid::setIsPainting(Layer* drawingTree) +void BaseLayerAndroid::setIsPainting() { - XLOG("BLA %p painting, dirty %d", this, isDirty()); - if (drawingTree) - drawingTree = drawingTree->getChild(0); - - if (countChildren()) - getChild(0)->setIsPainting(drawingTree); // TODO: move to parent impl - + XLOG("BLA %p setIsPainting, dirty %d", this, isDirty()); m_state->invalRegion(m_dirtyRegion); m_dirtyRegion.setEmpty(); } -void BaseLayerAndroid::mergeInvalsInto(Layer* replacementTree) +void BaseLayerAndroid::mergeInvalsInto(BaseLayerAndroid* replacementLayer) { - XLOG("merging invals (empty=%d) from BLA %p to %p", m_dirtyRegion.isEmpty(), this, replacementTree); - if (countChildren() && replacementTree->countChildren()) - getChild(0)->mergeInvalsInto(replacementTree->getChild(0)); - - replacementTree->markAsDirty(m_dirtyRegion); + replacementLayer->markAsDirty(m_dirtyRegion); } -bool BaseLayerAndroid::prepareBasePictureInGL(SkRect& viewport, float scale, - double currentTime) +void BaseLayerAndroid::prepareGL(const SkRect& viewport, float scale, double currentTime) { + XLOG("prepareGL BLA %p, m_state %p", this, m_state); + ZoomManager* zoomManager = m_state->zoomManager(); bool goingDown = m_state->goingDown(); @@ -241,8 +211,7 @@ bool BaseLayerAndroid::prepareBasePictureInGL(SkRect& viewport, float scale, nextTiledPage->setScale(scale); m_state->setFutureViewport(viewportTileBounds); - // ignore dirtiness return value since while zooming we repaint regardless - nextTiledPage->updateTileDirtiness(viewportTileBounds); + nextTiledPage->updateTileDirtiness(); nextTiledPage->prepare(goingDown, goingLeft, viewportTileBounds, TiledPage::VisibleBounds); @@ -279,10 +248,7 @@ bool BaseLayerAndroid::prepareBasePictureInGL(SkRect& viewport, float scale, m_state->swapPages(); } - bool needsRedraw = zooming; - - // if applied invals mark tiles dirty, need to redraw - needsRedraw |= tiledPage->updateTileDirtiness(preZoomBounds); + tiledPage->updateTileDirtiness(); // paint what's needed unless we're zooming, since the new tiles won't // be relevant soon anyway @@ -290,8 +256,7 @@ bool BaseLayerAndroid::prepareBasePictureInGL(SkRect& viewport, float scale, tiledPage->prepare(goingDown, goingLeft, preZoomBounds, TiledPage::ExpandedBounds); - XLOG("scrolling %d, zooming %d, needsRedraw %d", - scrolling, zooming, needsRedraw); + XLOG("scrollState %d, zooming %d", m_scrollState, zooming); // prefetch in the nextTiledPage if unused by zooming (even if not scrolling // since we want the tiles to be ready before they're needed) @@ -305,8 +270,6 @@ bool BaseLayerAndroid::prepareBasePictureInGL(SkRect& viewport, float scale, } tiledPage->prepareForDrawGL(transparency, preZoomBounds); - - return needsRedraw; } void BaseLayerAndroid::drawBasePictureInGL() @@ -315,13 +278,13 @@ void BaseLayerAndroid::drawBasePictureInGL() m_state->frontPage()->drawGL(); } -#endif // USE(ACCELERATED_COMPOSITING) - -void BaseLayerAndroid::updateLayerPositions(SkRect& visibleRect) +void BaseLayerAndroid::updateLayerPositions(const SkRect& visibleRect) { LayerAndroid* compositedRoot = static_cast<LayerAndroid*>(getChild(0)); + if (!compositedRoot) + return; TransformationMatrix ident; - compositedRoot->updateFixedLayersPositions(visibleRect); + compositedRoot->updateLayerPositions(visibleRect); FloatRect clip(0, 0, content()->width(), content()->height()); compositedRoot->updateGLPositionsAndScale( ident, clip, 1, m_state->zoomManager()->layersScale()); @@ -334,57 +297,16 @@ void BaseLayerAndroid::updateLayerPositions(SkRect& visibleRect) #endif } -bool BaseLayerAndroid::prepare(double currentTime, IntRect& viewRect, - SkRect& visibleRect, float scale) -{ - XLOG("preparing BLA %p", this); - - // base layer is simply drawn in prepare, since there is always a base layer it doesn't matter - bool needsRedraw = prepareBasePictureInGL(visibleRect, scale, currentTime); - - LayerAndroid* compositedRoot = static_cast<LayerAndroid*>(getChild(0)); - if (compositedRoot) { - updateLayerPositions(visibleRect); - - XLOG("preparing BLA %p, root %p", this, compositedRoot); - compositedRoot->prepare(); - } - - return needsRedraw; -} +#endif // USE(ACCELERATED_COMPOSITING) -bool BaseLayerAndroid::drawGL(IntRect& viewRect, SkRect& visibleRect, - float scale) +void BaseLayerAndroid::drawGL(float scale) { - XLOG("drawing BLA %p", this); + XLOG("drawGL BLA %p", this); // TODO: consider moving drawBackground outside of prepare (into tree manager) m_state->drawBackground(m_color); drawBasePictureInGL(); - - bool needsRedraw = false; - -#if USE(ACCELERATED_COMPOSITING) - - LayerAndroid* compositedRoot = static_cast<LayerAndroid*>(getChild(0)); - if (compositedRoot) { - updateLayerPositions(visibleRect); - // For now, we render layers only if the rendering mode - // is kAllTextures or kClippedTextures - if (compositedRoot->drawGL()) { - if (TilesManager::instance()->layerTexturesRemain()) { - // only try redrawing for layers if layer textures remain, - // otherwise we'll repaint without getting anything done - needsRedraw = true; - } - } - } - -#endif // USE(ACCELERATED_COMPOSITING) -#ifdef DEBUG - ClassTracker::instance()->show(); -#endif - return needsRedraw; + m_state->glExtras()->drawGL(0); } } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/BaseLayerAndroid.h b/Source/WebCore/platform/graphics/android/BaseLayerAndroid.h index f0c2766..5560f58 100644 --- a/Source/WebCore/platform/graphics/android/BaseLayerAndroid.h +++ b/Source/WebCore/platform/graphics/android/BaseLayerAndroid.h @@ -29,14 +29,14 @@ #include <utils/threads.h> #include "Color.h" -#include "GLWebViewState.h" -#include "IntRect.h" #include "Layer.h" #include "PictureSet.h" -#include "SkPicture.h" +#include "LayerContent.h" namespace WebCore { +class TiledPage; + class BaseLayerAndroid : public Layer { public: @@ -53,37 +53,36 @@ public: void setBackgroundColor(Color& color) { m_color = color; } Color getBackgroundColor() { return m_color; } #endif - void setContent(const android::PictureSet& src); - android::PictureSet* content() { return &m_content; } + void setContent(LayerContent* content); + LayerContent* content() { return m_content; } + // This method will paint using the current PictureSet onto // the passed canvas. We used it to paint the GL tiles as well as // WebView::copyBaseContentToPicture(), so a lock is necessary as // we are running in different threads. virtual bool drawCanvas(SkCanvas* canvas); - void updateLayerPositions(SkRect& visibleRect); - bool prepare(double currentTime, IntRect& viewRect, - SkRect& visibleRect, float scale); - bool drawGL(IntRect& viewRect, SkRect& visibleRect, float scale); + void updateLayerPositions(const SkRect& visibleRect); + void prepareGL(const SkRect& visibleRect, float scale, double currentTime); + void drawGL(float scale); // rendering asset management void swapTiles(); void setIsDrawing(bool isDrawing); - void setIsPainting(Layer* drawingTree); - void mergeInvalsInto(Layer* replacementTree); + void setIsPainting(); + void mergeInvalsInto(BaseLayerAndroid* replacementLayer); bool isReady(); private: #if USE(ACCELERATED_COMPOSITING) - void prefetchBasePicture(SkRect& viewport, float currentScale, + void prefetchBasePicture(const SkRect& viewport, float currentScale, TiledPage* prefetchTiledPage, bool draw); - bool prepareBasePictureInGL(SkRect& viewport, float scale, double currentTime); void drawBasePictureInGL(); android::Mutex m_drawLock; Color m_color; #endif - android::PictureSet m_content; + LayerContent* m_content; ScrollState m_scrollState; }; diff --git a/Source/WebCore/platform/graphics/android/BaseRenderer.cpp b/Source/WebCore/platform/graphics/android/BaseRenderer.cpp index 57baee8..832ed0c 100644 --- a/Source/WebCore/platform/graphics/android/BaseRenderer.cpp +++ b/Source/WebCore/platform/graphics/android/BaseRenderer.cpp @@ -41,11 +41,14 @@ #include <wtf/text/CString.h> -#ifdef DEBUG - #include <cutils/log.h> #include <wtf/CurrentTime.h> +#undef XLOGC +#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "BaseRenderer", __VA_ARGS__) + +#ifdef DEBUG + #undef XLOG #define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "BaseRenderer", __VA_ARGS__) @@ -56,6 +59,9 @@ #endif // DEBUG +#define UPDATE_COUNT_MASK 0xFF // displayed count wraps at 256 +#define UPDATE_COUNT_ALPHA_MASK 0x3F // alpha wraps at 64 + namespace WebCore { BaseRenderer::RendererType BaseRenderer::g_currentType = BaseRenderer::Raster; @@ -79,12 +85,12 @@ void BaseRenderer::swapRendererIfNeeded(BaseRenderer*& renderer) } void BaseRenderer::drawTileInfo(SkCanvas* canvas, - const TileRenderInfo& renderInfo, int pictureCount) + const TileRenderInfo& renderInfo, int updateCount) { SkPaint paint; char str[256]; snprintf(str, 256, "(%d,%d) %.2f, tl%x p%x c%d", renderInfo.x, renderInfo.y, - renderInfo.scale, this, renderInfo.tilePainter, pictureCount); + renderInfo.scale, this, renderInfo.tilePainter, updateCount); paint.setARGB(255, 0, 0, 0); canvas->drawText(str, strlen(str), 0, 10, paint); paint.setARGB(255, 255, 0, 0); @@ -112,7 +118,7 @@ void BaseRenderer::drawTileInfo(SkCanvas* canvas, canvas->drawText(str, strlen(str), 0, textY + 1, paint); } -int BaseRenderer::renderTiledContent(const TileRenderInfo& renderInfo) +void BaseRenderer::renderTiledContent(const TileRenderInfo& renderInfo) { const bool visualIndicator = TilesManager::instance()->getShowVisualIndicator(); const SkSize& tileSize = renderInfo.tileSize; @@ -122,7 +128,7 @@ int BaseRenderer::renderTiledContent(const TileRenderInfo& renderInfo) if (!canvas.getDevice()) { XLOG("Error: No Device"); - return 0; + return; } if (visualIndicator) @@ -131,17 +137,23 @@ int BaseRenderer::renderTiledContent(const TileRenderInfo& renderInfo) setupPartialInval(renderInfo, &canvas); canvas.translate(-renderInfo.x * tileSize.width(), -renderInfo.y * tileSize.height()); canvas.scale(renderInfo.scale, renderInfo.scale); - unsigned int pictureCount = 0; - renderInfo.tilePainter->paint(renderInfo.baseTile, &canvas, &pictureCount); + renderInfo.tilePainter->paint(renderInfo.baseTile, &canvas); if (visualIndicator) { canvas.restore(); - const int color = 20 + (pictureCount % 100); + unsigned int updateCount = renderInfo.tilePainter->getUpdateCount() & UPDATE_COUNT_MASK; + const int color = updateCount & UPDATE_COUNT_ALPHA_MASK; // only color the invalidated area SkPaint invalPaint; invalPaint.setARGB(color, 0, 255, 0); - canvas.drawIRect(*renderInfo.invalRect, invalPaint); + if (renderInfo.invalRect) + canvas.drawIRect(*renderInfo.invalRect, invalPaint); + else { + SkIRect rect; + rect.set(0, 0, tileSize.width(), tileSize.height()); + canvas.drawIRect(rect, invalPaint); + } // paint the tile boundaries SkPaint paint; @@ -154,12 +166,22 @@ int BaseRenderer::renderTiledContent(const TileRenderInfo& renderInfo) canvas.drawLine(0, 0, tileSize.width(), 0, paint); canvas.drawLine(tileSize.width(), 0, tileSize.width(), tileSize.height(), paint); + if (renderInfo.invalRect) { + // if partial inval... + int x = renderInfo.invalRect->fLeft; + int y = renderInfo.invalRect->fTop; + int w = renderInfo.invalRect->width(); + int h = renderInfo.invalRect->height(); + + paint.setARGB(128, 255, 255, 0); + canvas.drawLine(x, y, x + w, y + h, paint); + canvas.drawLine(x, y + h, x + w, y, paint); + } + if (renderInfo.measurePerf) - drawTileInfo(&canvas, renderInfo, pictureCount); + drawTileInfo(&canvas, renderInfo, updateCount); } - renderInfo.textureInfo->m_pictureCount = pictureCount; renderingComplete(renderInfo, &canvas); - return pictureCount; } } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/BaseRenderer.h b/Source/WebCore/platform/graphics/android/BaseRenderer.h index 7780db1..2defcc3 100644 --- a/Source/WebCore/platform/graphics/android/BaseRenderer.h +++ b/Source/WebCore/platform/graphics/android/BaseRenderer.h @@ -76,7 +76,7 @@ public: BaseRenderer(RendererType type) : m_type(type) {} virtual ~BaseRenderer() {} - int renderTiledContent(const TileRenderInfo& renderInfo); + void renderTiledContent(const TileRenderInfo& renderInfo); RendererType getType() { return m_type; } @@ -92,7 +92,7 @@ protected: virtual void renderingComplete(const TileRenderInfo& renderInfo, SkCanvas* canvas) = 0; void drawTileInfo(SkCanvas* canvas, const TileRenderInfo& renderInfo, - int pictureCount); + int updateCount); virtual const String* getPerformanceTags(int& tagCount) = 0; diff --git a/Source/WebCore/platform/graphics/android/BaseTile.cpp b/Source/WebCore/platform/graphics/android/BaseTile.cpp index 27bd482..de64425 100644 --- a/Source/WebCore/platform/graphics/android/BaseTile.cpp +++ b/Source/WebCore/platform/graphics/android/BaseTile.cpp @@ -54,6 +54,13 @@ #endif // DEBUG +// If the dirty portion of a tile exceeds this ratio, fully repaint. +// Lower values give fewer partial repaints, thus fewer front-to-back +// texture copies (cost will vary by device). It's a tradeoff between +// the rasterization cost and the FBO texture recopy cost when using +// GPU for the transfer queue. +#define MAX_INVAL_AREA 0.6 + namespace WebCore { BaseTile::BaseTile(bool isLayerTile) @@ -67,7 +74,7 @@ BaseTile::BaseTile(bool isLayerTile) , m_scale(1) , m_dirty(true) , m_repaintPending(false) - , m_lastDirtyPicture(0) + , m_fullRepaint(true) , m_isTexturePainted(false) , m_isLayerTile(isLayerTile) , m_drawCount(0) @@ -76,20 +83,6 @@ BaseTile::BaseTile(bool isLayerTile) #ifdef DEBUG_COUNT ClassTracker::instance()->increment("BaseTile"); #endif - m_currentDirtyAreaIndex = 0; - - // For EglImage Mode, the internal buffer should be 2. - // For Surface Texture mode, we only need one. - if (TilesManager::instance()->getSharedTextureMode() == EglImageMode) - m_maxBufferNumber = 2; - else - m_maxBufferNumber = 1; - - m_dirtyArea = new SkRegion[m_maxBufferNumber]; - m_fullRepaint = new bool[m_maxBufferNumber]; - for (int i = 0; i < m_maxBufferNumber; i++) - m_fullRepaint[i] = true; - m_renderer = BaseRenderer::createRenderer(); } @@ -101,8 +94,6 @@ BaseTile::~BaseTile() m_frontTexture->release(this); delete m_renderer; - delete[] m_dirtyArea; - delete[] m_fullRepaint; #ifdef DEBUG_COUNT ClassTracker::instance()->decrement("BaseTile"); @@ -113,7 +104,8 @@ BaseTile::~BaseTile() void BaseTile::setContents(TilePainter* painter, int x, int y, float scale) { - if ((m_painter != painter) + // TODO: investigate whether below check/discard is necessary + if (!painter || (m_x != x) || (m_y != y) || (m_scale != scale)) { @@ -174,15 +166,12 @@ bool BaseTile::removeTexture(BaseTileTexture* texture) return true; } -void BaseTile::markAsDirty(int unsigned pictureCount, - const SkRegion& dirtyArea) +void BaseTile::markAsDirty(const SkRegion& dirtyArea) { if (dirtyArea.isEmpty()) return; android::AutoMutex lock(m_atomicSync); - m_lastDirtyPicture = pictureCount; - for (int i = 0; i < m_maxBufferNumber; i++) - m_dirtyArea[i].op(dirtyArea, SkRegion::kUnion_Op); + m_dirtyArea.op(dirtyArea, SkRegion::kUnion_Op); // Check if we actually intersect with the area bool intersect = false; @@ -244,7 +233,8 @@ void BaseTile::setRepaintPending(bool pending) m_repaintPending = pending; } -void BaseTile::draw(float transparency, SkRect& rect, float scale) +void BaseTile::drawGL(float opacity, const SkRect& rect, float scale, + const TransformationMatrix* transform) { if (m_x < 0 || m_y < 0 || m_scale != scale) return; @@ -262,25 +252,7 @@ void BaseTile::draw(float transparency, SkRect& rect, float scale) if (!isTexturePainted) return; - TextureInfo* textureInfo = m_frontTexture->consumerLock(); - if (!textureInfo) { - m_frontTexture->consumerRelease(); - return; - } - - if (m_frontTexture->readyFor(this)) { - if (isLayerTile() && m_painter && m_painter->transform()) - TilesManager::instance()->shader()->drawLayerQuad(*m_painter->transform(), - rect, m_frontTexture->m_ownTextureId, - transparency, true); - else - TilesManager::instance()->shader()->drawQuad(rect, m_frontTexture->m_ownTextureId, - transparency); - } else { - XLOG("tile %p at %d, %d not readyfor (at draw),", this, m_x, m_y); - } - - m_frontTexture->consumerRelease(); + m_frontTexture->drawGL(isLayerTile(), rect, opacity, transform); } bool BaseTile::isTileReady() @@ -301,16 +273,7 @@ bool BaseTile::isTileReady() if (m_state != ReadyToSwap && m_state != UpToDate) return false; - texture->consumerLock(); - bool ready = texture->readyFor(this); - texture->consumerRelease(); - - if (ready) - return true; - - XLOG("tile %p at %d, %d not readyfor (at isTileReady)", this, m_x, m_y); - - return false; + return true; } bool BaseTile::intersectWithRect(int x, int y, int tileWidth, int tileHeight, @@ -350,7 +313,7 @@ void BaseTile::paintBitmap() m_atomicSync.lock(); bool dirty = m_dirty; BaseTileTexture* texture = m_backTexture; - SkRegion dirtyArea = m_dirtyArea[m_currentDirtyAreaIndex]; + SkRegion dirtyArea = m_dirtyArea; float scale = m_scale; const int x = m_x; const int y = m_y; @@ -365,23 +328,17 @@ void BaseTile::paintBitmap() this, m_state, m_frontTexture, m_backTexture); } m_state = PaintingStarted; - - texture->producerAcquireContext(); - TextureInfo* textureInfo = texture->producerLock(); + TextureInfo* textureInfo = texture->getTextureInfo(); m_atomicSync.unlock(); // 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; } - unsigned int pictureCount = 0; - // swap out the renderer if necessary BaseRenderer::swapRendererIfNeeded(m_renderer); - // setup the common renderInfo fields; TileRenderInfo renderInfo; renderInfo.x = x; @@ -399,82 +356,81 @@ void BaseTile::paintBitmap() bool fullRepaint = false; - if (m_fullRepaint[m_currentDirtyAreaIndex] + if (m_fullRepaint || textureInfo->m_width != tileWidth || textureInfo->m_height != tileHeight) { fullRepaint = true; } - bool surfaceTextureMode = textureInfo->getSharedTextureMode() == SurfaceTextureMode; - - if (surfaceTextureMode) - fullRepaint = true; - - while (!fullRepaint && !cliperator.done()) { - SkRect realTileRect; - SkRect dirtyRect; - dirtyRect.set(cliperator.rect()); - bool intersect = intersectWithRect(x, y, tileWidth, tileHeight, - scale, dirtyRect, realTileRect); - - // With SurfaceTexture, just repaint the entire tile if we intersect - // TODO: Implement the partial invalidate in Surface Texture Mode - if (intersect && surfaceTextureMode) { - fullRepaint = true; - break; - } - - if (intersect && !surfaceTextureMode) { - // initialize finalRealRect to the rounded values of realTileRect - SkIRect finalRealRect; - realTileRect.roundOut(&finalRealRect); - - // stash the int values of the current width and height - const int iWidth = finalRealRect.width(); - const int iHeight = finalRealRect.height(); - - if (iWidth == tileWidth || iHeight == tileHeight) { - fullRepaint = true; - break; + // For now, only do full repaint + fullRepaint = true; + + if (!fullRepaint) { + // compute the partial inval area + SkIRect totalRect; + totalRect.set(0, 0, 0, 0); + float tileSurface = tileWidth * tileHeight; + float tileSurfaceCap = MAX_INVAL_AREA * tileSurface; + + // We join all the invals in the same tile for now + while (!fullRepaint && !cliperator.done()) { + SkRect realTileRect; + SkRect dirtyRect; + dirtyRect.set(cliperator.rect()); + bool intersect = intersectWithRect(x, y, tileWidth, tileHeight, + scale, dirtyRect, realTileRect); + if (intersect) { + // initialize finalRealRect to the rounded values of realTileRect + SkIRect finalRealRect; + realTileRect.roundOut(&finalRealRect); + + // stash the int values of the current width and height + const int iWidth = finalRealRect.width(); + const int iHeight = finalRealRect.height(); + + if (iWidth == tileWidth || iHeight == tileHeight) { + fullRepaint = true; + break; + } + + // translate the rect into tile space coordinates + finalRealRect.fLeft = finalRealRect.fLeft % static_cast<int>(tileWidth); + finalRealRect.fTop = finalRealRect.fTop % static_cast<int>(tileHeight); + finalRealRect.fRight = finalRealRect.fLeft + iWidth; + finalRealRect.fBottom = finalRealRect.fTop + iHeight; + totalRect.join(finalRealRect); + float repaintSurface = totalRect.width() * totalRect.height(); + + if (repaintSurface > tileSurfaceCap) { + fullRepaint = true; + break; + } } - // translate the rect into tile space coordinates - finalRealRect.fLeft = finalRealRect.fLeft % static_cast<int>(tileWidth); - finalRealRect.fTop = finalRealRect.fTop % static_cast<int>(tileHeight); - finalRealRect.fRight = finalRealRect.fLeft + iWidth; - finalRealRect.fBottom = finalRealRect.fTop + iHeight; + cliperator.next(); + } - renderInfo.invalRect = &finalRealRect; + if (!fullRepaint) { + renderInfo.invalRect = &totalRect; renderInfo.measurePerf = false; - - pictureCount = m_renderer->renderTiledContent(renderInfo); + m_renderer->renderTiledContent(renderInfo); } - - cliperator.next(); } // Do a full repaint if needed if (fullRepaint) { - SkIRect rect; - rect.set(0, 0, tileWidth, tileHeight); - - renderInfo.invalRect = ▭ + renderInfo.invalRect = 0; renderInfo.measurePerf = TilesManager::instance()->getShowVisualIndicator(); - - pictureCount = m_renderer->renderTiledContent(renderInfo); + m_renderer->renderTiledContent(renderInfo); } m_atomicSync.lock(); -#if DEPRECATED_SURFACE_TEXTURE_MODE - texture->setTile(textureInfo, x, y, scale, painter, pictureCount); -#endif - texture->producerReleaseAndSwap(); if (texture == m_backTexture) { m_isTexturePainted = true; // set the fullrepaint flags - m_fullRepaint[m_currentDirtyAreaIndex] = false; + m_fullRepaint = false; // The various checks to see if we are still dirty... @@ -484,19 +440,11 @@ void BaseTile::paintBitmap() m_dirty = true; if (fullRepaint) - m_dirtyArea[m_currentDirtyAreaIndex].setEmpty(); + m_dirtyArea.setEmpty(); else - m_dirtyArea[m_currentDirtyAreaIndex].op(dirtyArea, SkRegion::kDifference_Op); + m_dirtyArea.op(dirtyArea, SkRegion::kDifference_Op); - if (!m_dirtyArea[m_currentDirtyAreaIndex].isEmpty()) - m_dirty = true; - - // Now we can swap the dirty areas - // TODO: For surface texture in Async mode, the index will be updated - // according to the current buffer just dequeued. - m_currentDirtyAreaIndex = (m_currentDirtyAreaIndex+1) % m_maxBufferNumber; - - if (!m_dirtyArea[m_currentDirtyAreaIndex].isEmpty()) + if (!m_dirtyArea.isEmpty()) m_dirty = true; XLOG("painted tile %p (%d, %d), texture %p, dirty=%d", this, x, y, texture, m_dirty); @@ -522,10 +470,9 @@ void BaseTile::discardTextures() { m_backTexture->release(this); m_backTexture = 0; } - for (int i = 0; i < m_maxBufferNumber; i++) { - m_dirtyArea[i].setEmpty(); - m_fullRepaint[i] = true; - } + m_dirtyArea.setEmpty(); + m_fullRepaint = true; + m_dirty = true; m_state = Unpainted; } @@ -589,9 +536,12 @@ void BaseTile::validatePaint() { // when both have happened, mark as 'ReadyToSwap' if (m_state == PaintingStarted) m_state = ValidatedUntransferred; - else if (m_state == TransferredUnvalidated) + else if (m_state == TransferredUnvalidated) { + // When the backTexture has been marked pureColor, we will skip the + // transfer and marked as ReadyToSwap, in this case, we don't want + // to reset m_dirty bit to true. m_state = ReadyToSwap; - else { + } else { XLOG("Note: validated tile %p at %d %d, state wasn't paintingstarted or transferred %d", this, m_x, m_y, m_state); // failed transferring, in which case mark dirty (since diff --git a/Source/WebCore/platform/graphics/android/BaseTile.h b/Source/WebCore/platform/graphics/android/BaseTile.h index 685ca43..f02386b 100644 --- a/Source/WebCore/platform/graphics/android/BaseTile.h +++ b/Source/WebCore/platform/graphics/android/BaseTile.h @@ -54,7 +54,7 @@ class GLWebViewState; * the BaseLayer's most recent PictureSet to a bitmap which is then uploaded * to the GPU. * 3. After the bitmap is uploaded to the GPU the main GL thread then uses the - * tile's draw() function to display the tile to the screen. + * tile's drawGL() function to display the tile to the screen. * 4. Steps 2-3 are repeated as necessary. * 5. The tile is destroyed when the user navigates to a new page. * @@ -101,7 +101,8 @@ public: bool isTileReady(); - void draw(float transparency, SkRect& rect, float scale); + void drawGL(float opacity, const SkRect& rect, float scale, + const TransformationMatrix* transform); // the only thread-safe function called by the background thread void paintBitmap(); @@ -111,8 +112,7 @@ public: SkRect& realTileRect); bool isTileVisible(const IntRect& viewTileBounds); - void markAsDirty(const unsigned int pictureCount, - const SkRegion& dirtyArea); + void markAsDirty(const SkRegion& dirtyArea); bool isDirty(); bool isRepaintPending(); void setRepaintPending(bool pending); @@ -166,16 +166,10 @@ private: // used to signal that a repaint is pending bool m_repaintPending; - // stores the id of the latest picture from webkit that caused this tile to - // become dirty. A tile is no longer dirty when it has been painted with a - // picture that is newer than this value. - unsigned int m_lastDirtyPicture; // store the dirty region - SkRegion* m_dirtyArea; - bool* m_fullRepaint; - int m_maxBufferNumber; - int m_currentDirtyAreaIndex; + SkRegion m_dirtyArea; + bool m_fullRepaint; // flag used to know if we have a texture that was painted at least once bool m_isTexturePainted; diff --git a/Source/WebCore/platform/graphics/android/BaseTileTexture.cpp b/Source/WebCore/platform/graphics/android/BaseTileTexture.cpp index caaf116..9403584 100644 --- a/Source/WebCore/platform/graphics/android/BaseTileTexture.cpp +++ b/Source/WebCore/platform/graphics/android/BaseTileTexture.cpp @@ -28,7 +28,6 @@ #include "BaseTile.h" #include "ClassTracker.h" -#include "DeleteTextureOperation.h" #include "GLUtils.h" #include "TilesManager.h" @@ -53,17 +52,12 @@ namespace WebCore { BaseTileTexture::BaseTileTexture(uint32_t w, uint32_t h) - : DoubleBufferedTexture(eglGetCurrentContext(), - TilesManager::instance()->getSharedTextureMode()) - , m_owner(0) - , m_busy(false) + : m_owner(0) + , m_isPureColor(false) { m_size.set(w, h); m_ownTextureId = 0; - // Make sure they are created on the UI thread. - TilesManager::instance()->transferQueue()->initSharedSurfaceTextures(w, h); - #ifdef DEBUG_COUNT ClassTracker::instance()->increment("BaseTileTexture"); #endif @@ -71,10 +65,6 @@ BaseTileTexture::BaseTileTexture(uint32_t w, uint32_t h) BaseTileTexture::~BaseTileTexture() { - if (m_sharedTextureMode == EglImageMode) { - SharedTexture* textures[3] = { m_textureA, m_textureB, 0 }; - destroyTextures(textures); - } #ifdef DEBUG_COUNT ClassTracker::instance()->decrement("BaseTileTexture"); #endif @@ -98,71 +88,6 @@ void BaseTileTexture::discardGLTexture() } } -void BaseTileTexture::destroyTextures(SharedTexture** textures) -{ - int 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 - // in the same EGLContext from which it was created. - textures[x]->lock(); - DeleteTextureOperation* operation = new DeleteTextureOperation( - textures[x]->getSourceTextureId(), textures[x]->getEGLImage()); - textures[x]->unlock(); - TilesManager::instance()->scheduleOperation(operation); - x++; - } -} - -TextureInfo* BaseTileTexture::producerLock() -{ - m_busyLock.lock(); - m_busy = true; - m_busyLock.unlock(); - return DoubleBufferedTexture::producerLock(); -} - -void BaseTileTexture::producerRelease() -{ - DoubleBufferedTexture::producerRelease(); - setNotBusy(); -} - -void BaseTileTexture::producerReleaseAndSwap() -{ - DoubleBufferedTexture::producerReleaseAndSwap(); - setNotBusy(); -} - -void BaseTileTexture::setNotBusy() -{ - android::Mutex::Autolock lock(m_busyLock); - m_busy = false; - m_busyCond.signal(); -} - -bool BaseTileTexture::busy() -{ - android::Mutex::Autolock lock(m_busyLock); - return m_busy; -} - -void BaseTileTexture::producerUpdate(TextureInfo* textureInfo, const SkBitmap& bitmap) -{ - // no need to upload a texture since the bitmap is empty - if (!bitmap.width() && !bitmap.height()) { - producerRelease(); - return; - } - - // After the tiled layer checked in, this is not called anyway. - // TODO: cleanup the old code path for layer painting - // GLUtils::paintTextureWithBitmap(info, m_size, bitmap, 0, 0); - - producerReleaseAndSwap(); -} - bool BaseTileTexture::acquire(TextureOwner* owner, bool force) { if (m_owner == owner) @@ -173,39 +98,21 @@ bool BaseTileTexture::acquire(TextureOwner* owner, bool force) bool BaseTileTexture::setOwner(TextureOwner* owner, bool force) { - // if the writable texture is busy (i.e. currently being written to) then we - // can't change the owner out from underneath that texture - m_busyLock.lock(); - while (m_busy && force) - m_busyCond.wait(m_busyLock); - bool busy = m_busy; - m_busyLock.unlock(); - - if (!busy) { - // if we are not busy we can try to remove the texture from the layer; - // LayerAndroid::removeTexture() is protected by the same lock as - // LayerAndroid::paintBitmapGL(), so either we execute removeTexture() - // first and paintBitmapGL() will bail out, or we execute it after, - // and paintBitmapGL() will mark the texture as busy before - // relinquishing the lock. LayerAndroid::removeTexture() will call - // BaseTileTexture::release(), which will then do nothing - // if the texture is busy and we then don't return true. - bool proceed = true; - if (m_owner && m_owner != owner) - proceed = m_owner->removeTexture(this); + bool proceed = true; + if (m_owner && m_owner != owner) + proceed = m_owner->removeTexture(this); - if (proceed) { - m_owner = owner; - return true; - } + if (proceed) { + m_owner = owner; + return true; } + return false; } bool BaseTileTexture::release(TextureOwner* owner) { - android::Mutex::Autolock lock(m_busyLock); - XLOG("texture %p releasing tile %p, m_owner %p, m_busy %d", this, owner, m_owner, m_busy); + XLOG("texture %p releasing tile %p, m_owner %p", this, owner, m_owner); if (m_owner != owner) return false; @@ -213,61 +120,33 @@ bool BaseTileTexture::release(TextureOwner* owner) return true; } -void BaseTileTexture::setTile(TextureInfo* info, int x, int y, - float scale, TilePainter* painter, - unsigned int pictureCount) -{ - TextureTileInfo* textureInfo = m_texturesInfo.get(getWriteableTexture()); - if (!textureInfo) { - textureInfo = new TextureTileInfo(); - } - textureInfo->m_x = x; - textureInfo->m_y = y; - textureInfo->m_scale = scale; - textureInfo->m_painter = painter; - textureInfo->m_picture = pictureCount; - m_texturesInfo.set(getWriteableTexture(), textureInfo); -} - -float BaseTileTexture::scale() -{ - TextureTileInfo* textureInfo = &m_ownTextureTileInfo; - return textureInfo->m_scale; -} - -// This function + TilesManager::addItemInTransferQueue() is replacing the -// setTile(). -void BaseTileTexture::setOwnTextureTileInfoFromQueue(const TextureTileInfo* info) +void BaseTileTexture::transferComplete() { - m_ownTextureTileInfo.m_x = info->m_x; - m_ownTextureTileInfo.m_y = info->m_y; - m_ownTextureTileInfo.m_scale = info->m_scale; - m_ownTextureTileInfo.m_painter = info->m_painter; - m_ownTextureTileInfo.m_picture = info->m_picture; - m_ownTextureTileInfo.m_inverted = TilesManager::instance()->invertedScreen(); if (m_owner) { BaseTile* owner = static_cast<BaseTile*>(m_owner); owner->backTextureTransfer(); - } - + } else + XLOGC("ERROR: owner missing after transfer of texture %p", this); } -bool BaseTileTexture::readyFor(BaseTile* baseTile) +void BaseTileTexture::drawGL(bool isLayer, const SkRect& rect, float opacity, + const TransformationMatrix* transform) { - const TextureTileInfo* info = &m_ownTextureTileInfo; - if (info && - (info->m_x == baseTile->x()) && - (info->m_y == baseTile->y()) && - (info->m_scale == baseTile->scale()) && - (info->m_painter == baseTile->painter()) && - (info->m_inverted == TilesManager::instance()->invertedScreen())) - return true; - - XLOG("texture %p readyFor return false for tile x, y (%d %d) texId %d ," - " BaseTileTexture %p, BaseTile is %p, SCALE %f, painter %p, inv %d", - this, baseTile->x(), baseTile->y(), m_ownTextureId, this, baseTile, - baseTile->scale(), baseTile->painter(), TilesManager::instance()->invertedScreen()); - return false; + ShaderProgram* shader = TilesManager::instance()->shader(); + if (isLayer && transform) { + if (isPureColor()) { + shader->drawLayerQuad(*transform, rect, 0, opacity, + true, GL_TEXTURE_2D, pureColor()); + } else { + shader->drawLayerQuad(*transform, rect, m_ownTextureId, + opacity, true); + } + } else { + if (isPureColor()) + shader->drawQuad(rect, 0, opacity, pureColor()); + else + shader->drawQuad(rect, m_ownTextureId, opacity); + } } } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/BaseTileTexture.h b/Source/WebCore/platform/graphics/android/BaseTileTexture.h index cd8e78b..321ca31 100644 --- a/Source/WebCore/platform/graphics/android/BaseTileTexture.h +++ b/Source/WebCore/platform/graphics/android/BaseTileTexture.h @@ -26,10 +26,11 @@ #ifndef BaseTileTexture_h #define BaseTileTexture_h -#include "DoubleBufferedTexture.h" #include "GLWebViewState.h" +#include "TextureInfo.h" #include "TextureOwner.h" #include "TilePainter.h" +#include <GLES2/gl2.h> #include <SkBitmap.h> class SkCanvas; @@ -38,67 +39,26 @@ namespace WebCore { class BaseTile; -class TextureTileInfo { -public: - TextureTileInfo() - : m_x(-1) - , m_y(-1) - , m_layerId(-1) - , m_scale(0) - , m_texture(0) - , m_painter(0) - , m_picture(0) - , m_inverted(false) - { - } - int m_x; - int m_y; - int m_layerId; - float m_scale; - TextureInfo* m_texture; - TilePainter* m_painter; - unsigned int m_picture; - bool m_inverted; -}; - -// DoubleBufferedTexture using a SkBitmap as backing mechanism -class BaseTileTexture : public DoubleBufferedTexture { +class BaseTileTexture { public: // This object is to be constructed on the consumer's thread and must have // a width and height greater than 0. BaseTileTexture(uint32_t w, uint32_t h); virtual ~BaseTileTexture(); - // these functions override their parent - virtual TextureInfo* producerLock(); - virtual void producerRelease(); - virtual void producerReleaseAndSwap(); - - // updates the texture with current bitmap and releases (and if needed also - // swaps) the texture. - virtual void producerUpdate(TextureInfo* textureInfo, const SkBitmap& bitmap); - // allows consumer thread to assign ownership of the texture to the tile. It // returns false if ownership cannot be transferred because the tile is busy bool acquire(TextureOwner* owner, bool force = false); bool release(TextureOwner* owner); - // removes Tile->Texture, and Texture->Tile links to fully discard the texture - void releaseAndRemoveFromTile(); - // set the texture owner if not busy. Return false if busy, true otherwise. bool setOwner(TextureOwner* owner, bool force = false); // private member accessor functions TextureOwner* owner() { return m_owner; } // only used by the consumer thread - bool busy(); - void setNotBusy(); - const SkSize& getSize() const { return m_size; } - void setTile(TextureInfo* info, int x, int y, float scale, - TilePainter* painter, unsigned int pictureCount); bool readyFor(BaseTile* baseTile); float scale(); @@ -108,31 +68,31 @@ public: void requireGLTexture(); void discardGLTexture(); - void setOwnTextureTileInfoFromQueue(const TextureTileInfo* info); + void transferComplete(); -protected: - HashMap<SharedTexture*, TextureTileInfo*> m_texturesInfo; + TextureInfo* getTextureInfo() { return &m_ownTextureInfo; } -private: - void destroyTextures(SharedTexture** textures); - TextureTileInfo m_ownTextureTileInfo; + // Make sure the following pureColor getter/setter are only read/written + // in UI thread. Therefore no need for a lock. + void setPure(bool pure) { m_isPureColor = pure; } + bool isPureColor() {return m_isPureColor; } + void setPureColor(const Color& color) { m_pureColor = color; setPure(true); } + Color pureColor() { return m_pureColor; } + void drawGL(bool isLayer, const SkRect& rect, float opacity, + const TransformationMatrix* transform); +private: + TextureInfo m_ownTextureInfo; SkSize m_size; SkBitmap::Config m_config; // BaseTile owning the texture, only modified by UI thread TextureOwner* m_owner; - // This values signals that the texture is currently in use by the consumer. - // This allows us to prevent the owner of the texture from changing while the - // consumer is holding a lock on the texture. - bool m_busy; - // We mutex protect the reads/writes of m_busy to ensure that we are reading - // the most up-to-date value even across processors in an SMP system. - android::Mutex m_busyLock; - // We use this condition variable to signal that the texture - // is not busy anymore - android::Condition m_busyCond; + // When the whole tile is single color, skip the transfer queue and draw + // it directly through shader. + bool m_isPureColor; + Color m_pureColor; }; } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/DoubleBufferedTexture.cpp b/Source/WebCore/platform/graphics/android/DoubleBufferedTexture.cpp deleted file mode 100644 index 4c5af9e..0000000 --- a/Source/WebCore/platform/graphics/android/DoubleBufferedTexture.cpp +++ /dev/null @@ -1,217 +0,0 @@ -/* - * 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 "DoubleBufferedTexture.h" - -#include "ClassTracker.h" -#include "GLUtils.h" - -#define LOG_NDEBUG 1 -#define LOG_TAG "DoubleBufferedTexture.cpp" -#include <utils/Log.h> - -namespace WebCore { - -DoubleBufferedTexture::DoubleBufferedTexture(EGLContext sharedContext, SharedTextureMode mode) -{ - m_sharedTextureMode = mode; - - m_textureA = new SharedTexture(m_sharedTextureMode); - if (m_sharedTextureMode == EglImageMode) - m_textureB = new SharedTexture(m_sharedTextureMode); - else - m_textureB = 0; - - m_display = eglGetCurrentDisplay(); - m_pContext = EGL_NO_CONTEXT; - m_cContext = sharedContext; - m_writeableTexture = m_textureA; - m_lockedConsumerTexture = GL_NO_TEXTURE; - m_supportsEGLImage = GLUtils::isEGLImageSupported(); -#ifdef DEBUG_COUNT - ClassTracker::instance()->increment("DoubleBufferedTexture"); -#endif -} - -DoubleBufferedTexture::~DoubleBufferedTexture() -{ -#ifdef DEBUG_COUNT - ClassTracker::instance()->decrement("DoubleBufferedTexture"); -#endif - delete m_textureA; - delete m_textureB; -} - -SharedTexture* DoubleBufferedTexture::getWriteableTexture() -{ - if (m_sharedTextureMode == SurfaceTextureMode) - return m_textureA; - return reinterpret_cast<SharedTexture*>( - android_atomic_release_load((int32_t*)&m_writeableTexture)); -} - -SharedTexture* DoubleBufferedTexture::getReadableTexture() -{ - if (m_sharedTextureMode == SurfaceTextureMode) - return m_textureA; - return (getWriteableTexture() != m_textureA) ? m_textureA : m_textureB; -} - -EGLContext DoubleBufferedTexture::producerAcquireContext() -{ - if (m_sharedTextureMode == SurfaceTextureMode) - return EGL_NO_CONTEXT; - - if (m_pContext != EGL_NO_CONTEXT) { - LOGV("AquireContext has previously generated a context.\n"); - return m_pContext; - } - - // check to see if a context already exists on this thread - EGLContext context = eglGetCurrentContext(); - - // if no context exists then create one - if (context == EGL_NO_CONTEXT) { - EGLContext sharedContext = m_supportsEGLImage ? EGL_NO_CONTEXT : m_cContext; - context = GLUtils::createBackgroundContext(sharedContext); - } - - if (context == EGL_NO_CONTEXT) { - LOGE("eglCreateContext failed"); - return EGL_NO_CONTEXT; - } - - // initialize the producer's textures - m_textureA->lock(); - if (m_sharedTextureMode == EglImageMode) - m_textureB->lock(); - - m_textureA->initSourceTexture(); - LOGV("Initialized Textures A (%d)", m_textureA->getSourceTextureId()); - if (m_sharedTextureMode == EglImageMode) { - m_textureB->initSourceTexture(); - LOGV("Initialized Textures B (%d)", m_textureB->getSourceTextureId()); - } - - m_textureA->unlock(); - if (m_sharedTextureMode == EglImageMode) - m_textureB->unlock(); - - m_pContext = context; - return context; -} - -// For MediaTexture only -void DoubleBufferedTexture::producerDeleteTextures() -{ - m_textureA->lock(); - if (m_sharedTextureMode == EglImageMode) - m_textureB->lock(); - - LOGV("Deleting Producer Textures A (%d)", m_textureA->getSourceTextureId()); - m_textureA->deleteSourceTexture(); - if (m_sharedTextureMode == EglImageMode){ - LOGV("Deleting Producer Textures B (%d)", m_textureB->getSourceTextureId()); - m_textureB->deleteSourceTexture(); - } - - m_textureA->unlock(); - if (m_sharedTextureMode == EglImageMode) - m_textureB->unlock(); -} - -// For MediaTexture only -void DoubleBufferedTexture::consumerDeleteTextures() -{ - m_textureA->lock(); - if (m_sharedTextureMode == EglImageMode) - m_textureB->lock(); - - LOGV("Deleting Consumer Textures A (%d)", m_textureA->getTargetTextureId()); - m_textureA->deleteTargetTexture(); - if (m_sharedTextureMode == EglImageMode) { - LOGV("Deleting Consumer Textures B (%d)", m_textureB->getTargetTextureId()); - m_textureB->deleteTargetTexture(); - } - - m_textureA->unlock(); - if (m_sharedTextureMode == EglImageMode) - m_textureB->unlock(); -} - -TextureInfo* DoubleBufferedTexture::producerLock() -{ - SharedTexture* sharedTex = getWriteableTexture(); - LOGV("Acquiring P Lock (%d)", sharedTex->getSourceTextureId()); - TextureInfo* texInfo = sharedTex->lockSource(); - LOGV("Acquired P Lock"); - - return texInfo; -} - -void DoubleBufferedTexture::producerRelease() -{ - // get the writable texture and unlock it - SharedTexture* sharedTex = getWriteableTexture(); - LOGV("Releasing P Lock (%d)", sharedTex->getSourceTextureId()); - sharedTex->releaseSource(); - LOGV("Released P Lock (%d)", sharedTex->getSourceTextureId()); -} - -void DoubleBufferedTexture::producerReleaseAndSwap() -{ - producerRelease(); - if (m_sharedTextureMode == EglImageMode) { - // swap the front and back buffers using an atomic op for the memory barrier - android_atomic_acquire_store((int32_t)getReadableTexture(), (int32_t*)&m_writeableTexture); - } -} - -TextureInfo* DoubleBufferedTexture::consumerLock() -{ - SharedTexture* sharedTex = getReadableTexture(); - LOGV("Acquiring C Lock (%d)", sharedTex->getSourceTextureId()); - m_lockedConsumerTexture = sharedTex; - - TextureInfo* texInfo = sharedTex->lockTarget(); - LOGV("Acquired C Lock"); - - if (!texInfo) - LOGV("Released C Lock (Empty)"); - - return texInfo; -} - -void DoubleBufferedTexture::consumerRelease() -{ - // we must check to see what texture the consumer had locked since the - // producer may have swapped out the readable buffer - SharedTexture* sharedTex = m_lockedConsumerTexture; - sharedTex->releaseTarget(); - LOGV("Released C Lock (%d)", sharedTex->getSourceTextureId()); -} - -} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/DumpLayer.cpp b/Source/WebCore/platform/graphics/android/DumpLayer.cpp new file mode 100644 index 0000000..5551965 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/DumpLayer.cpp @@ -0,0 +1,83 @@ +#include "config.h" +#include "DumpLayer.h" + +#if USE(ACCELERATED_COMPOSITING) + +namespace WebCore { + +void lwrite(FILE* file, const char* str) +{ + fwrite(str, sizeof(char), strlen(str), file); +} + +void writeIndent(FILE* file, int indentLevel) +{ + if (indentLevel) + fprintf(file, "%*s", indentLevel*2, " "); +} + +void writeln(FILE* file, int indentLevel, const char* str) +{ + writeIndent(file, indentLevel); + lwrite(file, str); + lwrite(file, "\n"); +} + +void writeIntVal(FILE* file, int indentLevel, const char* str, int value) +{ + writeIndent(file, indentLevel); + fprintf(file, "%s = %d;\n", str, value); +} + +void writeHexVal(FILE* file, int indentLevel, const char* str, int value) +{ + writeIndent(file, indentLevel); + fprintf(file, "%s = %x;\n", str, value); +} + +void writeFloatVal(FILE* file, int indentLevel, const char* str, float value) +{ + writeIndent(file, indentLevel); + fprintf(file, "%s = %.3f;\n", str, value); +} + +void writePoint(FILE* file, int indentLevel, const char* str, SkPoint point) +{ + writeIndent(file, indentLevel); + fprintf(file, "%s = { x = %.3f; y = %.3f; };\n", str, point.fX, point.fY); +} + +void writeIntPoint(FILE* file, int indentLevel, const char* str, IntPoint point) +{ + writeIndent(file, indentLevel); + fprintf(file, "%s = { x = %d; y = %d; };\n", str, point.x(), point.y()); +} + +void writeSize(FILE* file, int indentLevel, const char* str, SkSize size) +{ + writeIndent(file, indentLevel); + fprintf(file, "%s = { w = %.3f; h = %.3f; };\n", str, size.width(), size.height()); +} + +void writeRect(FILE* file, int indentLevel, const char* str, SkRect rect) +{ + writeIndent(file, indentLevel); + fprintf(file, "%s = { x = %.3f; y = %.3f; w = %.3f; h = %.3f; };\n", + str, rect.fLeft, rect.fTop, rect.width(), rect.height()); +} + +void writeMatrix(FILE* file, int indentLevel, const char* str, const TransformationMatrix& matrix) +{ + writeIndent(file, indentLevel); + fprintf(file, "%s = { (%.2f,%.2f,%.2f,%.2f),(%.2f,%.2f,%.2f,%.2f)," + "(%.2f,%.2f,%.2f,%.2f),(%.2f,%.2f,%.2f,%.2f) };\n", + str, + matrix.m11(), matrix.m12(), matrix.m13(), matrix.m14(), + matrix.m21(), matrix.m22(), matrix.m23(), matrix.m24(), + matrix.m31(), matrix.m32(), matrix.m33(), matrix.m34(), + matrix.m41(), matrix.m42(), matrix.m43(), matrix.m44()); +} + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/DumpLayer.h b/Source/WebCore/platform/graphics/android/DumpLayer.h new file mode 100644 index 0000000..5b30952 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/DumpLayer.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DumpLayer_h +#define DumpLayer_h + +#include "IntPoint.h" +#include "SkPoint.h" +#include "SkRect.h" +#include "SkSize.h" +#include "TransformationMatrix.h" + +// Debug tools : dump the layers tree in a file. +// The format is simple: +// properties have the form: key = value; +// all statements are finished with a semi-colon. +// value can be: +// - int +// - float +// - array of elements +// - composed type +// a composed type enclose properties in { and } +// an array enclose composed types in { }, separated with a comma. +// exemple: +// { +// x = 3; +// y = 4; +// value = { +// x = 3; +// y = 4; +// }; +// anarray = [ +// { x = 3; }, +// { y = 4; } +// ]; +// } + +namespace WebCore { + +void lwrite(FILE* file, const char* str); +void writeIndent(FILE* file, int indentLevel); +void writeln(FILE* file, int indentLevel, const char* str); +void writeIntVal(FILE* file, int indentLevel, const char* str, int value); +void writeHexVal(FILE* file, int indentLevel, const char* str, int value); +void writeFloatVal(FILE* file, int indentLevel, const char* str, float value); +void writePoint(FILE* file, int indentLevel, const char* str, SkPoint point); +void writeIntPoint(FILE* file, int indentLevel, const char* str, IntPoint point); +void writeSize(FILE* file, int indentLevel, const char* str, SkSize size); +void writeRect(FILE* file, int indentLevel, const char* str, SkRect rect); +void writeMatrix(FILE* file, int indentLevel, const char* str, const TransformationMatrix& matrix); + +} + +#endif // DumpLayer_h diff --git a/Source/WebCore/platform/graphics/android/FixedPositioning.cpp b/Source/WebCore/platform/graphics/android/FixedPositioning.cpp new file mode 100644 index 0000000..140411a --- /dev/null +++ b/Source/WebCore/platform/graphics/android/FixedPositioning.cpp @@ -0,0 +1,106 @@ +#include "config.h" +#include "FixedPositioning.h" + +#include "DumpLayer.h" +#include "IFrameLayerAndroid.h" +#include "TilesManager.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include <cutils/log.h> +#include <wtf/CurrentTime.h> +#include <wtf/text/CString.h> +#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "FixedPositioning", __VA_ARGS__) + +namespace WebCore { + +// Called when copying the layer tree to the UI +FixedPositioning::FixedPositioning(LayerAndroid* layer, const FixedPositioning& position) + : m_layer(layer) + , m_fixedLeft(position.m_fixedLeft) + , m_fixedTop(position.m_fixedTop) + , m_fixedRight(position.m_fixedRight) + , m_fixedBottom(position.m_fixedBottom) + , m_fixedMarginLeft(position.m_fixedMarginLeft) + , m_fixedMarginTop(position.m_fixedMarginTop) + , m_fixedMarginRight(position.m_fixedMarginRight) + , m_fixedMarginBottom(position.m_fixedMarginBottom) + , m_fixedRect(position.m_fixedRect) + , m_renderLayerPos(position.m_renderLayerPos) +{ +} + +// Executed on the UI +IFrameLayerAndroid* FixedPositioning::updatePosition(SkRect viewport, + IFrameLayerAndroid* parentIframeLayer) +{ + // So if this is a fixed layer inside a iframe, use the iframe offset + // and the iframe's size as the viewport and pass to the children + if (parentIframeLayer) { + viewport = SkRect::MakeXYWH(parentIframeLayer->iframeOffset().x(), + parentIframeLayer->iframeOffset().y(), + parentIframeLayer->getSize().width(), + parentIframeLayer->getSize().height()); + } + float w = viewport.width(); + float h = viewport.height(); + float dx = viewport.fLeft; + float dy = viewport.fTop; + float x = dx; + float y = dy; + + // It turns out that when it is 'auto', we should use the webkit value + // from the original render layer's X,Y, that will take care of alignment + // with the parent's layer and fix Margin etc. + if (!(m_fixedLeft.defined() || m_fixedRight.defined())) + x += m_renderLayerPos.x(); + else if (m_fixedLeft.defined() || !m_fixedRight.defined()) + x += m_fixedMarginLeft.calcFloatValue(w) + m_fixedLeft.calcFloatValue(w) - m_fixedRect.fLeft; + else + x += w - m_fixedMarginRight.calcFloatValue(w) - m_fixedRight.calcFloatValue(w) - m_fixedRect.fRight; + + if (!(m_fixedTop.defined() || m_fixedBottom.defined())) + y += m_renderLayerPos.y(); + else if (m_fixedTop.defined() || !m_fixedBottom.defined()) + y += m_fixedMarginTop.calcFloatValue(h) + m_fixedTop.calcFloatValue(h) - m_fixedRect.fTop; + else + y += h - m_fixedMarginBottom.calcFloatValue(h) - m_fixedBottom.calcFloatValue(h) - m_fixedRect.fBottom; + + m_layer->setPosition(x, y); + + return parentIframeLayer; +} + +void FixedPositioning::contentDraw(SkCanvas* canvas, Layer::PaintStyle style) +{ + if (TilesManager::instance()->getShowVisualIndicator()) { + SkPaint paint; + paint.setARGB(80, 255, 0, 0); + canvas->drawRect(m_fixedRect, paint); + } +} + +void writeLength(FILE* file, int indentLevel, const char* str, SkLength length) +{ + if (!length.defined()) + return; + writeIndent(file, indentLevel); + fprintf(file, "%s = { type = %d; value = %.2f; };\n", str, length.type, length.value); +} + +void FixedPositioning::dumpLayer(FILE* file, int indentLevel) const +{ + writeLength(file, indentLevel + 1, "fixedLeft", m_fixedLeft); + writeLength(file, indentLevel + 1, "fixedTop", m_fixedTop); + writeLength(file, indentLevel + 1, "fixedRight", m_fixedRight); + writeLength(file, indentLevel + 1, "fixedBottom", m_fixedBottom); + writeLength(file, indentLevel + 1, "fixedMarginLeft", m_fixedMarginLeft); + writeLength(file, indentLevel + 1, "fixedMarginTop", m_fixedMarginTop); + writeLength(file, indentLevel + 1, "fixedMarginRight", m_fixedMarginRight); + writeLength(file, indentLevel + 1, "fixedMarginBottom", m_fixedMarginBottom); + writeRect(file, indentLevel + 1, "fixedRect", m_fixedRect); +} + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/FixedPositioning.h b/Source/WebCore/platform/graphics/android/FixedPositioning.h new file mode 100644 index 0000000..973113b --- /dev/null +++ b/Source/WebCore/platform/graphics/android/FixedPositioning.h @@ -0,0 +1,128 @@ +/* + * Copyright 2012, 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 FixedPositioning_h +#define FixedPositioning_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "LayerAndroid.h" + +namespace WebCore { + +class IFrameLayerAndroid; + +struct SkLength { + enum SkLengthType { Undefined, Auto, Relative, + Percent, Fixed, Static, Intrinsic, MinIntrinsic }; + SkLengthType type; + SkScalar value; + SkLength() + { + type = Undefined; + value = 0; + } + bool defined() const + { + if (type == Undefined) + return false; + return true; + } + float calcFloatValue(float max) const + { + switch (type) { + case Percent: + return (max * value) / 100.0f; + case Fixed: + return value; + default: + return value; + } + } +}; + +class FixedPositioning { + +public: + FixedPositioning(LayerAndroid* layer = 0) : m_layer(layer) {} + FixedPositioning(LayerAndroid* layer, const FixedPositioning& position); + virtual ~FixedPositioning() {}; + + void setFixedPosition(SkLength left, // CSS left property + SkLength top, // CSS top property + SkLength right, // CSS right property + SkLength bottom, // CSS bottom property + SkLength marginLeft, // CSS margin-left property + SkLength marginTop, // CSS margin-top property + SkLength marginRight, // CSS margin-right property + SkLength marginBottom, // CSS margin-bottom property + const IntPoint& renderLayerPos, // For undefined fixed position + SkRect viewRect) { // view rect, can be smaller than the layer's + m_fixedLeft = left; + m_fixedTop = top; + m_fixedRight = right; + m_fixedBottom = bottom; + m_fixedMarginLeft = marginLeft; + m_fixedMarginTop = marginTop; + m_fixedMarginRight = marginRight; + m_fixedMarginBottom = marginBottom; + m_fixedRect = viewRect; + m_renderLayerPos = renderLayerPos; + } + + IFrameLayerAndroid* updatePosition(SkRect viewPort, + IFrameLayerAndroid* parentIframeLayer); + + void contentDraw(SkCanvas* canvas, Layer::PaintStyle style); + + void dumpLayer(FILE*, int indentLevel) const; + + // ViewStateSerializer friends + friend void android::serializeLayer(LayerAndroid* layer, SkWStream* stream); + friend LayerAndroid* android::deserializeLayer(int version, SkStream* stream); + +private: + LayerAndroid* m_layer; + + SkLength m_fixedLeft; + SkLength m_fixedTop; + SkLength m_fixedRight; + SkLength m_fixedBottom; + SkLength m_fixedMarginLeft; + SkLength m_fixedMarginTop; + SkLength m_fixedMarginRight; + SkLength m_fixedMarginBottom; + SkRect m_fixedRect; + + // When fixed element is undefined or auto, the render layer's position + // is needed for offset computation + IntPoint m_renderLayerPos; +}; + +} + +#endif // USE(ACCELERATED_COMPOSITING) + +#endif // FixedPositioning_h diff --git a/Source/WebCore/platform/graphics/android/FontAndroid.cpp b/Source/WebCore/platform/graphics/android/FontAndroid.cpp index 0a8c0c1..ef7740c 100644 --- a/Source/WebCore/platform/graphics/android/FontAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/FontAndroid.cpp @@ -52,6 +52,7 @@ #include <wtf/OwnPtr.h> #include <wtf/PassOwnArrayPtr.h> #include <wtf/PassOwnPtr.h> +#include <wtf/unicode/CharacterNames.h> #include <wtf/unicode/Unicode.h> #endif @@ -379,7 +380,7 @@ static int truncateFixedPointToInteger(HB_Fixed value) // can call |reset| to start over again. class TextRunWalker { public: - TextRunWalker(const TextRun&, unsigned, const Font*); + TextRunWalker(const TextRun&, int, int, const Font*); ~TextRunWalker(); bool isWordBreak(unsigned, bool); @@ -425,10 +426,10 @@ public: // Return the length of the array returned by |glyphs| unsigned length() const { return m_item.num_glyphs; } - // Return the x offset for each of the glyphs. Note that this is translated + // Return the offset for each of the glyphs. Note that this is translated // by the current x offset and that the x offset is updated for each script // run. - const SkScalar* xPositions() const { return m_xPositions; } + const SkPoint* positions() const { return m_positions; } // Get the advances (widths) for each glyph. const HB_Fixed* advances() const { return m_item.advances; } @@ -472,7 +473,7 @@ private: void createGlyphArrays(int); void resetGlyphArrays(); void shapeGlyphs(); - void setGlyphXPositions(bool); + void setGlyphPositions(bool); static void normalizeSpacesAndMirrorChars(const UChar* source, bool rtl, UChar* destination, int length); @@ -485,10 +486,11 @@ private: const Font* const m_font; HB_ShaperItem m_item; uint16_t* m_glyphs16; // A vector of 16-bit glyph ids. - SkScalar* m_xPositions; // A vector of x positions for each glyph. + SkPoint* m_positions; // A vector of positions for each glyph. ssize_t m_indexOfNextScriptRun; // Indexes the script run in |m_run|. - const unsigned m_startingX; // Offset in pixels of the first script run. - unsigned m_offsetX; // Offset in pixels to the start of the next script run. + const int m_startingX; // Offset in pixels of the first script run. + const int m_startingY; // Offset in pixels of the first script run. + int m_offsetX; // Offset in pixels to the start of the next script run. unsigned m_pixelWidth; // Width (in px) of the current script run. unsigned m_numCodePoints; // Code points in current script run. unsigned m_glyphsArrayCapacity; // Current size of all the Harfbuzz arrays. @@ -519,9 +521,10 @@ const char* TextRunWalker::paths[] = { "/system/fonts/DroidSansThai.ttf" }; -TextRunWalker::TextRunWalker(const TextRun& run, unsigned startingX, const Font* font) +TextRunWalker::TextRunWalker(const TextRun& run, int startingX, int startingY, const Font* font) : m_font(font) , m_startingX(startingX) + , m_startingY(startingY) , m_offsetX(m_startingX) , m_run(getNormalizedTextRun(run, m_normalizedRun, m_normalizedBuffer)) , m_iterateBackwards(m_run.rtl()) @@ -650,7 +653,7 @@ bool TextRunWalker::nextScriptRun() setupFontForScriptRun(); shapeGlyphs(); - setGlyphXPositions(rtl()); + setGlyphPositions(rtl()); return true; } @@ -737,6 +740,16 @@ void TextRunWalker::setupFontForScriptRun() } m_item.face = complexPlatformData->harfbuzzFace(); m_item.font->userData = const_cast<FontPlatformData*>(complexPlatformData); + + int size = complexPlatformData->size(); + m_item.font->x_ppem = size; + m_item.font->y_ppem = size; + // x_ and y_scale are the conversion factors from font design space (fEmSize) to 1/64th of device pixels in 16.16 format. + const int devicePixelFraction = 64; + const int multiplyFor16Dot16 = 1 << 16; + int scale = devicePixelFraction * size * multiplyFor16Dot16 / complexPlatformData->emSizeInFontUnits(); + m_item.font->x_scale = scale; + m_item.font->y_scale = scale; } HB_FontRec* TextRunWalker::allocHarfbuzzFont() @@ -745,13 +758,6 @@ HB_FontRec* TextRunWalker::allocHarfbuzzFont() memset(font, 0, sizeof(HB_FontRec)); font->klass = &harfbuzzSkiaClass; font->userData = 0; - // The values which harfbuzzSkiaClass returns are already scaled to - // pixel units, so we just set all these to one to disable further - // scaling. - font->x_ppem = 1; - font->y_ppem = 1; - font->x_scale = 1; - font->y_scale = 1; return font; } @@ -763,7 +769,7 @@ void TextRunWalker::deleteGlyphArrays() delete[] m_item.advances; delete[] m_item.offsets; delete[] m_glyphs16; - delete[] m_xPositions; + delete[] m_positions; } void TextRunWalker::createGlyphArrays(int size) @@ -774,7 +780,7 @@ void TextRunWalker::createGlyphArrays(int size) m_item.offsets = new HB_FixedPoint[size]; m_glyphs16 = new uint16_t[size]; - m_xPositions = new SkScalar[size]; + m_positions = new SkPoint[size]; m_item.num_glyphs = size; m_glyphsArrayCapacity = size; // Save the GlyphArrays size. @@ -790,7 +796,7 @@ void TextRunWalker::resetGlyphArrays() memset(m_item.advances, 0, size * sizeof(m_item.advances[0])); memset(m_item.offsets, 0, size * sizeof(m_item.offsets[0])); memset(m_glyphs16, 0, size * sizeof(m_glyphs16[0])); - memset(m_xPositions, 0, size * sizeof(m_xPositions[0])); + memset(m_positions, 0, size * sizeof(m_positions[0])); } void TextRunWalker::shapeGlyphs() @@ -810,7 +816,7 @@ void TextRunWalker::shapeGlyphs() } } -void TextRunWalker::setGlyphXPositions(bool isRTL) +void TextRunWalker::setGlyphPositions(bool isRTL) { int position = 0; // logClustersIndex indexes logClusters for the first (or last when @@ -825,7 +831,9 @@ void TextRunWalker::setGlyphXPositions(bool isRTL) int i = isRTL ? m_item.num_glyphs - iter - 1 : iter; m_glyphs16[i] = m_item.glyphs[i]; - m_xPositions[i] = SkIntToScalar(m_offsetX + position); + int offsetX = truncateFixedPointToInteger(m_item.offsets[i].x); + int offsetY = truncateFixedPointToInteger(m_item.offsets[i].y); + m_positions[i].set(SkIntToScalar(m_offsetX + position) + offsetX, m_startingY + offsetY); int advance = truncateFixedPointToInteger(m_item.advances[i]); // The first half of the conjunction works around the case where @@ -846,6 +854,21 @@ void TextRunWalker::setGlyphXPositions(bool isRTL) } } + // ZeroWidthJoiners and ZeroWidthNonJoiners should be stripped by + // Harfbuzz, but aren't. Check for zwj and zwnj and replace with a + // zero width space. We get the glyph data for space instead of + // zeroWidthSpace because the latter was seen to render with an + // unexpected code point (the symbol for a cloud). Since the standard + // space is in page zero and since we've also confirmed that there is + // no advance on this glyph, that should be ok. + if (0 == m_item.advances[i]) { + const HB_UChar16 c = m_item.string[m_item.item.pos + logClustersIndex]; + if ((c == zeroWidthJoiner) || (c == zeroWidthNonJoiner)) { + static Glyph spaceGlyph = m_font->glyphDataForCharacter(space, false).glyph; + m_glyphs16[i] = spaceGlyph; + } + } + // TODO We would like to add m_letterSpacing after each cluster, but I // don't know where the cluster information is. This is typically // fine for Roman languages, but breaks more complex languages @@ -878,10 +901,14 @@ void TextRunWalker::normalizeSpacesAndMirrorChars(const UChar* source, bool rtl, UChar32 character; int nextPosition = position; U16_NEXT(source, nextPosition, length, character); + if (Font::treatAsSpace(character)) - character = ' '; + character = space; + else if (Font::treatAsZeroWidthSpaceInComplexScript(character)) + character = zeroWidthSpace; else if (rtl) character = u_charMirror(character); + U16_APPEND(destination, position, length, character, error); ASSERT(!error); position = nextPosition; @@ -947,7 +974,7 @@ FloatRect Font::selectionRectForComplexText(const TextRun& run, { int fromX = -1, toX = -1, fromAdvance = -1, toAdvance = -1; - TextRunWalker walker(run, 0, this); + TextRunWalker walker(run, 0, 0, this); walker.setWordAndLetterSpacing(wordSpacing(), letterSpacing()); // Base will point to the x offset for the current script run. Note that, in @@ -974,14 +1001,14 @@ FloatRect Font::selectionRectForComplexText(const TextRun& run, // find which glyph this code-point contributed to and find its x // position. int glyph = walker.logClusters()[from]; - fromX = base + walker.xPositions()[glyph]; + fromX = base + walker.positions()[glyph].x(); fromAdvance = walker.advances()[glyph]; } else from -= numCodePoints; if (toX == -1 && to < numCodePoints) { int glyph = walker.logClusters()[to]; - toX = base + walker.xPositions()[glyph]; + toX = base + walker.positions()[glyph].x(); toAdvance = walker.advances()[glyph]; } else to -= numCodePoints; @@ -1028,7 +1055,7 @@ void Font::drawComplexText(GraphicsContext* gc, TextRun const& run, SkCanvas* canvas = gc->platformContext()->mCanvas; bool haveMultipleLayers = isCanvasMultiLayered(canvas); - TextRunWalker walker(run, point.x(), this); + TextRunWalker walker(run, point.x(), point.y(), this); walker.setWordAndLetterSpacing(wordSpacing(), letterSpacing()); walker.setPadding(run.expansion()); @@ -1036,14 +1063,14 @@ void Font::drawComplexText(GraphicsContext* gc, TextRun const& run, if (fill) { walker.fontPlatformDataForScriptRun()->setupPaint(&fillPaint); adjustTextRenderMode(&fillPaint, haveMultipleLayers); - canvas->drawPosTextH(walker.glyphs(), walker.length() << 1, - walker.xPositions(), point.y(), fillPaint); + canvas->drawPosText(walker.glyphs(), walker.length() << 1, + walker.positions(), fillPaint); } if (stroke) { walker.fontPlatformDataForScriptRun()->setupPaint(&strokePaint); adjustTextRenderMode(&strokePaint, haveMultipleLayers); - canvas->drawPosTextH(walker.glyphs(), walker.length() << 1, - walker.xPositions(), point.y(), strokePaint); + canvas->drawPosText(walker.glyphs(), walker.length() << 1, + walker.positions(), strokePaint); } } } @@ -1051,7 +1078,7 @@ void Font::drawComplexText(GraphicsContext* gc, TextRun const& run, float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>*, GlyphOverflow*) const { - TextRunWalker walker(run, 0, this); + TextRunWalker walker(run, 0, 0, this); walker.setWordAndLetterSpacing(wordSpacing(), letterSpacing()); return walker.widthOfFullRun(); } @@ -1083,7 +1110,7 @@ int Font::offsetForPositionForComplexText(const TextRun& run, float x, { // (Mac code ignores includePartialGlyphs, and they don't know what it's // supposed to do, so we just ignore it as well.) - TextRunWalker walker(run, 0, this); + TextRunWalker walker(run, 0, 0, this); walker.setWordAndLetterSpacing(wordSpacing(), letterSpacing()); // If this is RTL text, the first glyph from the left is actually the last diff --git a/Source/WebCore/platform/graphics/android/FontPlatformData.h b/Source/WebCore/platform/graphics/android/FontPlatformData.h index 5c3313e..1e46971 100644 --- a/Source/WebCore/platform/graphics/android/FontPlatformData.h +++ b/Source/WebCore/platform/graphics/android/FontPlatformData.h @@ -82,6 +82,7 @@ public: float size() const { return mTextSize; } unsigned hash() const; + int emSizeInFontUnits() const; bool isFixedPitch() const; #ifndef NDEBUG @@ -113,6 +114,7 @@ private: SkTypeface* mTypeface; float mTextSize; + mutable int mEmSizeInFontUnits; bool mFakeBold; bool mFakeItalic; FontOrientation mOrientation; diff --git a/Source/WebCore/platform/graphics/android/FontPlatformDataAndroid.cpp b/Source/WebCore/platform/graphics/android/FontPlatformDataAndroid.cpp index 3c90246..fc254c0 100644 --- a/Source/WebCore/platform/graphics/android/FontPlatformDataAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/FontPlatformDataAndroid.cpp @@ -33,6 +33,7 @@ #ifdef SUPPORT_COMPLEX_SCRIPTS #include "HarfbuzzSkia.h" #endif +#include "SkAdvancedTypefaceMetrics.h" #include "SkPaint.h" #include "SkTypeface.h" @@ -74,7 +75,7 @@ FontPlatformData::RefCountedHarfbuzzFace::~RefCountedHarfbuzzFace() } FontPlatformData::FontPlatformData() - : mTypeface(NULL), mTextSize(0), mFakeBold(false), mFakeItalic(false), + : mTypeface(NULL), mTextSize(0), mEmSizeInFontUnits(0), mFakeBold(false), mFakeItalic(false), mOrientation(Horizontal), mTextOrientation(TextOrientationVerticalRight) { inc_count(); @@ -87,10 +88,10 @@ FontPlatformData::FontPlatformData(const FontPlatformData& src) SkSafeRef(src.mTypeface); } - mTypeface = src.mTypeface; - - mTextSize = src.mTextSize; - mFakeBold = src.mFakeBold; + mTypeface = src.mTypeface; + mTextSize = src.mTextSize; + mEmSizeInFontUnits = src.mEmSizeInFontUnits; + mFakeBold = src.mFakeBold; mFakeItalic = src.mFakeItalic; m_harfbuzzFace = src.m_harfbuzzFace; mOrientation = src.mOrientation; @@ -102,7 +103,7 @@ FontPlatformData::FontPlatformData(const FontPlatformData& src) FontPlatformData::FontPlatformData(SkTypeface* tf, float textSize, bool fakeBold, bool fakeItalic, FontOrientation orientation, TextOrientation textOrientation) - : mTypeface(tf), mTextSize(textSize), mFakeBold(fakeBold), mFakeItalic(fakeItalic), + : mTypeface(tf), mTextSize(textSize), mEmSizeInFontUnits(0), mFakeBold(fakeBold), mFakeItalic(fakeItalic), mOrientation(orientation), mTextOrientation(textOrientation) { if (hashTableDeletedFontValue() != mTypeface) { @@ -114,8 +115,8 @@ FontPlatformData::FontPlatformData(SkTypeface* tf, float textSize, bool fakeBold } FontPlatformData::FontPlatformData(const FontPlatformData& src, float textSize) - : mTypeface(src.mTypeface), mTextSize(textSize), mFakeBold(src.mFakeBold), mFakeItalic(src.mFakeItalic), - m_harfbuzzFace(src.m_harfbuzzFace), mOrientation(src.mOrientation), mTextOrientation(src.mTextOrientation) + : mTypeface(src.mTypeface), mTextSize(textSize), mEmSizeInFontUnits(src.mEmSizeInFontUnits), mFakeBold(src.mFakeBold), mFakeItalic(src.mFakeItalic), + mOrientation(src.mOrientation), mTextOrientation(src.mTextOrientation), m_harfbuzzFace(src.m_harfbuzzFace) { if (hashTableDeletedFontValue() != mTypeface) { SkSafeRef(mTypeface); @@ -126,7 +127,7 @@ FontPlatformData::FontPlatformData(const FontPlatformData& src, float textSize) } FontPlatformData::FontPlatformData(float size, bool bold, bool oblique) - : mTypeface(NULL), mTextSize(size), mFakeBold(bold), mFakeItalic(oblique), + : mTypeface(NULL), mTextSize(size), mEmSizeInFontUnits(0), mFakeBold(bold), mFakeItalic(oblique), mOrientation(Horizontal), mTextOrientation(TextOrientationVerticalRight) { inc_count(); @@ -134,7 +135,7 @@ FontPlatformData::FontPlatformData(float size, bool bold, bool oblique) } FontPlatformData::FontPlatformData(const FontPlatformData& src, SkTypeface* tf) - : mTypeface(tf), mTextSize(src.mTextSize), mFakeBold(src.mFakeBold), + : mTypeface(tf), mTextSize(src.mTextSize), mEmSizeInFontUnits(0), mFakeBold(src.mFakeBold), mFakeItalic(src.mFakeItalic), mOrientation(src.mOrientation), mTextOrientation(src.mTextOrientation) { @@ -158,6 +159,22 @@ FontPlatformData::~FontPlatformData() } } +int FontPlatformData::emSizeInFontUnits() const +{ + if (mEmSizeInFontUnits) + return mEmSizeInFontUnits; + + SkAdvancedTypefaceMetrics* metrics = 0; + if (mTypeface) + metrics = mTypeface->getAdvancedTypefaceMetrics(SkAdvancedTypefaceMetrics::kNo_PerGlyphInfo); + if (metrics) { + mEmSizeInFontUnits = metrics->fEmSize; + metrics->unref(); + } else + mEmSizeInFontUnits = 1000; // default value copied from Skia. + return mEmSizeInFontUnits; +} + FontPlatformData& FontPlatformData::operator=(const FontPlatformData& src) { if (hashTableDeletedFontValue() != src.mTypeface) { @@ -167,9 +184,10 @@ FontPlatformData& FontPlatformData::operator=(const FontPlatformData& src) SkSafeUnref(mTypeface); } - mTypeface = src.mTypeface; - mTextSize = src.mTextSize; - mFakeBold = src.mFakeBold; + mTypeface = src.mTypeface; + mEmSizeInFontUnits = src.mEmSizeInFontUnits; + mTextSize = src.mTextSize; + mFakeBold = src.mFakeBold; mFakeItalic = src.mFakeItalic; m_harfbuzzFace = src.m_harfbuzzFace; mOrientation = src.mOrientation; @@ -180,10 +198,6 @@ FontPlatformData& FontPlatformData::operator=(const FontPlatformData& src) void FontPlatformData::setupPaint(SkPaint* paint) const { - float ts = mTextSize; - if (!(ts > 0)) - ts = 12; - if (hashTableDeletedFontValue() == mTypeface) paint->setTypeface(0); else @@ -192,7 +206,7 @@ void FontPlatformData::setupPaint(SkPaint* paint) const paint->setAntiAlias(true); paint->setSubpixelText(true); paint->setHinting(SkPaint::kSlight_Hinting); - paint->setTextSize(SkFloatToScalar(ts)); + paint->setTextSize(SkFloatToScalar(mTextSize)); paint->setFakeBoldText(mFakeBold); paint->setTextSkewX(mFakeItalic ? -SK_Scalar1/4 : 0); #ifndef SUPPORT_COMPLEX_SCRIPTS diff --git a/Source/WebCore/platform/graphics/android/GLExtras.cpp b/Source/WebCore/platform/graphics/android/GLExtras.cpp index 873ea33..dc983a6 100644 --- a/Source/WebCore/platform/graphics/android/GLExtras.cpp +++ b/Source/WebCore/platform/graphics/android/GLExtras.cpp @@ -26,7 +26,6 @@ #include "config.h" #include "DrawExtra.h" -#include "FindCanvas.h" #include "GLExtras.h" #include "IntRect.h" #include "TilesManager.h" @@ -52,21 +51,10 @@ // Touch ring border width. This is doubled if the ring is not pressed #define RING_BORDER_WIDTH 1 -// Color of the ring is 0x6633b5e5 (copied from framework's holo_light) -#define COLOR_HOLO_LIGHT &m_lightRingTexture, 0x33, 0xb5, 0xe5, 0.4f -// Color of the ring is 0x660099cc (copied from framework's holo_dark) -#define COLOR_HOLO_DARK &m_darkRingTexture, 0x00, 0x99, 0xcc, 0.6f -// Put a cap on the number of matches to draw. If the current page has more -// matches than this, only draw the focused match. This both prevents clutter -// on the page and keeps the performance happy -#define MAX_NUMBER_OF_MATCHES_TO_DRAW 101 GLExtras::GLExtras() - : m_findOnPage(0) - , m_ring(0) - , m_drawExtra(0) - , m_lightRingTexture(-1) - , m_darkRingTexture(-1) + : m_drawExtra(0) + , m_viewport() { } @@ -74,22 +62,28 @@ GLExtras::~GLExtras() { } -void GLExtras::drawRing(SkRect& srcRect, int* texture, int r, int g, int b, float a) +void GLExtras::drawRing(SkRect& srcRect, Color color, const TransformationMatrix* drawMat) { - if (*texture == -1) - *texture = GLUtils::createSampleColorTexture(r, g, b); - if (srcRect.fRight <= srcRect.fLeft || srcRect.fBottom <= srcRect.fTop) { // Invalid rect, reject it return; } XLOG("drawQuad [%fx%f, %f, %f]", srcRect.fLeft, srcRect.fTop, srcRect.width(), srcRect.height()); - TilesManager::instance()->shader()->drawQuad(srcRect, *texture, a); + // Pull the alpha out of the color so that the shader applies it correctly. + // Otherwise we either don't have blending enabled, or the alpha will get + // double applied + Color colorWithoutAlpha(0xFF000000 | color.rgb()); + float alpha = color.alpha() / (float) 255; + if (drawMat) { + TilesManager::instance()->shader()->drawLayerQuad(*drawMat, srcRect, 0, + alpha, false, 0, colorWithoutAlpha); + } else + TilesManager::instance()->shader()->drawQuad(srcRect, 0, alpha, colorWithoutAlpha); } -void GLExtras::drawRegion(const SkRegion& region, bool fill, - bool drawBorder, bool useDark) +void GLExtras::drawRegion(const SkRegion& region, bool fill, bool drawBorder, + const TransformationMatrix* drawMat, Color color) { if (region.isEmpty()) return; @@ -99,10 +93,7 @@ void GLExtras::drawRegion(const SkRegion& region, bool fill, const SkIRect& ir = rgnIter.rect(); SkRect r; r.set(ir.fLeft, ir.fTop, ir.fRight, ir.fBottom); - if (useDark) - drawRing(r, COLOR_HOLO_DARK); - else - drawRing(r, COLOR_HOLO_LIGHT); + drawRing(r, color, drawMat); rgnIter.next(); } } @@ -143,10 +134,7 @@ void GLExtras::drawRegion(const SkRegion& region, bool fill, clip.setRect(line); } r.set(line.fLeft, line.fTop, line.fRight, line.fBottom); - if (useDark) - drawRing(r, COLOR_HOLO_DARK); - else - drawRing(r, COLOR_HOLO_LIGHT); + drawRing(r, color, drawMat); if (startRect.isEmpty()) { startRect.set(line.fLeft, line.fTop, line.fRight, line.fBottom); } @@ -157,57 +145,8 @@ void GLExtras::drawRegion(const SkRegion& region, bool fill, } } -void GLExtras::drawCursorRings() -{ - SkRegion region; - for (size_t i = 0; i < m_ring->rings().size(); i++) { - IntRect rect = m_ring->rings().at(i); - if (i == 0) - region.setRect(rect); - else - region.op(rect, SkRegion::kUnion_Op); - } - drawRegion(region, m_ring->m_isPressed, !m_ring->m_isButton, false); -} - -void GLExtras::drawFindOnPage(SkRect& viewport) -{ - WTF::Vector<MatchInfo>* matches = m_findOnPage->matches(); - XLOG("drawFindOnPage, matches: %p", matches); - if (!matches || !m_findOnPage->isCurrentLocationValid()) - return; - int count = matches->size(); - int current = m_findOnPage->currentMatchIndex(); - XLOG("match count: %d", count); - if (count < MAX_NUMBER_OF_MATCHES_TO_DRAW) - for (int i = 0; i < count; i++) { - MatchInfo& info = matches->at(i); - const SkRegion& region = info.getLocation(); - SkIRect rect = region.getBounds(); - if (rect.intersect(viewport.fLeft, viewport.fTop, - viewport.fRight, viewport.fBottom)) - drawRegion(region, i == current, false, true); -#ifdef DEBUG - else - XLOG("Quick rejecting [%dx%d, %d, %d", rect.fLeft, rect.fTop, - rect.width(), rect.height()); -#endif // DEBUG - } - else { - MatchInfo& info = matches->at(current); - drawRegion(info.getLocation(), true, false, true); - } -} - -void GLExtras::drawGL(IntRect& webViewRect, SkRect& viewport, int titleBarHeight) +void GLExtras::drawGL(const LayerAndroid* layer) { - if (m_drawExtra) { - if (m_drawExtra == m_ring) - drawCursorRings(); - else if (m_drawExtra == m_findOnPage) - drawFindOnPage(viewport); - else - XLOGC("m_drawExtra %p is unknown! (cursor: %p, find: %p", - m_drawExtra, m_ring, m_findOnPage); - } + if (m_drawExtra) + m_drawExtra->drawGL(this, layer); } diff --git a/Source/WebCore/platform/graphics/android/GLExtras.h b/Source/WebCore/platform/graphics/android/GLExtras.h index c52e951..59a7c3c 100644 --- a/Source/WebCore/platform/graphics/android/GLExtras.h +++ b/Source/WebCore/platform/graphics/android/GLExtras.h @@ -26,41 +26,33 @@ #ifndef GLExtras_h #define GLExtras_h +#include "Color.h" +#include "DrawExtra.h" #include "SkRect.h" #include "SkRegion.h" -namespace android { - class FindOnPage; - class CursorRing; - class DrawExtra; -} - namespace WebCore { +class LayerAndroid; +class TransformationMatrix; + class GLExtras { public: GLExtras(); virtual ~GLExtras(); - void drawGL(IntRect& webViewRect, SkRect& viewport, int titleBarHeight); - void setFindOnPageExtra(android::FindOnPage* findOnPage) { - m_findOnPage = findOnPage; - } - void setCursorRingExtra(android::CursorRing* ring) { m_ring = ring; } + void drawGL(const LayerAndroid* layer); void setDrawExtra(android::DrawExtra* extra) { m_drawExtra = extra; } + void setViewport(const SkRect & viewport) { m_viewport = viewport; } -private: - void drawRing(SkRect& srcRect, int* texture, int r, int g, int b, float a); void drawRegion(const SkRegion& region, bool fill, bool drawBorder, - bool useDark = false); - void drawCursorRings(); - void drawFindOnPage(SkRect& viewport); + const TransformationMatrix* drawMat, Color color = COLOR_HOLO_LIGHT); + +private: + void drawRing(SkRect& srcRect, Color color, const TransformationMatrix* drawMat); - android::FindOnPage* m_findOnPage; - android::CursorRing* m_ring; android::DrawExtra* m_drawExtra; - int m_lightRingTexture; - int m_darkRingTexture; + SkRect m_viewport; }; } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/GLUtils.cpp b/Source/WebCore/platform/graphics/android/GLUtils.cpp index 97a53fe..3024d28 100644 --- a/Source/WebCore/platform/graphics/android/GLUtils.cpp +++ b/Source/WebCore/platform/graphics/android/GLUtils.cpp @@ -36,12 +36,11 @@ #include <wtf/CurrentTime.h> #include <wtf/text/CString.h> +#undef XLOGC +#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "GLUtils", __VA_ARGS__) #ifdef DEBUG -#include <cutils/log.h> -#include <wtf/text/CString.h> - #undef XLOG #define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "GLUtils", __VA_ARGS__) @@ -52,6 +51,11 @@ #endif // DEBUG +// We will limit GL error logging for LOG_VOLUME_PER_CYCLE times every +// LOG_VOLUME_PER_CYCLE seconds. +#define LOG_CYCLE 30.0 +#define LOG_VOLUME_PER_CYCLE 20 + struct ANativeWindowBuffer; namespace WebCore { @@ -116,10 +120,35 @@ void GLUtils::setOrthographicMatrix(TransformationMatrix& ortho, float left, flo // GL & EGL error checks ///////////////////////////////////////////////////////////////////////////////////////// -static void crashIfOOM(GLint errorCode) { +double GLUtils::m_previousLogTime = 0; +int GLUtils::m_currentLogCounter = 0; + +bool GLUtils::allowGLLog() +{ + if (m_currentLogCounter < LOG_VOLUME_PER_CYCLE) { + m_currentLogCounter++; + return true; + } + + // when we are in Log cycle and over the log limit, just return false + double currentTime = WTF::currentTime(); + double delta = currentTime - m_previousLogTime; + bool inLogCycle = (delta <= LOG_CYCLE) && (delta > 0); + if (inLogCycle) + return false; + + // When we are out of Log Cycle and over the log limit, we need to reset + // the counter and timer. + m_previousLogTime = currentTime; + m_currentLogCounter = 0; + return false; +} + +static void crashIfOOM(GLint errorCode) +{ const GLint OOM_ERROR_CODE = 0x505; if (errorCode == OOM_ERROR_CODE) { - XLOG("Fatal OOM detected."); + XLOGC("ERROR: Fatal OOM detected."); CRASH(); } } @@ -127,11 +156,17 @@ static void crashIfOOM(GLint errorCode) { void GLUtils::checkEglError(const char* op, EGLBoolean returnVal) { if (returnVal != EGL_TRUE) { - XLOG("EGL ERROR - %s() returned %d\n", op, returnVal); +#ifndef DEBUG + if (allowGLLog()) +#endif + XLOGC("EGL ERROR - %s() returned %d\n", op, returnVal); } for (EGLint error = eglGetError(); error != EGL_SUCCESS; error = eglGetError()) { - XLOG("after %s() eglError (0x%x)\n", op, error); +#ifndef DEBUG + if (allowGLLog()) +#endif + XLOGC("after %s() eglError (0x%x)\n", op, error); crashIfOOM(error); } } @@ -140,7 +175,10 @@ 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); +#ifndef DEBUG + if (allowGLLog()) +#endif + XLOGC("GL ERROR - after %s() glError (0x%x)\n", op, error); crashIfOOM(error); ret = true; } @@ -151,7 +189,10 @@ 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); +#ifndef DEBUG + if (allowGLLog()) +#endif + XLOGC("GL ERROR on %x - after %s() glError (0x%x)\n", p, op, error); crashIfOOM(error); ret = true; } @@ -161,7 +202,10 @@ bool GLUtils::checkGlErrorOn(void* p, const char* op) void GLUtils::checkSurfaceTextureError(const char* functionName, int status) { if (status != NO_ERROR) { - XLOG("ERROR at calling %s status is (%d)", functionName, status); +#ifndef DEBUG + if (allowGLLog()) +#endif + XLOGC("ERROR at calling %s status is (%d)", functionName, status); } } ///////////////////////////////////////////////////////////////////////////////////////// @@ -237,7 +281,7 @@ static EGLConfig defaultPbufferConfig(EGLDisplay display) eglChooseConfig(display, configAttribs, &config, 1, &numConfigs); GLUtils::checkEglError("eglPbufferConfig"); if (numConfigs != 1) - LOGI("eglPbufferConfig failed (%d)\n", numConfigs); + ALOGI("eglPbufferConfig failed (%d)\n", numConfigs); return config; } @@ -313,7 +357,8 @@ void GLUtils::deleteTexture(GLuint* texture) *texture = 0; } -GLuint GLUtils::createSampleColorTexture(int r, int g, int b) { +GLuint GLUtils::createSampleColorTexture(int r, int g, int b) +{ GLuint texture; glGenTextures(1, &texture); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); @@ -370,126 +415,120 @@ GLuint GLUtils::createBaseTileGLTexture(int width, int height) GLUtils::checkGlError("glTexImage2D"); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); +#ifdef DEBUG + delete pixels; +#endif return texture; } +bool GLUtils::isPureColorBitmap(const SkBitmap& bitmap, Color& pureColor) +{ + // If the bitmap is the pure color, skip the transfer step, and update the BaseTile Info. + // This check is taking < 1ms if we do full bitmap check per tile. + // TODO: use the SkPicture to determine whether or not a tile is single color. + pureColor = Color(Color::transparent); + bitmap.lockPixels(); + bool sameColor = true; + int bitmapWidth = bitmap.width(); + + // Create a row of pure color using the first pixel. + // TODO: improve the perf here, by either picking a random pixel, or + // creating an array of rows with pre-defined commonly used color, add + // smart LUT to speed things up if possible. + int* firstPixelPtr = static_cast<int*> (bitmap.getPixels()); + int* pixelsRow = new int[bitmapWidth]; + for (int i = 0; i < bitmapWidth; i++) + pixelsRow[i] = (*firstPixelPtr); + + // Then compare the pure color row with each row of the bitmap. + for (int j = 0; j < bitmap.height(); j++) { + if (memcmp(pixelsRow, &firstPixelPtr[bitmapWidth * j], 4 * bitmapWidth)) { + sameColor = false; + break; + } + } + delete pixelsRow; + pixelsRow = 0; + + if (sameColor) { + char* rgbaPtr = static_cast<char*>(bitmap.getPixels()); + pureColor = Color(rgbaPtr[0], rgbaPtr[1], rgbaPtr[2], rgbaPtr[3]); + XLOG("sameColor tile found , %x at (%d, %d, %d, %d)", + *firstPixelPtr, rgbaPtr[0], rgbaPtr[1], rgbaPtr[2], rgbaPtr[3]); + } + bitmap.unlockPixels(); + + return sameColor; +} + +// Return true when the tile is pure color. +bool GLUtils::skipTransferForPureColor(const TileRenderInfo* renderInfo, + const SkBitmap& bitmap) +{ + bool skipTransfer = false; + BaseTile* tilePtr = renderInfo->baseTile; + + // TODO: use pure color for partial invals as well + if (renderInfo->invalRect) + return false; + + if (tilePtr) { + BaseTileTexture* tileTexture = tilePtr->backTexture(); + // Check the bitmap, and make everything ready here. + Color pureColor; + if (tileTexture && isPureColorBitmap(bitmap, pureColor)) { + // update basetile's info + // Note that we are skipping the whole TransferQueue. + renderInfo->textureInfo->m_width = bitmap.width(); + renderInfo->textureInfo->m_height = bitmap.height(); + renderInfo->textureInfo->m_internalFormat = GL_RGBA; + + TilesManager::instance()->transferQueue()->addItemInPureColorQueue(renderInfo, + pureColor); + + skipTransfer = true; + } + } + return skipTransfer; +} + void GLUtils::paintTextureWithBitmap(const TileRenderInfo* renderInfo, const SkBitmap& bitmap) { if (!renderInfo) return; - const int x = renderInfo->invalRect->fLeft; - const int y = renderInfo->invalRect->fTop; const SkSize& requiredSize = renderInfo->tileSize; TextureInfo* textureInfo = renderInfo->textureInfo; - SharedTextureMode mode = textureInfo->getSharedTextureMode(); - if (requiredSize.equals(textureInfo->m_width, textureInfo->m_height)) { - if (mode == EglImageMode) - GLUtils::updateTextureWithBitmap(textureInfo->m_textureId, x, y, bitmap); - else if (mode == SurfaceTextureMode) -#if DEPRECATED_SURFACE_TEXTURE_MODE - GLUtils::updateSurfaceTextureWithBitmap(renderInfo, x, y, bitmap); -#else - GLUtils::updateSharedSurfaceTextureWithBitmap(renderInfo, x, y, bitmap); -#endif - } else { + if (skipTransferForPureColor(renderInfo, bitmap)) + return; + + if (requiredSize.equals(textureInfo->m_width, textureInfo->m_height)) + GLUtils::updateSharedSurfaceTextureWithBitmap(renderInfo, bitmap); + else { if (!requiredSize.equals(bitmap.width(), bitmap.height())) { XLOG("The bitmap size (%d,%d) does not equal the texture size (%d,%d)", bitmap.width(), bitmap.height(), requiredSize.width(), requiredSize.height()); } + GLUtils::updateSharedSurfaceTextureWithBitmap(renderInfo, bitmap); - if (mode == EglImageMode) - GLUtils::createTextureWithBitmap(textureInfo->m_textureId, bitmap); - else if (mode == SurfaceTextureMode) -#if DEPRECATED_SURFACE_TEXTURE_MODE - GLUtils::createSurfaceTextureWithBitmap(renderInfo, bitmap); -#else - GLUtils::updateSharedSurfaceTextureWithBitmap(renderInfo, 0, 0, bitmap); -#endif textureInfo->m_width = bitmap.width(); textureInfo->m_height = bitmap.height(); textureInfo->m_internalFormat = GL_RGBA; } } -#if DEPRECATED_SURFACE_TEXTURE_MODE -void GLUtils::createSurfaceTextureWithBitmap(const TileRenderInfo* renderInfo, const SkBitmap& bitmap, GLint filter) -{ - - TextureInfo* texture = renderInfo->textureInfo; - - texture->m_width = bitmap.width(); - texture->m_height = bitmap.height(); - texture->m_internalFormat = GL_RGBA; - - sp<android::SurfaceTexture> surfaceTexture = texture->m_surfaceTexture; - sp<ANativeWindow> ANW = texture->m_ANW; - - int result; - result = native_window_set_buffers_geometry(ANW.get(), - texture->m_width, texture->m_height, HAL_PIXEL_FORMAT_RGBA_8888); - checkSurfaceTextureError("native_window_set_buffers_geometry", result); - result = native_window_set_usage(ANW.get(), - GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN); - checkSurfaceTextureError("native_window_set_usage", result); - - updateSurfaceTextureWithBitmap(renderInfo, 0, 0, bitmap, filter); -} - -void GLUtils::updateSurfaceTextureWithBitmap(const TileRenderInfo* renderInfo, int x, int y, const SkBitmap& bitmap, GLint filter) -{ - TextureInfo* texture = renderInfo->textureInfo; - sp<android::SurfaceTexture> surfaceTexture = texture->m_surfaceTexture; - sp<ANativeWindow> ANW = texture->m_ANW; - - ANativeWindowBuffer* anb; - int status = ANW->dequeueBuffer(ANW.get(), &anb); - checkSurfaceTextureError("dequeueBuffer", status); - - if (status != NO_ERROR) { // FIXME: add proper error handling! - native_window_set_buffer_count(ANW.get(), 3); - return; - } - - sp<android::GraphicBuffer> buf(new android::GraphicBuffer(anb, false)); - status |= ANW->lockBuffer(ANW.get(), buf->getNativeBuffer()); - checkSurfaceTextureError("lockBuffer", status); - - // Fill the buffer with the content of the bitmap - uint8_t* img = 0; - status |= buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img)); - checkSurfaceTextureError("lock", status); - - if (status == NO_ERROR) { - int row, col; - int bpp = 4; // Now only deal with RGBA8888 format. - - bitmap.lockPixels(); - uint8_t* bitmapOrigin = static_cast<uint8_t*>(bitmap.getPixels()); - // Copied line by line since we need to handle the offsets and stride. - for (row = 0 ; row < bitmap.height(); row ++) { - uint8_t* dst = &(img[(buf->getStride() * (row + x) + y) * bpp]); - uint8_t* src = &(bitmapOrigin[bitmap.width() * row * bpp]); - memcpy(dst, src, bpp * bitmap.width()); - } - bitmap.unlockPixels(); - } - buf->unlock(); - status = ANW->queueBuffer(ANW.get(), buf->getNativeBuffer()); - checkSurfaceTextureError("queueBuffer", status); -} -#endif - -void GLUtils::updateSharedSurfaceTextureWithBitmap(const TileRenderInfo* renderInfo, int x, int y, const SkBitmap& bitmap) +void GLUtils::updateSharedSurfaceTextureWithBitmap(const TileRenderInfo* renderInfo, const SkBitmap& bitmap) { if (!renderInfo || !renderInfo->textureInfo || !renderInfo->baseTile) return; - TilesManager::instance()->transferQueue()->updateQueueWithBitmap(renderInfo, x, y, bitmap); + TilesManager::instance()->transferQueue()->updateQueueWithBitmap(renderInfo, bitmap); } void GLUtils::createTextureWithBitmap(GLuint texture, const SkBitmap& bitmap, GLint filter) @@ -505,7 +544,10 @@ void GLUtils::createTextureWithBitmap(GLuint texture, const SkBitmap& bitmap, GL 0, internalformat, type, bitmap.getPixels()); bitmap.unlockPixels(); if (GLUtils::checkGlError("glTexImage2D")) { - XLOG("GL ERROR: glTexImage2D parameters are : bitmap.width() %d, bitmap.height() %d," +#ifndef DEBUG + if (allowGLLog()) +#endif + XLOGC("GL ERROR: glTexImage2D parameters are : bitmap.width() %d, bitmap.height() %d," " internalformat 0x%x, type 0x%x, bitmap.getPixels() %p", bitmap.width(), bitmap.height(), internalformat, type, bitmap.getPixels()); } @@ -523,7 +565,8 @@ void GLUtils::createTextureWithBitmap(GLuint texture, const SkBitmap& bitmap, GL glDeleteFramebuffers(1, &fboID); } -void GLUtils::updateTextureWithBitmap(GLuint texture, int x, int y, const SkBitmap& bitmap, GLint filter) +void GLUtils::updateTextureWithBitmap(GLuint texture, const SkBitmap& bitmap, + const IntRect& inval, GLint filter) { glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glBindTexture(GL_TEXTURE_2D, texture); @@ -532,13 +575,21 @@ void GLUtils::updateTextureWithBitmap(GLuint texture, int x, int y, const SkBitm int internalformat = getInternalFormat(config); int type = getType(config); bitmap.lockPixels(); - glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, bitmap.width(), bitmap.height(), - internalformat, type, bitmap.getPixels()); + if (inval.isEmpty()) { + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bitmap.width(), bitmap.height(), + internalformat, type, bitmap.getPixels()); + } else { + glTexSubImage2D(GL_TEXTURE_2D, 0, inval.x(), inval.y(), inval.width(), inval.height(), + internalformat, type, bitmap.getPixels()); + } bitmap.unlockPixels(); if (GLUtils::checkGlError("glTexSubImage2D")) { - XLOG("GL ERROR: glTexSubImage2D parameters are : bitmap.width() %d, bitmap.height() %d," - " x %d, y %d, internalformat 0x%x, type 0x%x, bitmap.getPixels() %p", - bitmap.width(), bitmap.height(), x, y, internalformat, type, bitmap.getPixels()); +#ifndef DEBUG + if (allowGLLog()) +#endif + XLOGC("GL ERROR: glTexSubImage2D parameters are : bitmap.width() %d, bitmap.height() %d," + " internalformat 0x%x, type 0x%x, bitmap.getPixels() %p", + bitmap.width(), bitmap.height(), internalformat, type, bitmap.getPixels()); } glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); diff --git a/Source/WebCore/platform/graphics/android/GLUtils.h b/Source/WebCore/platform/graphics/android/GLUtils.h index 68acbab..e001aee 100644 --- a/Source/WebCore/platform/graphics/android/GLUtils.h +++ b/Source/WebCore/platform/graphics/android/GLUtils.h @@ -28,6 +28,7 @@ #if USE(ACCELERATED_COMPOSITING) +#include "Color.h" #include "SkBitmap.h" #include "SkMatrix.h" #include "SkSize.h" @@ -73,17 +74,20 @@ public: static GLuint createBaseTileGLTexture(int width, int height); static void createTextureWithBitmap(GLuint texture, const SkBitmap& bitmap, GLint filter = GL_LINEAR); - static void updateTextureWithBitmap(GLuint texture, int x, int y, const SkBitmap& bitmap, GLint filter = GL_LINEAR); + static void updateTextureWithBitmap(GLuint texture, const SkBitmap& bitmap, const IntRect&, GLint filter = GL_LINEAR); static void createEGLImageFromTexture(GLuint texture, EGLImageKHR* image); static void createTextureFromEGLImage(GLuint texture, EGLImageKHR image, GLint filter = GL_LINEAR); static void paintTextureWithBitmap(const TileRenderInfo* renderInfo, const SkBitmap& bitmap); -#if DEPRECATED_SURFACE_TEXTURE_MODE - static void createSurfaceTextureWithBitmap(const TileRenderInfo* , const SkBitmap& bitmap, GLint filter = GL_LINEAR); - static void updateSurfaceTextureWithBitmap(const TileRenderInfo* , int x, int y, const SkBitmap& bitmap, GLint filter = GL_LINEAR); -#endif - static void updateSharedSurfaceTextureWithBitmap(const TileRenderInfo* , int x, int y, const SkBitmap& bitmap); + static void updateSharedSurfaceTextureWithBitmap(const TileRenderInfo* , const SkBitmap& bitmap); static void convertToTransformationMatrix(const float* matrix, TransformationMatrix& transformMatrix); + + static bool isPureColorBitmap(const SkBitmap& bitmap, Color& pureColor); + static bool skipTransferForPureColor(const TileRenderInfo* renderInfo, + const SkBitmap& bitmap); + static bool allowGLLog(); + static double m_previousLogTime; + static int m_currentLogCounter; }; } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/GLWebViewState.cpp b/Source/WebCore/platform/graphics/android/GLWebViewState.cpp index 3bcda9a..97bd7a8 100644 --- a/Source/WebCore/platform/graphics/android/GLWebViewState.cpp +++ b/Source/WebCore/platform/graphics/android/GLWebViewState.cpp @@ -37,12 +37,11 @@ #include "SkPath.h" #include "TilesManager.h" #include "TilesTracker.h" -#include "TreeManager.h" -#include <wtf/CurrentTime.h> - -#include <pthread.h> - +#include "SurfaceCollection.h" +#include "SurfaceCollectionManager.h" #include <cutils/log.h> +#include <pthread.h> +#include <wtf/CurrentTime.h> #include <wtf/text/CString.h> #undef XLOGC @@ -69,24 +68,31 @@ #define MIN_SCALE_WARNING 0.1 #define MAX_SCALE_WARNING 10 +// fps indicator is FPS_INDICATOR_HEIGHT pixels high. +// The max width is equal to MAX_FPS_VALUE fps. +#define FPS_INDICATOR_HEIGHT 10 +#define MAX_FPS_VALUE 60 + +#define COLLECTION_SWAPPED_COUNTER_MODULE 10 + namespace WebCore { using namespace android; GLWebViewState::GLWebViewState() : m_zoomManager(this) - , m_currentPictureCounter(0) , m_usePageA(true) , m_frameworkInval(0, 0, 0, 0) , m_frameworkLayersInval(0, 0, 0, 0) , m_isScrolling(false) + , m_isViewportScrolling(false) , m_goingDown(true) , m_goingLeft(false) , m_expandedTileBoundsX(0) , m_expandedTileBoundsY(0) - , m_highEndGfx(false) , m_scale(1) , m_layersRenderingMode(kAllTextures) + , m_surfaceCollectionManager(this) { m_viewport.setEmpty(); m_futureViewportTileBounds.setEmpty(); @@ -108,9 +114,6 @@ GLWebViewState::GLWebViewState() GLWebViewState::~GLWebViewState() { - // Take care of the transfer queue such that Tex Gen thread will not stuck - TilesManager::instance()->unregisterGLWebViewState(this); - // We have to destroy the two tiled pages first as their destructor // may depend on the existence of this GLWebViewState and some of its // instance variables in order to complete. @@ -125,22 +128,22 @@ GLWebViewState::~GLWebViewState() } -void GLWebViewState::setBaseLayer(BaseLayerAndroid* layer, const SkRegion& inval, - bool showVisualIndicator, bool isPictureAfterFirstLayout) +bool GLWebViewState::setBaseLayer(BaseLayerAndroid* layer, bool showVisualIndicator, + bool isPictureAfterFirstLayout) { if (!layer || isPictureAfterFirstLayout) { - // TODO: move this into TreeManager + // TODO: move this into SurfaceCollectionManager m_zoomManager.swapPages(); // reset zoom state m_tiledPageA->discardTextures(); m_tiledPageB->discardTextures(); m_layersRenderingMode = kAllTextures; } if (layer) { - XLOG("new base layer %p, (inval region empty %d) with child %p", layer, inval.isEmpty(), layer->getChild(0)); + XLOG("new base layer %p, with child %p", layer, layer->getChild(0)); layer->setState(this); - layer->markAsDirty(inval); // TODO: set in webview.cpp } - m_treeManager.updateWithTree(layer, isPictureAfterFirstLayout); + bool queueFull = m_surfaceCollectionManager.updateWithSurfaceCollection( + new SurfaceCollection(layer), isPictureAfterFirstLayout); m_glExtras.setDrawExtra(0); #ifdef MEASURES_PERF @@ -150,11 +153,12 @@ void GLWebViewState::setBaseLayer(BaseLayerAndroid* layer, const SkRegion& inval #endif TilesManager::instance()->setShowVisualIndicator(showVisualIndicator); + return queueFull; } void GLWebViewState::scrollLayer(int layerId, int x, int y) { - m_treeManager.updateScrollableLayer(layerId, x, y); + m_surfaceCollectionManager.updateScrollableLayer(layerId, x, y); // TODO: only inval the area of the scrolled layer instead of // doing a fullInval() @@ -165,8 +169,8 @@ void GLWebViewState::scrollLayer(int layerId, int x, int y) void GLWebViewState::invalRegion(const SkRegion& region) { if (m_layersRenderingMode == kSingleSurfaceRendering) { - // TODO: do the union of both layers tree to compute - //the minimum inval instead of doing a fullInval() + // TODO: do the union of both layer trees to compute + // the minimum inval instead of doing a fullInval() fullInval(); return; } @@ -181,11 +185,10 @@ void GLWebViewState::invalRegion(const SkRegion& region) void GLWebViewState::inval(const IntRect& rect) { - m_currentPictureCounter++; if (!rect.isEmpty()) { // find which tiles fall within the invalRect and mark them as dirty - m_tiledPageA->invalidateRect(rect, m_currentPictureCounter); - m_tiledPageB->invalidateRect(rect, m_currentPictureCounter); + m_tiledPageA->invalidateRect(rect); + m_tiledPageB->invalidateRect(rect); if (m_frameworkInval.isEmpty()) m_frameworkInval = rect; else @@ -197,10 +200,9 @@ void GLWebViewState::inval(const IntRect& rect) TilesManager::instance()->getProfiler()->nextInval(rect, zoomManager()->currentScale()); } -unsigned int GLWebViewState::paintBaseLayerContent(SkCanvas* canvas) +void GLWebViewState::paintBaseLayerContent(SkCanvas* canvas) { - m_treeManager.drawCanvas(canvas, m_layersRenderingMode == kSingleSurfaceRendering); - return m_currentPictureCounter; + m_surfaceCollectionManager.drawCanvas(canvas, m_layersRenderingMode == kSingleSurfaceRendering); } TiledPage* GLWebViewState::sibling(TiledPage* page) @@ -231,21 +233,42 @@ void GLWebViewState::swapPages() int GLWebViewState::baseContentWidth() { - return m_treeManager.baseContentWidth(); + return m_surfaceCollectionManager.baseContentWidth(); } int GLWebViewState::baseContentHeight() { - return m_treeManager.baseContentHeight(); + return m_surfaceCollectionManager.baseContentHeight(); } -void GLWebViewState::setViewport(SkRect& viewport, float scale) +void GLWebViewState::setViewport(const SkRect& viewport, float scale) { - if ((m_viewport == viewport) && - (zoomManager()->futureScale() == scale)) + // allocate max possible number of tiles visible with this viewport / expandedTileBounds + const float invTileContentWidth = scale / TilesManager::tileWidth(); + const float invTileContentHeight = scale / TilesManager::tileHeight(); + + int viewMaxTileX = static_cast<int>(ceilf((viewport.width()-1) * invTileContentWidth)) + 1; + int viewMaxTileY = static_cast<int>(ceilf((viewport.height()-1) * invTileContentHeight)) + 1; + + TilesManager* manager = TilesManager::instance(); + int maxTextureCount = (viewMaxTileX + m_expandedTileBoundsX * 2) * + (viewMaxTileY + m_expandedTileBoundsY * 2) * (manager->highEndGfx() ? 4 : 2); + + manager->setMaxTextureCount(maxTextureCount); + m_tiledPageA->updateBaseTileSize(); + m_tiledPageB->updateBaseTileSize(); + + if ((m_viewport == viewport) + && (zoomManager()->futureScale() == scale)) { + // everything below will stay the same, early return. + m_isViewportScrolling = false; return; + } m_goingDown = m_viewport.fTop - viewport.fTop <= 0; m_goingLeft = m_viewport.fLeft - viewport.fLeft >= 0; + + // detect viewport scrolling from short programmatic scrolls/jumps + m_isViewportScrolling = m_viewport != viewport && SkRect::Intersects(m_viewport, viewport); m_viewport = viewport; XLOG("New VIEWPORT %.2f - %.2f %.2f - %.2f (w: %2.f h: %.2f scale: %.2f currentScale: %.2f futureScale: %.2f)", @@ -253,25 +276,11 @@ void GLWebViewState::setViewport(SkRect& viewport, float scale) m_viewport.width(), m_viewport.height(), scale, zoomManager()->currentScale(), zoomManager()->futureScale()); - const float invTileContentWidth = scale / TilesManager::tileWidth(); - const float invTileContentHeight = scale / TilesManager::tileHeight(); - m_viewportTileBounds.set( static_cast<int>(floorf(viewport.fLeft * invTileContentWidth)), static_cast<int>(floorf(viewport.fTop * invTileContentHeight)), static_cast<int>(ceilf(viewport.fRight * invTileContentWidth)), static_cast<int>(ceilf(viewport.fBottom * invTileContentHeight))); - - // allocate max possible number of tiles visible with this viewport - int viewMaxTileX = static_cast<int>(ceilf((viewport.width()-1) * invTileContentWidth)) + 1; - int viewMaxTileY = static_cast<int>(ceilf((viewport.height()-1) * invTileContentHeight)) + 1; - - int maxTextureCount = (viewMaxTileX + m_expandedTileBoundsX * 2) * - (viewMaxTileY + m_expandedTileBoundsY * 2) * (m_highEndGfx ? 4 : 2); - - TilesManager::instance()->setMaxTextureCount(maxTextureCount); - m_tiledPageA->updateBaseTileSize(); - m_tiledPageB->updateBaseTileSize(); } #ifdef MEASURES_PERF @@ -331,27 +340,34 @@ void GLWebViewState::drawBackground(Color& backgroundColor) glClear(GL_COLOR_BUFFER_BIT); } -double GLWebViewState::setupDrawing(IntRect& viewRect, SkRect& visibleRect, - IntRect& webViewRect, int titleBarHeight, - IntRect& screenClip, float scale) +double GLWebViewState::setupDrawing(const IntRect& viewRect, const SkRect& visibleRect, + const IntRect& webViewRect, int titleBarHeight, + const IntRect& screenClip, float scale) { int left = viewRect.x(); int top = viewRect.y(); int width = viewRect.width(); int height = viewRect.height(); - - ShaderProgram* shader = TilesManager::instance()->shader(); - if (shader->program() == -1) { - XLOG("Reinit shader"); - shader->init(); + TilesManager* tilesManager = TilesManager::instance(); + + // Make sure GL resources are created on the UI thread. + // They are created either for the first time, or after EGL context + // recreation caused by onTrimMemory in the framework. + ShaderProgram* shader = tilesManager->shader(); + if (shader->needsInit()) { + XLOGC("Reinit shader"); + shader->initGLResources(); + } + TransferQueue* transferQueue = tilesManager->transferQueue(); + if (transferQueue->needsInit()) { + XLOGC("Reinit transferQueue"); + transferQueue->initGLResources(TilesManager::tileWidth(), + TilesManager::tileHeight()); } - shader->setViewport(visibleRect, scale); - shader->setViewRect(viewRect); - shader->setWebViewRect(webViewRect); - shader->setTitleBarHeight(titleBarHeight); - shader->setScreenClip(screenClip); - shader->resetBlending(); + // TODO: Add the video GL resource re-initialization code here. + shader->setupDrawing(viewRect, visibleRect, webViewRect, + titleBarHeight, screenClip, scale); shader->calculateAnimationDelta(); glViewport(left + shader->getAnimationDeltaX(), @@ -447,25 +463,24 @@ void GLWebViewState::fullInval() bool GLWebViewState::drawGL(IntRect& rect, SkRect& viewport, IntRect* invalRect, IntRect& webViewRect, int titleBarHeight, IntRect& clip, float scale, - bool* treesSwappedPtr, bool* newTreeHasAnimPtr) + bool* collectionsSwappedPtr, bool* newCollectionHasAnimPtr) { + TilesManager* tilesManager = TilesManager::instance(); m_scale = scale; - TilesManager::instance()->getProfiler()->nextFrame(viewport.fLeft, - viewport.fTop, - viewport.fRight, - viewport.fBottom, - scale); - TilesManager::instance()->incDrawGLCount(); + tilesManager->getProfiler()->nextFrame(viewport.fLeft, viewport.fTop, + viewport.fRight, viewport.fBottom, + scale); + tilesManager->incDrawGLCount(); #ifdef DEBUG - TilesManager::instance()->getTilesTracker()->clear(); + tilesManager->getTilesTracker()->clear(); #endif float viewWidth = (viewport.fRight - viewport.fLeft) * TILE_PREFETCH_RATIO; float viewHeight = (viewport.fBottom - viewport.fTop) * TILE_PREFETCH_RATIO; - bool useMinimalMemory = TilesManager::instance()->useMinimalMemory(); - bool useHorzPrefetch = useMinimalMemory ? 0 : viewWidth < baseContentWidth(); - bool useVertPrefetch = useMinimalMemory ? 0 : viewHeight < baseContentHeight(); + bool noPrefetch = tilesManager->useMinimalMemory() || !tilesManager->highEndGfx(); + bool useHorzPrefetch = noPrefetch ? 0 : viewWidth < baseContentWidth(); + bool useVertPrefetch = noPrefetch ? 0 : viewHeight < baseContentHeight(); m_expandedTileBoundsX = (useHorzPrefetch) ? TILE_PREFETCH_DISTANCE : 0; m_expandedTileBoundsY = (useVertPrefetch) ? TILE_PREFETCH_DISTANCE : 0; @@ -473,10 +488,13 @@ bool GLWebViewState::drawGL(IntRect& rect, SkRect& viewport, IntRect* invalRect, rect.x(), rect.y(), rect.width(), rect.height(), viewport.fLeft, viewport.fTop, viewport.fRight, viewport.fBottom); - resetLayersDirtyArea(); + XLOG("drawGL, invalRect(%d, %d, %d, %d), webViewRect(%d, %d, %d, %d)" + "clip (%d, %d, %d, %d), scale %f", + invalRect->x(), invalRect->y(), invalRect->width(), invalRect->height(), + webViewRect.x(), webViewRect.y(), webViewRect.width(), webViewRect.height(), + clip.x(), clip.y(), clip.width(), clip.height(), scale); - // when adding or removing layers, use the the paintingBaseLayer's tree so - // that content that moves to the base layer from a layer is synchronized + resetLayersDirtyArea(); if (scale < MIN_SCALE_WARNING || scale > MAX_SCALE_WARNING) XLOGC("WARNING, scale seems corrupted before update: %e", scale); @@ -484,28 +502,31 @@ bool GLWebViewState::drawGL(IntRect& rect, SkRect& viewport, IntRect* invalRect, // Here before we draw, update the BaseTile which has updated content. // Inside this function, just do GPU blits from the transfer queue into // the BaseTiles' texture. - TilesManager::instance()->transferQueue()->updateDirtyBaseTiles(); + tilesManager->transferQueue()->updateDirtyBaseTiles(); // Upload any pending ImageTexture // Return true if we still have some images to upload. // TODO: upload as many textures as possible within a certain time limit bool ret = ImagesManager::instance()->prepareTextures(this); - if (scale < MIN_SCALE_WARNING || scale > MAX_SCALE_WARNING) + if (scale < MIN_SCALE_WARNING || scale > MAX_SCALE_WARNING) { XLOGC("WARNING, scale seems corrupted after update: %e", scale); + CRASH(); + } // gather the textures we can use - TilesManager::instance()->gatherLayerTextures(); + tilesManager->gatherLayerTextures(); double currentTime = setupDrawing(rect, viewport, webViewRect, titleBarHeight, clip, scale); TexturesResult nbTexturesNeeded; bool fastSwap = isScrolling() || m_layersRenderingMode == kSingleSurfaceRendering; - ret |= m_treeManager.drawGL(currentTime, rect, viewport, - scale, fastSwap, - treesSwappedPtr, newTreeHasAnimPtr, - &nbTexturesNeeded); + m_glExtras.setViewport(viewport); + ret |= m_surfaceCollectionManager.drawGL(currentTime, rect, viewport, + scale, fastSwap, + collectionsSwappedPtr, newCollectionHasAnimPtr, + &nbTexturesNeeded); if (!ret) resetFrameworkInval(); @@ -518,16 +539,11 @@ bool GLWebViewState::drawGL(IntRect& rect, SkRect& viewport, IntRect* invalRect, nbTexturesNeeded.clipped += nbTexturesForImages; ret |= setLayersRenderingMode(nbTexturesNeeded); - FloatRect extrasclip(0, 0, rect.width(), rect.height()); - TilesManager::instance()->shader()->clip(extrasclip); - - m_glExtras.drawGL(webViewRect, viewport, titleBarHeight); - glBindBuffer(GL_ARRAY_BUFFER, 0); // Clean up GL textures for video layer. - TilesManager::instance()->videoLayerManager()->deleteUnusedTextures(); - ret |= TilesManager::instance()->invertedScreenSwitch(); + tilesManager->videoLayerManager()->deleteUnusedTextures(); + ret |= tilesManager->invertedScreenSwitch(); if (ret) { // ret==true && empty inval region means we've inval'd everything, @@ -535,13 +551,13 @@ bool GLWebViewState::drawGL(IntRect& rect, SkRect& viewport, IntRect* invalRect, // until tile generation catches up and we swap pages. bool fullScreenInval = m_frameworkInval.isEmpty(); - if (TilesManager::instance()->invertedScreenSwitch()) { + if (tilesManager->invertedScreenSwitch()) { fullScreenInval = true; - TilesManager::instance()->setInvertedScreenSwitch(false); + tilesManager->setInvertedScreenSwitch(false); } if (!fullScreenInval) { - FloatRect frameworkInval = TilesManager::instance()->shader()->rectInInvScreenCoord( + FloatRect frameworkInval = tilesManager->shader()->rectInInvScreenCoord( m_frameworkInval); // Inflate the invalidate rect to avoid precision lost. frameworkInval.inflate(1); @@ -556,7 +572,7 @@ bool GLWebViewState::drawGL(IntRect& rect, SkRect& viewport, IntRect* invalRect, invalRect->setHeight(inval.height()); XLOG("invalRect(%d, %d, %d, %d)", inval.x(), - inval.y(), inval.width(), inval.height()); + inval.y(), inval.width(), inval.height()); if (!invalRect->intersects(rect)) { // invalidate is occurring offscreen, do full inval to guarantee redraw @@ -574,6 +590,30 @@ bool GLWebViewState::drawGL(IntRect& rect, SkRect& viewport, IntRect* invalRect, resetFrameworkInval(); } + showFrameInfo(rect, *collectionsSwappedPtr); + +#ifdef DEBUG + tilesManager->getTilesTracker()->showTrackTextures(); +#endif + + return ret; +} + +void GLWebViewState::showFrameInfo(const IntRect& rect, bool collectionsSwapped) +{ + bool showVisualIndicator = TilesManager::instance()->getShowVisualIndicator(); + + bool drawOrDumpFrameInfo = showVisualIndicator; +#ifdef MEASURES_PERF + drawOrDumpFrameInfo |= m_measurePerfs; +#endif + if (!drawOrDumpFrameInfo) + return; + + double currentDrawTime = WTF::currentTime(); + double delta = currentDrawTime - m_prevDrawTime; + m_prevDrawTime = currentDrawTime; + #ifdef MEASURES_PERF if (m_measurePerfs) { m_delayTimes[m_timeCounter++] = delta; @@ -582,12 +622,37 @@ bool GLWebViewState::drawGL(IntRect& rect, SkRect& viewport, IntRect* invalRect, } #endif -#ifdef DEBUG - TilesManager::instance()->getTilesTracker()->showTrackTextures(); - ImagesManager::instance()->showImages(); -#endif + IntRect frameInfoRect = rect; + frameInfoRect.setHeight(FPS_INDICATOR_HEIGHT); + double ratio = (1.0 / delta) / MAX_FPS_VALUE; - return ret; + clearRectWithColor(frameInfoRect, 1, 1, 1, 1); + frameInfoRect.setWidth(frameInfoRect.width() * ratio); + clearRectWithColor(frameInfoRect, 1, 0, 0, 1); + + // Draw the collection swap counter as a circling progress bar. + // This will basically show how fast we are updating the collection. + static int swappedCounter = 0; + if (collectionsSwapped) + swappedCounter = (swappedCounter + 1) % COLLECTION_SWAPPED_COUNTER_MODULE; + + frameInfoRect = rect; + frameInfoRect.setHeight(FPS_INDICATOR_HEIGHT); + frameInfoRect.move(0, FPS_INDICATOR_HEIGHT); + + clearRectWithColor(frameInfoRect, 1, 1, 1, 1); + ratio = (swappedCounter + 1.0) / COLLECTION_SWAPPED_COUNTER_MODULE; + + frameInfoRect.setWidth(frameInfoRect.width() * ratio); + clearRectWithColor(frameInfoRect, 0, 1, 0, 1); +} + +void GLWebViewState::clearRectWithColor(const IntRect& rect, float r, float g, + float b, float a) +{ + glScissor(rect.x(), rect.y(), rect.width(), rect.height()); + glClearColor(r, g, b, a); + glClear(GL_COLOR_BUFFER_BIT); } } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/GLWebViewState.h b/Source/WebCore/platform/graphics/android/GLWebViewState.h index 8d89704..fcdd07c 100644 --- a/Source/WebCore/platform/graphics/android/GLWebViewState.h +++ b/Source/WebCore/platform/graphics/android/GLWebViewState.h @@ -36,7 +36,7 @@ #include "SkRect.h" #include "SkRegion.h" #include "TiledPage.h" -#include "TreeManager.h" +#include "SurfaceCollectionManager.h" #include "ZoomManager.h" #include <utils/threads.h> @@ -175,8 +175,8 @@ public: const SkIRect& futureViewport() const { return m_futureViewportTileBounds; } void setFutureViewport(const SkIRect& viewport) { m_futureViewportTileBounds = viewport; } - unsigned int paintBaseLayerContent(SkCanvas* canvas); - void setBaseLayer(BaseLayerAndroid* layer, const SkRegion& inval, bool showVisualIndicator, + void paintBaseLayerContent(SkCanvas* canvas); + bool setBaseLayer(BaseLayerAndroid* layer, bool showVisualIndicator, bool isPictureAfterFirstLayout); void paintExtras(); @@ -191,23 +191,16 @@ public: int baseContentWidth(); int baseContentHeight(); - void setViewport(SkRect& viewport, float scale); - // a rect containing the coordinates of all tiles in the current viewport const SkIRect& viewportTileBounds() const { return m_viewportTileBounds; } // a rect containing the viewportTileBounds before there was a scale change const SkIRect& preZoomBounds() const { return m_preZoomBounds; } void setPreZoomBounds(const SkIRect& bounds) { m_preZoomBounds = bounds; } - unsigned int currentPictureCounter() const { return m_currentPictureCounter; } - void setIsScrolling(bool isScrolling) { m_isScrolling = isScrolling; } - bool isScrolling() { return m_isScrolling; } + bool isScrolling() { return m_isScrolling || m_isViewportScrolling; } void drawBackground(Color& backgroundColor); - double setupDrawing(IntRect& viewRect, SkRect& visibleRect, - IntRect& webViewRect, int titleBarHeight, - IntRect& screenClip, float scale); bool setLayersRenderingMode(TexturesResult&); void fullInval(); @@ -215,7 +208,7 @@ public: bool drawGL(IntRect& rect, SkRect& viewport, IntRect* invalRect, IntRect& webViewRect, int titleBarHeight, IntRect& clip, float scale, - bool* treesSwappedPtr, bool* newTreeHasAnimPtr); + bool* collectionsSwappedPtr, bool* newCollectionHasAnimPtr); #ifdef MEASURES_PERF void dumpMeasures(); @@ -234,7 +227,6 @@ public: int expandedTileBoundsX() { return m_expandedTileBoundsX; } int expandedTileBoundsY() { return m_expandedTileBoundsY; } - void setHighEndGfx(bool highEnd) { m_highEndGfx = highEnd; } float scale() { return m_scale; } @@ -254,6 +246,14 @@ public: private: void inval(const IntRect& rect); + void setViewport(const SkRect& viewport, float scale); + double setupDrawing(const IntRect& viewRect, const SkRect& visibleRect, + const IntRect& webViewRect, int titleBarHeight, + const IntRect& screenClip, float scale); + void showFrameInfo(const IntRect& rect, bool collectionsSwapped); + void clearRectWithColor(const IntRect& rect, float r, float g, + float b, float a); + double m_prevDrawTime; ZoomManager m_zoomManager; android::Mutex m_tiledPageLock; @@ -262,7 +262,6 @@ private: SkIRect m_futureViewportTileBounds; SkIRect m_preZoomBounds; - unsigned int m_currentPictureCounter; bool m_usePageA; TiledPage* m_tiledPageA; TiledPage* m_tiledPageB; @@ -279,17 +278,17 @@ private: GLExtras m_glExtras; bool m_isScrolling; + bool m_isViewportScrolling; bool m_goingDown; bool m_goingLeft; int m_expandedTileBoundsX; int m_expandedTileBoundsY; - bool m_highEndGfx; float m_scale; LayersRenderingMode m_layersRenderingMode; - TreeManager m_treeManager; + SurfaceCollectionManager m_surfaceCollectionManager; }; } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/GaneshRenderer.cpp b/Source/WebCore/platform/graphics/android/GaneshRenderer.cpp index 29acb2b..c90ddb3 100644 --- a/Source/WebCore/platform/graphics/android/GaneshRenderer.cpp +++ b/Source/WebCore/platform/graphics/android/GaneshRenderer.cpp @@ -84,20 +84,16 @@ void GaneshRenderer::setupCanvas(const TileRenderInfo& renderInfo, SkCanvas* can GaneshContext* ganesh = GaneshContext::instance(); -#if !DEPRECATED_SURFACE_TEXTURE_MODE - if (renderInfo.textureInfo->getSharedTextureMode() == SurfaceTextureMode) { - TransferQueue* tileQueue = TilesManager::instance()->transferQueue(); - - tileQueue->lockQueue(); - - bool ready = tileQueue->readyForUpdate(); - if (!ready) { - XLOG("!ready"); - tileQueue->unlockQueue(); - return; - } + TransferQueue* tileQueue = TilesManager::instance()->transferQueue(); + + tileQueue->lockQueue(); + + bool ready = tileQueue->readyForUpdate(); + if (!ready) { + XLOG("!ready"); + tileQueue->unlockQueue(); + return; } -#endif SkDevice* device = NULL; if (renderInfo.tileSize.width() == TilesManager::tileWidth() @@ -117,12 +113,6 @@ void GaneshRenderer::setupCanvas(const TileRenderInfo& renderInfo, SkCanvas* can // set the GPU device to the canvas canvas->setDevice(device); - - // invert canvas contents - if (renderInfo.textureInfo->getSharedTextureMode() == EglImageMode) { - canvas->scale(SK_Scalar1, -SK_Scalar1); - canvas->translate(0, -renderInfo.tileSize.height()); - } } void GaneshRenderer::setupPartialInval(const TileRenderInfo& renderInfo, SkCanvas* canvas) @@ -148,14 +138,10 @@ void GaneshRenderer::renderingComplete(const TileRenderInfo& renderInfo, SkCanva // In SurfaceTextureMode we must call swapBuffers to unlock and post the // tile's ANativeWindow (i.e. SurfaceTexture) buffer - if (renderInfo.textureInfo->getSharedTextureMode() == SurfaceTextureMode) { -#if !DEPRECATED_SURFACE_TEXTURE_MODE - TransferQueue* tileQueue = TilesManager::instance()->transferQueue(); - eglSwapBuffers(eglGetCurrentDisplay(), tileQueue->m_eglSurface); - tileQueue->addItemInTransferQueue(&renderInfo, GpuUpload, 0); - tileQueue->unlockQueue(); -#endif - } + TransferQueue* tileQueue = TilesManager::instance()->transferQueue(); + eglSwapBuffers(eglGetCurrentDisplay(), tileQueue->m_eglSurface); + tileQueue->addItemInTransferQueue(&renderInfo, GpuUpload, 0); + tileQueue->unlockQueue(); if (renderInfo.measurePerf) m_perfMon.stop(TAG_UPDATE_TEXTURE); diff --git a/Source/WebCore/platform/graphics/android/GradientAndroid.cpp b/Source/WebCore/platform/graphics/android/GradientAndroid.cpp index b8dc9dd..6007a0a 100644 --- a/Source/WebCore/platform/graphics/android/GradientAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/GradientAndroid.cpp @@ -113,7 +113,6 @@ SkShader* Gradient::getShader(SkShader::TileMode mode) void Gradient::fill(GraphicsContext* context, const FloatRect& rect) { - SkRect r; SkPaint paint; // we don't care about the mode, so try to use the existing one SkShader::TileMode mode = m_gradient ? m_gradient->m_tileMode : diff --git a/Source/WebCore/platform/graphics/android/GraphicsContextAndroid.cpp b/Source/WebCore/platform/graphics/android/GraphicsContextAndroid.cpp index a490d5f..0aa1ae6 100644 --- a/Source/WebCore/platform/graphics/android/GraphicsContextAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/GraphicsContextAndroid.cpp @@ -26,6 +26,7 @@ #include "GraphicsContext.h" #include "AffineTransform.h" +#include "Font.h" #include "Gradient.h" #include "NotImplemented.h" #include "Path.h" @@ -36,6 +37,7 @@ #include "SkBlurMaskFilter.h" #include "SkCanvas.h" #include "SkColorPriv.h" +#include "SkCornerPathEffect.h" #include "SkDashPathEffect.h" #include "SkDevice.h" #include "SkGradientShader.h" @@ -127,9 +129,6 @@ public: SkColor fillColor; SkColor strokeColor; bool useAA; - // This is a list of clipping paths which are currently active, in the - // order in which they were pushed. - WTF::Vector<SkPath> antiAliasClipPaths; State() : pathEffect(0) @@ -246,9 +245,6 @@ public: void restore() { - if (!m_state->antiAliasClipPaths.isEmpty()) - applyAntiAliasedClipPaths(m_state->antiAliasClipPaths); - m_state->~State(); m_stateStack.pop_back(); m_state = static_cast<State*>(m_stateStack.back()); @@ -370,51 +366,6 @@ public: return false; } - void clipPathAntiAliased(const SkPath& clipPath) - { - // If we are currently tracking any anti-alias clip paths, then we already - // have a layer in place and don't need to add another. - bool haveLayerOutstanding = m_state->antiAliasClipPaths.size(); - - // See comments in applyAntiAliasedClipPaths about how this works. - m_state->antiAliasClipPaths.append(clipPath); - if (!haveLayerOutstanding) { - SkRect bounds = clipPath.getBounds(); - if (m_platformGfxCtx && m_platformGfxCtx->mCanvas) { - m_platformGfxCtx->mCanvas->saveLayerAlpha(&bounds, 255, - static_cast<SkCanvas::SaveFlags>(SkCanvas::kHasAlphaLayer_SaveFlag - | SkCanvas::kFullColorLayer_SaveFlag - | SkCanvas::kClipToLayer_SaveFlag)); - m_platformGfxCtx->mCanvas->save(); - } else - ASSERT(0); - } - } - - void applyAntiAliasedClipPaths(WTF::Vector<SkPath>& paths) - { - // Anti-aliased clipping: - // - // Refer to PlatformContextSkia.cpp's applyAntiAliasedClipPaths() for more details - - if (m_platformGfxCtx && m_platformGfxCtx->mCanvas) - m_platformGfxCtx->mCanvas->restore(); - - SkPaint paint; - paint.setXfermodeMode(SkXfermode::kClear_Mode); - paint.setAntiAlias(true); - paint.setStyle(SkPaint::kFill_Style); - - if (m_platformGfxCtx && m_platformGfxCtx->mCanvas) { - for (size_t i = paths.size() - 1; i < paths.size(); --i) { - paths[i].setFillType(SkPath::kInverseWinding_FillType); - m_platformGfxCtx->mCanvas->drawPath(paths[i], paint); - } - m_platformGfxCtx->mCanvas->restore(); - } else - ASSERT(0); - } - PlatformGraphicsContext* getPlatformGfxCtx() { return m_platformGfxCtx; @@ -848,7 +799,7 @@ void GraphicsContext::clip(const Path& path) if (paintingDisabled()) return; - m_data->clipPathAntiAliased(*path.platformPath()); + GC2CANVAS(this)->clipPath(*path.platformPath(), SkRegion::kIntersect_Op, true); } void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness) @@ -868,7 +819,7 @@ void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness r.inset(SkIntToScalar(thickness + 1), SkIntToScalar(thickness + 1)); path.addOval(r, SkPath::kCCW_Direction); } - m_data->clipPathAntiAliased(path); + GC2CANVAS(this)->clipPath(path, SkRegion::kIntersect_Op, true); } void GraphicsContext::canvasClip(const Path& path) @@ -1000,9 +951,33 @@ void GraphicsContext::clearPlatformShadow() /////////////////////////////////////////////////////////////////////////////// -void GraphicsContext::drawFocusRing(const Vector<IntRect>&, int, int, const Color&) +void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int /* width */, int /* offset */, const Color& color) { - // Do nothing, since we draw the focus ring independently. + if (paintingDisabled()) + return; + + unsigned rectCount = rects.size(); + if (!rectCount) + return; + + SkRegion focusRingRegion; + const SkScalar focusRingOutset = WebCoreFloatToSkScalar(0.8); + for (unsigned i = 0; i < rectCount; i++) { + SkIRect r = rects[i]; + r.inset(-focusRingOutset, -focusRingOutset); + focusRingRegion.op(r, SkRegion::kUnion_Op); + } + + SkPath path; + SkPaint paint; + paint.setAntiAlias(true); + paint.setStyle(SkPaint::kStroke_Style); + + paint.setColor(color.rgb()); + paint.setStrokeWidth(focusRingOutset * 2); + paint.setPathEffect(new SkCornerPathEffect(focusRingOutset * 2))->unref(); + focusRingRegion.getBoundaryPath(&path); + platformContext()->mCanvas->drawPath(path, paint); } void GraphicsContext::drawFocusRing(const Path&, int, int, const Color&) @@ -1291,6 +1266,25 @@ void GraphicsContext::clipConvexPolygon(size_t numPoints, const FloatPoint*, boo // FIXME: IMPLEMENT! } +void GraphicsContext::drawHighlightForText(const Font& font, const TextRun& run, const FloatPoint& point, int h, const Color& backgroundColor, ColorSpace colorSpace, int from, int to, bool isActive) +{ + if (paintingDisabled()) + return; + + IntRect rect = (IntRect)font.selectionRectForText(run, point, h, from, to); + if (isActive) + fillRect(rect, backgroundColor, colorSpace); + else { + int x = rect.x(), y = rect.y(), w = rect.width(), h = rect.height(); + const int t = 3, t2 = t * 2; + + fillRect(IntRect(x, y, w, t), backgroundColor, colorSpace); + fillRect(IntRect(x, y+h-t, w, t), backgroundColor, colorSpace); + fillRect(IntRect(x, y+t, t, h-t2), backgroundColor, colorSpace); + fillRect(IntRect(x+w-t, y+t, t, h-t2), backgroundColor, colorSpace); + } +} + } // namespace WebCore /////////////////////////////////////////////////////////////////////////////// diff --git a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp index 567b54b..6bc2dc7 100644 --- a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp @@ -22,12 +22,16 @@ #include "AndroidAnimation.h" #include "Animation.h" #include "FloatRect.h" +#include "FixedPositioning.h" #include "GraphicsContext.h" +#include "IFrameContentLayerAndroid.h" +#include "IFrameLayerAndroid.h" #include "Image.h" #include "ImagesManager.h" #include "Layer.h" #include "Length.h" #include "MediaLayer.h" +#include "PictureLayerContent.h" #include "PlatformBridge.h" #include "PlatformGraphicsContext.h" #include "RenderLayerBacking.h" @@ -232,8 +236,12 @@ void GraphicsLayerAndroid::updateFixedPosition() return; // We will need the Iframe flag in the LayerAndroid tree for fixed position - if (view->isRenderIFrame()) - m_contentLayer->setIsIframe(true); + if (view->isRenderIFrame() && !m_contentLayer->isIFrame()) { + LayerAndroid* layer = new IFrameLayerAndroid(*m_contentLayer); + m_contentLayer->unref(); + m_contentLayer = layer; + } + // If we are a fixed position layer, just set it if (view->isPositioned() && view->style()->position() == FixedPosition) { // We need to get the passed CSS properties for the element @@ -264,12 +272,20 @@ void GraphicsLayerAndroid::updateFixedPosition() SkRect viewRect; viewRect.set(paintingOffsetX, paintingOffsetY, paintingOffsetX + w, paintingOffsetY + h); IntPoint renderLayerPos(renderLayer->x(), renderLayer->y()); - m_contentLayer->setFixedPosition(left, top, right, bottom, - marginLeft, marginTop, - marginRight, marginBottom, - renderLayerPos, - viewRect); - } + + FixedPositioning* fixedPosition = m_contentLayer->fixedPosition(); + if (!fixedPosition) { + fixedPosition = new FixedPositioning(); + m_contentLayer->setFixedPosition(fixedPosition); + } + + fixedPosition->setFixedPosition(left, top, right, bottom, + marginLeft, marginTop, + marginRight, marginBottom, + renderLayerPos, + viewRect); + } else if (m_contentLayer->isFixed()) + m_contentLayer->setFixedPosition(0); } void GraphicsLayerAndroid::setPosition(const FloatPoint& point) @@ -508,6 +524,8 @@ void GraphicsLayerAndroid::updateScrollingLayers() if (layerNeedsOverflow) { ASSERT(!m_foregroundLayer && !m_foregroundClipLayer); m_foregroundLayer = new ScrollableLayerAndroid(layer); + + // TODO: can clip layer be set to not intrinsically composited? m_foregroundClipLayer = new LayerAndroid(layer); m_foregroundClipLayer->setMasksToBounds(true); m_foregroundClipLayer->addChild(m_foregroundLayer); @@ -518,7 +536,7 @@ void GraphicsLayerAndroid::updateScrollingLayers() // No need to copy the children as they will be removed and synced. m_contentLayer->removeChildren(); // Replace the content layer with a scrollable layer. - LayerAndroid* layer = new ScrollableLayerAndroid(*m_contentLayer); + LayerAndroid* layer = new IFrameContentLayerAndroid(*m_contentLayer); m_contentLayer->unref(); m_contentLayer = layer; if (m_parent) { @@ -555,6 +573,21 @@ void GraphicsLayerAndroid::updateScrollingLayers() #endif } +void GraphicsLayerAndroid::updateScrollOffset() { + RenderLayer* layer = renderLayerFromClient(m_client); + if (!layer || !(m_foregroundLayer || m_contentLayer->contentIsScrollable())) + return; + if (m_foregroundLayer) { + IntSize scroll = layer->scrolledContentOffset(); + m_foregroundLayer->setScrollOffset(IntPoint(scroll.width(), scroll.height())); + } else if (m_contentLayer->isIFrameContent()) { + IntPoint p(layer->renderer()->frame()->view()->scrollX(), + layer->renderer()->frame()->view()->scrollY()); + static_cast<IFrameContentLayerAndroid*>(m_contentLayer)->setIFrameScrollOffset(p); + } + askForSync(); +} + bool GraphicsLayerAndroid::repaint() { LOG("(%x) repaint(), gPaused(%d) m_needsRepaint(%d) m_haveContents(%d) ", @@ -571,16 +604,17 @@ bool GraphicsLayerAndroid::repaint() PaintingPhase phase(this); // Paint the background into a separate context. phase.set(GraphicsLayerPaintBackground); - if (!paintContext(m_contentLayer->recordContext(), layerBounds)) + if (!paintContext(m_contentLayer, layerBounds)) return false; - m_contentLayer->checkTextPresence(); // Construct the foreground layer and draw. RenderBox* box = layer->renderBox(); int outline = box->view()->maximalOutlineSize(); IntRect contentsRect(0, 0, - box->borderLeft() + box->borderRight() + layer->scrollWidth(), - box->borderTop() + box->borderBottom() + layer->scrollHeight()); + box->borderLeft() + box->borderRight() + layer->scrollWidth() + + layer->verticalScrollbarWidth(), + box->borderTop() + box->borderBottom() + layer->scrollHeight() + + layer->horizontalScrollbarHeight()); contentsRect.inflate(outline); // Update the foreground layer size. m_foregroundLayer->setSize(contentsRect.width(), contentsRect.height()); @@ -591,8 +625,7 @@ bool GraphicsLayerAndroid::repaint() IntSize scroll = layer->scrolledContentOffset(); layer->scrollToOffset(0, 0); // At this point, it doesn't matter if painting failed. - (void) paintContext(m_foregroundLayer->recordContext(), contentsRect); - m_foregroundLayer->checkTextPresence(); + (void) paintContext(m_foregroundLayer, contentsRect); layer->scrollToOffset(scroll.width(), scroll.height()); // Construct the clip layer for masking the contents. @@ -606,6 +639,11 @@ bool GraphicsLayerAndroid::repaint() m_foregroundClipLayer->setPosition(x, y); m_foregroundClipLayer->setSize(width, height); + int rtlOffset = 0; // LTR uses no offset. + if (!layer->renderer()->style()->isLeftToRightDirection()) + rtlOffset = layer->scrollWidth() - width; // Scroll all the way right. + m_foregroundLayer->setScrollOffset(IntPoint(scroll.width() + rtlOffset, + scroll.height())); // Need to offset the foreground layer by the clip layer in order // for the contents to be in the correct position. m_foregroundLayer->setPosition(-x, -y); @@ -619,19 +657,21 @@ bool GraphicsLayerAndroid::repaint() SkRegion region; region.setRect(0, 0, contentsRect.width(), contentsRect.height()); m_foregroundLayer->markAsDirty(region); - m_foregroundLayer->needsRepaint(); } else { // If there is no contents clip, we can draw everything into one // picture. - if (!paintContext(m_contentLayer->recordContext(), layerBounds)) + bool painting = paintContext(m_contentLayer, layerBounds); + if (!painting) return false; - m_contentLayer->checkTextPresence(); // Check for a scrollable iframe and report the scrolling // limits based on the view size. - if (m_contentLayer->contentIsScrollable()) { + if (m_contentLayer->isIFrameContent()) { FrameView* view = layer->renderer()->frame()->view(); - static_cast<ScrollableLayerAndroid*>(m_contentLayer)->setScrollLimits( + static_cast<IFrameContentLayerAndroid*>(m_contentLayer)->setScrollLimits( m_position.x(), m_position.y(), view->layoutWidth(), view->layoutHeight()); + LOG("setScrollLimits(%.2f, %.2f, w: %d h: %d) layer %d, frame scroll position is %d, %d", + m_position.x(), m_position.y(), view->layoutWidth(), view->layoutHeight(), + m_contentLayer->uniqueId(), view->scrollX(), view->scrollY()); } } @@ -644,7 +684,6 @@ bool GraphicsLayerAndroid::repaint() m_contentLayer->markAsDirty(m_dirtyRegion); m_dirtyRegion.setEmpty(); - m_contentLayer->needsRepaint(); m_needsRepaint = false; return true; @@ -654,7 +693,6 @@ bool GraphicsLayerAndroid::repaint() // texture. Only do so if we effectively have a new image! m_contentLayer->markAsDirty(m_dirtyRegion); m_dirtyRegion.setEmpty(); - m_contentLayer->needsRepaint(); m_newImage = false; m_needsRepaint = false; return true; @@ -662,19 +700,32 @@ bool GraphicsLayerAndroid::repaint() return false; } -bool GraphicsLayerAndroid::paintContext(SkPicture* context, +bool GraphicsLayerAndroid::paintContext(LayerAndroid* layer, const IntRect& rect) { - SkAutoPictureRecord arp(context, rect.width(), rect.height()); - SkCanvas* canvas = arp.getRecordingCanvas(); + if (!layer) + return false; - if (!canvas) + SkPicture* picture = new SkPicture(); + SkCanvas* canvas = picture->beginRecording(rect.width(), rect.height(), 0); + if (!canvas) { + picture->endRecording(); + SkSafeUnref(picture); return false; + } PlatformGraphicsContext platformContext(canvas); GraphicsContext graphicsContext(&platformContext); paintGraphicsLayerContents(graphicsContext, rect); + + picture->endRecording(); + + PictureLayerContent* layerContent = new PictureLayerContent(picture); + layerContent->checkForOptimisations(); + layer->setContent(layerContent); + SkSafeUnref(layerContent); + SkSafeUnref(picture); return true; } @@ -749,7 +800,7 @@ bool GraphicsLayerAndroid::createAnimationFromKeyframes(const KeyframeValueList& KeyframeValueList* operationsList = new KeyframeValueList(AnimatedPropertyOpacity); for (unsigned int i = 0; i < valueList.size(); i++) { FloatAnimationValue* originalValue = (FloatAnimationValue*)valueList.at(i); - PassRefPtr<TimingFunction> timingFunction(const_cast<TimingFunction*>(originalValue->timingFunction())); + RefPtr<TimingFunction> timingFunction(const_cast<TimingFunction*>(originalValue->timingFunction())); FloatAnimationValue* value = new FloatAnimationValue(originalValue->keyTime(), originalValue->value(), timingFunction); @@ -791,7 +842,7 @@ bool GraphicsLayerAndroid::createTransformAnimationsFromKeyframes(const Keyframe KeyframeValueList* operationsList = new KeyframeValueList(AnimatedPropertyWebkitTransform); for (unsigned int i = 0; i < valueList.size(); i++) { TransformAnimationValue* originalValue = (TransformAnimationValue*)valueList.at(i); - PassRefPtr<TimingFunction> timingFunction(const_cast<TimingFunction*>(originalValue->timingFunction())); + RefPtr<TimingFunction> timingFunction(const_cast<TimingFunction*>(originalValue->timingFunction())); TransformAnimationValue* value = new TransformAnimationValue(originalValue->keyTime(), originalValue->value(), timingFunction); @@ -988,6 +1039,12 @@ void GraphicsLayerAndroid::gatherRootLayers(Vector<const RenderLayer*>& list) void GraphicsLayerAndroid::syncCompositingStateForThisLayerOnly() { + if (m_contentLayer) { + RenderLayer* renderLayer = renderLayerFromClient(m_client); + int intrinsicallyComposited = renderLayer ? renderLayer->intrinsicallyComposited() : true; + m_contentLayer->setIntrinsicallyComposited(intrinsicallyComposited); + } + updateScrollingLayers(); updateFixedPosition(); syncChildren(); diff --git a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.h b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.h index e6d75b0..1eb77d6 100644 --- a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.h +++ b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.h @@ -24,7 +24,9 @@ #include "GraphicsLayer.h" #include "GraphicsLayerClient.h" #include "LayerAndroid.h" +#include "LayerContent.h" #include "RefPtr.h" +#include "ScrollableLayerAndroid.h" #include "SkBitmapRef.h" #include "Vector.h" @@ -122,9 +124,12 @@ public: void notifyClientAnimationStarted(); LayerAndroid* contentLayer() { return m_contentLayer; } + ScrollableLayerAndroid* foregroundLayer() { return m_foregroundLayer; } static int instancesCount(); + virtual void updateScrollOffset(); + private: void askForSync(); @@ -139,7 +144,7 @@ private: bool repaint(); void needsNotifyClient(); - bool paintContext(SkPicture* context, const IntRect& rect); + bool paintContext(LayerAndroid* layer, const IntRect& rect); bool m_needsSyncChildren; bool m_needsSyncMask; diff --git a/Source/WebCore/platform/graphics/android/IFrameContentLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/IFrameContentLayerAndroid.cpp new file mode 100644 index 0000000..70b5c67 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/IFrameContentLayerAndroid.cpp @@ -0,0 +1,42 @@ +#include "config.h" +#include "IFrameContentLayerAndroid.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include <cutils/log.h> +#include <wtf/CurrentTime.h> +#include <wtf/text/CString.h> +#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "IFrameContentLayerAndroid", __VA_ARGS__) + +namespace WebCore { + +bool IFrameContentLayerAndroid::scrollTo(int x, int y) +{ + IntRect scrollBounds; + getScrollBounds(&scrollBounds); + if (!scrollBounds.width() && !scrollBounds.height()) + return false; + SkScalar newX = SkScalarPin(x, scrollBounds.x(), scrollBounds.width()); + SkScalar newY = SkScalarPin(y, scrollBounds.y(), scrollBounds.height()); + // Check for no change. + if (newX == m_iframeScrollOffset.x() && newY == m_iframeScrollOffset.y()) + return false; + newX = newX - m_iframeScrollOffset.x(); + newY = newY - m_iframeScrollOffset.y(); + setScrollOffset(IntPoint(newX, newY)); + return true; +} + +void IFrameContentLayerAndroid::getScrollRect(SkIRect* out) const +{ + const SkPoint& pos = getPosition(); + out->fLeft = m_scrollLimits.fLeft - pos.fX + m_iframeScrollOffset.x(); + out->fTop = m_scrollLimits.fTop - pos.fY + m_iframeScrollOffset.y(); + + out->fRight = getSize().width() - m_scrollLimits.width(); + out->fBottom = getSize().height() - m_scrollLimits.height(); +} + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/IFrameContentLayerAndroid.h b/Source/WebCore/platform/graphics/android/IFrameContentLayerAndroid.h new file mode 100644 index 0000000..64b2d06 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/IFrameContentLayerAndroid.h @@ -0,0 +1,78 @@ +/* + * Copyright 2012, 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 IFrameContentLayerAndroid_h +#define IFrameContentLayerAndroid_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "ScrollableLayerAndroid.h" + +namespace WebCore { + +class IFrameContentLayerAndroid : public ScrollableLayerAndroid { + +public: + IFrameContentLayerAndroid(RenderLayer* owner) + : ScrollableLayerAndroid(owner) {} + IFrameContentLayerAndroid(const ScrollableLayerAndroid& layer) + : ScrollableLayerAndroid(layer) {} + IFrameContentLayerAndroid(const LayerAndroid& layer) + : ScrollableLayerAndroid(layer) {} + IFrameContentLayerAndroid(const IFrameContentLayerAndroid& layer) + : ScrollableLayerAndroid(layer) + , m_iframeScrollOffset(layer.m_iframeScrollOffset) {} + + virtual ~IFrameContentLayerAndroid() {}; + + // isIFrame() return true for compatibility reason (see ViewStateSerializer) + virtual bool isIFrame() const { return true; } + virtual bool isIFrameContent() const { return true; } + + virtual LayerAndroid* copy() const { return new IFrameContentLayerAndroid(*this); } + virtual SubclassType subclassType() { return LayerAndroid::IFrameContentLayer; } + + // Scrolls to the given position in the layer. + // Returns whether or not any scrolling was required. + virtual bool scrollTo(int x, int y); + + // Fills the rect with the current scroll offset and the maximum scroll offset. + // fLeft = scrollX + // fTop = scrollY + // fRight = maxScrollX + // fBottom = maxScrollY + virtual void getScrollRect(SkIRect*) const; + + void setIFrameScrollOffset(IntPoint offset) { m_iframeScrollOffset = offset; } + +private: + IntPoint m_iframeScrollOffset; +}; + +} + +#endif // USE(ACCELERATED_COMPOSITING) + +#endif // IFrameContentLayerAndroid_h diff --git a/Source/WebCore/platform/graphics/android/IFrameLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/IFrameLayerAndroid.cpp new file mode 100644 index 0000000..dfff91b --- /dev/null +++ b/Source/WebCore/platform/graphics/android/IFrameLayerAndroid.cpp @@ -0,0 +1,42 @@ +#include "config.h" +#include "IFrameLayerAndroid.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include <cutils/log.h> +#include <wtf/CurrentTime.h> +#include <wtf/text/CString.h> + +#include "DumpLayer.h" + +#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "IFrameLayerAndroid", __VA_ARGS__) + +namespace WebCore { + +IFrameLayerAndroid* IFrameLayerAndroid::updatePosition(SkRect viewport, + IFrameLayerAndroid* parentIframeLayer) +{ + // As we are an iframe, accumulate the offset from the parent with + // the current position, and change the parent pointer. + + // If this is the top level, take the current position + SkPoint parentOffset; + parentOffset.set(0,0); + if (parentIframeLayer) + parentOffset = parentIframeLayer->getPosition(); + + SkPoint offset = parentOffset + getPosition(); + m_iframeOffset = IntPoint(offset.fX, offset.fY); + + return this; +} + +void IFrameLayerAndroid::dumpLayer(FILE* file, int indentLevel) const +{ + writeIntVal(file, indentLevel + 1, "m_isIframe", true); + writeIntPoint(file, indentLevel + 1, "m_iframeOffset", m_iframeOffset); +} + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/DoubleBufferedTexture.h b/Source/WebCore/platform/graphics/android/IFrameLayerAndroid.h index 821b79b..e12188a 100644 --- a/Source/WebCore/platform/graphics/android/DoubleBufferedTexture.h +++ b/Source/WebCore/platform/graphics/android/IFrameLayerAndroid.h @@ -1,5 +1,5 @@ /* - * Copyright 2010, The Android Open Source Project + * Copyright 2012, The Android Open Source Project * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -23,52 +23,46 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef DoubleBufferedTexture_h -#define DoubleBufferedTexture_h +#ifndef IFrameLayerAndroid_h +#define IFrameLayerAndroid_h -#include "SharedTexture.h" -#include <EGL/egl.h> +#if USE(ACCELERATED_COMPOSITING) + +#include "LayerAndroid.h" namespace WebCore { -class DoubleBufferedTexture { +class IFrameLayerAndroid : public LayerAndroid { + public: - // consumer thread functions - DoubleBufferedTexture(EGLContext sharedContext, SharedTextureMode mode); - virtual ~DoubleBufferedTexture(); - - // provider thread functions - virtual TextureInfo* producerLock(); - virtual void producerRelease(); - virtual void producerReleaseAndSwap(); - EGLContext producerAcquireContext(); - void producerDeleteTextures(); - - // consumer thread functions - TextureInfo* consumerLock(); - void consumerRelease(); - void consumerDeleteTextures(); - -protected: - SharedTexture* getReadableTexture(); - SharedTexture* getWriteableTexture(); - - SharedTexture* m_textureA; - SharedTexture* m_textureB; - - SharedTextureMode m_sharedTextureMode; -private: + IFrameLayerAndroid(RenderLayer* owner) + : LayerAndroid(owner) {} + IFrameLayerAndroid(const LayerAndroid& layer) + : LayerAndroid(layer) {} + IFrameLayerAndroid(const IFrameLayerAndroid& layer) + : LayerAndroid(layer) + , m_iframeOffset(layer.m_iframeOffset) {} + + virtual ~IFrameLayerAndroid() {}; + + virtual bool isIFrame() const { return true; } - SharedTexture* m_writeableTexture; - SharedTexture* m_lockedConsumerTexture; // only used by the consumer + virtual LayerAndroid* copy() const { return new IFrameLayerAndroid(*this); } + virtual SubclassType subclassType() { return LayerAndroid::IFrameLayer; } - EGLDisplay m_display; - EGLContext m_pContext; - EGLContext m_cContext; + virtual IFrameLayerAndroid* updatePosition(SkRect viewport, + IFrameLayerAndroid* parentIframeLayer); - bool m_supportsEGLImage; + virtual void dumpLayer(FILE*, int indentLevel) const; + + const IntPoint& iframeOffset() const { return m_iframeOffset; } + +private: + IntPoint m_iframeOffset; }; -} // namespace WebCore +} + +#endif // USE(ACCELERATED_COMPOSITING) -#endif // DoubleBufferedTexture_h +#endif // IFrameLayerAndroid_h diff --git a/Source/WebCore/platform/graphics/android/ImageAndroid.cpp b/Source/WebCore/platform/graphics/android/ImageAndroid.cpp index 01fe272..8e0c112 100644 --- a/Source/WebCore/platform/graphics/android/ImageAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/ImageAndroid.cpp @@ -44,7 +44,7 @@ #include "SkTemplates.h" #include "SkiaUtils.h" -#include <utils/AssetManager.h> +#include <androidfw/AssetManager.h> //#define TRACE_SUBSAMPLED_BITMAPS //#define TRACE_SKIPPED_BITMAPS diff --git a/Source/WebCore/platform/graphics/android/ImageBufferAndroid.cpp b/Source/WebCore/platform/graphics/android/ImageBufferAndroid.cpp index 751a08f..f148881 100644 --- a/Source/WebCore/platform/graphics/android/ImageBufferAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/ImageBufferAndroid.cpp @@ -196,7 +196,7 @@ void ImageBuffer::putUnmultipliedImageData(ByteArray* source, const IntSize& sou ASSERT(destx >= 0); ASSERT(destx < m_size.width()); ASSERT(originx >= 0); - ASSERT(originx <= sourceRect.right()); + ASSERT(originx <= sourceRect.maxX()); int endx = destPoint.x() + sourceRect.maxX(); ASSERT(endx <= m_size.width()); @@ -208,7 +208,7 @@ void ImageBuffer::putUnmultipliedImageData(ByteArray* source, const IntSize& sou ASSERT(desty >= 0); ASSERT(desty < m_size.height()); ASSERT(originy >= 0); - ASSERT(originy <= sourceRect.bottom()); + ASSERT(originy <= sourceRect.maxY()); int endy = destPoint.y() + sourceRect.maxY(); ASSERT(endy <= m_size.height()); diff --git a/Source/WebCore/platform/graphics/android/ImageTexture.cpp b/Source/WebCore/platform/graphics/android/ImageTexture.cpp index 577e7f0..815a70a 100644 --- a/Source/WebCore/platform/graphics/android/ImageTexture.cpp +++ b/Source/WebCore/platform/graphics/android/ImageTexture.cpp @@ -188,18 +188,18 @@ bool ImageTexture::prepareGL(GLWebViewState* state) return false; if (!m_texture && m_picture) { - m_texture = new TiledTexture(this); + m_texture = new TiledTexture(); SkRegion region; region.setRect(0, 0, m_image->width(), m_image->height()); - m_texture->update(region, m_picture); + m_texture->markAsDirty(region); } 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->prepareGL(state, 1.0, visibleArea, this); + if (m_texture->isReady()) { m_texture->swapTiles(); return false; } @@ -230,7 +230,20 @@ float ImageTexture::opacity() return m_layer->drawOpacity(); } -void ImageTexture::drawGL(LayerAndroid* layer) +bool ImageTexture::paint(BaseTile* tile, SkCanvas* canvas) +{ + if (!m_picture) { + XLOG("IT %p COULDNT PAINT, NO PICTURE", this); + return false; + } + + XLOG("IT %p painting tile %d, %d with picture %p", this, tile->x(), tile->y(), m_picture); + canvas->drawPicture(*m_picture); + + return true; +} + +void ImageTexture::drawGL(LayerAndroid* layer, float opacity) { if (!layer) return; @@ -240,8 +253,10 @@ void ImageTexture::drawGL(LayerAndroid* layer) // 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(); + if (m_texture) { + IntRect visibleArea = m_layer->visibleArea(); + m_texture->drawGL(visibleArea, opacity, transform()); + } m_layer = 0; } diff --git a/Source/WebCore/platform/graphics/android/ImageTexture.h b/Source/WebCore/platform/graphics/android/ImageTexture.h index 6c6a075..91c8a29 100644 --- a/Source/WebCore/platform/graphics/android/ImageTexture.h +++ b/Source/WebCore/platform/graphics/android/ImageTexture.h @@ -67,13 +67,13 @@ class TiledTexture; // so that we can share the same textures and limits as the rest of the layers. // ///////////////////////////////////////////////////////////////////////////////// -class ImageTexture : public SurfacePainter { +class ImageTexture : public TilePainter { public: ImageTexture(SkBitmap* bmp, unsigned crc); virtual ~ImageTexture(); bool prepareGL(GLWebViewState*); - void drawGL(LayerAndroid* painter); + void drawGL(LayerAndroid* layer, float opacity); void drawCanvas(SkCanvas*, SkRect&); bool hasContentToShow(); SkBitmap* bitmap() { return m_image; } @@ -85,14 +85,15 @@ public: bool equalsCRC(unsigned crc); // methods used by TiledTexture - virtual const TransformationMatrix* transform(); + virtual bool paint(BaseTile* tile, SkCanvas* canvas); virtual float opacity(); int nbTextures(); - virtual SurfaceType type() { return SurfacePainter::ImageSurface; } + virtual SurfaceType type() { return TilePainter::Image; } private: + const TransformationMatrix* transform(); SkBitmapRef* m_imageRef; SkBitmap* m_image; diff --git a/Source/WebCore/platform/graphics/android/InspectorCanvas.cpp b/Source/WebCore/platform/graphics/android/InspectorCanvas.cpp new file mode 100644 index 0000000..0137cec --- /dev/null +++ b/Source/WebCore/platform/graphics/android/InspectorCanvas.cpp @@ -0,0 +1,149 @@ +/* + * Copyright 2011, 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 "InspectorCanvas.h" + +#include "SkPicture.h" + +#include <cutils/log.h> +#include <wtf/CurrentTime.h> +#include <wtf/text/CString.h> + +#undef XLOGC +#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "InspectorCanvas", __VA_ARGS__) + +#ifdef DEBUG + +#undef XLOG +#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "InspectorCanvas", __VA_ARGS__) + +#else + +#undef XLOG +#define XLOG(...) + +#endif // DEBUG + + +namespace WebCore { + + +void InspectorCanvas::setHasText() +{ + m_hasText = true; + setHasContent(); +} + +void InspectorCanvas::setHasContent() +{ + m_hasContent = true; + if (m_hasText) { + // has text. Have to paint properly, so no further + // information is useful + m_picture->abortPlayback(); + } +} + +void InspectorCanvas::setIsBackground(const SkPaint& paint) +{ + // TODO: if the paint is a solid color, opaque, and the last instruction in + // the picture, replace the picture with simple draw rect info + setHasContent(); +} + +void InspectorCanvas::commonDrawBitmap(const SkBitmap& bitmap, + const SkIRect* rect, + const SkMatrix&, + const SkPaint&) +{ + setHasContent(); +} + +void InspectorCanvas::drawPaint(const SkPaint& paint) +{ + setHasContent(); +} + +void InspectorCanvas::drawPath(const SkPath&, const SkPaint& paint) +{ + setHasContent(); +} +void InspectorCanvas::drawPoints(PointMode, size_t, + const SkPoint [], const SkPaint& paint) +{ + setHasContent(); +} + +void InspectorCanvas::drawRect(const SkRect& rect, const SkPaint& paint) +{ + if (rect.fLeft == 0 + && rect.fTop == 0 + && rect.width() >= m_picture->width() + && rect.height() >= m_picture->height()) { + // rect same size as canvas, treat layer as a single color rect until + // more content is drawn + setIsBackground(paint); + } else { + // regular rect drawing path + setHasContent(); + } + XLOG("draw rect at %f %f, size %f %f, picture size %d %d", + rect.fLeft, rect.fTop, rect.width(), rect.height(), + m_picture->width(), m_picture->height()); +} +void InspectorCanvas::drawSprite(const SkBitmap& , int , int , + const SkPaint* paint) +{ + setHasContent(); +} + +void InspectorCanvas::drawText(const void*, size_t byteLength, SkScalar, + SkScalar, const SkPaint& paint) +{ + setHasText(); +} + +void InspectorCanvas::drawPosText(const void* , size_t byteLength, + const SkPoint [], const SkPaint& paint) +{ + setHasText(); +} + +void InspectorCanvas::drawPosTextH(const void*, size_t byteLength, + const SkScalar [], SkScalar, + const SkPaint& paint) +{ + setHasText(); +} + +void InspectorCanvas::drawTextOnPath(const void*, size_t byteLength, + const SkPath&, const SkMatrix*, + const SkPaint& paint) +{ + setHasText(); +} + +} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/InspectorCanvas.h b/Source/WebCore/platform/graphics/android/InspectorCanvas.h new file mode 100644 index 0000000..415a579 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/InspectorCanvas.h @@ -0,0 +1,102 @@ +/* + * Copyright 2011, 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 InspectorCanvas_h +#define InspectorCanvas_h + +#include "SkBounder.h" +#include "SkCanvas.h" + +namespace WebCore { + +class InspectorBounder : public SkBounder { + virtual bool onIRect(const SkIRect& rect) + { + return false; + } +}; + +class InspectorCanvas : public SkCanvas { +public: + InspectorCanvas(SkBounder* bounder, SkPicture* picture) + : m_picture(picture) + , m_hasText(false) + , m_hasContent(false) + { + setBounder(bounder); + } + + bool hasText() {return m_hasText;} + bool hasContent() {return m_hasContent;} + + virtual bool clipPath(const SkPath&, SkRegion::Op) { + return true; + } + + virtual void commonDrawBitmap(const SkBitmap& bitmap, + const SkIRect* rect, + const SkMatrix&, + const SkPaint&); + + virtual void drawPaint(const SkPaint& paint); + virtual void drawPath(const SkPath&, const SkPaint& paint); + virtual void drawPoints(PointMode, size_t, + const SkPoint [], const SkPaint& paint); + + virtual void drawRect(const SkRect& , const SkPaint& paint); + virtual void drawSprite(const SkBitmap& , int , int , + const SkPaint* paint = NULL); + + virtual void drawText(const void*, size_t byteLength, SkScalar, + SkScalar, const SkPaint& paint); + virtual void drawPosText(const void* , size_t byteLength, + const SkPoint [], const SkPaint& paint); + virtual void drawPosTextH(const void*, size_t byteLength, + const SkScalar [], SkScalar, + const SkPaint& paint); + virtual void drawTextOnPath(const void*, size_t byteLength, + const SkPath&, const SkMatrix*, + const SkPaint& paint); + +private: + + // vector instructions exist, must repaint at any scale + void setHasText(); + + // painting is required + void setHasContent(); + + // rect covering entire content, don't need to use a texture if nothing else + // is painted + void setIsBackground(const SkPaint& paint); + + SkPicture* m_picture; + bool m_hasText; + bool m_hasContent; +}; + +} // namespace WebCore + +#endif // InspectorCanvas_h diff --git a/Source/WebCore/platform/graphics/android/Layer.cpp b/Source/WebCore/platform/graphics/android/Layer.cpp index 9280461..7453a24 100644 --- a/Source/WebCore/platform/graphics/android/Layer.cpp +++ b/Source/WebCore/platform/graphics/android/Layer.cpp @@ -158,13 +158,9 @@ void Layer::localToAncestor(const Layer* ancestor, SkMatrix* matrix) const { /////////////////////////////////////////////////////////////////////////////// -void Layer::onDraw(SkCanvas*, SkScalar opacity) { -// SkDebugf("----- no onDraw for %p\n", this); -} - #include "SkString.h" -void Layer::draw(SkCanvas* canvas, SkScalar opacity) { +void Layer::draw(SkCanvas* canvas, android::DrawExtra* extra, SkScalar opacity) { #if 0 SkString str1, str2; // getMatrix().toDumpString(&str1); @@ -193,7 +189,7 @@ void Layer::draw(SkCanvas* canvas, SkScalar opacity) { canvas->concat(tmp); } - onDraw(canvas, opacity); + onDraw(canvas, opacity, extra, FlattenedLayers); #ifdef DEBUG_DRAW_LAYER_BOUNDS { @@ -213,7 +209,7 @@ void Layer::draw(SkCanvas* canvas, SkScalar opacity) { if (count > 0) { canvas->concat(getChildrenMatrix()); for (int i = 0; i < count; i++) { - getChild(i)->draw(canvas, opacity); + getChild(i)->draw(canvas, extra, opacity); } } } diff --git a/Source/WebCore/platform/graphics/android/Layer.h b/Source/WebCore/platform/graphics/android/Layer.h index 5200a3d..e872278 100644 --- a/Source/WebCore/platform/graphics/android/Layer.h +++ b/Source/WebCore/platform/graphics/android/Layer.h @@ -17,6 +17,7 @@ #ifndef Layer_DEFINED #define Layer_DEFINED +#include "DrawExtra.h" #include "TestExport.h" #include "SkRefCnt.h" #include "SkTDArray.h" @@ -64,19 +65,6 @@ public: void setChildrenMatrix(const SkMatrix& matrix) { m_childrenMatrix = matrix; } // rendering asset management - - // tell rendering assets to update their tile content with most recent painted data - virtual void swapTiles() {} - - // tell rendering assets to use this layer tree for drawing - virtual void setIsDrawing(bool isDrawing) {} - - // take rendering assets from drawing tree, or create if they don't exist - virtual void setIsPainting(Layer* drawingTree) {} - - // if a similar layer exists in the replacement tree, add invals to it - virtual void mergeInvalsInto(Layer* replacementTree) {} - void markAsDirty(const SkRegion& invalRegion) { m_dirtyRegion.op(invalRegion, SkRegion::kUnion_Op); } @@ -87,14 +75,6 @@ public: // drawing - virtual bool isReady() { return false; } - - // TODO: clean out several of these, leave them in GLWebViewState - - virtual bool prepare(double currentTime, WebCore::IntRect& viewRect, - SkRect& visibleRect, float scale) { return 0; } - virtual bool drawGL(WebCore::IntRect& viewRect, - SkRect& visibleRect, float scale) { return 0; } WebCore::GLWebViewState* state() { return m_state; } void setState(WebCore::GLWebViewState* state); @@ -165,17 +145,15 @@ public: // paint method virtual bool drawCanvas(SkCanvas*) { return false; } - void draw(SkCanvas*, SkScalar opacity); - void draw(SkCanvas* canvas) { - this->draw(canvas, SK_Scalar1); - } + void draw(SkCanvas*, android::DrawExtra* extra, SkScalar opacity = SK_Scalar1); void setHasOverflowChildren(bool value) { m_hasOverflowChildren = value; } virtual bool contentIsScrollable() const { return false; } + typedef enum { MergedLayers, UnmergedLayers, FlattenedLayers } PaintStyle; protected: - virtual void onDraw(SkCanvas*, SkScalar opacity); + virtual void onDraw(SkCanvas*, SkScalar opacity, android::DrawExtra* extra, PaintStyle style) {} bool m_hasOverflowChildren; diff --git a/Source/WebCore/platform/graphics/android/LayerAndroid.cpp b/Source/WebCore/platform/graphics/android/LayerAndroid.cpp index 962bcdf..7886d7b 100644 --- a/Source/WebCore/platform/graphics/android/LayerAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/LayerAndroid.cpp @@ -6,13 +6,17 @@ #include "AndroidAnimation.h" #include "ClassTracker.h" #include "DrawExtra.h" +#include "DumpLayer.h" +#include "FixedPositioning.h" #include "GLUtils.h" #include "ImagesManager.h" +#include "InspectorCanvas.h" +#include "LayerContent.h" +#include "LayerGroup.h" #include "MediaLayer.h" -#include "PaintedSurface.h" #include "ParseCanvas.h" +#include "PictureLayerContent.h" #include "SkBitmapRef.h" -#include "SkBounder.h" #include "SkDrawFilter.h" #include "SkPaint.h" #include "SkPicture.h" @@ -24,6 +28,12 @@ #define LAYER_DEBUG // Add diagonals for debugging #undef LAYER_DEBUG +#define DISABLE_LAYER_MERGE +#undef DISABLE_LAYER_MERGE + +#define LAYER_GROUPING_DEBUG +#undef LAYER_GROUPING_DEBUG + #include <cutils/log.h> #include <wtf/text/CString.h> #define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "LayerAndroid", __VA_ARGS__) @@ -55,112 +65,29 @@ private: int m_opacity; }; -class HasTextBounder : public SkBounder { - virtual bool onIRect(const SkIRect& rect) - { - return false; - } -}; - -class HasTextCanvas : public SkCanvas { -public: - HasTextCanvas(SkBounder* bounder, SkPicture* picture) - : m_picture(picture) - , m_hasText(false) - { - setBounder(bounder); - } - - void setHasText() - { - m_hasText = true; - m_picture->abortPlayback(); - } - - bool hasText() - { - return m_hasText; - } - - virtual bool clipPath(const SkPath&, SkRegion::Op) { - return true; - } - - virtual void commonDrawBitmap(const SkBitmap& bitmap, - const SkIRect* rect, - const SkMatrix&, - const SkPaint&) {} - - virtual void drawPaint(const SkPaint& paint) {} - virtual void drawPath(const SkPath&, const SkPaint& paint) {} - virtual void drawPoints(PointMode, size_t, - const SkPoint [], const SkPaint& paint) {} - - virtual void drawRect(const SkRect& , const SkPaint& paint) {} - virtual void drawSprite(const SkBitmap& , int , int , - const SkPaint* paint = NULL) {} - - virtual void drawText(const void*, size_t byteLength, SkScalar, - SkScalar, const SkPaint& paint) - { - setHasText(); - } - - virtual void drawPosText(const void* , size_t byteLength, - const SkPoint [], const SkPaint& paint) - { - setHasText(); - } - - virtual void drawPosTextH(const void*, size_t byteLength, - const SkScalar [], SkScalar, - const SkPaint& paint) - { - setHasText(); - } - - virtual void drawTextOnPath(const void*, size_t byteLength, - const SkPath&, const SkMatrix*, - const SkPaint& paint) - { - setHasText(); - } - - virtual void drawPicture(SkPicture& picture) { - SkCanvas::drawPicture(picture); - } - -private: - - SkPicture* m_picture; - bool m_hasText; -}; - /////////////////////////////////////////////////////////////////////////////// LayerAndroid::LayerAndroid(RenderLayer* owner) : Layer(), m_haveClip(false), - m_isFixed(false), - m_isIframe(false), m_backfaceVisibility(true), m_visible(true), m_preserves3D(false), m_anchorPointZ(0), - m_recordingPicture(0), + m_fixedPosition(0), + m_zValue(0), m_uniqueId(++gUniqueId), - m_texture(0), + m_content(0), m_imageCRC(0), - m_pictureUsed(0), m_scale(1), m_lastComputeTextureSize(0), m_owningLayer(owner), m_type(LayerAndroid::WebCoreLayer), - m_hasText(true) + m_intrinsicallyComposited(true), + m_layerGroup(0) { m_backgroundColor = 0; m_preserves3D = false; - m_iframeOffset.set(0,0); m_dirtyRegion.setEmpty(); #ifdef DEBUG_COUNT ClassTracker::instance()->increment("LayerAndroid"); @@ -170,42 +97,38 @@ LayerAndroid::LayerAndroid(RenderLayer* owner) : Layer(), LayerAndroid::LayerAndroid(const LayerAndroid& layer) : Layer(layer), m_haveClip(layer.m_haveClip), - m_isIframe(layer.m_isIframe), + m_fixedPosition(0), + m_zValue(layer.m_zValue), m_uniqueId(layer.m_uniqueId), - m_texture(0), m_owningLayer(layer.m_owningLayer), m_type(LayerAndroid::UILayer), - m_hasText(true) + m_intrinsicallyComposited(layer.m_intrinsicallyComposited), + m_layerGroup(0) { - m_isFixed = layer.m_isFixed; m_imageCRC = layer.m_imageCRC; if (m_imageCRC) ImagesManager::instance()->retainImage(m_imageCRC); - m_renderLayerPos = layer.m_renderLayerPos; m_transform = layer.m_transform; m_backfaceVisibility = layer.m_backfaceVisibility; m_visible = layer.m_visible; m_backgroundColor = layer.m_backgroundColor; - m_fixedLeft = layer.m_fixedLeft; - m_fixedTop = layer.m_fixedTop; - m_fixedRight = layer.m_fixedRight; - m_fixedBottom = layer.m_fixedBottom; - m_fixedMarginLeft = layer.m_fixedMarginLeft; - m_fixedMarginTop = layer.m_fixedMarginTop; - m_fixedMarginRight = layer.m_fixedMarginRight; - m_fixedMarginBottom = layer.m_fixedMarginBottom; - m_fixedRect = layer.m_fixedRect; - m_iframeOffset = layer.m_iframeOffset; - m_recordingPicture = layer.m_recordingPicture; - SkSafeRef(m_recordingPicture); + m_offset = layer.m_offset; + + m_content = layer.m_content; + SkSafeRef(m_content); m_preserves3D = layer.m_preserves3D; m_anchorPointZ = layer.m_anchorPointZ; + + if (layer.m_fixedPosition) { + m_fixedPosition = new FixedPositioning(this, *layer.m_fixedPosition); + Layer::setShouldInheritFromRootTransform(true); + } + m_drawTransform = layer.m_drawTransform; m_childrenTransform = layer.m_childrenTransform; - m_pictureUsed = layer.m_pictureUsed; m_dirtyRegion = layer.m_dirtyRegion; m_scale = layer.m_scale; m_lastComputeTextureSize = 0; @@ -218,48 +141,27 @@ LayerAndroid::LayerAndroid(const LayerAndroid& layer) : Layer(layer), m_animations.add(it->first, it->second); } - m_hasText = layer.m_hasText; - #ifdef DEBUG_COUNT ClassTracker::instance()->increment("LayerAndroid - recopy (UI)"); ClassTracker::instance()->add(this); #endif } -void LayerAndroid::checkTextPresence() -{ - if (m_recordingPicture) { - // Let's check if we have text or not. If we don't, we can limit - // ourselves to scale 1! - HasTextBounder hasTextBounder; - HasTextCanvas checker(&hasTextBounder, m_recordingPicture); - SkBitmap bitmap; - bitmap.setConfig(SkBitmap::kARGB_8888_Config, - m_recordingPicture->width(), - m_recordingPicture->height()); - checker.setBitmapDevice(bitmap); - checker.drawPicture(*m_recordingPicture); - m_hasText = checker.hasText(); - } -} - LayerAndroid::LayerAndroid(SkPicture* picture) : Layer(), m_haveClip(false), - m_isFixed(false), - m_isIframe(false), - m_recordingPicture(picture), + m_fixedPosition(0), + m_zValue(0), m_uniqueId(++gUniqueId), - m_texture(0), m_imageCRC(0), m_scale(1), m_lastComputeTextureSize(0), m_owningLayer(0), m_type(LayerAndroid::NavCacheLayer), - m_hasText(true) + m_intrinsicallyComposited(true), + m_layerGroup(0) { m_backgroundColor = 0; - SkSafeRef(m_recordingPicture); - m_iframeOffset.set(0,0); + m_content = new PictureLayerContent(picture); m_dirtyRegion.setEmpty(); #ifdef DEBUG_COUNT ClassTracker::instance()->increment("LayerAndroid - from picture"); @@ -271,8 +173,11 @@ LayerAndroid::~LayerAndroid() { if (m_imageCRC) ImagesManager::instance()->releaseImage(m_imageCRC); + if (m_fixedPosition) + delete m_fixedPosition; - SkSafeUnref(m_recordingPicture); + SkSafeUnref(m_content); + // Don't unref m_layerGroup, owned by BaseLayerAndroid m_animations.clear(); #ifdef DEBUG_COUNT ClassTracker::instance()->remove(this); @@ -285,6 +190,11 @@ LayerAndroid::~LayerAndroid() #endif } +bool LayerAndroid::hasText() +{ + return m_content && m_content->hasText(); +} + static int gDebugNbAnims = 0; bool LayerAndroid::evaluateAnimations() @@ -395,8 +305,6 @@ void LayerAndroid::setBackgroundColor(SkColor color) m_backgroundColor = color; } -static int gDebugChildLevel; - FloatPoint LayerAndroid::translation() const { TransformationMatrix::DecomposedType tDecomp; @@ -454,216 +362,38 @@ void LayerAndroid::clipInner(SkTDArray<SkRect>* region, localBounds.intersect(local); if (localBounds.isEmpty()) return; - if (m_recordingPicture && boundsIsUnique(*region, localBounds)) + if (m_content && boundsIsUnique(*region, localBounds)) *region->append() = localBounds; for (int i = 0; i < countChildren(); i++) getChild(i)->clipInner(region, m_haveClip ? localBounds : local); } -class FindCheck : public SkBounder { -public: - FindCheck() - : m_drew(false) - , m_drewText(false) - { - } - - bool drew() const { return m_drew; } - bool drewText() const { return m_drewText; } - void reset() { m_drew = m_drewText = false; } - -protected: - virtual bool onIRect(const SkIRect& ) - { - m_drew = true; - return false; - } - - virtual bool onIRectGlyph(const SkIRect& , const SkBounder::GlyphRec& ) - { - m_drew = m_drewText = true; - return false; - } - - bool m_drew; - bool m_drewText; -}; - -class FindCanvas : public ParseCanvas { -public: - void draw(SkPicture* picture, SkScalar offsetX, SkScalar offsetY) - { - save(); - translate(-offsetX, -offsetY); - picture->draw(this); - restore(); - } -}; - -class LayerAndroid::FindState { -public: - static const int TOUCH_SLOP = 10; - - FindState(int x, int y) - : m_x(x) - , m_y(y) - , m_bestX(x) - , m_bestY(y) - , m_best(0) - { - m_bitmap.setConfig(SkBitmap::kARGB_8888_Config, TOUCH_SLOP * 2, - TOUCH_SLOP * 2); - m_checker.setBounder(&m_findCheck); - m_checker.setBitmapDevice(m_bitmap); - } - - const LayerAndroid* best() const { return m_best; } - int bestX() const { return m_bestX; } - int bestY() const { return m_bestY; } - - bool drew(SkPicture* picture, const SkRect& localBounds) - { - m_findCheck.reset(); - SkScalar localX = SkIntToScalar(m_x - TOUCH_SLOP) - localBounds.fLeft; - SkScalar localY = SkIntToScalar(m_y - TOUCH_SLOP) - localBounds.fTop; - m_checker.draw(picture, localX, localY); - return m_findCheck.drew(); - } - - bool drewText() { return m_findCheck.drewText(); } - - void setBest(const LayerAndroid* best, int x, int y) - { - m_best = best; - m_bestX = x; - m_bestY = y; - } - int x() const { return m_x; } - int y() const { return m_y; } - - void setLocation(int x, int y) - { - m_x = x; - m_y = y; - } - -protected: - int m_x; - int m_y; - int m_bestX; - int m_bestY; - const LayerAndroid* m_best; - FindCheck m_findCheck; - SkBitmap m_bitmap; - FindCanvas m_checker; -}; - -void LayerAndroid::findInner(LayerAndroid::FindState& state) const -{ - int x = state.x(); - int y = state.y(); - SkRect localBounds; - bounds(&localBounds); - if (!localBounds.contains(x, y)) - return; - // Move into local coordinates. - state.setLocation(x - localBounds.fLeft, y - localBounds.fTop); - 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 (!contentIsScrollable() && !state.drew(m_recordingPicture, localBounds)) - return; - state.setBest(this, testX, testY); // set last match (presumably on top) -} - -const LayerAndroid* LayerAndroid::find(int* xPtr, int* yPtr, SkPicture* root) const +IFrameLayerAndroid* LayerAndroid::updatePosition(SkRect viewport, + IFrameLayerAndroid* parentIframeLayer) { - FindState state(*xPtr, *yPtr); - SkRect rootBounds; - rootBounds.setEmpty(); - if (root && state.drew(root, rootBounds) && state.drewText()) - return 0; // use the root picture only if it contains the text - findInner(state); - *xPtr = state.bestX(); - *yPtr = state.bestY(); - return state.best(); + // subclasses can implement this virtual function to modify their position + if (m_fixedPosition) + return m_fixedPosition->updatePosition(viewport, parentIframeLayer); + return parentIframeLayer; } -/////////////////////////////////////////////////////////////////////////////// - -bool LayerAndroid::updateFixedLayersPositions(SkRect viewport, LayerAndroid* parentIframeLayer) +void LayerAndroid::updateLayerPositions(SkRect viewport, IFrameLayerAndroid* parentIframeLayer) { - bool hasFixedElements = false; XLOG("updating fixed positions, using viewport %fx%f - %fx%f", viewport.fLeft, viewport.fTop, viewport.width(), viewport.height()); - // If this is an iframe, accumulate the offset from the parent with - // current position, and change the parent pointer. - if (m_isIframe) { - // If this is the top level, take the current position - SkPoint parentOffset; - parentOffset.set(0,0); - if (parentIframeLayer) - parentOffset = parentIframeLayer->getPosition(); - - m_iframeOffset = parentOffset + getPosition(); - - parentIframeLayer = this; - } - if (m_isFixed) { - hasFixedElements = true; - // So if this is a fixed layer inside a iframe, use the iframe offset - // and the iframe's size as the viewport and pass to the children - if (parentIframeLayer) { - viewport = SkRect::MakeXYWH(parentIframeLayer->m_iframeOffset.fX, - parentIframeLayer->m_iframeOffset.fY, - parentIframeLayer->getSize().width(), - parentIframeLayer->getSize().height()); - } - float w = viewport.width(); - float h = viewport.height(); - float dx = viewport.fLeft; - float dy = viewport.fTop; - float x = dx; - float y = dy; - - // It turns out that when it is 'auto', we should use the webkit value - // from the original render layer's X,Y, that will take care of alignment - // with the parent's layer and fix Margin etc. - if (!(m_fixedLeft.defined() || m_fixedRight.defined())) - x += m_renderLayerPos.x(); - else if (m_fixedLeft.defined() || !m_fixedRight.defined()) - x += m_fixedMarginLeft.calcFloatValue(w) + m_fixedLeft.calcFloatValue(w) - m_fixedRect.fLeft; - else - x += w - m_fixedMarginRight.calcFloatValue(w) - m_fixedRight.calcFloatValue(w) - m_fixedRect.fRight; - - if (!(m_fixedTop.defined() || m_fixedBottom.defined())) - y += m_renderLayerPos.y(); - else if (m_fixedTop.defined() || !m_fixedBottom.defined()) - y += m_fixedMarginTop.calcFloatValue(h) + m_fixedTop.calcFloatValue(h) - m_fixedRect.fTop; - else - y += h - m_fixedMarginBottom.calcFloatValue(h) - m_fixedBottom.calcFloatValue(h) - m_fixedRect.fBottom; - - this->setPosition(x, y); - } + IFrameLayerAndroid* iframeLayer = updatePosition(viewport, parentIframeLayer); int count = this->countChildren(); for (int i = 0; i < count; i++) - hasFixedElements |= this->getChild(i)->updateFixedLayersPositions(viewport, parentIframeLayer); - - return hasFixedElements; + this->getChild(i)->updateLayerPositions(viewport, iframeLayer); } void LayerAndroid::updatePositions() { // apply the viewport to us - if (!m_isFixed) { + if (!isFixed()) { // turn our fields into a matrix. // // FIXME: this should happen in the caller, and we should remove these @@ -685,13 +415,11 @@ void LayerAndroid::updateGLPositionsAndScale(const TransformationMatrix& parentM m_atomicSync.lock(); IntSize layerSize(getSize().width(), getSize().height()); FloatPoint anchorPoint(getAnchorPoint().fX, getAnchorPoint().fY); - FloatPoint position(getPosition().fX, getPosition().fY); - float centerOffsetX = (0.5f - anchorPoint.x()) * layerSize.width(); - float centerOffsetY = (0.5f - anchorPoint.y()) * layerSize.height(); + FloatPoint position(getPosition().fX - m_offset.x(), getPosition().fY - m_offset.y()); float originX = anchorPoint.x() * layerSize.width(); float originY = anchorPoint.y() * layerSize.height(); TransformationMatrix localMatrix; - if (!m_isFixed) + if (!isFixed()) localMatrix = parentMatrix; localMatrix.translate3d(originX + position.x(), originY + position.y(), @@ -759,13 +487,27 @@ void LayerAndroid::updateGLPositionsAndScale(const TransformationMatrix& parentM // now apply it to our children + TransformationMatrix childMatrix; + childMatrix = localMatrix; + childMatrix.translate3d(m_offset.x(), m_offset.y(), 0); if (!m_childrenTransform.isIdentity()) { - localMatrix.translate(getSize().width() * 0.5f, getSize().height() * 0.5f); - localMatrix.multiply(m_childrenTransform); - localMatrix.translate(-getSize().width() * 0.5f, -getSize().height() * 0.5f); + childMatrix.translate(getSize().width() * 0.5f, getSize().height() * 0.5f); + childMatrix.multiply(m_childrenTransform); + childMatrix.translate(-getSize().width() * 0.5f, -getSize().height() * 0.5f); } for (int i = 0; i < count; i++) - this->getChild(i)->updateGLPositionsAndScale(localMatrix, drawClip(), opacity, scale); + this->getChild(i)->updateGLPositionsAndScale(childMatrix, drawClip(), opacity, scale); +} + +bool LayerAndroid::visible() { + // TODO: avoid climbing tree each access + LayerAndroid* current = this; + while (current->getParent()) { + if (!current->m_visible) + return false; + current = static_cast<LayerAndroid*>(current->getParent()); + } + return true; } void LayerAndroid::setContentsImage(SkBitmapRef* img) @@ -775,16 +517,16 @@ void LayerAndroid::setContentsImage(SkBitmapRef* img) m_imageCRC = image ? image->imageCRC() : 0; } -bool LayerAndroid::needsTexture() +void LayerAndroid::setContent(LayerContent* content) { - return m_imageCRC || (m_recordingPicture - && m_recordingPicture->width() && m_recordingPicture->height()); + SkSafeRef(content); + SkSafeUnref(m_content); + m_content = content; } -void LayerAndroid::removeTexture(PaintedSurface* texture) +bool LayerAndroid::needsTexture() { - if (texture == m_texture) - m_texture = 0; + return m_content && !m_content->isEmpty(); } IntRect LayerAndroid::clippedRect() const @@ -816,18 +558,6 @@ int LayerAndroid::nbTexturedLayers() return nb; } -void LayerAndroid::computeTexturesAmount(TexturesResult* result) -{ - if (!result) - return; - - int count = this->countChildren(); - for (int i = 0; i < count; i++) - this->getChild(i)->computeTexturesAmount(result); - if (m_texture && m_visible) - m_texture->computeTexturesAmount(result); -} - void LayerAndroid::showLayer(int indent) { char spaces[256]; @@ -848,9 +578,9 @@ void LayerAndroid::showLayer(int indent) IntRect visible = visibleArea(); IntRect clip(m_clippingRect.x(), m_clippingRect.y(), m_clippingRect.width(), m_clippingRect.height()); - XLOGC("%s [%d:0x%x] - %s %s - area (%d, %d, %d, %d) - visible (%d, %d, %d, %d) " - "clip (%d, %d, %d, %d) %s %s prepareContext(%x), pic w: %d h: %d", - spaces, uniqueId(), m_owningLayer, + XLOGC("%s %s (%d) [%d:0x%x] - %s %s - area (%d, %d, %d, %d) - visible (%d, %d, %d, %d) " + "clip (%d, %d, %d, %d) %s %s m_content(%x), pic w: %d h: %d", + spaces, subclassName().latin1().data(), subclassType(), uniqueId(), m_owningLayer, needsTexture() ? "needs a texture" : "no texture", m_imageCRC ? "has an image" : "no image", tr.x(), tr.y(), tr.width(), tr.height(), @@ -858,77 +588,26 @@ void LayerAndroid::showLayer(int indent) clip.x(), clip.y(), clip.width(), clip.height(), contentIsScrollable() ? "SCROLLABLE" : "", isFixed() ? "FIXED" : "", - m_recordingPicture, - m_recordingPicture ? m_recordingPicture->width() : -1, - m_recordingPicture ? m_recordingPicture->height() : -1); + m_content, + m_content ? m_content->width() : -1, + m_content ? m_content->height() : -1); int count = this->countChildren(); for (int i = 0; i < count; i++) this->getChild(i)->showLayer(indent + 1); } -void LayerAndroid::swapTiles() -{ - int count = this->countChildren(); - for (int i = 0; i < count; i++) - this->getChild(i)->swapTiles(); - - if (m_texture) - m_texture->swapTiles(); -} - -void LayerAndroid::setIsDrawing(bool isDrawing) -{ - int count = this->countChildren(); - for (int i = 0; i < count; i++) - this->getChild(i)->setIsDrawing(isDrawing); - - if (m_texture) { - m_texture->setDrawingLayer(isDrawing ? this : 0); - m_texture->clearPaintingLayer(); - } -} - -void LayerAndroid::setIsPainting(Layer* drawingTree) -{ - XLOG("setting layer %p as painting, needs texture %d, drawing tree %p", - this, needsTexture(), drawingTree); - int count = this->countChildren(); - for (int i = 0; i < count; i++) - this->getChild(i)->setIsPainting(drawingTree); - - - LayerAndroid* drawingLayer = 0; - if (drawingTree) - drawingLayer = static_cast<LayerAndroid*>(drawingTree)->findById(uniqueId()); - - obtainTextureForPainting(drawingLayer); -} - -void LayerAndroid::mergeInvalsInto(Layer* replacementTree) +void LayerAndroid::mergeInvalsInto(LayerAndroid* replacementTree) { int count = this->countChildren(); for (int i = 0; i < count; i++) this->getChild(i)->mergeInvalsInto(replacementTree); - LayerAndroid* replacementLayer = static_cast<LayerAndroid*>(replacementTree)->findById(uniqueId()); + LayerAndroid* replacementLayer = replacementTree->findById(uniqueId()); if (replacementLayer) replacementLayer->markAsDirty(m_dirtyRegion); } -bool LayerAndroid::isReady() -{ - int count = countChildren(); - for (int i = 0; i < count; i++) - if (!getChild(i)->isReady()) - return false; - - if (m_texture) - return m_texture->isReady(); - // TODO: image, check if uploaded? - return true; -} - bool LayerAndroid::updateWithTree(LayerAndroid* newTree) { // Disable fast update for now @@ -966,78 +645,128 @@ bool LayerAndroid::updateWithLayer(LayerAndroid* layer) if (m_imageCRC != layer->m_imageCRC) m_visible = false; - if ((m_recordingPicture != layer->m_recordingPicture) + if ((m_content != layer->m_content) || (m_imageCRC != layer->m_imageCRC)) return true; return false; } -void LayerAndroid::obtainTextureForPainting(LayerAndroid* drawingLayer) +static inline bool compareLayerZ(const LayerAndroid* a, const LayerAndroid* b) { - if (!needsTexture()) - return; + return a->zValue() > b->zValue(); +} - if (m_imageCRC) { - if (m_texture) { - m_texture->setDrawingLayer(0); - m_texture->clearPaintingLayer(); - m_texture = 0; - } - } else { - if (drawingLayer) { - // if a previous tree had the same layer, paint with that painted surface - m_texture = drawingLayer->m_texture; - } +bool LayerAndroid::canJoinGroup(LayerGroup* group) +{ +#if DISABLE_LAYER_MERGE + return false; +#else + // returns true if the layer can be merged onto the layergroup + if (!group) + return false; - if (!m_texture) - m_texture = new PaintedSurface(); + LayerAndroid* lastLayer = group->getFirstLayer(); - // pass the invalidated regions to the PaintedSurface - m_texture->setPaintingLayer(this, m_dirtyRegion); - } - m_dirtyRegion.setEmpty(); -} + // isolate non-tiled layers + // TODO: remove this check so that multiple tiled layers with a invisible + // one inbetween can be merged + if (!needsTexture() || !lastLayer->needsTexture()) + return false; + // isolate clipped layers + // TODO: paint correctly with clip when merged + if (m_haveClip || lastLayer->m_haveClip) + return false; -static inline bool compareLayerZ(const LayerAndroid* a, const LayerAndroid* b) -{ - return a->zValue() > b->zValue(); -} + // isolate intrinsically composited layers + if (m_intrinsicallyComposited || lastLayer->m_intrinsicallyComposited) + return false; -// We call this in WebViewCore, when copying the tree of layers. -// As we construct a new tree that will be passed on the UI, -// we mark the webkit-side tree as having no more dirty region -// (otherwise we would continuously have those dirty region UI-side) -void LayerAndroid::clearDirtyRegion() -{ - int count = this->countChildren(); - for (int i = 0; i < count; i++) - this->getChild(i)->clearDirtyRegion(); + // TODO: investigate potential for combining transformed layers + if (!m_drawTransform.isIdentityOrTranslation() + || !lastLayer->m_drawTransform.isIdentityOrTranslation()) + return false; - m_dirtyRegion.setEmpty(); + // currently, we don't group zoomable with non-zoomable layers (unless the + // group or the layer doesn't need a texture) + if (group->needsTexture() && needsTexture() && m_content->hasText() != group->hasText()) + return false; + + // TODO: compare other layer properties - fixed? overscroll? transformed? + return true; +#endif } -void LayerAndroid::prepare() +void LayerAndroid::assignGroups(LayerMergeState* mergeState) { - XLOG("LA %p preparing, m_texture %p", this, m_texture); + // recurse through layers in draw order, and merge layers when able + + bool needNewGroup = !mergeState->currentLayerGroup + || mergeState->nonMergeNestedLevel > 0 + || !canJoinGroup(mergeState->currentLayerGroup); + + if (needNewGroup) { + mergeState->currentLayerGroup = new LayerGroup(); + mergeState->groupList->append(mergeState->currentLayerGroup); + } + +#ifdef LAYER_GROUPING_DEBUG + XLOGC("%*slayer %p(%d) rl %p %s group %p, fixed %d, anim %d, intCom %d, haveClip %d scroll %d", + 4*mergeState->depth, "", this, m_uniqueId, m_owningLayer, + needNewGroup ? "NEW" : "joins", mergeState->currentLayerGroup, + m_isFixed, m_animations.size() != 0, + m_intrinsicallyComposited, + m_haveClip, + contentIsScrollable()); +#endif + + mergeState->currentLayerGroup->addLayer(this, m_drawTransform); + m_layerGroup = mergeState->currentLayerGroup; + + if (m_haveClip || contentIsScrollable() || isFixed()) { + // disable layer merging within the children of these layer types + mergeState->nonMergeNestedLevel++; + } + + // pass the layergroup through children in drawing order, so that they may + // attach themselves (and paint on it) if possible, or ignore it and create + // a new one if not int count = this->countChildren(); if (count > 0) { + mergeState->depth++; Vector <LayerAndroid*> sublayers; for (int i = 0; i < count; i++) - sublayers.append(this->getChild(i)); + sublayers.append(getChild(i)); - // now we sort for the transparency + // sort for the transparency std::stable_sort(sublayers.begin(), sublayers.end(), compareLayerZ); + for (int i = 0; i < count; i++) + sublayers[i]->assignGroups(mergeState); + mergeState->depth--; + } - // iterate in reverse so top layers get textures first - for (int i = count-1; i >= 0; i--) - sublayers[i]->prepare(); + if (m_haveClip || contentIsScrollable() || isFixed()) { + // re-enable joining + mergeState->nonMergeNestedLevel--; + + // disallow layers painting after to join with this group + mergeState->currentLayerGroup = 0; } +} - if (m_texture) - m_texture->prepare(m_state); +// We call this in WebViewCore, when copying the tree of layers. +// As we construct a new tree that will be passed on the UI, +// we mark the webkit-side tree as having no more dirty region +// (otherwise we would continuously have those dirty region UI-side) +void LayerAndroid::clearDirtyRegion() +{ + int count = this->countChildren(); + for (int i = 0; i < count; i++) + this->getChild(i)->clearDirtyRegion(); + + m_dirtyRegion.setEmpty(); } IntRect LayerAndroid::unclippedArea() @@ -1072,7 +801,7 @@ IntRect LayerAndroid::visibleArea() return rect; } -bool LayerAndroid::drawCanvas(SkCanvas* canvas) +bool LayerAndroid::drawCanvas(SkCanvas* canvas, bool drawChildren, PaintStyle style) { if (!m_visible) return false; @@ -1091,16 +820,14 @@ bool LayerAndroid::drawCanvas(SkCanvas* canvas) SkMatrix canvasMatrix = canvas->getTotalMatrix(); matrix.postConcat(canvasMatrix); canvas->setMatrix(matrix); - SkRect layerRect; - layerRect.fLeft = 0; - layerRect.fTop = 0; - layerRect.fRight = getWidth(); - layerRect.fBottom = getHeight(); - onDraw(canvas, m_drawOpacity); + onDraw(canvas, m_drawOpacity, 0, style); } + if (!drawChildren) + return false; + // When the layer is dirty, the UI thread should be notified to redraw. - askScreenUpdate |= drawChildrenCanvas(canvas); + askScreenUpdate |= drawChildrenCanvas(canvas, style); m_atomicSync.lock(); if (askScreenUpdate || m_hasRunningAnimations || m_drawTransform.hasPerspective()) addDirtyArea(); @@ -1109,57 +836,29 @@ bool LayerAndroid::drawCanvas(SkCanvas* canvas) return askScreenUpdate; } -bool LayerAndroid::drawGL() +bool LayerAndroid::drawGL(bool layerTilesDisabled) { - FloatRect clippingRect = TilesManager::instance()->shader()->rectInScreenCoord(m_clippingRect); - TilesManager::instance()->shader()->clip(clippingRect); - if (!m_visible) - return false; + if (!layerTilesDisabled && m_imageCRC) { + ImageTexture* imageTexture = ImagesManager::instance()->retainImage(m_imageCRC); + if (imageTexture) + imageTexture->drawGL(this, getOpacity()); + ImagesManager::instance()->releaseImage(m_imageCRC); + } + m_state->glExtras()->drawGL(this); bool askScreenUpdate = false; - if (m_state->layersRenderingMode() < GLWebViewState::kScrollableAndFixedLayers) { - if (m_texture) - askScreenUpdate |= m_texture->draw(); - if (m_imageCRC) { - ImageTexture* imageTexture = ImagesManager::instance()->retainImage(m_imageCRC); - if (imageTexture) - imageTexture->drawGL(this); - ImagesManager::instance()->releaseImage(m_imageCRC); - } - } - - // When the layer is dirty, the UI thread should be notified to redraw. - askScreenUpdate |= drawChildrenGL(); m_atomicSync.lock(); - if (askScreenUpdate || m_hasRunningAnimations || m_drawTransform.hasPerspective()) + if (m_hasRunningAnimations || m_drawTransform.hasPerspective()) { + askScreenUpdate = true; addDirtyArea(); - - m_atomicSync.unlock(); - return askScreenUpdate; -} - -bool LayerAndroid::drawChildrenCanvas(SkCanvas* canvas) -{ - bool askScreenUpdate = 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]; - askScreenUpdate |= layer->drawCanvas(canvas); - } } + m_atomicSync.unlock(); return askScreenUpdate; } -bool LayerAndroid::drawChildrenGL() +bool LayerAndroid::drawChildrenCanvas(SkCanvas* canvas, PaintStyle style) { bool askScreenUpdate = false; int count = this->countChildren(); @@ -1172,40 +871,45 @@ bool LayerAndroid::drawChildrenGL() std::stable_sort(sublayers.begin(), sublayers.end(), compareLayerZ); for (int i = 0; i < count; i++) { LayerAndroid* layer = sublayers[i]; - askScreenUpdate |= layer->drawGL(); + askScreenUpdate |= layer->drawCanvas(canvas, true, style); } } return askScreenUpdate; } -void LayerAndroid::contentDraw(SkCanvas* canvas) +void LayerAndroid::contentDraw(SkCanvas* canvas, PaintStyle style) { - if (m_recordingPicture) - canvas->drawPicture(*m_recordingPicture); + if (m_content) + m_content->draw(canvas); if (TilesManager::instance()->getShowVisualIndicator()) { float w = getSize().width(); float h = getSize().height(); SkPaint paint; - paint.setARGB(128, 255, 0, 0); + + if (style == MergedLayers) + paint.setARGB(255, 255, 255, 0); + else if (style == UnmergedLayers) + paint.setARGB(255, 255, 0, 0); + else if (style == FlattenedLayers) + paint.setARGB(255, 255, 0, 255); + canvas->drawLine(0, 0, w, h, paint); canvas->drawLine(0, h, w, 0, paint); - paint.setARGB(128, 0, 255, 0); + canvas->drawLine(0, 0, 0, h, paint); canvas->drawLine(0, h, w, h, paint); canvas->drawLine(w, h, w, 0, paint); canvas->drawLine(w, 0, 0, 0, paint); - - if (m_isFixed) { - SkPaint paint; - paint.setARGB(80, 255, 0, 0); - canvas->drawRect(m_fixedRect, paint); - } } + + if (m_fixedPosition) + return m_fixedPosition->contentDraw(canvas, style); } -void LayerAndroid::onDraw(SkCanvas* canvas, SkScalar opacity) +void LayerAndroid::onDraw(SkCanvas* canvas, SkScalar opacity, + android::DrawExtra* extra, PaintStyle style) { if (m_haveClip) { SkRect r; @@ -1214,7 +918,7 @@ void LayerAndroid::onDraw(SkCanvas* canvas, SkScalar opacity) return; } - if (!prepareContext()) + if (masksToBounds() || !m_content) return; // we just have this save/restore for opacity... @@ -1234,179 +938,23 @@ void LayerAndroid::onDraw(SkCanvas* canvas, SkScalar opacity) } ImagesManager::instance()->releaseImage(m_imageCRC); } - contentDraw(canvas); -} - -SkPicture* LayerAndroid::recordContext() -{ - if (prepareContext(true)) - return m_recordingPicture; - return 0; -} - -bool LayerAndroid::prepareContext(bool force) -{ - if (masksToBounds()) - return false; - - if (force || !m_recordingPicture || - (m_recordingPicture && - ((m_recordingPicture->width() != (int) getSize().width()) || - (m_recordingPicture->height() != (int) getSize().height())))) { - SkSafeUnref(m_recordingPicture); - m_recordingPicture = new SkPicture(); - } - - return m_recordingPicture; -} - -SkRect LayerAndroid::subtractLayers(const SkRect& visibleRect) const -{ - SkRect result; - if (m_recordingPicture) { - // FIXME: This seems wrong. localToGlobal() applies the full local transform, - // se surely we should operate globalMatrix on size(), not bounds() with - // the position removed? Perhaps we never noticed the bug because most - // layers don't use a local transform? - // See http://b/5338388 - SkRect globalRect = bounds(); - globalRect.offset(-getPosition()); // localToGlobal adds in position - SkMatrix globalMatrix; - localToGlobal(&globalMatrix); - globalMatrix.mapRect(&globalRect); - SkIRect roundedGlobal; - globalRect.round(&roundedGlobal); - SkIRect iVisibleRect; - visibleRect.round(&iVisibleRect); - SkRegion visRegion(iVisibleRect); - visRegion.op(roundedGlobal, SkRegion::kDifference_Op); - result.set(visRegion.getBounds()); -#if DEBUG_NAV_UI - SkDebugf("%s visibleRect=(%g,%g,r=%g,b=%g) globalRect=(%g,%g,r=%g,b=%g)" - "result=(%g,%g,r=%g,b=%g)", __FUNCTION__, - visibleRect.fLeft, visibleRect.fTop, - visibleRect.fRight, visibleRect.fBottom, - globalRect.fLeft, globalRect.fTop, - globalRect.fRight, globalRect.fBottom, - result.fLeft, result.fTop, result.fRight, result.fBottom); -#endif - } else - result = visibleRect; - for (int i = 0; i < countChildren(); i++) - result = getChild(i)->subtractLayers(result); - return result; -} - -// Debug tools : dump the layers tree in a file. -// The format is simple: -// properties have the form: key = value; -// all statements are finished with a semi-colon. -// value can be: -// - int -// - float -// - array of elements -// - composed type -// a composed type enclose properties in { and } -// an array enclose composed types in { }, separated with a comma. -// exemple: -// { -// x = 3; -// y = 4; -// value = { -// x = 3; -// y = 4; -// }; -// anarray = [ -// { x = 3; }, -// { y = 4; } -// ]; -// } - -void lwrite(FILE* file, const char* str) -{ - fwrite(str, sizeof(char), strlen(str), file); -} - -void writeIndent(FILE* file, int indentLevel) -{ - if (indentLevel) - fprintf(file, "%*s", indentLevel*2, " "); -} - -void writeln(FILE* file, int indentLevel, const char* str) -{ - writeIndent(file, indentLevel); - lwrite(file, str); - lwrite(file, "\n"); -} - -void writeIntVal(FILE* file, int indentLevel, const char* str, int value) -{ - writeIndent(file, indentLevel); - fprintf(file, "%s = %d;\n", str, value); -} - -void writeHexVal(FILE* file, int indentLevel, const char* str, int value) -{ - writeIndent(file, indentLevel); - fprintf(file, "%s = %x;\n", str, value); -} - -void writeFloatVal(FILE* file, int indentLevel, const char* str, float value) -{ - writeIndent(file, indentLevel); - fprintf(file, "%s = %.3f;\n", str, value); -} - -void writePoint(FILE* file, int indentLevel, const char* str, SkPoint point) -{ - writeIndent(file, indentLevel); - fprintf(file, "%s = { x = %.3f; y = %.3f; };\n", str, point.fX, point.fY); -} - -void writeSize(FILE* file, int indentLevel, const char* str, SkSize size) -{ - writeIndent(file, indentLevel); - fprintf(file, "%s = { w = %.3f; h = %.3f; };\n", str, size.width(), size.height()); -} - -void writeRect(FILE* file, int indentLevel, const char* str, SkRect rect) -{ - writeIndent(file, indentLevel); - fprintf(file, "%s = { x = %.3f; y = %.3f; w = %.3f; h = %.3f; };\n", - str, rect.fLeft, rect.fTop, rect.width(), rect.height()); -} - -void writeLength(FILE* file, int indentLevel, const char* str, SkLength length) -{ - if (!length.defined()) - return; - writeIndent(file, indentLevel); - fprintf(file, "%s = { type = %d; value = %.2f; };\n", str, length.type, length.value); + contentDraw(canvas, style); + if (extra) + extra->draw(canvas, this); } -void writeMatrix(FILE* file, int indentLevel, const char* str, const TransformationMatrix& matrix) -{ - writeIndent(file, indentLevel); - fprintf(file, "%s = { (%.2f,%.2f,%.2f,%.2f),(%.2f,%.2f,%.2f,%.2f)," - "(%.2f,%.2f,%.2f,%.2f),(%.2f,%.2f,%.2f,%.2f) };\n", - str, - matrix.m11(), matrix.m12(), matrix.m13(), matrix.m14(), - matrix.m21(), matrix.m22(), matrix.m23(), matrix.m24(), - matrix.m31(), matrix.m32(), matrix.m33(), matrix.m34(), - matrix.m41(), matrix.m42(), matrix.m43(), matrix.m44()); +void LayerAndroid::setFixedPosition(FixedPositioning* position) { + if (m_fixedPosition && m_fixedPosition != position) + delete m_fixedPosition; + m_fixedPosition = position; } -void LayerAndroid::dumpLayers(FILE* file, int indentLevel) const +void LayerAndroid::dumpLayer(FILE* file, int indentLevel) const { - writeln(file, indentLevel, "{"); - writeHexVal(file, indentLevel + 1, "layer", (int)this); writeIntVal(file, indentLevel + 1, "layerId", m_uniqueId); writeIntVal(file, indentLevel + 1, "haveClip", m_haveClip); - writeIntVal(file, indentLevel + 1, "isFixed", m_isFixed); - writeIntVal(file, indentLevel + 1, "m_isIframe", m_isIframe); - writePoint(file, indentLevel + 1, "m_iframeOffset", m_iframeOffset); + writeIntVal(file, indentLevel + 1, "isFixed", isFixed()); writeFloatVal(file, indentLevel + 1, "opacity", getOpacity()); writeSize(file, indentLevel + 1, "size", getSize()); @@ -1417,22 +965,20 @@ void LayerAndroid::dumpLayers(FILE* file, int indentLevel) const writeMatrix(file, indentLevel + 1, "transformMatrix", m_transform); writeRect(file, indentLevel + 1, "clippingRect", SkRect(m_clippingRect)); - if (m_isFixed) { - writeLength(file, indentLevel + 1, "fixedLeft", m_fixedLeft); - writeLength(file, indentLevel + 1, "fixedTop", m_fixedTop); - writeLength(file, indentLevel + 1, "fixedRight", m_fixedRight); - writeLength(file, indentLevel + 1, "fixedBottom", m_fixedBottom); - writeLength(file, indentLevel + 1, "fixedMarginLeft", m_fixedMarginLeft); - writeLength(file, indentLevel + 1, "fixedMarginTop", m_fixedMarginTop); - writeLength(file, indentLevel + 1, "fixedMarginRight", m_fixedMarginRight); - writeLength(file, indentLevel + 1, "fixedMarginBottom", m_fixedMarginBottom); - writeRect(file, indentLevel + 1, "fixedRect", m_fixedRect); + if (m_content) { + writeIntVal(file, indentLevel + 1, "m_content.width", m_content->width()); + writeIntVal(file, indentLevel + 1, "m_content.height", m_content->height()); } - if (m_recordingPicture) { - writeIntVal(file, indentLevel + 1, "m_recordingPicture.width", m_recordingPicture->width()); - writeIntVal(file, indentLevel + 1, "m_recordingPicture.height", m_recordingPicture->height()); - } + if (m_fixedPosition) + return m_fixedPosition->dumpLayer(file, indentLevel); +} + +void LayerAndroid::dumpLayers(FILE* file, int indentLevel) const +{ + writeln(file, indentLevel, "{"); + + dumpLayer(file, indentLevel); if (countChildren()) { writeln(file, indentLevel + 1, "children = ["); diff --git a/Source/WebCore/platform/graphics/android/LayerAndroid.h b/Source/WebCore/platform/graphics/android/LayerAndroid.h index c1f1bc9..459c159 100644 --- a/Source/WebCore/platform/graphics/android/LayerAndroid.h +++ b/Source/WebCore/platform/graphics/android/LayerAndroid.h @@ -48,52 +48,28 @@ class SkPicture; namespace WebCore { class LayerAndroid; +class LayerContent; +class LayerGroup; class ImageTexture; } namespace android { class DrawExtra; void serializeLayer(WebCore::LayerAndroid* layer, SkWStream* stream); -WebCore::LayerAndroid* deserializeLayer(SkStream* stream); +WebCore::LayerAndroid* deserializeLayer(int version, SkStream* stream); void cleanupImageRefs(WebCore::LayerAndroid* layer); } using namespace android; -struct SkLength { - enum SkLengthType { Undefined, Auto, Relative, Percent, Fixed, Static, Intrinsic, MinIntrinsic }; - SkLengthType type; - SkScalar value; - SkLength() - { - type = Undefined; - value = 0; - } - bool defined() const - { - if (type == Undefined) - return false; - return true; - } - float calcFloatValue(float max) const - { - switch (type) { - case Percent: - return (max * value) / 100.0f; - case Fixed: - return value; - default: - return value; - } - } -}; - namespace WebCore { class AndroidAnimation; class BaseTileTexture; +class FixedPositioning; class GLWebViewState; -class LayerAndroidFindState; +class IFrameLayerAndroid; +class LayerMergeState; class RenderLayer; class TiledPage; class PaintedSurface; @@ -115,7 +91,24 @@ public: class TEST_EXPORT LayerAndroid : public Layer { public: - enum LayerType { UndefinedLayer, WebCoreLayer, UILayer, NavCacheLayer }; + typedef enum { UndefinedLayer, WebCoreLayer, UILayer, NavCacheLayer } LayerType; + typedef enum { StandardLayer, ScrollableLayer, + IFrameLayer, IFrameContentLayer } SubclassType; + + String subclassName() + { + switch (subclassType()) { + case LayerAndroid::StandardLayer: + return "StandardLayer"; + case LayerAndroid::ScrollableLayer: + return "ScrollableLayer"; + case LayerAndroid::IFrameLayer: + return "IFrameLayer"; + case LayerAndroid::IFrameContentLayer: + return "IFrameContentLayer"; + } + return "Undefined"; + } LayerAndroid(RenderLayer* owner); LayerAndroid(const LayerAndroid& layer); @@ -139,30 +132,23 @@ public: IntRect visibleArea(); virtual bool needsTexture(); - void removeTexture(PaintedSurface*); // Debug helper methods int nbLayers(); int nbTexturedLayers(); void showLayer(int indent = 0); - void computeTexturesAmount(TexturesResult*); - float getScale() { return m_scale; } - // draw layer and its children via Z, pre-order traversal - virtual bool drawGL(); - bool drawChildrenGL(); - virtual bool drawCanvas(SkCanvas*); - bool drawChildrenCanvas(SkCanvas*); - - // prepare layer and its children via reverse-Z, post-order traversal - void prepare(); + virtual bool drawGL(bool layerTilesDisabled); + virtual bool drawCanvas(SkCanvas* canvas, bool drawChildren, PaintStyle style); + bool drawChildrenCanvas(SkCanvas* canvas, PaintStyle style); void updateGLPositionsAndScale(const TransformationMatrix& parentMatrix, const FloatRect& clip, float opacity, float scale); void setDrawOpacity(float opacity) { m_drawOpacity = opacity; } float drawOpacity() { return m_drawOpacity; } + bool visible(); void setVisible(bool value) { m_visible = value; } bool preserves3D() { return m_preserves3D; } @@ -175,30 +161,8 @@ public: void setDrawClip(const FloatRect& rect) { m_clippingRect = rect; } const FloatRect& drawClip() { return m_clippingRect; } - void setFixedPosition(SkLength left, // CSS left property - SkLength top, // CSS top property - SkLength right, // CSS right property - SkLength bottom, // CSS bottom property - SkLength marginLeft, // CSS margin-left property - SkLength marginTop, // CSS margin-top property - SkLength marginRight, // CSS margin-right property - SkLength marginBottom, // CSS margin-bottom property - const IntPoint& renderLayerPos, // For undefined fixed position - SkRect viewRect) { // view rect, can be smaller than the layer's - m_fixedLeft = left; - m_fixedTop = top; - m_fixedRight = right; - m_fixedBottom = bottom; - m_fixedMarginLeft = marginLeft; - m_fixedMarginTop = marginTop; - m_fixedMarginRight = marginRight; - m_fixedMarginBottom = marginBottom; - m_fixedRect = viewRect; - m_isFixed = true; - m_renderLayerPos = renderLayerPos; - setShouldInheritFromRootTransform(true); - } - + const IntPoint& scrollOffset() const { return m_offset; } + void setScrollOffset(IntPoint offset) { m_offset = offset; } void setBackgroundColor(SkColor color); void setMaskLayer(LayerAndroid*); void setMasksToBounds(bool masksToBounds) @@ -207,7 +171,8 @@ public: } bool masksToBounds() const { return m_haveClip; } - SkPicture* recordContext(); + LayerContent* content() { return m_content; } + void setContent(LayerContent* content); void addAnimation(PassRefPtr<AndroidAnimation> anim); void removeAnimationsForProperty(AnimatedPropertyID property); @@ -218,13 +183,7 @@ public: bool hasAnimations() const; void addDirtyArea(); - SkPicture* picture() const { return m_recordingPicture; } - - // Given a rect in global space, subtracts from it the bounds of this layer - // and of all of its children. Returns the bounding rectangle of the result, - // in global space. - SkRect subtractLayers(const SkRect&) const; - + virtual void dumpLayer(FILE*, int indentLevel) const; void dumpLayers(FILE*, int indentLevel) const; void dumpToLog() const; @@ -234,7 +193,9 @@ public: This call is recursive, so it should be called on the root of the hierarchy. */ - bool updateFixedLayersPositions(SkRect viewPort, LayerAndroid* parentIframeLayer = 0); + void updateLayerPositions(SkRect viewPort, IFrameLayerAndroid* parentIframeLayer = 0); + virtual IFrameLayerAndroid* updatePosition(SkRect viewport, + IFrameLayerAndroid* parentIframeLayer); /** Call this to update the position attribute, so that later calls like bounds() will report the corrected position. @@ -256,7 +217,6 @@ public: return static_cast<LayerAndroid*>(this->INHERITED::getChild(index)); } int uniqueId() const { return m_uniqueId; } - bool isFixed() { return m_isFixed; } /** This sets a content image -- calling it means we will use the image directly when drawing the layer instead of using @@ -270,62 +230,62 @@ public: virtual LayerAndroid* copy() const { return new LayerAndroid(*this); } - void needsRepaint() { m_pictureUsed++; } - unsigned int pictureUsed() { return m_pictureUsed; } - void clearDirtyRegion(); - void contentDraw(SkCanvas*); + virtual void contentDraw(SkCanvas* canvas, PaintStyle style); virtual bool isMedia() const { return false; } virtual bool isVideo() const { return false; } + bool isFixed() const { return m_fixedPosition; } + virtual bool isIFrame() const { return false; } + virtual bool isIFrameContent() const { return false; } + + void setFixedPosition(FixedPositioning* position); + FixedPositioning* fixedPosition() { return m_fixedPosition; } RenderLayer* owningLayer() const { return m_owningLayer; } - void setIsIframe(bool isIframe) { m_isIframe = isIframe; } float zValue() const { return m_zValue; } // ViewStateSerializer friends friend void android::serializeLayer(LayerAndroid* layer, SkWStream* stream); - friend LayerAndroid* android::deserializeLayer(SkStream* stream); + friend LayerAndroid* android::deserializeLayer(int version, SkStream* stream); friend void android::cleanupImageRefs(LayerAndroid* layer); - PaintedSurface* texture() { return m_texture; } - void obtainTextureForPainting(LayerAndroid* drawingLayer); - // Update layers using another tree. Only works for basic properties // such as the position, the transform. Return true if anything more // complex is needed. bool updateWithTree(LayerAndroid*); virtual bool updateWithLayer(LayerAndroid*); - int type() { return m_type; } + LayerType type() { return m_type; } + virtual SubclassType subclassType() { return LayerAndroid::StandardLayer; } - bool hasText() { return m_hasText; } - void checkTextPresence(); + bool hasText(); void copyAnimationStartTimesRecursive(LayerAndroid* oldTree); // rendering asset management - void swapTiles(); - void setIsDrawing(bool isDrawing); - void setIsPainting(Layer* drawingTree); - void mergeInvalsInto(Layer* replacementTree); - bool isReady(); + SkRegion* getInvalRegion() { return &m_dirtyRegion; } + void mergeInvalsInto(LayerAndroid* replacementTree); -protected: - virtual void onDraw(SkCanvas*, SkScalar opacity); + bool canJoinGroup(LayerGroup* group); + void assignGroups(LayerMergeState* mergeState); + LayerGroup* group() { return m_layerGroup; } + void setIntrinsicallyComposited(bool intCom) { m_intrinsicallyComposited = intCom; } + +protected: + virtual void onDraw(SkCanvas*, SkScalar opacity, android::DrawExtra* extra, PaintStyle style); + IntPoint m_offset; TransformationMatrix m_drawTransform; private: - class FindState; #if DUMP_NAV_CACHE friend class CachedLayer::Debug; // debugging access only #endif void copyAnimationStartTimes(LayerAndroid* oldLayer); - void findInner(FindState&) const; bool prepareContext(bool force = false); void clipInner(SkTDArray<SkRect>* region, const SkRect& local) const; @@ -334,23 +294,7 @@ private: // ------------------------------------------------------------------- bool m_haveClip; - bool m_isFixed; bool m_backgroundColorSet; - bool m_isIframe; - - SkLength m_fixedLeft; - SkLength m_fixedTop; - SkLength m_fixedRight; - SkLength m_fixedBottom; - SkLength m_fixedMarginLeft; - SkLength m_fixedMarginTop; - SkLength m_fixedMarginRight; - SkLength m_fixedMarginBottom; - SkRect m_fixedRect; - - // When fixed element is undefined or auto, the render layer's position - // is needed for offset computation - IntPoint m_renderLayerPos; bool m_backfaceVisibility; bool m_visible; @@ -361,13 +305,7 @@ private: float m_anchorPointZ; float m_drawOpacity; - // Note that m_recordingPicture and m_imageRef are mutually exclusive; - // m_recordingPicture is used when WebKit is asked to paint the layer's - // content, while m_imageRef contains an image that we directly - // composite, using the layer's dimensions as a destination rect. - // We do this as if the layer only contains an image, directly compositing - // it is a much faster method than using m_recordingPicture. - SkPicture* m_recordingPicture; + FixedPositioning* m_fixedPosition; typedef HashMap<pair<String, int>, RefPtr<AndroidAnimation> > KeyframesMap; KeyframesMap m_animations; @@ -379,19 +317,21 @@ private: // Fields that are not serialized (generated, cached, or non-serializable) // ------------------------------------------------------------------- - SkPoint m_iframeOffset; - float m_zValue; FloatRect m_clippingRect; int m_uniqueId; - PaintedSurface* m_texture; + // Note that m_content and m_imageCRC are mutually exclusive; + // m_content is used when WebKit is asked to paint the layer's + // content, while m_imageCRC references an image that we directly + // composite, using the layer's dimensions as a destination rect. + // We do this as if the layer only contains an image, directly compositing + // it is a much faster method than using m_content. + LayerContent* m_content; unsigned m_imageCRC; - unsigned int m_pictureUsed; - // used to signal the framework we need a repaint bool m_hasRunningAnimations; @@ -408,9 +348,12 @@ private: RenderLayer* m_owningLayer; - int m_type; + LayerType m_type; + SubclassType m_subclassType; + + bool m_intrinsicallyComposited; - bool m_hasText; + LayerGroup* m_layerGroup; typedef Layer INHERITED; }; diff --git a/Source/WebCore/platform/graphics/android/LayerContent.h b/Source/WebCore/platform/graphics/android/LayerContent.h new file mode 100644 index 0000000..32108ec --- /dev/null +++ b/Source/WebCore/platform/graphics/android/LayerContent.h @@ -0,0 +1,51 @@ +/* + * Copyright 2012, 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 LayerContent_h +#define LayerContent_h + +#include "SkRefCnt.h" + +class SkCanvas; +class SkPicture; +class SkWStream; + +namespace WebCore { + +class LayerContent : public SkRefCnt { +public: + virtual int width() = 0; + virtual int height() = 0; + virtual bool isEmpty() = 0; + virtual void checkForOptimisations() = 0; + virtual bool hasText() = 0; + virtual void draw(SkCanvas* canvas) = 0; + + virtual void serialize(SkWStream* stream) = 0; +}; + +} // WebCore + +#endif // LayerContent_h diff --git a/Source/WebCore/platform/graphics/android/LayerGroup.cpp b/Source/WebCore/platform/graphics/android/LayerGroup.cpp new file mode 100644 index 0000000..af45e41 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/LayerGroup.cpp @@ -0,0 +1,306 @@ +/* + * Copyright 2012, 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 "LayerGroup.h" + +#include "ClassTracker.h" +#include "LayerAndroid.h" +#include "TiledTexture.h" +#include "TilesManager.h" + +#include <cutils/log.h> +#include <wtf/CurrentTime.h> +#include <wtf/text/CString.h> + +#undef XLOGC +#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "LayerGroup", __VA_ARGS__) + +#ifdef DEBUG + +#undef XLOG +#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "LayerGroup", __VA_ARGS__) + +#else + +#undef XLOG +#define XLOG(...) + +#endif // DEBUG + +// LayerGroups with an area larger than 2048*2048 should never be unclipped +#define MAX_UNCLIPPED_AREA 4194304 + +namespace WebCore { + +LayerGroup::LayerGroup() + : m_dualTiledTexture(0) + , m_needsTexture(false) + , m_hasText(false) +{ +#ifdef DEBUG_COUNT + ClassTracker::instance()->increment("LayerGroup"); +#endif +} + +LayerGroup::~LayerGroup() +{ + for (unsigned int i = 0; i < m_layers.size(); i++) + SkSafeUnref(m_layers[i]); + if (m_dualTiledTexture) + SkSafeUnref(m_dualTiledTexture); +#ifdef DEBUG_COUNT + ClassTracker::instance()->decrement("LayerGroup"); +#endif +} + +bool LayerGroup::tryUpdateLayerGroup(LayerGroup* oldLayerGroup) +{ + if (!needsTexture() || !oldLayerGroup->needsTexture()) + return false; + + // merge layer group based on first layer ID + if (getFirstLayer()->uniqueId() != oldLayerGroup->getFirstLayer()->uniqueId()) + return false; + + m_dualTiledTexture = oldLayerGroup->m_dualTiledTexture; + SkSafeRef(m_dualTiledTexture); + + XLOG("%p taking old DTT %p from group %p, nt %d", + this, m_dualTiledTexture, oldLayerGroup, oldLayerGroup->needsTexture()); + + if (!m_dualTiledTexture) { + // no DTT to inval, so don't worry about it. + return true; + } + + if (singleLayer() && oldLayerGroup->singleLayer()) { + // both are single matching layers, simply apply inval + SkRegion* layerInval = getFirstLayer()->getInvalRegion(); + m_dualTiledTexture->markAsDirty(*layerInval); + } else { + SkRegion invalRegion; + bool fullInval = m_layers.size() != oldLayerGroup->m_layers.size(); + if (!fullInval) { + for (unsigned int i = 0; i < m_layers.size(); i++) { + if (m_layers[i]->uniqueId() != oldLayerGroup->m_layers[i]->uniqueId()) { + // layer list has changed, fully invalidate + // TODO: partially invalidate based on layer size/position + fullInval = true; + break; + } else if (!m_layers[i]->getInvalRegion()->isEmpty()) { + // merge layer inval - translate the layer's inval region into group coordinates + SkPoint pos = m_layers[i]->getPosition(); + m_layers[i]->getInvalRegion()->translate(pos.fX, pos.fY); + invalRegion.op(*(m_layers[i]->getInvalRegion()), SkRegion::kUnion_Op); + break; + } + } + } + + if (fullInval) + invalRegion.setRect(-1e8, -1e8, 2e8, 2e8); + + m_dualTiledTexture->markAsDirty(invalRegion); + } + return true; +} + +void LayerGroup::addLayer(LayerAndroid* layer, const TransformationMatrix& transform) +{ + m_layers.append(layer); + SkSafeRef(layer); + + m_needsTexture |= layer->needsTexture(); + m_hasText |= layer->hasText(); + + // calculate area size for comparison later + IntRect rect = layer->unclippedArea(); + SkPoint pos = layer->getPosition(); + rect.setLocation(IntPoint(pos.fX, pos.fY)); + + if (layer->needsTexture()) { + if (m_unclippedArea.isEmpty()) { + m_drawTransform = transform; + m_drawTransform.translate3d(-pos.fX, -pos.fY, 0); + m_unclippedArea = rect; + } else + m_unclippedArea.unite(rect); + XLOG("LG %p adding LA %p, size %d, %d %dx%d, now LG size %d,%d %dx%d", + this, layer, rect.x(), rect.y(), rect.width(), rect.height(), + m_unclippedArea.x(), m_unclippedArea.y(), + m_unclippedArea.width(), m_unclippedArea.height()); + } +} + +IntRect LayerGroup::visibleArea() +{ + if (singleLayer()) + return getFirstLayer()->visibleArea(); + + IntRect rect = m_unclippedArea; + + // clip with the viewport in documents coordinate + IntRect documentViewport(TilesManager::instance()->shader()->documentViewport()); + rect.intersect(documentViewport); + + // TODO: handle recursive layer clip + + return rect; +} + +void LayerGroup::prepareGL(bool layerTilesDisabled) +{ + if (!m_dualTiledTexture) { + XLOG("prepareGL on LG %p, no DTT, needsTexture? %d", + this, m_dualTiledTexture, needsTexture()); + + if (needsTexture()) + m_dualTiledTexture = new DualTiledTexture(); + else + return; + } + + if (layerTilesDisabled) { + m_dualTiledTexture->discardTextures(); + } else { + bool allowZoom = hasText(); // only allow for scale > 1 if painting vectors + IntRect prepareArea = computePrepareArea(); + + XLOG("prepareGL on LG %p with DTT %p, %d layers", + this, m_dualTiledTexture, m_layers.size()); + m_dualTiledTexture->prepareGL(getFirstLayer()->state(), allowZoom, + prepareArea, this); + } +} + +bool LayerGroup::drawGL(bool layerTilesDisabled) +{ + if (!getFirstLayer()->visible()) + return false; + + FloatRect drawClip = getFirstLayer()->drawClip(); + FloatRect clippingRect = TilesManager::instance()->shader()->rectInScreenCoord(drawClip); + TilesManager::instance()->shader()->clip(clippingRect); + + bool askRedraw = false; + if (m_dualTiledTexture && !layerTilesDisabled) { + XLOG("drawGL on LG %p with DTT %p", this, m_dualTiledTexture); + + IntRect drawArea = visibleArea(); + askRedraw |= m_dualTiledTexture->drawGL(drawArea, opacity(), drawTransform()); + } + + // draw member layers (draws image textures, glextras) + for (unsigned int i = 0; i < m_layers.size(); i++) + askRedraw |= m_layers[i]->drawGL(layerTilesDisabled); + + return askRedraw; +} + +void LayerGroup::swapTiles() +{ + if (!m_dualTiledTexture) + return; + + m_dualTiledTexture->swapTiles(); +} + +bool LayerGroup::isReady() +{ + if (!m_dualTiledTexture) + return true; + + return m_dualTiledTexture->isReady(); +} + +IntRect LayerGroup::computePrepareArea() { + IntRect area; + + if (!getFirstLayer()->contentIsScrollable() + && getFirstLayer()->state()->layersRenderingMode() == GLWebViewState::kAllTextures) { + + area = singleLayer() ? getFirstLayer()->unclippedArea() : m_unclippedArea; + + double total = ((double) area.width()) * ((double) area.height()); + if (total > MAX_UNCLIPPED_AREA) + area = visibleArea(); + } else { + area = visibleArea(); + } + + return area; +} + +void LayerGroup::computeTexturesAmount(TexturesResult* result) +{ + if (!m_dualTiledTexture) + return; + + m_dualTiledTexture->computeTexturesAmount(result, getFirstLayer()); +} + +bool LayerGroup::paint(BaseTile* tile, SkCanvas* canvas) +{ + if (singleLayer()) { + getFirstLayer()->contentDraw(canvas, Layer::UnmergedLayers); + } else { + SkAutoCanvasRestore acr(canvas, true); + SkMatrix matrix; + GLUtils::toSkMatrix(matrix, m_drawTransform); + + SkMatrix inverse; + inverse.reset(); + matrix.invert(&inverse); + + SkMatrix canvasMatrix = canvas->getTotalMatrix(); + inverse.postConcat(canvasMatrix); + canvas->setMatrix(inverse); + + for (unsigned int i=0; i<m_layers.size(); i++) + m_layers[i]->drawCanvas(canvas, false, Layer::MergedLayers); + } + return true; +} + +float LayerGroup::opacity() +{ + if (singleLayer()) + return getFirstLayer()->getOpacity(); + return 1.0; +} + +const TransformationMatrix* LayerGroup::drawTransform() +{ + // single layer groups query the layer's draw transform, while multi-layer + // groups copy the draw transform once, during initialization + // TODO: support fixed multi-layer groups by querying the changing drawTransform + if (singleLayer()) + return getFirstLayer()->drawTransform(); + + return &m_drawTransform; +} + +} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/LayerGroup.h b/Source/WebCore/platform/graphics/android/LayerGroup.h new file mode 100644 index 0000000..90001a5 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/LayerGroup.h @@ -0,0 +1,105 @@ +/* + * Copyright 2012, 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 LayerGroup_h +#define LayerGroup_h + +#include "IntRect.h" +#include "TilePainter.h" +#include "Vector.h" + +class SkCanvas; +class SkRegion; + +namespace WebCore { + +class BaseTile; +class DualTiledTexture; +class TexturesResult; +class LayerAndroid; + +class LayerGroup : public TilePainter { +public: + LayerGroup(); + virtual ~LayerGroup(); + + bool tryUpdateLayerGroup(LayerGroup* oldLayerGroup); + + + void addLayer(LayerAndroid* layer, const TransformationMatrix& transform); + IntRect visibleArea(); + void prepareGL(bool layerTilesDisabled); + bool drawGL(bool layerTilesDisabled); + void swapTiles(); + bool isReady(); + + IntRect computePrepareArea(); + void computeTexturesAmount(TexturesResult* result); + + LayerAndroid* getFirstLayer() { return m_layers[0]; } + bool singleLayer() { return m_layers.size() == 1; } + bool needsTexture() { return m_needsTexture; } + bool hasText() { return m_hasText; } + + // TilePainter methods + virtual bool paint(BaseTile* tile, SkCanvas* canvas); + virtual float opacity(); +private: + const TransformationMatrix* drawTransform(); + IntRect m_unclippedArea; + TransformationMatrix m_drawTransform; + + DualTiledTexture* m_dualTiledTexture; + bool m_needsTexture; + bool m_hasText; + Vector<LayerAndroid*> m_layers; +}; + +class LayerMergeState { +public: + LayerMergeState(Vector<LayerGroup*>* const allGroups) + : groupList(allGroups) + , currentLayerGroup(0) + , nonMergeNestedLevel(-1) // start at -1 to ignore first LayerAndroid's clipping + , depth(0) + {} + + // vector storing all generated layer groups + Vector<LayerGroup*>* const groupList; + + // currently merging group. if cleared, no more layers may join + LayerGroup* currentLayerGroup; + + // records depth within non-mergeable parents (clipping, fixed, scrolling) + // and disable merging therein. + int nonMergeNestedLevel; + + // counts layer tree depth for debugging + int depth; +}; + +} // namespace WebCore + +#endif //#define LayerGroup_h diff --git a/Source/WebCore/platform/graphics/android/MediaLayer.cpp b/Source/WebCore/platform/graphics/android/MediaLayer.cpp index 12cfe38..c2f3630 100644 --- a/Source/WebCore/platform/graphics/android/MediaLayer.cpp +++ b/Source/WebCore/platform/graphics/android/MediaLayer.cpp @@ -66,7 +66,7 @@ MediaLayer::~MediaLayer() m_mediaTexture->decStrong(this); } -bool MediaLayer::drawGL() +bool MediaLayer::drawGL(bool layerTilesDisabled) { FloatRect clippingRect = TilesManager::instance()->shader()->rectInScreenCoord(drawClip()); TilesManager::instance()->shader()->clip(clippingRect); @@ -92,8 +92,7 @@ bool MediaLayer::drawGL() // draw any content or video if present m_mediaTexture->draw(m, m_drawTransform, mediaBounds); - - return drawChildrenGL(); + return false; } ANativeWindow* MediaLayer::acquireNativeWindowForContent() diff --git a/Source/WebCore/platform/graphics/android/MediaLayer.h b/Source/WebCore/platform/graphics/android/MediaLayer.h index b94ec53..907c53c 100644 --- a/Source/WebCore/platform/graphics/android/MediaLayer.h +++ b/Source/WebCore/platform/graphics/android/MediaLayer.h @@ -36,7 +36,7 @@ public: MediaLayer(const MediaLayer& layer); virtual ~MediaLayer(); - virtual bool drawGL(); + virtual bool drawGL(bool layerTilesDisabled); virtual void paintBitmapGL() const { }; virtual bool needsTexture() { return false; } diff --git a/Source/WebCore/platform/graphics/android/MediaPlayerPrivateAndroid.h b/Source/WebCore/platform/graphics/android/MediaPlayerPrivateAndroid.h index 404ef08..535e7ae 100644 --- a/Source/WebCore/platform/graphics/android/MediaPlayerPrivateAndroid.h +++ b/Source/WebCore/platform/graphics/android/MediaPlayerPrivateAndroid.h @@ -95,6 +95,7 @@ public: virtual void onPosterFetched(SkBitmap*) { } void onBuffering(int percent); void onTimeupdate(int position); + void onRestoreState(); // These following two functions are used to turn on inline video support bool supportsAcceleratedRendering() const { return true; } diff --git a/Source/WebCore/platform/graphics/android/MediaTexture.cpp b/Source/WebCore/platform/graphics/android/MediaTexture.cpp index 1676186..2582a53 100644 --- a/Source/WebCore/platform/graphics/android/MediaTexture.cpp +++ b/Source/WebCore/platform/graphics/android/MediaTexture.cpp @@ -191,8 +191,7 @@ void MediaTexture::draw(const TransformationMatrix& contentMatrix, bool forceAlphaBlending = !( PIXEL_FORMAT_RGBX_8888 == f || PIXEL_FORMAT_RGB_888 == f || - PIXEL_FORMAT_RGB_565 == f || - PIXEL_FORMAT_RGB_332 == f); + PIXEL_FORMAT_RGB_565 == f); TilesManager::instance()->shader()->drawLayerQuad(contentMatrix, mediaBounds, @@ -283,7 +282,6 @@ void MediaTexture::setDimensions(const ANativeWindow* window, void MediaTexture::setFramerateCallback(const ANativeWindow* window, FramerateCallbackProc callback) { - XLOG("Release ANW %p (%p):(%p)", this, m_surfaceTexture.get(), m_surfaceTextureClient.get()); android::Mutex::Autolock lock(m_mediaLock); for (unsigned int i = 0; i < m_videoTextures.size(); i++) { if (m_videoTextures[i]->nativeWindow.get() == window) { diff --git a/Source/WebCore/platform/graphics/android/PaintTileOperation.cpp b/Source/WebCore/platform/graphics/android/PaintTileOperation.cpp index 2d69706..a79298c 100644 --- a/Source/WebCore/platform/graphics/android/PaintTileOperation.cpp +++ b/Source/WebCore/platform/graphics/android/PaintTileOperation.cpp @@ -28,18 +28,19 @@ #include "ImageTexture.h" #include "ImagesManager.h" #include "LayerAndroid.h" -#include "PaintedSurface.h" +#include "TiledPage.h" +#include "TilesManager.h" namespace WebCore { -PaintTileOperation::PaintTileOperation(BaseTile* tile, SurfacePainter* surface) - : QueuedOperation(QueuedOperation::PaintTile, tile->page()) +PaintTileOperation::PaintTileOperation(BaseTile* tile, TilePainter* painter) + : QueuedOperation(tile->page()) , m_tile(tile) - , m_surface(surface) + , m_painter(painter) { if (m_tile) m_tile->setRepaintPending(true); - SkSafeRef(m_surface); + SkSafeRef(m_painter); } PaintTileOperation::~PaintTileOperation() @@ -49,18 +50,16 @@ PaintTileOperation::~PaintTileOperation() m_tile = 0; } - if (m_surface && m_surface->type() == SurfacePainter::ImageSurface) { - ImageTexture* image = static_cast<ImageTexture*>(m_surface); + if (m_painter && m_painter->type() == TilePainter::Image) { + ImageTexture* image = static_cast<ImageTexture*>(m_painter); ImagesManager::instance()->releaseImage(image->imageCRC()); } else { - SkSafeUnref(m_surface); + SkSafeUnref(m_painter); } } bool PaintTileOperation::operator==(const QueuedOperation* operation) { - if (operation->type() != type()) - return false; const PaintTileOperation* op = static_cast<const PaintTileOperation*>(operation); return op->m_tile == m_tile; } diff --git a/Source/WebCore/platform/graphics/android/PaintTileOperation.h b/Source/WebCore/platform/graphics/android/PaintTileOperation.h index bc74d03..4e98287 100644 --- a/Source/WebCore/platform/graphics/android/PaintTileOperation.h +++ b/Source/WebCore/platform/graphics/android/PaintTileOperation.h @@ -33,12 +33,12 @@ namespace WebCore { class LayerAndroid; -class SurfacePainter; +class TilePainter; class ImageTexture; class PaintTileOperation : public QueuedOperation { public: - PaintTileOperation(BaseTile* tile, SurfacePainter* surface = 0); + PaintTileOperation(BaseTile* tile, TilePainter* painter = 0); virtual ~PaintTileOperation(); virtual bool operator==(const QueuedOperation* operation); virtual void run(); @@ -49,25 +49,21 @@ public: private: BaseTile* m_tile; - SurfacePainter* m_surface; + TilePainter* m_painter; }; class ScaleFilter : public OperationFilter { public: - ScaleFilter(TilePainter* painter, float scale) + ScaleFilter(const TilePainter* painter, float scale) : m_painter(painter) , m_scale(scale) {} virtual bool check(QueuedOperation* operation) { - if (operation->type() == QueuedOperation::PaintTile) { - PaintTileOperation* op = static_cast<PaintTileOperation*>(operation); - if ((op->painter() == m_painter) && (op->scale() != m_scale)) - return true; - } - return false; + PaintTileOperation* op = static_cast<PaintTileOperation*>(operation); + return ((op->painter() == m_painter) && (op->scale() != m_scale)); } private: - TilePainter* m_painter; + const TilePainter* m_painter; float m_scale; }; @@ -77,12 +73,8 @@ public: TilePainterFilter(TilePainter* painter) : m_painter(painter) {} virtual bool check(QueuedOperation* operation) { - if (operation->type() == QueuedOperation::PaintTile) { - PaintTileOperation* op = static_cast<PaintTileOperation*>(operation); - if (op->painter() == m_painter) - return true; - } - return false; + PaintTileOperation* op = static_cast<PaintTileOperation*>(operation); + return op->painter() == m_painter; } private: TilePainter* m_painter; diff --git a/Source/WebCore/platform/graphics/android/PaintedSurface.cpp b/Source/WebCore/platform/graphics/android/PaintedSurface.cpp deleted file mode 100644 index 45c7579..0000000 --- a/Source/WebCore/platform/graphics/android/PaintedSurface.cpp +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Copyright 2011, 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 "PaintedSurface.h" - - -#include "LayerAndroid.h" -#include "TiledTexture.h" -#include "TilesManager.h" -#include "SkCanvas.h" -#include "SkPicture.h" - -#include <cutils/log.h> -#include <wtf/CurrentTime.h> -#include <wtf/text/CString.h> - -#undef XLOGC -#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "PaintedSurface", __VA_ARGS__) - -#ifdef DEBUG - -#undef XLOG -#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "PaintedSurface", __VA_ARGS__) - -#else - -#undef XLOG -#define XLOG(...) - -#endif // DEBUG - -// Layers with an area larger than 2048*2048 should never be unclipped -#define MAX_UNCLIPPED_AREA 4194304 - -namespace WebCore { - -PaintedSurface::PaintedSurface() - : m_drawingLayer(0) - , m_paintingLayer(0) - , m_tiledTexture(0) - , m_scale(0) - , m_pictureUsed(0) -{ - TilesManager::instance()->addPaintedSurface(this); -#ifdef DEBUG_COUNT - ClassTracker::instance()->increment("PaintedSurface"); -#endif - m_tiledTexture = new DualTiledTexture(this); -} - -PaintedSurface::~PaintedSurface() -{ -#ifdef DEBUG_COUNT - ClassTracker::instance()->decrement("PaintedSurface"); -#endif - delete m_tiledTexture; -} - -void PaintedSurface::prepare(GLWebViewState* state) -{ - XLOG("PS %p has PL %p, DL %p", this, m_paintingLayer, m_drawingLayer); - LayerAndroid* paintingLayer = m_paintingLayer; - if (!paintingLayer) - paintingLayer = m_drawingLayer; - - if (!paintingLayer) - return; - - bool startFastSwap = false; - if (state->isScrolling()) { - // when scrolling, block updates and swap tiles as soon as they're ready - startFastSwap = true; - } - - XLOG("prepare layer %d %x at scale %.2f", - paintingLayer->uniqueId(), paintingLayer, - paintingLayer->getScale()); - - IntRect visibleArea = computeVisibleArea(paintingLayer); - - m_scale = state->scale(); - - // If we do not have text, we may as well limit ourselves to - // a scale factor of one... this saves up textures. - if (m_scale > 1 && !paintingLayer->hasText()) - m_scale = 1; - - m_tiledTexture->prepare(state, m_scale, m_pictureUsed != paintingLayer->pictureUsed(), - startFastSwap, visibleArea); -} - -bool PaintedSurface::draw() -{ - if (!m_drawingLayer || !m_drawingLayer->needsTexture()) - return false; - - bool askRedraw = false; - if (m_tiledTexture) - askRedraw = m_tiledTexture->draw(); - - return askRedraw; -} - -void PaintedSurface::setPaintingLayer(LayerAndroid* layer, const SkRegion& dirtyArea) -{ - m_paintingLayer = layer; - if (m_tiledTexture) - m_tiledTexture->update(dirtyArea, layer->picture()); -} - -bool PaintedSurface::isReady() -{ - if (m_tiledTexture) - return m_tiledTexture->isReady(); - return false; -} - -void PaintedSurface::swapTiles() -{ - if (m_tiledTexture) - m_tiledTexture->swapTiles(); -} - -float PaintedSurface::opacity() { - if (m_drawingLayer) - return m_drawingLayer->drawOpacity(); - return 1.0; -} - -const TransformationMatrix* PaintedSurface::transform() { - // used exclusively for drawing, so only use m_drawingLayer - if (!m_drawingLayer) - return 0; - - return m_drawingLayer->drawTransform(); -} - -void PaintedSurface::computeTexturesAmount(TexturesResult* result) -{ - if (!m_tiledTexture) - return; - - // for now, always done on drawinglayer - LayerAndroid* layer = m_drawingLayer; - - if (!layer) - return; - - IntRect unclippedArea = layer->unclippedArea(); - IntRect clippedVisibleArea = layer->visibleArea(); - // get two numbers here: - // - textures needed for a clipped area - // - textures needed for an un-clipped area - int nbTexturesUnclipped = m_tiledTexture->nbTextures(unclippedArea, m_scale); - int nbTexturesClipped = m_tiledTexture->nbTextures(clippedVisibleArea, m_scale); - - // Set kFixedLayers level - if (layer->isFixed()) - result->fixed += nbTexturesClipped; - - // Set kScrollableAndFixedLayers level - if (layer->contentIsScrollable() - || layer->isFixed()) - result->scrollable += nbTexturesClipped; - - // Set kClippedTextures level - result->clipped += nbTexturesClipped; - - // Set kAllTextures level - if (layer->contentIsScrollable()) - result->full += nbTexturesClipped; - else - result->full += nbTexturesUnclipped; -} - -IntRect PaintedSurface::computeVisibleArea(LayerAndroid* layer) { - IntRect area; - if (!layer) - return area; - - if (!layer->contentIsScrollable() - && layer->state()->layersRenderingMode() == GLWebViewState::kAllTextures) { - area = layer->unclippedArea(); - double total = ((double) area.width()) * ((double) area.height()); - if (total > MAX_UNCLIPPED_AREA) - area = layer->visibleArea(); - } else { - area = layer->visibleArea(); - } - - return area; -} - -bool PaintedSurface::owns(BaseTileTexture* texture) -{ - if (m_tiledTexture) - return m_tiledTexture->owns(texture); - return false; -} - -} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/PaintedSurface.h b/Source/WebCore/platform/graphics/android/PaintedSurface.h deleted file mode 100644 index b8ab7b8..0000000 --- a/Source/WebCore/platform/graphics/android/PaintedSurface.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright 2011, 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 PaintedSurface_h -#define PaintedSurface_h - -#include "BaseTileTexture.h" -#include "ClassTracker.h" -#include "IntRect.h" -#include "LayerAndroid.h" -#include "SkRefCnt.h" -#include "TextureOwner.h" -#include "TilesManager.h" -#include "TilePainter.h" -#include "TransformationMatrix.h" - -class SkCanvas; -class SkRegion; - -namespace WebCore { - -class DualTiledTexture; - -class PaintedSurface : public SurfacePainter { -public: - PaintedSurface(); - virtual ~PaintedSurface(); - - // PaintedSurface methods - - void prepare(GLWebViewState*); - bool draw(); - bool paint(SkCanvas*); - - void setDrawingLayer(LayerAndroid* layer) { m_drawingLayer = layer; } - LayerAndroid* drawingLayer() { return m_drawingLayer; } - - void setPaintingLayer(LayerAndroid* layer, const SkRegion& dirtyArea); - void clearPaintingLayer() { m_paintingLayer = 0; } - LayerAndroid* paintingLayer() { return m_paintingLayer; } - - void swapTiles(); - bool isReady(); - - bool owns(BaseTileTexture* texture); - - void computeTexturesAmount(TexturesResult*); - IntRect computeVisibleArea(LayerAndroid*); - - // TilePainter methods for TiledTexture - virtual const TransformationMatrix* transform(); - virtual float opacity(); - - // used by TiledTexture - float scale() { return m_scale; } - unsigned int pictureUsed() { return m_pictureUsed; } - -private: - LayerAndroid* m_drawingLayer; - LayerAndroid* m_paintingLayer; - DualTiledTexture* m_tiledTexture; - - float m_scale; - - unsigned int m_pictureUsed; - - android::Mutex m_layerLock; -}; - -} // namespace WebCore - -#endif // PaintedSurface_h diff --git a/Source/WebCore/platform/graphics/android/PerformanceMonitor.cpp b/Source/WebCore/platform/graphics/android/PerformanceMonitor.cpp index 241cbef..902fa1e 100644 --- a/Source/WebCore/platform/graphics/android/PerformanceMonitor.cpp +++ b/Source/WebCore/platform/graphics/android/PerformanceMonitor.cpp @@ -69,7 +69,6 @@ void PerformanceMonitor::stop(const String &tag) float mtime = (seconds * 1000.0) + (useconds/1000.0); - float avg = 0; if (item->average_ms) { item->average_ms = (item->average_ms + mtime) / 2; } else diff --git a/Source/WebCore/platform/graphics/android/PictureLayerContent.cpp b/Source/WebCore/platform/graphics/android/PictureLayerContent.cpp new file mode 100644 index 0000000..cf2e569 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/PictureLayerContent.cpp @@ -0,0 +1,103 @@ +#include "config.h" +#include "PictureLayerContent.h" + +#include "InspectorCanvas.h" +#include "SkPicture.h" + +namespace WebCore { + +PictureLayerContent::PictureLayerContent(SkPicture* picture) + : m_picture(picture) + , m_checkedContent(false) + , m_hasText(true) +{ + SkSafeRef(m_picture); +} + +PictureLayerContent::PictureLayerContent(const PictureLayerContent& content) + : m_picture(content.m_picture) + , m_checkedContent(content.m_checkedContent) + , m_hasText(content.m_hasText) +{ + SkSafeRef(m_picture); +} + +PictureLayerContent::~PictureLayerContent() +{ + SkSafeUnref(m_picture); +} + +int PictureLayerContent::width() +{ + if (!m_picture) + return 0; + return m_picture->width(); +} + +int PictureLayerContent::height() +{ + if (!m_picture) + return 0; + return m_picture->height(); +} + +bool PictureLayerContent::isEmpty() +{ + if (!m_picture) + return true; + if (m_picture->width() == 0 + || m_picture->height() == 0) + return true; + return false; +} + +void PictureLayerContent::checkForOptimisations() +{ + if (!m_checkedContent) + hasText(); // for now only check the presence of text +} + +bool PictureLayerContent::hasText() +{ + if (m_checkedContent) + return m_hasText; + + // Let's check if we have text or not. If we don't, we can limit + // ourselves to scale 1! + InspectorBounder inspectorBounder; + InspectorCanvas checker(&inspectorBounder, m_picture); + SkBitmap bitmap; + bitmap.setConfig(SkBitmap::kARGB_8888_Config, + m_picture->width(), + m_picture->height()); + checker.setBitmapDevice(bitmap); + checker.drawPicture(*m_picture); + m_hasText = checker.hasText(); + if (!checker.hasContent()) { + // no content to draw, discard picture so UI / tile generation + // doesn't bother with it + SkSafeUnref(m_picture); + m_picture = 0; + } + + m_checkedContent = true; + + return m_hasText; +} + +void PictureLayerContent::draw(SkCanvas* canvas) +{ + if (!m_picture) + return; + + canvas->drawPicture(*m_picture); +} + +void PictureLayerContent::serialize(SkWStream* stream) +{ + if (!m_picture) + return; + m_picture->serialize(stream); +} + +} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/DeleteTextureOperation.h b/Source/WebCore/platform/graphics/android/PictureLayerContent.h index f3cb57c..94bdfac 100644 --- a/Source/WebCore/platform/graphics/android/DeleteTextureOperation.h +++ b/Source/WebCore/platform/graphics/android/PictureLayerContent.h @@ -1,5 +1,5 @@ /* - * Copyright 2010, The Android Open Source Project + * Copyright 2012, The Android Open Source Project * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -23,39 +23,33 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef DeleteTextureOperation_h -#define DeleteTextureOperation_h +#ifndef PictureLayerContent_h +#define PictureLayerContent_h -#include "GLUtils.h" -#include "QueuedOperation.h" +#include "LayerContent.h" namespace WebCore { -class DeleteTextureOperation : public QueuedOperation { +class PictureLayerContent : public LayerContent { public: - DeleteTextureOperation(GLuint textureId, EGLImageKHR eglImage) - : QueuedOperation(QueuedOperation::DeleteTexture, 0) - , m_textureId(textureId) - , m_eglImage(eglImage) {} - virtual bool operator==(const QueuedOperation* operation) - { - if (operation->type() != type()) - return false; - const DeleteTextureOperation* op = static_cast<const DeleteTextureOperation*>(operation); - return op->m_textureId == m_textureId; - } - virtual void run() - { - if (m_textureId) - GLUtils::deleteTexture(&m_textureId); - if (m_eglImage) - eglDestroyImageKHR(eglGetCurrentDisplay(), m_eglImage); - } + PictureLayerContent(SkPicture* picture); + PictureLayerContent(const PictureLayerContent& content); + ~PictureLayerContent(); + + virtual int width(); + virtual int height(); + virtual bool isEmpty(); + virtual void checkForOptimisations(); + virtual bool hasText(); + virtual void draw(SkCanvas* canvas); + virtual void serialize(SkWStream* stream); + private: - GLuint m_textureId; - EGLImageKHR m_eglImage; + SkPicture* m_picture; + bool m_checkedContent; + bool m_hasText; }; -} +} // WebCore -#endif // DeleteTextureOperation_h +#endif // PictureLayerContent_h diff --git a/Source/WebCore/platform/graphics/android/PictureSetLayerContent.cpp b/Source/WebCore/platform/graphics/android/PictureSetLayerContent.cpp new file mode 100644 index 0000000..bc024eb --- /dev/null +++ b/Source/WebCore/platform/graphics/android/PictureSetLayerContent.cpp @@ -0,0 +1,35 @@ +#include "config.h" +#include "PictureSetLayerContent.h" + +#include "SkPicture.h" + +namespace WebCore { + +PictureSetLayerContent::PictureSetLayerContent(const android::PictureSet& pictureSet) +{ + m_pictureSet.set(pictureSet); +} + +PictureSetLayerContent::~PictureSetLayerContent() +{ + m_pictureSet.clear(); +} + +void PictureSetLayerContent::draw(SkCanvas* canvas) +{ + if (!m_pictureSet.isEmpty()) + m_pictureSet.draw(canvas); +} + +void PictureSetLayerContent::serialize(SkWStream* stream) +{ + if (!stream) + return; + SkPicture picture; + draw(picture.beginRecording(m_pictureSet.width(), m_pictureSet.height(), + SkPicture::kUsePathBoundsForClip_RecordingFlag)); + picture.endRecording(); + picture.serialize(stream); +} + +} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/PictureSetLayerContent.h b/Source/WebCore/platform/graphics/android/PictureSetLayerContent.h new file mode 100644 index 0000000..61fc3f4 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/PictureSetLayerContent.h @@ -0,0 +1,53 @@ +/* + * Copyright 2012, 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 PictureSetLayerContent_h +#define PictureSetLayerContent_h + +#include "LayerContent.h" +#include "PictureSet.h" + +namespace WebCore { + +class PictureSetLayerContent : public LayerContent { +public: + PictureSetLayerContent(const android::PictureSet& pictureSet); + ~PictureSetLayerContent(); + + virtual int width() { return m_pictureSet.width(); } + virtual int height() { return m_pictureSet.height(); } + virtual bool isEmpty() { return m_pictureSet.isEmpty(); } + virtual void checkForOptimisations() {} + virtual bool hasText() { return true; } + virtual void draw(SkCanvas* canvas); + virtual void serialize(SkWStream* stream); + +private: + android::PictureSet m_pictureSet; +}; + +} // WebCore + +#endif // PictureLayerContent_h diff --git a/Source/WebCore/platform/graphics/android/PlatformGraphicsContext.h b/Source/WebCore/platform/graphics/android/PlatformGraphicsContext.h index d22dbd8..80ea5d6 100644 --- a/Source/WebCore/platform/graphics/android/PlatformGraphicsContext.h +++ b/Source/WebCore/platform/graphics/android/PlatformGraphicsContext.h @@ -28,7 +28,6 @@ #include "IntRect.h" #include "RenderSkinAndroid.h" -#include "RenderSkinButton.h" #include "SkCanvas.h" #include "SkPicture.h" #include "SkTDArray.h" diff --git a/Source/WebCore/platform/graphics/android/QueuedOperation.h b/Source/WebCore/platform/graphics/android/QueuedOperation.h index 1a83f65..2f36547 100644 --- a/Source/WebCore/platform/graphics/android/QueuedOperation.h +++ b/Source/WebCore/platform/graphics/android/QueuedOperation.h @@ -32,18 +32,14 @@ class TiledPage; class QueuedOperation { public: - enum OperationType { Undefined, PaintTile, PaintLayer, DeleteTexture }; - QueuedOperation(OperationType type, TiledPage* page) - : m_type(type) - , m_page(page) {} + QueuedOperation(TiledPage* page) + : m_page(page) {} virtual ~QueuedOperation() {} virtual void run() = 0; virtual bool operator==(const QueuedOperation* operation) = 0; virtual int priority() { return -1; } - OperationType type() const { return m_type; } TiledPage* page() const { return m_page; } private: - OperationType m_type; TiledPage* m_page; }; @@ -66,20 +62,6 @@ private: TiledPage* m_page; }; -class PagePaintFilter : public OperationFilter { -public: - PagePaintFilter(TiledPage* page) : m_page(page) {} - virtual bool check(QueuedOperation* operation) - { - if (operation->type() == QueuedOperation::PaintTile - && operation->page() == m_page) - return true; - return false; - } -private: - TiledPage* m_page; -}; - } #endif // QueuedOperation_h diff --git a/Source/WebCore/platform/graphics/android/RasterRenderer.cpp b/Source/WebCore/platform/graphics/android/RasterRenderer.cpp index 9991fbd..f52af60 100644 --- a/Source/WebCore/platform/graphics/android/RasterRenderer.cpp +++ b/Source/WebCore/platform/graphics/android/RasterRenderer.cpp @@ -112,8 +112,14 @@ void RasterRenderer::setupCanvas(const TileRenderInfo& renderInfo, SkCanvas* can device->unref(); - // ensure the canvas origin is translated to the coordinates of our inval rect - canvas->translate(-renderInfo.invalRect->fLeft, -renderInfo.invalRect->fTop); + // If we have a partially painted bitmap + if (renderInfo.invalRect) { + SkRect clipRect = SkRect::MakeWH(renderInfo.invalRect->width(), + renderInfo.invalRect->height()); + // ensure the canvas origin is translated to the coordinates of our inval rect + canvas->clipRect(clipRect); + canvas->translate(-renderInfo.invalRect->fLeft, -renderInfo.invalRect->fTop); + } } void RasterRenderer::renderingComplete(const TileRenderInfo& renderInfo, SkCanvas* canvas) diff --git a/Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.cpp index 3c2ced5..dffab58 100644 --- a/Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.cpp @@ -5,31 +5,43 @@ #if USE(ACCELERATED_COMPOSITING) +#include <wtf/CurrentTime.h> +#include <cutils/log.h> +#include <wtf/text/CString.h> +#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "ScrollableLayerAndroid", __VA_ARGS__) + namespace WebCore { bool ScrollableLayerAndroid::scrollTo(int x, int y) { - SkIRect scrollBounds; - getScrollRect(&scrollBounds); - if (!scrollBounds.fRight && !scrollBounds.fBottom) + IntRect scrollBounds; + getScrollBounds(&scrollBounds); + if (!scrollBounds.width() && !scrollBounds.height()) return false; - - SkScalar newX = SkScalarPin(x, 0, scrollBounds.fRight); - SkScalar newY = SkScalarPin(y, 0, scrollBounds.fBottom); + SkScalar newX = SkScalarPin(x, scrollBounds.x(), scrollBounds.width()); + SkScalar newY = SkScalarPin(y, scrollBounds.y(), scrollBounds.height()); // Check for no change. - if (newX == scrollBounds.fLeft && newY == scrollBounds.fTop) + if (newX == m_offset.x() && newY == m_offset.y()) return false; - - setPosition(m_scrollLimits.fLeft - newX, m_scrollLimits.fTop - newY); - + setScrollOffset(IntPoint(newX, newY)); return true; } +void ScrollableLayerAndroid::getScrollBounds(IntRect* out) const +{ + const SkPoint& pos = getPosition(); + out->setX(m_scrollLimits.fLeft - pos.fX); + out->setY(m_scrollLimits.fTop - pos.fY); + out->setWidth(getSize().width() - m_scrollLimits.width()); + out->setHeight(getSize().height() - m_scrollLimits.height()); +} + void ScrollableLayerAndroid::getScrollRect(SkIRect* out) const { const SkPoint& pos = getPosition(); - out->fLeft = m_scrollLimits.fLeft - pos.fX; - out->fTop = m_scrollLimits.fTop - pos.fY; + out->fLeft = m_scrollLimits.fLeft - pos.fX + m_offset.x(); + out->fTop = m_scrollLimits.fTop - pos.fY + m_offset.y(); + out->fRight = getSize().width() - m_scrollLimits.width(); out->fBottom = getSize().height() - m_scrollLimits.height(); } diff --git a/Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.h b/Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.h index 5cba5d9..1f289e6 100644 --- a/Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.h +++ b/Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.h @@ -41,19 +41,20 @@ public: virtual bool contentIsScrollable() const { return true; } virtual LayerAndroid* copy() const { return new ScrollableLayerAndroid(*this); } + virtual SubclassType subclassType() { return LayerAndroid::ScrollableLayer; } virtual bool updateWithLayer(LayerAndroid*) { return true; } // Scrolls to the given position in the layer. // Returns whether or not any scrolling was required. - bool scrollTo(int x, int y); + virtual bool scrollTo(int x, int y); // Fills the rect with the current scroll offset and the maximum scroll offset. // fLeft = scrollX // fTop = scrollY // fRight = maxScrollX // fBottom = maxScrollY - void getScrollRect(SkIRect*) const; + virtual void getScrollRect(SkIRect*) const; void setScrollLimits(float x, float y, float width, float height) { @@ -68,9 +69,12 @@ public: bool scrollRectIntoView(const SkIRect&); friend void android::serializeLayer(LayerAndroid* layer, SkWStream* stream); - friend LayerAndroid* android::deserializeLayer(SkStream* stream); + friend LayerAndroid* android::deserializeLayer(int version, SkStream* stream); + +protected: + + void getScrollBounds(IntRect*) const; -private: // The position of the visible area of the layer, relative to the parent // layer. This is fixed during scrolling. We acheive scrolling by modifying // the position of the layer. diff --git a/Source/WebCore/platform/graphics/android/ShaderProgram.cpp b/Source/WebCore/platform/graphics/android/ShaderProgram.cpp index 2a6a488..74a74e1 100644 --- a/Source/WebCore/platform/graphics/android/ShaderProgram.cpp +++ b/Source/WebCore/platform/graphics/android/ShaderProgram.cpp @@ -38,9 +38,21 @@ #include <wtf/CurrentTime.h> #include <wtf/text/CString.h> +#undef XLOGC +#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "ShaderProgram", __VA_ARGS__) + +#ifdef DEBUG + #undef XLOG #define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "ShaderProgram", __VA_ARGS__) +#else + +#undef XLOG +#define XLOG(...) + +#endif // DEBUG + namespace WebCore { static const char gVertexShader[] = @@ -62,6 +74,26 @@ static const char gFragmentShader[] = " gl_FragColor *= alpha; " "}\n"; +// We could pass the pureColor into either Vertex or Frag Shader. +// The reason we passed the color into the Vertex Shader is that some driver +// might create redundant copy when uniforms in fragment shader changed. +static const char gPureColorVertexShader[] = + "attribute vec4 vPosition;\n" + "uniform mat4 projectionMatrix;\n" + "uniform vec4 inputColor;\n" + "varying vec4 v_color;\n" + "void main() {\n" + " gl_Position = projectionMatrix * vPosition;\n" + " v_color = inputColor;\n" + "}\n"; + +static const char gPureColorFragmentShader[] = + "precision mediump float;\n" + "varying vec4 v_color;\n" + "void main() {\n" + " gl_FragColor = v_color;\n" + "}\n"; + static const char gFragmentShaderInverted[] = "precision mediump float;\n" "varying vec2 v_texCoord; \n" @@ -140,7 +172,7 @@ GLuint ShaderProgram::loadShader(GLenum shaderType, const char* pSource) char* buf = (char*) malloc(infoLen); if (buf) { glGetShaderInfoLog(shader, infoLen, 0, buf); - XLOG("could not compile shader %d:\n%s\n", shaderType, buf); + XLOGC("could not compile shader %d:\n%s\n", shaderType, buf); free(buf); } glDeleteShader(shader); @@ -151,17 +183,17 @@ GLuint ShaderProgram::loadShader(GLenum shaderType, const char* pSource) return shader; } -GLuint ShaderProgram::createProgram(const char* pVertexSource, const char* pFragmentSource) +GLint ShaderProgram::createProgram(const char* pVertexSource, const char* pFragmentSource) { GLuint vertexShader = loadShader(GL_VERTEX_SHADER, pVertexSource); if (!vertexShader) { - XLOG("couldn't load the vertex shader!"); + XLOGC("couldn't load the vertex shader!"); return -1; } GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pFragmentSource); if (!pixelShader) { - XLOG("couldn't load the pixel shader!"); + XLOGC("couldn't load the pixel shader!"); return -1; } @@ -181,7 +213,7 @@ GLuint ShaderProgram::createProgram(const char* pVertexSource, const char* pFrag char* buf = (char*) malloc(bufLength); if (buf) { glGetProgramInfoLog(program, bufLength, 0, buf); - XLOG("could not link program:\n%s\n", buf); + XLOGC("could not link program:\n%s\n", buf); free(buf); } } @@ -189,6 +221,9 @@ GLuint ShaderProgram::createProgram(const char* pVertexSource, const char* pFrag program = -1; } } + + ShaderResource newResource(program, vertexShader, pixelShader); + m_resources.append(newResource); return program; } @@ -197,57 +232,101 @@ ShaderProgram::ShaderProgram() , m_contrast(1) , m_alphaLayer(false) , m_currentScale(1.0f) + , m_needsInit(true) { - init(); } -void ShaderProgram::init() +void ShaderProgram::cleanupGLResources() +{ + for (unsigned int i = 0; i < m_resources.size(); i++) { + glDetachShader(m_resources[i].program, m_resources[i].vertexShader); + glDetachShader(m_resources[i].program, m_resources[i].fragmentShader); + glDeleteShader(m_resources[i].vertexShader); + glDeleteShader(m_resources[i].fragmentShader); + glDeleteProgram(m_resources[i].program); + } + glDeleteBuffers(1, m_textureBuffer); + + m_resources.clear(); + m_needsInit = true; + GLUtils::checkGlError("cleanupGLResources"); + + return; +} + +void ShaderProgram::initGLResources() { - m_program = createProgram(gVertexShader, gFragmentShader); - m_programInverted = createProgram(gVertexShader, gFragmentShaderInverted); - m_videoProgram = createProgram(gVideoVertexShader, gVideoFragmentShader); - m_surfTexOESProgram = + // To detect whether or not resources for ShaderProgram allocated + // successfully, we clean up pre-existing errors here and will check for + // new errors at the end of this function. + GLUtils::checkGlError("before initGLResources"); + + GLint tex2DProgram = createProgram(gVertexShader, gFragmentShader); + GLint pureColorProgram = createProgram(gPureColorVertexShader, gPureColorFragmentShader); + GLint tex2DInvProgram = createProgram(gVertexShader, gFragmentShaderInverted); + GLint videoProgram = createProgram(gVideoVertexShader, gVideoFragmentShader); + GLint texOESProgram = createProgram(gVertexShader, gSurfaceTextureOESFragmentShader); - m_surfTexOESProgramInverted = + GLint texOESInvProgram = createProgram(gVertexShader, gSurfaceTextureOESFragmentShaderInverted); - if (m_program == -1 - || m_programInverted == -1 - || m_videoProgram == -1 - || m_surfTexOESProgram == -1 - || m_surfTexOESProgramInverted == -1) + if (tex2DProgram == -1 + || pureColorProgram == -1 + || tex2DInvProgram == -1 + || videoProgram == -1 + || texOESProgram == -1 + || texOESInvProgram == -1) { + m_needsInit = true; return; + } - m_hProjectionMatrix = glGetUniformLocation(m_program, "projectionMatrix"); - m_hAlpha = glGetUniformLocation(m_program, "alpha"); - m_hTexSampler = glGetUniformLocation(m_program, "s_texture"); - m_hPosition = glGetAttribLocation(m_program, "vPosition"); - - m_hProjectionMatrixInverted = glGetUniformLocation(m_programInverted, "projectionMatrix"); - m_hAlphaInverted = glGetUniformLocation(m_programInverted, "alpha"); - m_hContrastInverted = glGetUniformLocation(m_surfTexOESProgramInverted, "contrast"); - m_hTexSamplerInverted = glGetUniformLocation(m_programInverted, "s_texture"); - m_hPositionInverted = glGetAttribLocation(m_programInverted, "vPosition"); - - m_hVideoProjectionMatrix = - glGetUniformLocation(m_videoProgram, "projectionMatrix"); - m_hVideoTextureMatrix = glGetUniformLocation(m_videoProgram, "textureMatrix"); - m_hVideoTexSampler = glGetUniformLocation(m_videoProgram, "s_yuvTexture"); - m_hVideoPosition = glGetAttribLocation(m_program, "vPosition"); - - m_hSTOESProjectionMatrix = - glGetUniformLocation(m_surfTexOESProgram, "projectionMatrix"); - m_hSTOESAlpha = glGetUniformLocation(m_surfTexOESProgram, "alpha"); - m_hSTOESTexSampler = glGetUniformLocation(m_surfTexOESProgram, "s_texture"); - m_hSTOESPosition = glGetAttribLocation(m_surfTexOESProgram, "vPosition"); - - m_hSTOESProjectionMatrixInverted = - glGetUniformLocation(m_surfTexOESProgramInverted, "projectionMatrix"); - m_hSTOESAlphaInverted = glGetUniformLocation(m_surfTexOESProgramInverted, "alpha"); - m_hSTOESContrastInverted = glGetUniformLocation(m_surfTexOESProgramInverted, "contrast"); - m_hSTOESTexSamplerInverted = glGetUniformLocation(m_surfTexOESProgramInverted, "s_texture"); - m_hSTOESPositionInverted = glGetAttribLocation(m_surfTexOESProgramInverted, "vPosition"); - + GLint pureColorPosition = glGetAttribLocation(pureColorProgram, "vPosition"); + GLint pureColorProjMtx = glGetUniformLocation(pureColorProgram, "projectionMatrix"); + GLint pureColorValue = glGetUniformLocation(pureColorProgram, "inputColor"); + m_handleArray[PureColor].init(-1, -1, pureColorPosition, pureColorProgram, + pureColorProjMtx, pureColorValue, -1, -1); + + GLint tex2DAlpha = glGetUniformLocation(tex2DProgram, "alpha"); + GLint tex2DPosition = glGetAttribLocation(tex2DProgram, "vPosition"); + GLint tex2DProjMtx = glGetUniformLocation(tex2DProgram, "projectionMatrix"); + GLint tex2DTexSampler = glGetUniformLocation(tex2DProgram, "s_texture"); + m_handleArray[Tex2D].init(tex2DAlpha, -1, tex2DPosition, tex2DProgram, + tex2DProjMtx, -1, tex2DTexSampler, -1); + + GLint tex2DInvAlpha = glGetUniformLocation(tex2DInvProgram, "alpha"); + GLint tex2DInvContrast = glGetUniformLocation(tex2DInvProgram, "contrast"); + GLint tex2DInvPosition = glGetAttribLocation(tex2DInvProgram, "vPosition"); + GLint tex2DInvProjMtx = glGetUniformLocation(tex2DInvProgram, "projectionMatrix"); + GLint tex2DInvTexSampler = glGetUniformLocation(tex2DInvProgram, "s_texture"); + m_handleArray[Tex2DInv].init(tex2DInvAlpha, tex2DInvContrast, + tex2DInvPosition, tex2DInvProgram, + tex2DInvProjMtx, -1, + tex2DInvTexSampler, -1); + + GLint texOESAlpha = glGetUniformLocation(texOESProgram, "alpha"); + GLint texOESPosition = glGetAttribLocation(texOESProgram, "vPosition"); + GLint texOESProjMtx = glGetUniformLocation(texOESProgram, "projectionMatrix"); + GLint texOESTexSampler = glGetUniformLocation(texOESProgram, "s_texture"); + m_handleArray[TexOES].init(texOESAlpha, -1, texOESPosition, texOESProgram, + texOESProjMtx, -1, texOESTexSampler, -1); + + GLint texOESInvAlpha = glGetUniformLocation(texOESInvProgram, "alpha"); + GLint texOESInvContrast = glGetUniformLocation(texOESInvProgram, "contrast"); + GLint texOESInvPosition = glGetAttribLocation(texOESInvProgram, "vPosition"); + GLint texOESInvProjMtx = glGetUniformLocation(texOESInvProgram, "projectionMatrix"); + GLint texOESInvTexSampler = glGetUniformLocation(texOESInvProgram, "s_texture"); + m_handleArray[TexOESInv].init(texOESInvAlpha, texOESInvContrast, + texOESInvPosition, texOESInvProgram, + texOESInvProjMtx, -1, + texOESInvTexSampler, -1); + + GLint videoPosition = glGetAttribLocation(videoProgram, "vPosition"); + GLint videoProjMtx = glGetUniformLocation(videoProgram, "projectionMatrix"); + GLint videoTexSampler = glGetUniformLocation(videoProgram, "s_yuvTexture"); + GLint videoTexMtx = glGetUniformLocation(videoProgram, "textureMatrix"); + m_handleArray[Video].init(-1, -1, videoPosition, videoProgram, + videoProjMtx, -1, videoTexSampler, + videoTexMtx); const GLfloat coord[] = { 0.0f, 0.0f, // C @@ -260,7 +339,14 @@ void ShaderProgram::init() glBindBuffer(GL_ARRAY_BUFFER, m_textureBuffer[0]); glBufferData(GL_ARRAY_BUFFER, 2 * 4 * sizeof(GLfloat), coord, GL_STATIC_DRAW); - GLUtils::checkGlError("init"); + TransformationMatrix matrix; + // Map x,y from (0,1) to (-1, 1) + matrix.scale3d(2, 2, 1); + matrix.translate3d(-0.5, -0.5, 0); + GLUtils::toGLMatrix(m_transferProjMtx, matrix); + + m_needsInit = GLUtils::checkGlError("initGLResources"); + return; } void ShaderProgram::resetBlending() @@ -288,17 +374,71 @@ void ShaderProgram::setBlendingState(bool enableBlending) // Drawing ///////////////////////////////////////////////////////////////////////////////////////// -void ShaderProgram::setViewport(SkRect& viewport, float scale) +void ShaderProgram::setupDrawing(const IntRect& viewRect, const SkRect& visibleRect, + const IntRect& webViewRect, int titleBarHeight, + const IntRect& screenClip, float scale) { + m_webViewRect = webViewRect; + m_titleBarHeight = titleBarHeight; + + //// viewport //// TransformationMatrix ortho; - GLUtils::setOrthographicMatrix(ortho, viewport.fLeft, viewport.fTop, - viewport.fRight, viewport.fBottom, -1000, 1000); - m_projectionMatrix = ortho; - m_viewport = viewport; + GLUtils::setOrthographicMatrix(ortho, visibleRect.fLeft, visibleRect.fTop, + visibleRect.fRight, visibleRect.fBottom, -1000, 1000); + // In most case , visibleRect / viewRect * scale should 1.0, but for the + // translation case, the scale factor can be 1 but visibleRect is smaller + // than viewRect, we need to tune in this factor to make sure we scale them + // right. Conceptually, that means, no matter how animation affects the + // visibleRect, the scaling should respect the viewRect if zoomScale is 1.0. + // Note that at TiledPage, we already scale the tile size inversely to make + // zooming animation right. + float orthoScaleX = scale * visibleRect.width() / viewRect.width(); + float orthoScaleY = scale * visibleRect.height() / viewRect.height(); + + TransformationMatrix orthoScale; + orthoScale.scale3d(orthoScaleX, orthoScaleY, 1.0); + + m_projectionMatrix = ortho * orthoScale; + m_viewport = visibleRect; m_currentScale = scale; + + + //// viewRect //// + m_viewRect = viewRect; + + // We do clipping using glScissor, which needs to take + // coordinates in screen space. The following matrix transform + // content coordinates in screen coordinates. + TransformationMatrix viewTranslate; + viewTranslate.translate(1.0, 1.0); + + TransformationMatrix viewScale; + viewScale.scale3d(m_viewRect.width() * 0.5f, m_viewRect.height() * 0.5f, 1); + + m_documentToScreenMatrix = viewScale * viewTranslate * m_projectionMatrix; + + viewTranslate.scale3d(1, -1, 1); + m_documentToInvScreenMatrix = viewScale * viewTranslate * m_projectionMatrix; + + IntRect rect(0, 0, m_webViewRect.width(), m_webViewRect.height()); + m_documentViewport = m_documentToScreenMatrix.inverse().mapRect(rect); + + + //// clipping //// + IntRect mclip = screenClip; + + // the clip from frameworks is in full screen coordinates + mclip.setY(screenClip.y() - m_webViewRect.y() - m_titleBarHeight); + FloatRect tclip = convertInvScreenCoordToScreenCoord(mclip); + m_screenClip.setLocation(IntPoint(tclip.x(), tclip.y())); + // use ceilf to handle view -> doc -> view coord rounding errors + m_screenClip.setSize(IntSize(ceilf(tclip.width()), ceilf(tclip.height()))); + + resetBlending(); } -void ShaderProgram::setProjectionMatrix(SkRect& geometry, GLint projectionMatrixHandle) +// Calculate the matrix given the geometry. +void ShaderProgram::setProjectionMatrix(const SkRect& geometry, GLfloat* mtxPtr) { TransformationMatrix translate; translate.translate3d(geometry.fLeft, geometry.fTop, 0.0); @@ -312,113 +452,75 @@ void ShaderProgram::setProjectionMatrix(SkRect& geometry, GLint projectionMatrix else total = m_projectionMatrix * translate * scale; - GLfloat projectionMatrix[16]; - GLUtils::toGLMatrix(projectionMatrix, total); - glUniformMatrix4fv(projectionMatrixHandle, 1, GL_FALSE, projectionMatrix); + GLUtils::toGLMatrix(mtxPtr, total); } -void ShaderProgram::drawQuadInternal(SkRect& geometry, - GLint textureId, - float opacity, - GLint program, - GLint projectionMatrixHandle, - GLint texSampler, - GLenum textureTarget, - GLint position, - GLint alpha, - GLint texFilter, - GLint contrast) +// Calculate the right color value sent into the shader considering the (0,1) +// clamp and alpha blending. +Color ShaderProgram::shaderColor(Color pureColor, float opacity) { - glUseProgram(program); - - if (!geometry.isEmpty()) - setProjectionMatrix(geometry, projectionMatrixHandle); - else { - TransformationMatrix matrix; - // Map x,y from (0,1) to (-1, 1) - matrix.scale3d(2, 2, 1); - matrix.translate3d(-0.5, -0.5, 0); - GLfloat projectionMatrix[16]; - GLUtils::toGLMatrix(projectionMatrix, matrix); - glUniformMatrix4fv(projectionMatrixHandle, 1, GL_FALSE, projectionMatrix); + float r = pureColor.red() / 255.0; + float g = pureColor.green() / 255.0; + float b = pureColor.blue() / 255.0; + float a = pureColor.alpha() / 255.0; + + if (TilesManager::instance()->invertedScreen()) { + float intensity = a - (0.2989 * r + 0.5866 * g + 0.1145 * b); + intensity = ((intensity - a / 2.0) * m_contrast) + a / 2.0; + intensity *= opacity; + return Color(intensity, intensity, intensity, a * opacity); } - - glActiveTexture(GL_TEXTURE0); - glUniform1i(texSampler, 0); - glBindTexture(textureTarget, textureId); - glTexParameteri(textureTarget, GL_TEXTURE_MIN_FILTER, texFilter); - glTexParameteri(textureTarget, GL_TEXTURE_MAG_FILTER, texFilter); - glTexParameteri(textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - glBindBuffer(GL_ARRAY_BUFFER, m_textureBuffer[0]); - glEnableVertexAttribArray(position); - glVertexAttribPointer(position, 2, GL_FLOAT, GL_FALSE, 0, 0); - glUniform1f(alpha, opacity); - if (contrast != -1) - glUniform1f(contrast, m_contrast); - - setBlendingState(opacity < 1.0); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + return Color(r * opacity, g * opacity, b * opacity, a * opacity); } -void ShaderProgram::drawQuad(SkRect& geometry, int textureId, float opacity, - GLenum textureTarget, GLint texFilter) +// For shaders using texture, it is easy to get the type from the textureTarget. +ShaderType ShaderProgram::getTextureShaderType(GLenum textureTarget) { + ShaderType type = UndefinedShader; if (textureTarget == GL_TEXTURE_2D) { - if (!TilesManager::instance()->invertedScreen()) { - drawQuadInternal(geometry, textureId, opacity, m_program, - m_hProjectionMatrix, - m_hTexSampler, GL_TEXTURE_2D, - m_hPosition, m_hAlpha, texFilter); - } else { + if (!TilesManager::instance()->invertedScreen()) + type = Tex2D; + else { // With the new GPU texture upload path, we do not use an FBO // to blit the texture we receive from the TexturesGenerator thread. // To implement inverted rendering, we thus have to do the rendering // live, by using a different shader. - drawQuadInternal(geometry, textureId, opacity, m_programInverted, - m_hProjectionMatrixInverted, - m_hTexSamplerInverted, GL_TEXTURE_2D, - m_hPositionInverted, m_hAlphaInverted, texFilter, - m_hContrastInverted); + type = Tex2DInv; } - } else if (textureTarget == GL_TEXTURE_EXTERNAL_OES - && !TilesManager::instance()->invertedScreen()) { - drawQuadInternal(geometry, textureId, opacity, m_surfTexOESProgram, - m_hSTOESProjectionMatrix, - m_hSTOESTexSampler, GL_TEXTURE_EXTERNAL_OES, - m_hSTOESPosition, m_hSTOESAlpha, texFilter); - } else if (textureTarget == GL_TEXTURE_EXTERNAL_OES - && TilesManager::instance()->invertedScreen()) { - drawQuadInternal(geometry, textureId, opacity, m_surfTexOESProgramInverted, - m_hSTOESProjectionMatrixInverted, - m_hSTOESTexSamplerInverted, GL_TEXTURE_EXTERNAL_OES, - m_hSTOESPositionInverted, m_hSTOESAlphaInverted, - texFilter, m_hSTOESContrastInverted); + } else if (textureTarget == GL_TEXTURE_EXTERNAL_OES) { + if (!TilesManager::instance()->invertedScreen()) + type = TexOES; + else + type = TexOESInv; } - GLUtils::checkGlError("drawQuad"); + return type; } -void ShaderProgram::setViewRect(const IntRect& viewRect) +void ShaderProgram::drawQuad(const SkRect& geometry, int textureId, float opacity, + Color pureColor, GLenum textureTarget, GLint texFilter) { - m_viewRect = viewRect; - - // We do clipping using glScissor, which needs to take - // coordinates in screen space. The following matrix transform - // content coordinates in screen coordinates. - TransformationMatrix translate; - translate.translate(1.0, 1.0); - - TransformationMatrix scale; - scale.scale3d(m_viewRect.width() * 0.5f, m_viewRect.height() * 0.5f, 1); - - m_documentToScreenMatrix = scale * translate * m_projectionMatrix; - - translate.scale3d(1, -1, 1); - m_documentToInvScreenMatrix = scale * translate * m_projectionMatrix; - - IntRect rect(0, 0, m_webViewRect.width(), m_webViewRect.height()); - m_documentViewport = m_documentToScreenMatrix.inverse().mapRect(rect); + ShaderType type = UndefinedShader; + if (!textureId) { + pureColor = shaderColor(pureColor, opacity); + if (pureColor.rgb() == Color::transparent && opacity < 1.0) + return; + type = PureColor; + } else + type = getTextureShaderType(textureTarget); + + if (type != UndefinedShader) { + // The matrix is either for the transfer queue or the tiles + GLfloat* finalMatrix = m_transferProjMtx; + GLfloat projectionMatrix[16]; + if (!geometry.isEmpty()) { + setProjectionMatrix(geometry, projectionMatrix); + finalMatrix = projectionMatrix; + } + setBlendingState(opacity < 1.0); + drawQuadInternal(type, finalMatrix, textureId, opacity, textureTarget, + texFilter, pureColor); + } + GLUtils::checkGlError("drawQuad"); } // This function transform a clip rect extracted from the current layer @@ -465,18 +567,6 @@ FloatRect ShaderProgram::convertScreenCoordToInvScreenCoord(const FloatRect& rec return rectInInvScreenCoord(documentRect); } -void ShaderProgram::setScreenClip(const IntRect& clip) -{ - m_screenClip = clip; - IntRect mclip = clip; - - // the clip from frameworks is in full screen coordinates - mclip.setY(clip.y() - m_webViewRect.y() - m_titleBarHeight); - FloatRect tclip = convertInvScreenCoordToScreenCoord(mclip); - IntRect screenClip(tclip.x(), tclip.y(), tclip.width(), tclip.height()); - m_screenClip = screenClip; -} - // clip is in screen coordinates void ShaderProgram::clip(const FloatRect& clip) { @@ -530,40 +620,45 @@ float ShaderProgram::zValue(const TransformationMatrix& drawMatrix, float w, flo return result.z(); } -void ShaderProgram::drawLayerQuadInternal(const GLfloat* projectionMatrix, - int textureId, float opacity, - GLenum textureTarget, GLint program, - GLint matrix, GLint texSample, - GLint position, GLint alpha, - GLint contrast) +void ShaderProgram::drawQuadInternal(ShaderType type, const GLfloat* matrix, + int textureId, float opacity, + GLenum textureTarget, GLenum filter, + const Color& pureColor) { - glUseProgram(program); - glUniformMatrix4fv(matrix, 1, GL_FALSE, projectionMatrix); - - glActiveTexture(GL_TEXTURE0); - glUniform1i(texSample, 0); - glBindTexture(textureTarget, textureId); - glTexParameteri(textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - + glUseProgram(m_handleArray[type].programHandle); + glUniformMatrix4fv(m_handleArray[type].projMtxHandle, 1, GL_FALSE, matrix); + + if (type != PureColor) { + glActiveTexture(GL_TEXTURE0); + glUniform1i(m_handleArray[type].texSamplerHandle, 0); + glBindTexture(textureTarget, textureId); + glTexParameteri(textureTarget, GL_TEXTURE_MIN_FILTER, filter); + glTexParameteri(textureTarget, GL_TEXTURE_MAG_FILTER, filter); + glUniform1f(m_handleArray[type].alphaHandle, opacity); + + GLint contrastHandle = m_handleArray[type].contrastHandle; + if (contrastHandle != -1) + glUniform1f(contrastHandle, m_contrast); + } else { + glUniform4f(m_handleArray[type].pureColorHandle, + pureColor.red() / 255.0, pureColor.green() / 255.0, + pureColor.blue() / 255.0, pureColor.alpha() / 255.0); + } + GLint positionHandle = m_handleArray[type].positionHandle; glBindBuffer(GL_ARRAY_BUFFER, m_textureBuffer[0]); - glEnableVertexAttribArray(position); - glVertexAttribPointer(position, 2, GL_FLOAT, GL_FALSE, 0, 0); - glUniform1f(alpha, opacity); - if (contrast != -1) - glUniform1f(contrast, m_contrast); -} + glEnableVertexAttribArray(positionHandle); + glVertexAttribPointer(positionHandle, 2, GL_FLOAT, GL_FALSE, 0, 0); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); +} void ShaderProgram::drawLayerQuad(const TransformationMatrix& drawMatrix, const SkRect& geometry, int textureId, float opacity, bool forceBlending, - GLenum textureTarget) + GLenum textureTarget, + Color pureColor) { - TransformationMatrix modifiedDrawMatrix = drawMatrix; // move the drawing depending on where the texture is on the layer modifiedDrawMatrix.translate(geometry.fLeft, geometry.fTop); @@ -578,37 +673,23 @@ void ShaderProgram::drawLayerQuad(const TransformationMatrix& drawMatrix, GLfloat projectionMatrix[16]; GLUtils::toGLMatrix(projectionMatrix, renderMatrix); - if (textureTarget == GL_TEXTURE_2D) { - if (!TilesManager::instance()->invertedScreen()) { - drawLayerQuadInternal(projectionMatrix, textureId, opacity, - GL_TEXTURE_2D, m_program, - m_hProjectionMatrix, m_hTexSampler, - m_hPosition, m_hAlpha); - } else { - drawLayerQuadInternal(projectionMatrix, textureId, opacity, - GL_TEXTURE_2D, m_programInverted, - m_hProjectionMatrixInverted, m_hTexSamplerInverted, - m_hPositionInverted, m_hAlphaInverted, - m_hContrastInverted); - } - } else if (textureTarget == GL_TEXTURE_EXTERNAL_OES - && !TilesManager::instance()->invertedScreen()) { - drawLayerQuadInternal(projectionMatrix, textureId, opacity, - GL_TEXTURE_EXTERNAL_OES, m_surfTexOESProgram, - m_hSTOESProjectionMatrix, m_hSTOESTexSampler, - m_hSTOESPosition, m_hSTOESAlpha); - } else if (textureTarget == GL_TEXTURE_EXTERNAL_OES - && TilesManager::instance()->invertedScreen()) { - drawLayerQuadInternal(projectionMatrix, textureId, opacity, - GL_TEXTURE_EXTERNAL_OES, m_surfTexOESProgramInverted, - m_hSTOESProjectionMatrixInverted, m_hSTOESTexSamplerInverted, - m_hSTOESPositionInverted, m_hSTOESAlphaInverted, - m_hSTOESContrastInverted); + bool enableBlending = forceBlending || opacity < 1.0; + + ShaderType type = UndefinedShader; + if (!textureId) { + pureColor = shaderColor(pureColor, opacity); + if (pureColor.rgb() == Color::transparent && enableBlending) + return; + type = PureColor; + } else + type = getTextureShaderType(textureTarget); + + if (type != UndefinedShader) { + setBlendingState(enableBlending); + drawQuadInternal(type, projectionMatrix, textureId, opacity, + textureTarget, GL_LINEAR, pureColor); } - setBlendingState(forceBlending || opacity < 1.0); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - GLUtils::checkGlError("drawLayerQuad"); } @@ -617,7 +698,7 @@ void ShaderProgram::drawVideoLayerQuad(const TransformationMatrix& drawMatrix, int textureId) { // switch to our custom yuv video rendering program - glUseProgram(m_videoProgram); + glUseProgram(m_handleArray[Video].programHandle); TransformationMatrix modifiedDrawMatrix = drawMatrix; modifiedDrawMatrix.translate(geometry.fLeft, geometry.fTop); @@ -626,16 +707,19 @@ void ShaderProgram::drawVideoLayerQuad(const TransformationMatrix& drawMatrix, GLfloat projectionMatrix[16]; GLUtils::toGLMatrix(projectionMatrix, renderMatrix); - glUniformMatrix4fv(m_hVideoProjectionMatrix, 1, GL_FALSE, projectionMatrix); - glUniformMatrix4fv(m_hVideoTextureMatrix, 1, GL_FALSE, textureMatrix); + glUniformMatrix4fv(m_handleArray[Video].projMtxHandle, 1, GL_FALSE, + projectionMatrix); + glUniformMatrix4fv(m_handleArray[Video].videoMtxHandle, 1, GL_FALSE, + textureMatrix); glActiveTexture(GL_TEXTURE0); - glUniform1i(m_hVideoTexSampler, 0); + glUniform1i(m_handleArray[Video].texSamplerHandle, 0); glBindTexture(GL_TEXTURE_EXTERNAL_OES, textureId); + GLint videoPosition = m_handleArray[Video].positionHandle; glBindBuffer(GL_ARRAY_BUFFER, m_textureBuffer[0]); - glEnableVertexAttribArray(m_hVideoPosition); - glVertexAttribPointer(m_hVideoPosition, 2, GL_FLOAT, GL_FALSE, 0, 0); + glEnableVertexAttribArray(videoPosition); + glVertexAttribPointer(videoPosition, 2, GL_FLOAT, GL_FALSE, 0, 0); setBlendingState(false); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); diff --git a/Source/WebCore/platform/graphics/android/ShaderProgram.h b/Source/WebCore/platform/graphics/android/ShaderProgram.h index 9ab7a46..98d45b5 100644 --- a/Source/WebCore/platform/graphics/android/ShaderProgram.h +++ b/Source/WebCore/platform/graphics/android/ShaderProgram.h @@ -19,6 +19,7 @@ #if USE(ACCELERATED_COMPOSITING) +#include "Color.h" #include "FloatRect.h" #include "IntRect.h" #include "SkRect.h" @@ -29,14 +30,85 @@ namespace WebCore { +enum ShaderType { + UndefinedShader = -1, + PureColor, + Tex2D, + Tex2DInv, + TexOES, + TexOESInv, + Video, + // When growing this enum list, make sure to insert before the + // MaxShaderNumber and init the m_handleArray accordingly. + MaxShaderNumber +}; + +struct ShaderHandles { + ShaderHandles() + : alphaHandle(-1) + , contrastHandle(-1) + , positionHandle(-1) + , programHandle(-1) + , projMtxHandle(-1) + , pureColorHandle(-1) + , texSamplerHandle(-1) + , videoMtxHandle(-1) + { + } + + void init(GLint alphaHdl, GLint contrastHdl, GLint posHdl, GLint pgmHdl, + GLint projMtxHdl, GLint colorHdl, GLint texSamplerHdl, + GLint videoMtxHdl) + { + alphaHandle = alphaHdl; + contrastHandle = contrastHdl; + positionHandle = posHdl; + programHandle = pgmHdl; + projMtxHandle = projMtxHdl; + pureColorHandle = colorHdl; + texSamplerHandle = texSamplerHdl; + videoMtxHandle = videoMtxHdl; + } + + GLint alphaHandle; + GLint contrastHandle; + GLint positionHandle; + GLint programHandle; + GLint projMtxHandle; + GLint pureColorHandle; + GLint texSamplerHandle; + GLint videoMtxHandle; +}; + +struct ShaderResource { + ShaderResource() + : program(-1) + , vertexShader(-1) + , fragmentShader(-1) + { + }; + + ShaderResource(GLuint prog, GLuint vertex, GLuint fragment) + : program(prog) + , vertexShader(vertex) + , fragmentShader(fragment) + { + }; + + GLuint program; + GLuint vertexShader; + GLuint fragmentShader; +}; + class ShaderProgram { public: ShaderProgram(); - void init(); - int program() { return m_program; } - + void initGLResources(); + void cleanupGLResources(); // Drawing - void setViewport(SkRect& viewport, float scale); + void setupDrawing(const IntRect& viewRect, const SkRect& visibleRect, + const IntRect& webViewRect, int titleBarHeight, + const IntRect& screenClip, float scale); float zValue(const TransformationMatrix& drawMatrix, float w, float h); // For drawQuad and drawLayerQuad, they can handle 3 cases for now: @@ -44,22 +116,18 @@ public: // Normal texture in GL_TEXTURE_2D target. // 2) textureTarget == GL_TEXTURE_EXTERNAL_OES // Surface texture in GL_TEXTURE_EXTERNAL_OES target. - // 3) textureTarget == 0 (Will be deprecated soon) - // Surface texture in GL_TEXTURE_2D target. - // - // TODO: Shrink the support modes into 2 (1 and 2) after media framework - // support Surface texture in GL_TEXTURE_EXTERNAL_OES target on all - // platforms. - void drawQuad(SkRect& geometry, int textureId, float opacity, + // 3) textureId == 0 + // No texture needed, just a pureColor quad. + void drawQuad(const SkRect& geometry, int textureId, float opacity, Color pureColor = Color(), GLenum textureTarget = GL_TEXTURE_2D, GLint texFilter = GL_LINEAR); void drawLayerQuad(const TransformationMatrix& drawMatrix, const SkRect& geometry, int textureId, float opacity, bool forceBlending = false, - GLenum textureTarget = GL_TEXTURE_2D); + GLenum textureTarget = GL_TEXTURE_2D, + Color pureColor = Color()); void drawVideoLayerQuad(const TransformationMatrix& drawMatrix, float* textureMatrix, SkRect& geometry, int textureId); - void setViewRect(const IntRect& viewRect); FloatRect rectInScreenCoord(const TransformationMatrix& drawMatrix, const IntSize& size); FloatRect rectInInvScreenCoord(const TransformationMatrix& drawMatrix, @@ -71,16 +139,13 @@ public: FloatRect convertInvScreenCoordToScreenCoord(const FloatRect& rect); FloatRect convertScreenCoordToInvScreenCoord(const FloatRect& rect); - void setTitleBarHeight(int height) { m_titleBarHeight = height; } - void setWebViewRect(const IntRect& rect) { m_webViewRect = rect; } - void setScreenClip(const IntRect& clip); void clip(const FloatRect& rect); IntRect clippedRectWithViewport(const IntRect& rect, int margin = 0); FloatRect documentViewport() { return m_documentViewport; } - void resetBlending(); float contrast() { return m_contrast; } - void setContrast(float c) { + void setContrast(float c) + { float contrast = c; if (contrast < 0) contrast = 0; @@ -100,33 +165,22 @@ public: void calculateAnimationDelta(); int getAnimationDeltaX() { return m_animationDelta.x(); } int getAnimationDeltaY() { return m_animationDelta.y(); } + bool needsInit() { return m_needsInit; } private: GLuint loadShader(GLenum shaderType, const char* pSource); - GLuint createProgram(const char* vertexSource, const char* fragmentSource); - void setProjectionMatrix(SkRect& geometry, GLint projectionMatrixHandle); - + GLint createProgram(const char* vertexSource, const char* fragmentSource); + void setProjectionMatrix(const SkRect& geometry, GLfloat* mtxPtr); void setBlendingState(bool enableBlending); - - void drawQuadInternal(SkRect& geometry, GLint textureId, float opacity, - GLint program, GLint projectionMatrixHandle, - GLint texSampler, GLenum textureTarget, - GLint position, GLint alpha, - GLint texFilter, GLint contrast = -1); - - void drawLayerQuadInternal(const GLfloat* projectionMatrix, int textureId, - float opacity, GLenum textureTarget, GLint program, - GLint matrix, GLint texSample, - GLint position, GLint alpha, GLint contrast = -1); + void drawQuadInternal(ShaderType type, const GLfloat* matrix, int textureId, + float opacity, GLenum textureTarget, GLenum filter, + const Color& pureColor); + Color shaderColor(Color pureColor, float opacity); + ShaderType getTextureShaderType(GLenum textureTarget); + void resetBlending(); bool m_blendingEnabled; - int m_program; - int m_programInverted; - int m_videoProgram; - int m_surfTexOESProgram; - int m_surfTexOESProgramInverted; - TransformationMatrix m_projectionMatrix; GLuint m_textureBuffer[1]; @@ -141,37 +195,9 @@ private: FloatRect m_documentViewport; - // uniforms - GLint m_hProjectionMatrix; - GLint m_hAlpha; - GLint m_hTexSampler; - GLint m_hProjectionMatrixInverted; - GLint m_hAlphaInverted; - GLint m_hContrastInverted; - GLint m_hTexSamplerInverted; - GLint m_hVideoProjectionMatrix; - GLint m_hVideoTextureMatrix; - GLint m_hVideoTexSampler; - - GLint m_hSTOESProjectionMatrix; - GLint m_hSTOESAlpha; - GLint m_hSTOESTexSampler; - GLint m_hSTOESPosition; - - GLint m_hSTOESProjectionMatrixInverted; - GLint m_hSTOESAlphaInverted; - GLint m_hSTOESContrastInverted; - GLint m_hSTOESTexSamplerInverted; - GLint m_hSTOESPositionInverted; - float m_contrast; - // attribs - GLint m_hPosition; - GLint m_hPositionInverted; - GLint m_hVideoPosition; - - bool m_alphaLayer; + bool m_alphaLayer; TransformationMatrix m_webViewMatrix; float m_currentScale; @@ -184,8 +210,23 @@ private: // TODO: Given that m_webViewMatrix contains most of the tranformation // information, we should be able to get rid of some parameter we got from // Java side and simplify our code. - TransformationMatrix m_repositionMatrix; + TransformationMatrix m_repositionMatrix; IntPoint m_animationDelta; + + // Put all the uniform location (handle) info into an array, and group them + // by the shader's type, this can help to clean up the interface. + // TODO: use the type and data comparison to skip GL call if possible. + ShaderHandles m_handleArray[MaxShaderNumber]; + + // If there is any GL error happens such that the Shaders are not initialized + // successfully at the first time, then we need to init again when we draw. + bool m_needsInit; + + // For transfer queue blitting, we need a special matrix map from (0,1) to + // (-1,1) + GLfloat m_transferProjMtx[16]; + + Vector<ShaderResource> m_resources; }; } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/SharedTexture.cpp b/Source/WebCore/platform/graphics/android/SharedTexture.cpp deleted file mode 100644 index 74cd2c6..0000000 --- a/Source/WebCore/platform/graphics/android/SharedTexture.cpp +++ /dev/null @@ -1,248 +0,0 @@ -/* - * 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 "SharedTexture.h" - -#include "GLUtils.h" -#include <android/native_window.h> -#include <gui/SurfaceTexture.h> -#include <gui/SurfaceTextureClient.h> - -#define LOG_NDEBUG 1 -#define LOG_TAG "SharedTexture.cpp" -#include <utils/Log.h> - -namespace WebCore { - -SharedTexture::SharedTexture(SharedTextureMode mode) -{ - m_sharedTextureMode = mode; - - m_sourceTexture = new TextureInfo(m_sharedTextureMode); - m_targetTexture = 0; - - if (m_sharedTextureMode == EglImageMode) { - m_targetTexture = new TextureInfo(m_sharedTextureMode); - m_eglImage = EGL_NO_IMAGE_KHR; - m_isNewImage = true; - m_syncObject = EGL_NO_SYNC_KHR; - - // Defer initialization of these values until we initialize the source - // texture. This ensures that this initialization happens in the appropriate - // thread. - m_display = 0; - m_supportsEGLImage = false; - m_supportsEGLFenceSyncKHR = false; - } else if (m_sharedTextureMode == SurfaceTextureMode) { -#if DEPRECATED_SURFACE_TEXTURE_MODE - glGenTextures(1, &m_sourceTexture->m_textureId); - - m_sourceTexture->m_surfaceTexture = - new android::SurfaceTexture(m_sourceTexture->m_textureId, false); - m_sourceTexture->m_ANW = - new android::SurfaceTextureClient(m_sourceTexture->m_surfaceTexture); -#endif - } -} - -// called by the consumer when it no longer wants to consume and after it has -// terminated all providers. If EGLImages are used, the deletion of the -// source texture and EGLImage is the responsibility of the caller. -SharedTexture::~SharedTexture() -{ - if (m_sharedTextureMode == EglImageMode) - deleteTargetTexture(); - else if (m_sharedTextureMode == SurfaceTextureMode) { -#if DEPRECATED_SURFACE_TEXTURE_MODE - m_sourceTexture->m_surfaceTexture.clear(); - m_sourceTexture->m_ANW.clear(); - GLUtils::deleteTexture(&m_sourceTexture->m_textureId); -#endif - } - delete m_sourceTexture; - delete m_targetTexture; -} - - -void SharedTexture::initSourceTexture() -{ - if (m_sharedTextureMode == SurfaceTextureMode) - return; - - m_display = eglGetCurrentDisplay(); - m_supportsEGLImage = GLUtils::isEGLImageSupported(); - m_supportsEGLFenceSyncKHR = GLUtils::isEGLFenceSyncSupported(); - - // TODO temporarily disable fence sync until the EGL framework fixes - // performance issues that result from consistently adding/removing fences. - m_supportsEGLFenceSyncKHR = false; - - LOGI("imageEGL: %d syncKHR: %d", m_supportsEGLImage, m_supportsEGLFenceSyncKHR); - - glGenTextures(1, &m_sourceTexture->m_textureId); - -} - -// For MediaTexture only -void SharedTexture::deleteSourceTexture() -{ - if (m_sharedTextureMode == SurfaceTextureMode) - return; - // We need to delete the source texture and EGLImage in the thread in which - // it was created. In theory we should be able to delete the EGLImage - // from either thread, but it currently throws an error if not deleted - // in the same EGLContext from which it was created. - if (m_supportsEGLImage) { - GLUtils::deleteTexture(&m_sourceTexture->m_textureId); - if (m_eglImage != EGL_NO_IMAGE_KHR) { - eglDestroyImageKHR(eglGetCurrentDisplay(), m_eglImage); - m_eglImage = EGL_NO_IMAGE_KHR; - m_isNewImage = true; - } - LOGI("Deleted Source Texture and EGLImage"); - } -} - -// For MediaTexture only -void SharedTexture::deleteTargetTexture() -{ - if (m_sharedTextureMode == SurfaceTextureMode) - return; - - if (m_supportsEGLImage) - GLUtils::deleteTexture(&m_targetTexture->m_textureId); - else - GLUtils::deleteTexture(&m_sourceTexture->m_textureId); -} - -TextureInfo* SharedTexture::lockSource() -{ - if (m_sharedTextureMode == SurfaceTextureMode) - return m_sourceTexture; - - 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) - LOGE("Sync timeout for shared texture (%d)", m_sourceTexture->m_textureId); - - eglDestroySyncKHR(m_display, m_syncObject); - m_syncObject = EGL_NO_SYNC_KHR; - } - return m_sourceTexture; -} - -void SharedTexture::releaseSource() -{ - if (m_sharedTextureMode == SurfaceTextureMode) - return; - - if (m_supportsEGLImage) { - // delete the existing image if needed - if (!m_sourceTexture->equalsAttributes(m_targetTexture)) { - if (m_eglImage != EGL_NO_IMAGE_KHR) { - eglDestroyImageKHR(m_display, m_eglImage); - m_eglImage = EGL_NO_IMAGE_KHR; - m_isNewImage = true; - } - m_targetTexture->copyAttributes(m_sourceTexture); - } - - // create an image from the texture, only when the texture is valid - if (m_eglImage == EGL_NO_IMAGE_KHR && m_sourceTexture->m_width - && m_sourceTexture->m_height) { - GLUtils::createEGLImageFromTexture(m_sourceTexture->m_textureId, &m_eglImage); - LOGV("Generating Image (%d) 0x%x", m_sourceTexture->m_textureId, m_eglImage); - - glFinish(); // ensures the texture is ready to be used by the consumer - } - - } else { - - m_targetTexture = m_sourceTexture; - - // in the case of shared contexts we must flush the texture edits to the - // GPU. This ensures the edits complete prior to allowing the texture to - // be bound on the producers context. - glFlush(); - } - - m_lock.unlock(); -} - -TextureInfo* SharedTexture::lockTarget() -{ - // Note that the source and targe are the same when using Surface Texture. - if (m_sharedTextureMode == SurfaceTextureMode) { -#if DEPRECATED_SURFACE_TEXTURE_MODE - m_sourceTexture->m_surfaceTexture->updateTexImage(); -#endif - return m_sourceTexture; - } - - m_lock.lock(); - - 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) - 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; - } - return m_targetTexture; -} - -void SharedTexture::releaseTarget() -{ - if (m_sharedTextureMode == SurfaceTextureMode) - return; - - if (m_supportsEGLFenceSyncKHR) { - if (m_syncObject != EGL_NO_SYNC_KHR) - eglDestroySyncKHR(m_display, m_syncObject); - 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 - // we support an EGL sync we will leave flush enable in order to test - // with modest performance. - glFlush(); - } - - m_lock.unlock(); -} - -} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/SharedTexture.h b/Source/WebCore/platform/graphics/android/SharedTexture.h deleted file mode 100644 index 305a442..0000000 --- a/Source/WebCore/platform/graphics/android/SharedTexture.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - * 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 SharedTexture_h -#define SharedTexture_h - -#include "TextureInfo.h" -#include <EGL/egl.h> -#include <EGL/eglext.h> -#include <GLES2/gl2.h> -#include <GLES2/gl2ext.h> -#include <utils/threads.h> - -namespace WebCore { - -/** - * SharedTexture is a class that encapsulates all the necessary variables - * needed to share a single texture across threads. In the case that threads - * communicate using EGL's sharedContext mechanism or do not support the proper - * EGLImage extensions the targetTexture, eglImage, and isNewImage variables are - * not used. - */ -class SharedTexture { -public: - // consumer thread functions - SharedTexture(SharedTextureMode mode); - ~SharedTexture(); - - TextureInfo* lockSource(); - void releaseSource(); - - TextureInfo* lockTarget(); - void releaseTarget(); - - // these locks are only used for the methods below - void lock() { m_lock.lock(); } - void unlock() { m_lock.unlock(); } - - void initSourceTexture(); // producer thread only - void deleteSourceTexture(); // producer thread only - void deleteTargetTexture(); // consumer thread only - GLuint getSourceTextureId() { return m_sourceTexture->m_textureId; } - GLuint getTargetTextureId() { return m_targetTexture->m_textureId; } - EGLImageKHR getEGLImage() { return m_eglImage; } - -private: - /** - * The mutex is used to ensure that the contents of the struct are current across - * threads and that only one thread is manipulating the texture at a given time. - */ - android::Mutex m_lock; - /** - * The texture and its associated metadata that is used by the producer. The - * texture is created in the producer's thread and can only be read by the - * consumer when the consumer shares the same context as the producer. The - * metadata is used to track changes to the texture that would orphan the - * target texture and require a new EGLImage to be constructed. - */ - TextureInfo* m_sourceTexture; - /** - * The target texture stores the id and metadata of the texture that is to be - * used by the consumer. In the case where EGLImages are supported this hold - * the current eglImage target. - */ - TextureInfo* m_targetTexture; - /** - * The EGLImage is used to share the texture between EGLContexts on two - * different threads. This serves as an alternative to sharing the contexts - * but is only used if GL and EGL support the required extensions. - */ - EGLImageKHR m_eglImage; - /** - * This flag is used to determine if the eglImage has been updated. This - * signals the consumer thread to rebind the targetTexture to the new image. - */ - bool m_isNewImage; - /** - * The sync allows the consumer to release the lock prior to the commands - * executing on the GPU. Prior to releasing the lock the consumer creates - * a sync object and stores it here. After locking the texture the client - * must check that the sync has completed prior to manipulating the texture. - * This value is only used if the proper EGL extensions are supported. - */ - EGLSyncKHR m_syncObject; - - EGLDisplay m_display; - - bool m_supportsEGLImage; - bool m_supportsEGLFenceSyncKHR; - - SharedTextureMode m_sharedTextureMode; -}; - -} // namespace WebCore - -#endif // SharedTexture_h diff --git a/Source/WebCore/platform/graphics/android/SurfaceCollection.cpp b/Source/WebCore/platform/graphics/android/SurfaceCollection.cpp new file mode 100644 index 0000000..23abc06 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/SurfaceCollection.cpp @@ -0,0 +1,285 @@ +/* + * Copyright 2012, 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 "SurfaceCollection.h" + +#include "BaseLayerAndroid.h" +#include "ClassTracker.h" +#include "LayerAndroid.h" +#include "LayerGroup.h" +#include "GLWebViewState.h" +#include "ScrollableLayerAndroid.h" +#include "TilesManager.h" + +#include <cutils/log.h> +#include <wtf/CurrentTime.h> +#include <wtf/text/CString.h> + +#undef XLOGC +#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "SurfaceCollection", __VA_ARGS__) + +#ifdef DEBUG + +#undef XLOG +#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "SurfaceCollection", __VA_ARGS__) + +#else + +#undef XLOG +#define XLOG(...) + +#endif // DEBUG + +namespace WebCore { + +//////////////////////////////////////////////////////////////////////////////// +// TILED PAINTING / GROUPS // +//////////////////////////////////////////////////////////////////////////////// + +SurfaceCollection::SurfaceCollection(BaseLayerAndroid* baseLayer) + : m_baseLayer(baseLayer) + , m_compositedRoot(0) +{ + if (!m_baseLayer) + return; + + SkSafeRef(m_baseLayer); + if (m_baseLayer->countChildren()) { + m_compositedRoot = static_cast<LayerAndroid*>(m_baseLayer->getChild(0)); + + // calculate draw transforms and z values + SkRect visibleRect = SkRect::MakeLTRB(0, 0, 1, 1); + m_baseLayer->updateLayerPositions(visibleRect); + + // allocate groups for layers, merging where possible + XLOG("new tree, allocating groups for tree %p", m_baseLayer); + + LayerMergeState layerMergeState(&m_layerGroups); + m_compositedRoot->assignGroups(&layerMergeState); + } + + // set the layergroups' and tiledpages' update count, to be drawn on painted tiles + unsigned int updateCount = TilesManager::instance()->incWebkitContentUpdates(); + for (unsigned int i = 0; i < m_layerGroups.size(); i++) + m_layerGroups[i]->setUpdateCount(updateCount); + m_baseLayer->state()->frontPage()->setUpdateCount(updateCount); + m_baseLayer->state()->backPage()->setUpdateCount(updateCount); + +#ifdef DEBUG_COUNT + ClassTracker::instance()->increment("SurfaceCollection"); +#endif +} + +SurfaceCollection::~SurfaceCollection() +{ + SkSafeUnref(m_baseLayer); + for (unsigned int i = 0; i < m_layerGroups.size(); i++) + SkSafeUnref(m_layerGroups[i]); + m_layerGroups.clear(); + +#ifdef DEBUG_COUNT + ClassTracker::instance()->decrement("SurfaceCollection"); +#endif +} + +void SurfaceCollection::prepareGL(const SkRect& visibleRect, float scale, double currentTime) +{ + if (!m_baseLayer) + return; + + m_baseLayer->prepareGL(visibleRect, scale, currentTime); + + if (m_compositedRoot) { + m_baseLayer->updateLayerPositions(visibleRect); + bool layerTilesDisabled = m_compositedRoot->state()->layersRenderingMode() + > GLWebViewState::kClippedTextures; + for (unsigned int i = 0; i < m_layerGroups.size(); i++) + m_layerGroups[i]->prepareGL(layerTilesDisabled); + } +} + +bool SurfaceCollection::drawGL(const SkRect& visibleRect, float scale) +{ +#ifdef DEBUG_COUNT + ClassTracker::instance()->show(); +#endif + + if (!m_baseLayer) + return false; + + m_baseLayer->drawGL(scale); + + bool needsRedraw = false; + if (m_compositedRoot) { + m_baseLayer->updateLayerPositions(visibleRect); + bool layerTilesDisabled = m_compositedRoot->state()->layersRenderingMode() + > GLWebViewState::kClippedTextures; + for (unsigned int i = 0; i < m_layerGroups.size(); i++) + needsRedraw |= m_layerGroups[i]->drawGL(layerTilesDisabled); + } + + return needsRedraw; +} + +void SurfaceCollection::swapTiles() +{ + if (!m_baseLayer) + return; + + m_baseLayer->swapTiles(); + + for (unsigned int i = 0; i < m_layerGroups.size(); i++) + m_layerGroups[i]->swapTiles(); +} + +bool SurfaceCollection::isReady() +{ + if (!m_baseLayer) + return true; + + if (!m_baseLayer->isReady()) + return false; + + if (!m_compositedRoot) + return true; + + // Override layer readiness check for single surface mode + if (m_compositedRoot->state()->layersRenderingMode() > GLWebViewState::kClippedTextures) { + // TODO: single surface mode should be properly double buffered + return true; + } + + for (unsigned int i = 0; i < m_layerGroups.size(); i++) { + if (!m_layerGroups[i]->isReady()) { + XLOG("layer group %p isn't ready", m_layerGroups[i]); + return false; + } + } + return true; +} + +void SurfaceCollection::computeTexturesAmount(TexturesResult* result) +{ + for (unsigned int i = 0; i < m_layerGroups.size(); i++) + m_layerGroups[i]->computeTexturesAmount(result); +} + +void SurfaceCollection::drawCanvas(SkCanvas* canvas, bool drawLayers) +{ + // TODO: move this functionality out! + if (!m_baseLayer) + return; + + m_baseLayer->drawCanvas(canvas); + + // draw the layers onto the same canvas (for single surface mode) + if (drawLayers && m_compositedRoot) + m_compositedRoot->drawCanvas(canvas, true, Layer::FlattenedLayers); +} + + +//////////////////////////////////////////////////////////////////////////////// +// RECURSIVE ANIMATION / INVALS / LAYERS // +//////////////////////////////////////////////////////////////////////////////// + +void SurfaceCollection::setIsPainting(SurfaceCollection* drawingSurface) +{ + if (!m_baseLayer) + return; + + m_baseLayer->setIsPainting(); + + if (!drawingSurface) + return; + + for (unsigned int i = 0; i < m_layerGroups.size(); i++) { + LayerGroup* newLayerGroup = m_layerGroups[i]; + if (!newLayerGroup->needsTexture()) + continue; + + for (unsigned int j = 0; j < drawingSurface->m_layerGroups.size(); j++) { + LayerGroup* oldLayerGroup = drawingSurface->m_layerGroups[j]; + if (newLayerGroup->tryUpdateLayerGroup(oldLayerGroup)) + break; + } + } +} + +void SurfaceCollection::setIsDrawing() +{ + if (m_compositedRoot) + m_compositedRoot->initAnimations(); +} + +void SurfaceCollection::mergeInvalsInto(SurfaceCollection* replacementSurface) +{ + if (!m_baseLayer) + return; + + m_baseLayer->mergeInvalsInto(replacementSurface->m_baseLayer); + + if (m_compositedRoot && replacementSurface->m_compositedRoot) + m_compositedRoot->mergeInvalsInto(replacementSurface->m_compositedRoot); +} + +void SurfaceCollection::evaluateAnimations(double currentTime) +{ + if (m_compositedRoot) + m_compositedRoot->evaluateAnimations(currentTime); +} + +bool SurfaceCollection::hasCompositedLayers() +{ + return m_compositedRoot != 0; +} + +bool SurfaceCollection::hasCompositedAnimations() +{ + return m_compositedRoot != 0 && m_compositedRoot->hasAnimations(); +} + +int SurfaceCollection::baseContentWidth() +{ + // TODO: move this functionality out! + return m_baseLayer ? m_baseLayer->content()->width() : 0; +} + +int SurfaceCollection::baseContentHeight() +{ + // TODO: move this functionality out! + return m_baseLayer ? m_baseLayer->content()->height() : 0; +} + +void SurfaceCollection::updateScrollableLayer(int layerId, int x, int y) +{ + if (m_compositedRoot) { + LayerAndroid* layer = m_compositedRoot->findById(layerId); + if (layer && layer->contentIsScrollable()) + static_cast<ScrollableLayerAndroid*>(layer)->scrollTo(x, y); + } +} + +} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/SurfaceCollection.h b/Source/WebCore/platform/graphics/android/SurfaceCollection.h new file mode 100644 index 0000000..921929b --- /dev/null +++ b/Source/WebCore/platform/graphics/android/SurfaceCollection.h @@ -0,0 +1,77 @@ +/* + * Copyright 2012, 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 SurfaceCollection_h +#define SurfaceCollection_h + +#include "SkRefCnt.h" +#include "SkRect.h" +#include "Vector.h" + +class SkCanvas; +class SkRegion; + +namespace WebCore { + +class BaseLayerAndroid; +class LayerAndroid; +class LayerGroup; +class TexturesResult; + +class SurfaceCollection : public SkRefCnt { +// TODO: investigate webkit threadsafe ref counting +public: + SurfaceCollection(BaseLayerAndroid* baseLayer); + virtual ~SurfaceCollection(); + + // Tiled painting methods (executed on groups) + void prepareGL(const SkRect& visibleRect, float scale, double currentTime); + bool drawGL(const SkRect& visibleRect, float scale); + void swapTiles(); + bool isReady(); + void computeTexturesAmount(TexturesResult* result); + void drawCanvas(SkCanvas* canvas, bool drawLayers); + + // Recursive tree methods (animations, invals, etc) + void setIsPainting(SurfaceCollection* drawingSurfaceCollection); + void setIsDrawing(); + void mergeInvalsInto(SurfaceCollection* replacementSurfaceCollection); + void evaluateAnimations(double currentTime); + + bool hasCompositedLayers(); + bool hasCompositedAnimations(); + int baseContentWidth(); + int baseContentHeight(); + void updateScrollableLayer(int layerId, int x, int y); + +private: + BaseLayerAndroid* m_baseLayer; + LayerAndroid* m_compositedRoot; + Vector<LayerGroup*> m_layerGroups; +}; + +} // namespace WebCore + +#endif //#define SurfaceCollection_h diff --git a/Source/WebCore/platform/graphics/android/SurfaceCollectionManager.cpp b/Source/WebCore/platform/graphics/android/SurfaceCollectionManager.cpp new file mode 100644 index 0000000..8ffcabd --- /dev/null +++ b/Source/WebCore/platform/graphics/android/SurfaceCollectionManager.cpp @@ -0,0 +1,287 @@ +/* + * Copyright 2011, 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 "SurfaceCollectionManager.h" + +#include "BaseLayerAndroid.h" +#include "LayerGroup.h" +#include "TilesManager.h" +#include "SurfaceCollection.h" + +#include <cutils/log.h> +#include <wtf/CurrentTime.h> +#include <wtf/text/CString.h> + +#undef XLOGC +#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "SurfaceCollectionManager", __VA_ARGS__) + +#ifdef DEBUG + +#undef XLOG +#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "SurfaceCollectionManager", __VA_ARGS__) + +#else + +#undef XLOG +#define XLOG(...) + +#endif // DEBUG + +namespace WebCore { + +SurfaceCollectionManager::SurfaceCollectionManager(GLWebViewState* state) + : m_state(state) + , m_drawingCollection(0) + , m_paintingCollection(0) + , m_queuedCollection(0) + , m_fastSwapMode(false) +{ +} + +SurfaceCollectionManager::~SurfaceCollectionManager() +{ + clearCollections(); +} + +// the painting collection has finished painting: +// discard the drawing collection +// swap the painting collection in place of the drawing collection +// and start painting the queued collection +void SurfaceCollectionManager::swap() +{ + // swap can't be called unless painting just finished + ASSERT(m_paintingCollection); + + android::Mutex::Autolock lock(m_paintSwapLock); + + XLOG("SWAPPING, D %p, P %p, Q %p", + m_drawingCollection, m_paintingCollection, m_queuedCollection); + + // if we have a drawing collection, discard it since the painting collection is done + if (m_drawingCollection) { + XLOG("destroying drawing collection %p", m_drawingCollection); + SkSafeUnref(m_drawingCollection); + } + + // painting collection becomes the drawing collection + XLOG("drawing collection %p", m_paintingCollection); + m_paintingCollection->setIsDrawing(); // initialize animations + + if (m_queuedCollection) { + // start painting with the queued collection + XLOG("now painting collection %p", m_queuedCollection); + m_queuedCollection->setIsPainting(m_paintingCollection); + } + m_drawingCollection = m_paintingCollection; + m_paintingCollection = m_queuedCollection; + m_queuedCollection = 0; + + XLOG("SWAPPING COMPLETE, D %p, P %p, Q %p", + m_drawingCollection, m_paintingCollection, m_queuedCollection); +} + +// clear all of the content in the three collections held by the collection manager +void SurfaceCollectionManager::clearCollections() +{ + XLOG("SurfaceCollectionManager %p removing PS from state %p", this, m_state); + + SkSafeUnref(m_drawingCollection); + m_drawingCollection = 0; + SkSafeUnref(m_paintingCollection); + m_paintingCollection = 0; + SkSafeUnref(m_queuedCollection); + m_queuedCollection = 0; +} + +// a new layer collection has arrived, queue it if we're painting something already, +// or start painting it if we aren't. Returns true if the manager has two collections +// already queued. +bool SurfaceCollectionManager::updateWithSurfaceCollection(SurfaceCollection* newCollection, + bool brandNew) +{ + XLOG("updateWithSurfaceCollection - %p, has children %d, has animations %d", + newCollection, newCollection->hasCompositedLayers(), + newCollection->hasCompositedAnimations); + + // can't have a queued collection unless have a painting collection too + ASSERT(m_paintingCollection || !m_queuedCollection); + + android::Mutex::Autolock lock(m_paintSwapLock); + + if (!newCollection || brandNew) { + clearCollections(); + if (brandNew) { + m_paintingCollection = newCollection; + m_paintingCollection->setIsPainting(m_drawingCollection); + } + return false; + } + + if (m_queuedCollection || m_paintingCollection) { + // currently painting, so defer this new collection + if (m_queuedCollection) { + // already have a queued collection, copy over invals so the regions are + // eventually repainted and let the old queued collection be discarded + m_queuedCollection->mergeInvalsInto(newCollection); + + if (!TilesManager::instance()->useDoubleBuffering()) { + // not double buffering, count discarded collection/webkit paint as an update + TilesManager::instance()->incContentUpdates(); + } + + XLOG("DISCARDING collection - %p, has children %d, has animations %d", + newCollection, newCollection->hasCompositedLayers(), + newCollection->hasCompositedAnimations()); + } + SkSafeUnref(m_queuedCollection); + m_queuedCollection = newCollection; + } else { + // don't have painting collection, paint this one! + m_paintingCollection = newCollection; + m_paintingCollection->setIsPainting(m_drawingCollection); + } + return m_drawingCollection && TilesManager::instance()->useDoubleBuffering(); +} + +void SurfaceCollectionManager::updateScrollableLayer(int layerId, int x, int y) +{ + if (m_queuedCollection) + m_queuedCollection->updateScrollableLayer(layerId, x, y); + if (m_paintingCollection) + m_paintingCollection->updateScrollableLayer(layerId, x, y); + if (m_drawingCollection) + m_drawingCollection->updateScrollableLayer(layerId, x, y); +} + +bool SurfaceCollectionManager::drawGL(double currentTime, IntRect& viewRect, + SkRect& visibleRect, float scale, + bool enterFastSwapMode, + bool* collectionsSwappedPtr, bool* newCollectionHasAnimPtr, + TexturesResult* texturesResultPtr) +{ + m_fastSwapMode |= enterFastSwapMode; + + XLOG("drawGL, D %p, P %p, Q %p, fastSwap %d", + m_drawingCollection, m_paintingCollection, m_queuedCollection, m_fastSwapMode); + + bool ret = false; + bool didCollectionSwap = false; + if (m_paintingCollection) { + XLOG("preparing painting collection %p", m_paintingCollection); + + m_paintingCollection->evaluateAnimations(currentTime); + + m_paintingCollection->prepareGL(visibleRect, scale, currentTime); + m_paintingCollection->computeTexturesAmount(texturesResultPtr); + + if (!TilesManager::instance()->useDoubleBuffering() || m_paintingCollection->isReady()) { + XLOG("have painting collection %p ready, swapping!", m_paintingCollection); + didCollectionSwap = true; + TilesManager::instance()->incContentUpdates(); + if (collectionsSwappedPtr) + *collectionsSwappedPtr = true; + if (newCollectionHasAnimPtr) + *newCollectionHasAnimPtr = m_paintingCollection->hasCompositedAnimations(); + swap(); + } + } else if (m_drawingCollection) { + XLOG("preparing drawing collection %p", m_drawingCollection); + m_drawingCollection->prepareGL(visibleRect, scale, currentTime); + m_drawingCollection->computeTexturesAmount(texturesResultPtr); + } + + if (m_drawingCollection) { + bool drawingReady = didCollectionSwap || m_drawingCollection->isReady(); + + // call the page swap callback if registration happened without more collections enqueued + if (collectionsSwappedPtr && drawingReady && !m_paintingCollection) + *collectionsSwappedPtr = true; + + if (didCollectionSwap || m_fastSwapMode || (drawingReady && !m_paintingCollection)) + m_drawingCollection->swapTiles(); + + if (drawingReady) { + // exit fast swap mode, as content is up to date + m_fastSwapMode = false; + } else { + // drawing isn't ready, must redraw + ret = true; + } + + m_drawingCollection->evaluateAnimations(currentTime); + XLOG("drawing collection %p", m_drawingCollection); + ret |= m_drawingCollection->drawGL(visibleRect, scale); + } else { + // Dont have a drawing collection, draw white background + Color defaultBackground = Color::white; + m_state->drawBackground(defaultBackground); + } + + if (m_paintingCollection) { + XLOG("still have painting collection %p", m_paintingCollection); + return true; + } + + return ret; +} + +// draw for base tile - called on TextureGeneration thread +void SurfaceCollectionManager::drawCanvas(SkCanvas* canvas, bool drawLayers) +{ + SurfaceCollection* paintingCollection = 0; + m_paintSwapLock.lock(); + paintingCollection = m_paintingCollection ? m_paintingCollection : m_drawingCollection; + SkSafeRef(paintingCollection); + m_paintSwapLock.unlock(); + + if (!paintingCollection) + return; + + paintingCollection->drawCanvas(canvas, drawLayers); + + SkSafeUnref(paintingCollection); +} + +// TODO: refactor this functionality elsewhere +int SurfaceCollectionManager::baseContentWidth() +{ + if (m_paintingCollection) + return m_paintingCollection->baseContentWidth(); + else if (m_drawingCollection) + return m_drawingCollection->baseContentWidth(); + return 0; +} + +int SurfaceCollectionManager::baseContentHeight() +{ + if (m_paintingCollection) + return m_paintingCollection->baseContentHeight(); + else if (m_drawingCollection) + return m_drawingCollection->baseContentHeight(); + return 0; +} + +} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/TreeManager.h b/Source/WebCore/platform/graphics/android/SurfaceCollectionManager.h index 83d5300..76e5e9e 100644 --- a/Source/WebCore/platform/graphics/android/TreeManager.h +++ b/Source/WebCore/platform/graphics/android/SurfaceCollectionManager.h @@ -23,61 +23,57 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef TreeManager_h -#define TreeManager_h +#ifndef SurfaceCollectionManager_h +#define SurfaceCollectionManager_h #include "TestExport.h" #include <utils/threads.h> -#include "PerformanceMonitor.h" -class Layer; class SkRect; class SkCanvas; namespace WebCore { +class GLWebViewState; class IntRect; class TexturesResult; +class SurfaceCollection; -class TEST_EXPORT TreeManager { +class TEST_EXPORT SurfaceCollectionManager { public: - TreeManager(); + SurfaceCollectionManager(GLWebViewState* state); - ~TreeManager(); + ~SurfaceCollectionManager(); - void updateWithTree(Layer* tree, bool brandNew); + bool updateWithSurfaceCollection(SurfaceCollection* collection, bool brandNew); void updateScrollableLayer(int layerId, int x, int y); bool drawGL(double currentTime, IntRect& viewRect, SkRect& visibleRect, float scale, - bool enterFastSwapMode, bool* treesSwappedPtr, bool* newTreeHasAnimPtr, + bool enterFastSwapMode, bool* collectionsSwappedPtr, bool* newCollectionHasAnimPtr, TexturesResult* texturesResultPtr); void drawCanvas(SkCanvas* canvas, bool drawLayers); - // used in debugging (to avoid exporting TilesManager symbols) - static int getTotalPaintedSurfaceCount(); - int baseContentWidth(); int baseContentHeight(); private: - static void updateScrollableLayerInTree(Layer* tree, int layerId, int x, int y); - void swap(); - void clearTrees(); + void clearCollections(); android::Mutex m_paintSwapLock; - Layer* m_drawingTree; - Layer* m_paintingTree; - Layer* m_queuedTree; + GLWebViewState* m_state; + + SurfaceCollection* m_drawingCollection; + SurfaceCollection* m_paintingCollection; + SurfaceCollection* m_queuedCollection; bool m_fastSwapMode; - PerformanceMonitor m_perf; }; } // namespace WebCore -#endif //#define TreeManager_h +#endif //#define SurfaceCollectionManager_h diff --git a/Source/WebCore/platform/graphics/android/TextureInfo.cpp b/Source/WebCore/platform/graphics/android/TextureInfo.cpp index aff9a3d..f5c8b02 100644 --- a/Source/WebCore/platform/graphics/android/TextureInfo.cpp +++ b/Source/WebCore/platform/graphics/android/TextureInfo.cpp @@ -35,14 +35,12 @@ namespace WebCore { -TextureInfo::TextureInfo(SharedTextureMode mode) +TextureInfo::TextureInfo() { m_textureId = GL_NO_TEXTURE; m_width = 0; m_height = 0; m_internalFormat = 0; - m_sharedTextureMode = mode; - m_pictureCount = 0; } bool TextureInfo::equalsAttributes(const TextureInfo* otherTexture) diff --git a/Source/WebCore/platform/graphics/android/TextureInfo.h b/Source/WebCore/platform/graphics/android/TextureInfo.h index aca74b7..4684df2 100644 --- a/Source/WebCore/platform/graphics/android/TextureInfo.h +++ b/Source/WebCore/platform/graphics/android/TextureInfo.h @@ -34,8 +34,6 @@ #include "BaseTile.h" using android::sp; -#define DEPRECATED_SURFACE_TEXTURE_MODE 0 - namespace android { class SurfaceTexture; } @@ -47,34 +45,20 @@ static const GLuint GL_NO_TEXTURE = 0; * TextureInfo is a class that stores both the texture and metadata about the * texture. */ -enum SharedTextureMode { - EglImageMode, - SurfaceTextureMode -}; class TextureInfo { public: - - TextureInfo(SharedTextureMode mode); + TextureInfo(); bool equalsAttributes(const TextureInfo* otherTexture); void copyAttributes(const TextureInfo* sourceTexture); - SharedTextureMode getSharedTextureMode() { return m_sharedTextureMode; } bool operator==(const TextureInfo& otherTexture); GLuint m_textureId; int32_t m_width; int32_t m_height; GLenum m_internalFormat; - - // Surface Texture specific data -#if DEPRECATED_SURFACE_TEXTURE_MODE - sp<android::SurfaceTexture> m_surfaceTexture; -#endif - int m_pictureCount; -private: - SharedTextureMode m_sharedTextureMode; }; } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/TexturesGenerator.cpp b/Source/WebCore/platform/graphics/android/TexturesGenerator.cpp index bccb99b..4f7c1f0 100644 --- a/Source/WebCore/platform/graphics/android/TexturesGenerator.cpp +++ b/Source/WebCore/platform/graphics/android/TexturesGenerator.cpp @@ -67,7 +67,7 @@ void TexturesGenerator::removeOperationsForPage(TiledPage* page) void TexturesGenerator::removePaintOperationsForPage(TiledPage* page, bool waitForRunning) { - removeOperationsForFilter(new PagePaintFilter(page), waitForRunning); + removeOperationsForFilter(new PageFilter(page), waitForRunning); } void TexturesGenerator::removeOperationsForFilter(OperationFilter* filter) diff --git a/Source/WebCore/platform/graphics/android/TilePainter.h b/Source/WebCore/platform/graphics/android/TilePainter.h index 4d0f5dc..34e877e 100644 --- a/Source/WebCore/platform/graphics/android/TilePainter.h +++ b/Source/WebCore/platform/graphics/android/TilePainter.h @@ -35,20 +35,20 @@ namespace WebCore { class BaseTile; -class TilePainter { +class TilePainter : public SkRefCnt { +// TODO: investigate webkit threadsafe ref counting public: - virtual ~TilePainter() { } - virtual bool paint(BaseTile* tile, SkCanvas*, unsigned int*) = 0; - virtual const TransformationMatrix* transform() { return 0; } -}; + virtual ~TilePainter() { } + virtual bool paint(BaseTile* tile, SkCanvas* canvas) = 0; + virtual float opacity() { return 1.0; } + enum SurfaceType { Painted, Image }; + virtual SurfaceType type() { return Painted; } -class SurfacePainter : public SkRefCnt { -public: - virtual ~SurfacePainter() { } - virtual const TransformationMatrix* transform() { return 0; } - virtual float opacity() { return 1.0; } - enum SurfaceType { PaintedSurface, ImageSurface }; - virtual SurfaceType type() { return PaintedSurface; } + unsigned int getUpdateCount() { return m_updateCount; } + void setUpdateCount(unsigned int updateCount) { m_updateCount = updateCount; } + +private: + unsigned int m_updateCount; }; } diff --git a/Source/WebCore/platform/graphics/android/TiledPage.cpp b/Source/WebCore/platform/graphics/android/TiledPage.cpp index 31a0593..629b095 100644 --- a/Source/WebCore/platform/graphics/android/TiledPage.cpp +++ b/Source/WebCore/platform/graphics/android/TiledPage.cpp @@ -65,7 +65,6 @@ TiledPage::TiledPage(int id, GLWebViewState* state) , m_scale(1) , m_invScale(1) , m_glWebViewState(state) - , m_latestPictureInval(0) , m_prepare(false) , m_isPrefetchPage(false) , m_willDraw(false) @@ -93,9 +92,13 @@ void TiledPage::updateBaseTileSize() TiledPage::~TiledPage() { + TilesManager* tilesManager = TilesManager::instance(); // In order to delete the page we must ensure that none of its BaseTiles are // currently painting or scheduled to be painted by the TextureGenerator - TilesManager::instance()->removeOperationsForPage(this); + tilesManager->removeOperationsForPage(this); + // Discard the transfer queue after the removal operation to make sure + // no tiles for this page will be left in the transfer queue. + tilesManager->transferQueue()->setPendingDiscardWithLock(); delete[] m_baseTiles; #ifdef DEBUG_COUNT ClassTracker::instance()->decrement("TiledPage"); @@ -122,8 +125,9 @@ void TiledPage::discardTextures() return; } -void TiledPage::invalidateRect(const IntRect& inval, const unsigned int pictureCount) +void TiledPage::invalidateRect(const IntRect& inval) { +#ifdef DEBUG // Given the current scale level we need to mark the appropriate tiles as dirty const float invTileContentWidth = m_scale / TilesManager::tileWidth(); const float invTileContentHeight = m_scale / TilesManager::tileHeight(); @@ -134,11 +138,10 @@ void TiledPage::invalidateRect(const IntRect& inval, const unsigned int pictureC const int lastDirtyTileY = static_cast<int>(ceilf(inval.maxY() * invTileContentHeight)); XLOG("Marking X %d-%d and Y %d-%d dirty", firstDirtyTileX, lastDirtyTileX, firstDirtyTileY, lastDirtyTileY); +#endif // We defer marking the tile as dirty until the next time we need to prepare // to draw. - m_invalRegion.op(firstDirtyTileX, firstDirtyTileY, lastDirtyTileX, lastDirtyTileY, SkRegion::kUnion_Op); - m_invalTilesRegion.op(inval.x(), inval.y(), inval.maxX(), inval.maxY(), SkRegion::kUnion_Op); - m_latestPictureInval = pictureCount; + m_invalRegion.op(inval.x(), inval.y(), inval.maxX(), inval.maxY(), SkRegion::kUnion_Op); } void TiledPage::prepareRow(bool goingLeft, int tilesInRow, int firstTileX, int y, const SkIRect& tileBounds) @@ -201,32 +204,17 @@ void TiledPage::prepareRow(bool goingLeft, int tilesInRow, int firstTileX, int y } } -bool TiledPage::updateTileDirtiness(const SkIRect& tileBounds) +void TiledPage::updateTileDirtiness() { - if (!m_glWebViewState || tileBounds.isEmpty()) { - m_invalRegion.setEmpty(); - m_invalTilesRegion.setEmpty(); - return false; - } - - bool visibleTileIsDirty = false; - for (int x = 0; x < m_baseTileSize; x++) { + if (!m_glWebViewState || m_invalRegion.isEmpty()) + return; - BaseTile& tile = m_baseTiles[x]; - - // if the tile is in the dirty region then we must invalidate it - if (m_invalRegion.contains(tile.x(), tile.y())) { - tile.markAsDirty(m_latestPictureInval, m_invalTilesRegion); - if (tileBounds.contains(tile.x(), tile.y())) - visibleTileIsDirty = true; - } - } + for (int x = 0; x < m_baseTileSize; x++) + m_baseTiles[x].markAsDirty(m_invalRegion); // clear the invalidated region as all tiles within that region have now // been marked as dirty. m_invalRegion.setEmpty(); - m_invalTilesRegion.setEmpty(); - return visibleTileIsDirty; } void TiledPage::prepare(bool goingDown, bool goingLeft, const SkIRect& tileBounds, PrepareBounds bounds) @@ -242,11 +230,6 @@ void TiledPage::prepare(bool goingDown, bool goingLeft, const SkIRect& tileBound int nbTilesWidth = tileBounds.width(); int nbTilesHeight = tileBounds.height(); - // Expand number of tiles to allow tiles outside of viewport to be prepared for - // smoother scrolling. - int nTilesToPrepare = nbTilesWidth * nbTilesHeight; - int nMaxTilesPerPage = m_baseTileSize / 2; - if (bounds == ExpandedBounds) { // prepare tiles outside of the visible bounds int expandX = m_glWebViewState->expandedTileBoundsX(); @@ -276,8 +259,8 @@ void TiledPage::prepare(bool goingDown, bool goingLeft, const SkIRect& tileBound nbTilesHeight += firstTileY; firstTileY = 0; } - nbTilesWidth = std::min(nbTilesWidth, maxX - firstTileX); - nbTilesHeight = std::min(nbTilesHeight, maxY - firstTileY); + nbTilesWidth = std::min(nbTilesWidth, maxX - firstTileX + 1); + nbTilesHeight = std::min(nbTilesHeight, maxY - firstTileY + 1); // check against corrupted scale values giving bad height/width (use float to avoid overflow) float numTiles = static_cast<float>(nbTilesHeight) * static_cast<float>(nbTilesWidth); @@ -349,20 +332,20 @@ bool TiledPage::swapBuffersIfReady(const SkIRect& tileBounds, float scale) swaps++; } - XLOG("%p greedy swapped %d textures, returning true", this, swaps); + XLOG("%p greedy swapped %d textures, returning %d", this, swaps, fullSwap); return fullSwap; } -void TiledPage::prepareForDrawGL(float transparency, const SkIRect& tileBounds) +void TiledPage::prepareForDrawGL(float opacity, const SkIRect& tileBounds) { m_willDraw = true; - m_transparency = transparency; + m_opacity = opacity; m_tileBounds = tileBounds; } void TiledPage::drawGL() { - if (!m_glWebViewState || m_transparency == 0 || !m_willDraw) + if (!m_glWebViewState || m_opacity == 0 || !m_willDraw) return; const float tileWidth = TilesManager::tileWidth() * m_invScale; @@ -378,7 +361,7 @@ void TiledPage::drawGL() rect.fRight = rect.fLeft + tileWidth; rect.fBottom = rect.fTop + tileHeight; - tile.draw(m_transparency, rect, m_scale); + tile.drawGL(m_opacity, rect, m_scale, 0); } TilesManager::instance()->getProfiler()->nextTile(tile, m_invScale, tileInView); @@ -386,7 +369,7 @@ void TiledPage::drawGL() m_willDraw = false; // don't redraw until re-prepared } -bool TiledPage::paint(BaseTile* tile, SkCanvas* canvas, unsigned int* pictureUsed) +bool TiledPage::paint(BaseTile* tile, SkCanvas* canvas) { static SkPaintFlagsDrawFilter prefetchFilter(SkPaint::kAllFlags, SkPaint::kAntiAlias_Flag); @@ -397,7 +380,7 @@ bool TiledPage::paint(BaseTile* tile, SkCanvas* canvas, unsigned int* pictureUse if (isPrefetchPage()) canvas->setDrawFilter(&prefetchFilter); - *pictureUsed = m_glWebViewState->paintBaseLayerContent(canvas); + m_glWebViewState->paintBaseLayerContent(canvas); return true; } diff --git a/Source/WebCore/platform/graphics/android/TiledPage.h b/Source/WebCore/platform/graphics/android/TiledPage.h index 791e1f6..5587618 100644 --- a/Source/WebCore/platform/graphics/android/TiledPage.h +++ b/Source/WebCore/platform/graphics/android/TiledPage.h @@ -65,9 +65,8 @@ public: // prepare the page for display on the screen void prepare(bool goingDown, bool goingLeft, const SkIRect& tileBounds, PrepareBounds bounds); - // update tiles with inval information, return true if visible ones are - // dirty (and thus repaint needed) - bool updateTileDirtiness(const SkIRect& tileBounds); + // update tiles with inval information + void updateTileDirtiness(); // returns true if the page can't draw the entire region (may still be stale) bool hasMissingContent(const SkIRect& tileBounds); @@ -76,14 +75,14 @@ public: // swap 'buffers' by swapping each modified texture bool swapBuffersIfReady(const SkIRect& tileBounds, float scale); - // save the transparency and bounds to be drawn in drawGL() - void prepareForDrawGL(float transparency, const SkIRect& tileBounds); + // save the opacity and bounds to be drawn in drawGL() + void prepareForDrawGL(float opacity, const SkIRect& tileBounds); // draw the page on the screen void drawGL(); // TilePainter implementation // used by individual tiles to generate the bitmap for their tile - bool paint(BaseTile*, SkCanvas*, unsigned int*); + bool paint(BaseTile* tile, SkCanvas* canvas); // used by individual tiles to get the information about the current picture GLWebViewState* glWebViewState() { return m_glWebViewState; } @@ -93,7 +92,7 @@ public: //TODO: clear all textures if this is called with a new value void setScale(float scale) { m_scale = scale; m_invScale = 1 / scale; } - void invalidateRect(const IntRect& invalRect, const unsigned int pictureCount); + void invalidateRect(const IntRect& invalRect); void discardTextures(); void updateBaseTileSize(); bool scrollingDown() { return m_scrollingDown; } @@ -116,15 +115,8 @@ private: float m_invScale; GLWebViewState* m_glWebViewState; - // used to identify the tiles that have been invalidated (marked dirty) since - // the last time updateTileState() has been called. The region is stored in - // terms of the (x,y) coordinates used to determine the location of the tile - // within the page, not in content/view pixel coordinates. - SkRegion m_invalRegion; - // inval regions in content coordinates - SkRegion m_invalTilesRegion; - unsigned int m_latestPictureInval; + SkRegion m_invalRegion; // in content coordinates bool m_prepare; bool m_scrollingDown; bool m_isPrefetchPage; @@ -132,7 +124,7 @@ private: // info saved in prepare, used in drawGL() bool m_willDraw; SkIRect m_tileBounds; - float m_transparency; + float m_opacity; }; } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/TiledTexture.cpp b/Source/WebCore/platform/graphics/android/TiledTexture.cpp index d538416..57d7683 100644 --- a/Source/WebCore/platform/graphics/android/TiledTexture.cpp +++ b/Source/WebCore/platform/graphics/android/TiledTexture.cpp @@ -29,7 +29,6 @@ #include "TilesManager.h" #include "TilesTracker.h" -#include "PaintedSurface.h" #include "PaintTileOperation.h" #include "SkCanvas.h" #include "SkPicture.h" @@ -57,14 +56,13 @@ namespace WebCore { TiledTexture::~TiledTexture() { - SkSafeUnref(m_paintingPicture); #ifdef DEBUG_COUNT ClassTracker::instance()->decrement("TiledTexture"); #endif removeTiles(); } -bool TiledTexture::ready() +bool TiledTexture::isReady() { bool tilesAllReady = true; bool tilesVisible = false; @@ -99,13 +97,13 @@ void TiledTexture::swapTiles() XLOG("TT %p swapping, swaps = %d", this, swaps); } -IntRect TiledTexture::computeTilesArea(IntRect& visibleArea, float scale) +IntRect TiledTexture::computeTilesArea(const IntRect& contentArea, float scale) { IntRect computedArea; - IntRect area(visibleArea.x() * scale, - visibleArea.y() * scale, - ceilf(visibleArea.width() * scale), - ceilf(visibleArea.height() * scale)); + IntRect area(contentArea.x() * scale, + contentArea.y() * scale, + ceilf(contentArea.width() * scale), + ceilf(contentArea.height() * scale)); XLOG("TT %p prepare, scale %f, area %d x %d", this, scale, area.width(), area.height()); @@ -127,22 +125,19 @@ IntRect TiledTexture::computeTilesArea(IntRect& visibleArea, float scale) return computedArea; } -void TiledTexture::prepare(GLWebViewState* state, float scale, bool repaint, - bool startFastSwap, IntRect& visibleArea) +void TiledTexture::prepareGL(GLWebViewState* state, float scale, + const IntRect& prepareArea, TilePainter* painter) { - if (!m_surface) - return; - // first, how many tiles do we need - m_area = computeTilesArea(visibleArea, scale); + m_area = computeTilesArea(prepareArea, scale); if (m_area.isEmpty()) return; - XLOG("for TiledTexture %p, we prepare with scale %.2f, have a visible area of " + XLOG("prepare TiledTexture %p with scale %.2f, prepareArea " " %d, %d - %d x %d, corresponding to %d, %d x - %d x %d tiles", this, scale, - visibleArea.x(), visibleArea.y(), - visibleArea.width(), visibleArea.height(), + prepareArea.x(), prepareArea.y(), + prepareArea.width(), prepareArea.height(), m_area.x(), m_area.y(), m_area.width(), m_area.height()); @@ -150,45 +145,36 @@ void TiledTexture::prepare(GLWebViewState* state, float scale, bool repaint, m_prevTileY = m_area.y(); if (scale != m_scale) - TilesManager::instance()->removeOperationsForFilter(new ScaleFilter(this, scale)); + TilesManager::instance()->removeOperationsForFilter(new ScaleFilter(painter, scale)); m_scale = scale; // apply dirty region to affected tiles if (!m_dirtyRegion.isEmpty()) { - for (unsigned int i = 0; i < m_tiles.size(); i++) { - // TODO: don't mark all tiles dirty - m_tiles[i]->markAsDirty(1, m_dirtyRegion); - } + for (unsigned int i = 0; i < m_tiles.size(); i++) + m_tiles[i]->markAsDirty(m_dirtyRegion); + m_dirtyRegion.setEmpty(); } - m_dirtyRegion.setEmpty(); for (int i = 0; i < m_area.width(); i++) { if (goingDown) { - for (int j = 0; j < m_area.height(); j++) { - prepareTile(repaint, m_area.x() + i, m_area.y() + j); - } + for (int j = 0; j < m_area.height(); j++) + prepareTile(m_area.x() + i, m_area.y() + j, painter); } else { - for (int j = m_area.height() - 1; j >= 0; j--) { - prepareTile(repaint, m_area.x() + i, m_area.y() + j); - } + for (int j = m_area.height() - 1; j >= 0; j--) + prepareTile(m_area.x() + i, m_area.y() + j, painter); } } } -void TiledTexture::update(const SkRegion& invalRegion, SkPicture* picture) +void TiledTexture::markAsDirty(const SkRegion& invalRegion) { - XLOG("TT %p update, current region empty %d, new empty %d, painting picture %p", - this, m_dirtyRegion.isEmpty(), invalRegion.isEmpty(), picture); + XLOG("TT %p markAsDirty, current region empty %d, new empty %d", + this, m_dirtyRegion.isEmpty(), invalRegion.isEmpty()); m_dirtyRegion.op(invalRegion, SkRegion::kUnion_Op); - - android::Mutex::Autolock lock(m_paintingPictureSync); - SkSafeRef(picture); - SkSafeUnref(m_paintingPicture); - m_paintingPicture = picture; } -void TiledTexture::prepareTile(bool repaint, int x, int y) +void TiledTexture::prepareTile(int x, int y, TilePainter* painter) { BaseTile* tile = getTile(x, y); if (!tile) { @@ -196,18 +182,18 @@ void TiledTexture::prepareTile(bool repaint, int x, int y) m_tiles.append(tile); } - XLOG("preparing tile %p at %d, %d, painter is this %p", tile, x, y, this); - tile->setContents(this, x, y, m_scale); + XLOG("preparing tile %p at %d, %d, painter is %p", tile, x, y, painter); + tile->setContents(painter, x, y, m_scale); // TODO: move below (which is largely the same for layers / tiled page) into - // prepare() function + // prepareGL() function if (tile->isDirty() || !tile->frontTexture()) tile->reserveTexture(); - bool hasPicture = m_paintingPicture != 0; // safely read on UI thread, since only UI thread writes - if (tile->backTexture() && tile->isDirty() && !tile->isRepaintPending() && hasPicture) { - PaintTileOperation *operation = new PaintTileOperation(tile, m_surface); + if (tile->backTexture() && tile->isDirty() && !tile->isRepaintPending()) { + XLOG("painting TT %p's tile %d %d for LG %p", this, x, y, painter); + PaintTileOperation *operation = new PaintTileOperation(tile, painter); TilesManager::instance()->scheduleOperation(operation); } } @@ -239,17 +225,14 @@ int TiledTexture::nbTextures(IntRect& area, float scale) return numberTextures; } -bool TiledTexture::draw() +bool TiledTexture::drawGL(const IntRect& visibleArea, float opacity, + const TransformationMatrix* transform) { - if (!m_surface) - return true; - - XLOG("TT %p draw", this); - #ifdef DEBUG TilesManager::instance()->getTilesTracker()->trackLayer(); #endif + m_area = computeTilesArea(visibleArea, m_scale); if (m_area.width() == 0 || m_area.height() == 0) return false; @@ -261,6 +244,7 @@ bool TiledTexture::draw() const float tileWidth = TilesManager::layerTileWidth() * m_invScale; const float tileHeight = TilesManager::layerTileHeight() * m_invScale; + int drawn = 0; bool askRedraw = false; for (unsigned int i = 0; i < m_tiles.size(); i++) { BaseTile* tile = m_tiles[i]; @@ -272,48 +256,25 @@ bool TiledTexture::draw() rect.fTop = tile->y() * tileHeight; rect.fRight = rect.fLeft + tileWidth; rect.fBottom = rect.fTop + tileHeight; - XLOG("- [%d], { painter %x vs %x }, tile %x (layer tile: %d) %d,%d at scale %.2f vs %.2f [ready: %d] dirty: %d", - i, this, tile->painter(), tile, tile->isLayerTile(), tile->x(), tile->y(), + XLOG("tile %p (layer tile: %d) %d,%d at scale %.2f vs %.2f [ready: %d] dirty: %d", + tile, tile->isLayerTile(), tile->x(), tile->y(), tile->scale(), m_scale, tile->isTileReady(), tile->isDirty()); - tile->draw(m_surface->opacity(), rect, m_scale); + tile->drawGL(opacity, rect, m_scale, transform); + if (tile->frontTexture()) + drawn++; #ifdef DEBUG - TilesManager::instance()->getTilesTracker()->track(tile->isTileReady(), tile->backTexture()); + TilesManager::instance()->getTilesTracker()->track( + tile->isTileReady(), tile->backTexture()); #endif } } + XLOG("TT %p drew %d tiles, redraw due to notready %d, scale %f", + this, drawn, askRedraw, m_scale); // need to redraw if some visible tile wasn't ready return askRedraw; } -bool TiledTexture::paint(BaseTile* tile, SkCanvas* canvas, unsigned int* pictureUsed) -{ - m_paintingPictureSync.lock(); - SkPicture* picture = m_paintingPicture; - SkSafeRef(picture); - m_paintingPictureSync.unlock(); - - if (!picture) { - XLOG("TT %p COULDNT PAINT, NO PICTURE", this); - return false; - } - - XLOG("TT %p painting tile %d, %d with picture %p", this, tile->x(), tile->y(), picture); - - canvas->drawPicture(*picture); - - SkSafeUnref(picture); - - return true; -} - -const TransformationMatrix* TiledTexture::transform() -{ - if (!m_surface) - return 0; - return m_surface->transform(); -} - void TiledTexture::removeTiles() { for (unsigned int i = 0; i < m_tiles.size(); i++) { @@ -324,6 +285,7 @@ void TiledTexture::removeTiles() void TiledTexture::discardTextures() { + XLOG("TT %p discarding textures", this); for (unsigned int i = 0; i < m_tiles.size(); i++) m_tiles[i]->discardTextures(); } @@ -340,10 +302,10 @@ bool TiledTexture::owns(BaseTileTexture* texture) return false; } -DualTiledTexture::DualTiledTexture(SurfacePainter* surface) +DualTiledTexture::DualTiledTexture() { - m_textureA = new TiledTexture(surface); - m_textureB = new TiledTexture(surface); + m_textureA = new TiledTexture(); + m_textureB = new TiledTexture(); m_frontTexture = m_textureA; m_backTexture = m_textureB; m_scale = -1; @@ -357,13 +319,22 @@ DualTiledTexture::~DualTiledTexture() delete m_textureB; } -void DualTiledTexture::prepare(GLWebViewState* state, float scale, bool repaint, - bool startFastSwap, IntRect& visibleArea) +void DualTiledTexture::prepareGL(GLWebViewState* state, bool allowZoom, + const IntRect& prepareArea, TilePainter* painter) { // If we are zooming, we will use the previously used area, to prevent the // frontTexture to try to allocate more tiles than what it has already if (!m_zooming) - m_preZoomVisibleArea = visibleArea; + m_preZoomPrepareArea = prepareArea; + + float scale = state->scale(); + if (scale > 1 && !allowZoom) + scale = 1; + + if (m_scale == -1) { + m_scale = scale; + m_futureScale = scale; + } if (m_futureScale != scale) { m_futureScale = scale; @@ -371,16 +342,17 @@ void DualTiledTexture::prepare(GLWebViewState* state, float scale, bool repaint, m_zooming = true; } - XLOG("Preparing DTT %p with scale %.2f, m_scale %.2f, futureScale: %.2f, zooming: %d", - this, scale, m_scale, m_futureScale, m_zooming); + XLOG("Prepare DTT %p with scale %.2f, m_scale %.2f, futureScale: %.2f, zooming: %d, f %p, b %p", + this, scale, m_scale, m_futureScale, m_zooming, + m_frontTexture, m_backTexture); if (m_scale > 0) - m_frontTexture->prepare(state, m_scale, repaint, startFastSwap, m_preZoomVisibleArea); + m_frontTexture->prepareGL(state, m_scale, m_preZoomPrepareArea, painter); // If we had a scheduled update if (m_zooming && m_zoomUpdateTime < WTF::currentTime()) { - m_backTexture->prepare(state, m_futureScale, repaint, startFastSwap, visibleArea); - if (m_backTexture->ready()) { + m_backTexture->prepareGL(state, m_futureScale, prepareArea, painter); + if (m_backTexture->isReady()) { m_backTexture->swapTiles(); swap(); m_zooming = false; @@ -396,18 +368,19 @@ void DualTiledTexture::swap() m_backTexture->discardTextures(); } -bool DualTiledTexture::draw() +bool DualTiledTexture::drawGL(const IntRect& visibleArea, float opacity, + const TransformationMatrix* transform) { - bool needsRepaint = m_frontTexture->draw(); + bool needsRepaint = m_frontTexture->drawGL(visibleArea, opacity, transform); needsRepaint |= m_zooming; needsRepaint |= (m_scale <= 0); return needsRepaint; } -void DualTiledTexture::update(const SkRegion& dirtyArea, SkPicture* picture) +void DualTiledTexture::markAsDirty(const SkRegion& dirtyArea) { - m_backTexture->update(dirtyArea, picture); - m_frontTexture->update(dirtyArea, picture); + m_backTexture->markAsDirty(dirtyArea); + m_frontTexture->markAsDirty(dirtyArea); } void DualTiledTexture::swapTiles() @@ -423,4 +396,39 @@ bool DualTiledTexture::owns(BaseTileTexture* texture) return owns; } +void DualTiledTexture::computeTexturesAmount(TexturesResult* result, LayerAndroid* layer) +{ + // TODO: shouldn't use layer, as this DTT may paint multiple layers + if (!layer) + return; + + IntRect unclippedArea = layer->unclippedArea(); + IntRect clippedVisibleArea = layer->visibleArea(); + + // get two numbers here: + // - textures needed for a clipped area + // - textures needed for an un-clipped area + TiledTexture* tiledTexture = m_zooming ? m_backTexture : m_frontTexture; + int nbTexturesUnclipped = tiledTexture->nbTextures(unclippedArea, m_scale); + int nbTexturesClipped = tiledTexture->nbTextures(clippedVisibleArea, m_scale); + + // Set kFixedLayers level + if (layer->isFixed()) + result->fixed += nbTexturesClipped; + + // Set kScrollableAndFixedLayers level + if (layer->contentIsScrollable() + || layer->isFixed()) + result->scrollable += nbTexturesClipped; + + // Set kClippedTextures level + result->clipped += nbTexturesClipped; + + // Set kAllTextures level + if (layer->contentIsScrollable()) + result->full += nbTexturesClipped; + else + result->full += nbTexturesUnclipped; +} + } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/TiledTexture.h b/Source/WebCore/platform/graphics/android/TiledTexture.h index 444ab14..cf7c77c 100644 --- a/Source/WebCore/platform/graphics/android/TiledTexture.h +++ b/Source/WebCore/platform/graphics/android/TiledTexture.h @@ -31,6 +31,7 @@ #include "ClassTracker.h" #include "IntRect.h" #include "LayerAndroid.h" +#include "SkRefCnt.h" #include "SkRegion.h" #include "TextureOwner.h" #include "TilePainter.h" @@ -39,12 +40,10 @@ class SkCanvas; namespace WebCore { -class TiledTexture : public TilePainter { +class TiledTexture { public: - TiledTexture(SurfacePainter* surface) - : m_paintingPicture(0) - , m_surface(surface) - , m_prevTileX(0) + TiledTexture() + : m_prevTileX(0) , m_prevTileY(0) , m_scale(1) , m_swapWhateverIsReady(false) @@ -57,15 +56,15 @@ public: virtual ~TiledTexture(); - IntRect computeTilesArea(IntRect& visibleArea, float scale); + IntRect computeTilesArea(const IntRect& contentArea, float scale); - void prepare(GLWebViewState* state, float scale, bool repaint, - bool startFastSwap, IntRect& visibleArea); + void prepareGL(GLWebViewState* state, float scale, + const IntRect& prepareArea, TilePainter* painter); void swapTiles(); - bool draw(); + bool drawGL(const IntRect& visibleArea, float opacity, const TransformationMatrix* transform); - void prepareTile(bool repaint, int x, int y); - void update(const SkRegion& dirtyArea, SkPicture* picture); + void prepareTile(int x, int y, TilePainter* painter); + void markAsDirty(const SkRegion& dirtyArea); BaseTile* getTile(int x, int y); @@ -73,28 +72,17 @@ public: void discardTextures(); bool owns(BaseTileTexture* texture); - // TilePainter methods - bool paint(BaseTile* tile, SkCanvas*, unsigned int*); - virtual const TransformationMatrix* transform(); - float scale() { return m_scale; } - bool ready(); + bool isReady(); int nbTextures(IntRect& area, float scale); private: bool tileIsVisible(BaseTile* tile); - // protect m_paintingPicture - // update() on UI thread modifies - // paint() on texture gen thread reads - android::Mutex m_paintingPictureSync; - SkPicture* m_paintingPicture; - - SurfacePainter* m_surface; Vector<BaseTile*> m_tiles; - // tile coordinates in viewport, set in prepare() + // tile coordinates in viewport, set in prepareGL() IntRect m_area; SkRegion m_dirtyRegion; @@ -106,20 +94,27 @@ private: bool m_swapWhateverIsReady; }; -class DualTiledTexture { +class DualTiledTexture : public SkRefCnt { +// TODO: investigate webkit threadsafe ref counting public: - DualTiledTexture(SurfacePainter* surface); + DualTiledTexture(); ~DualTiledTexture(); - void prepare(GLWebViewState* state, float scale, bool repaint, - bool startFastSwap, IntRect& area); + void prepareGL(GLWebViewState* state, bool allowZoom, + const IntRect& prepareArea, TilePainter* painter); void swapTiles(); void swap(); - bool draw(); - void update(const SkRegion& dirtyArea, SkPicture* picture); + bool drawGL(const IntRect& visibleArea, float opacity, const TransformationMatrix* transform); + void markAsDirty(const SkRegion& dirtyArea); bool owns(BaseTileTexture* texture); + void computeTexturesAmount(TexturesResult* result, LayerAndroid* layer); + void discardTextures() + { + m_textureA->discardTextures(); + m_textureB->discardTextures(); + } bool isReady() { - return !m_zooming && m_frontTexture->ready(); + return !m_zooming && m_frontTexture->isReady(); } int nbTextures(IntRect& area, float scale) @@ -142,7 +137,7 @@ private: float m_futureScale; double m_zoomUpdateTime; bool m_zooming; - IntRect m_preZoomVisibleArea; + IntRect m_preZoomPrepareArea; }; } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/TilesManager.cpp b/Source/WebCore/platform/graphics/android/TilesManager.cpp index 62324d7..5e9bf58 100644 --- a/Source/WebCore/platform/graphics/android/TilesManager.cpp +++ b/Source/WebCore/platform/graphics/android/TilesManager.cpp @@ -29,7 +29,6 @@ #if USE(ACCELERATED_COMPOSITING) #include "BaseTile.h" -#include "PaintedSurface.h" #include "SkCanvas.h" #include "SkDevice.h" #include "SkPaint.h" @@ -96,6 +95,7 @@ int TilesManager::getMaxTextureAllocation() TilesManager::TilesManager() : m_layerTexturesRemain(true) + , m_highEndGfx(false) , m_maxTextureCount(0) , m_maxLayerTextureCount(0) , m_generatorReady(false) @@ -103,6 +103,10 @@ TilesManager::TilesManager() , m_invertedScreen(false) , m_invertedScreenSwitch(false) , m_useMinimalMemory(true) + , m_useDoubleBuffering(true) + , m_contentUpdates(0) + , m_webkitContentUpdates(0) + , m_queue(0) , m_drawGLCount(1) , m_lastTimeLayersUsed(0) , m_hasLayerTextures(false) @@ -155,7 +159,7 @@ void TilesManager::allocateTiles() m_tilesTextures.size() * LAYER_TILE_WIDTH * LAYER_TILE_HEIGHT * 4 / 1024 / 1024); } -void TilesManager::deallocateTextures(bool allTextures) +void TilesManager::discardTextures(bool allTextures, bool glTextures) { const unsigned int max = m_textures.size(); @@ -169,24 +173,52 @@ void TilesManager::deallocateTextures(bool allTextures) sparedDrawCount = std::max(sparedDrawCount, owner->drawCount()); } } - deallocateTexturesVector(sparedDrawCount, m_textures); - deallocateTexturesVector(sparedDrawCount, m_tilesTextures); + discardTexturesVector(sparedDrawCount, m_textures, glTextures); + discardTexturesVector(sparedDrawCount, m_tilesTextures, glTextures); } -void TilesManager::deallocateTexturesVector(unsigned long long sparedDrawCount, - WTF::Vector<BaseTileTexture*>& textures) +void TilesManager::discardTexturesVector(unsigned long long sparedDrawCount, + WTF::Vector<BaseTileTexture*>& textures, + bool deallocateGLTextures) { const unsigned int max = textures.size(); int dealloc = 0; + WTF::Vector<int> discardedIndex; for (unsigned int i = 0; i < max; i++) { TextureOwner* owner = textures[i]->owner(); if (!owner || owner->drawCount() < sparedDrawCount) { - textures[i]->discardGLTexture(); + if (deallocateGLTextures) { + // deallocate textures' gl memory + textures[i]->discardGLTexture(); + discardedIndex.append(i); + } else if (owner) { + // simply detach textures from owner + static_cast<BaseTile*>(owner)->discardTextures(); + } dealloc++; } } - XLOG("Deallocated %d gl textures (out of %d base tiles and %d layer tiles)", - dealloc, max, maxLayer); + + bool base = textures == m_textures; + // Clean up the vector of BaseTileTextures and reset the max texture count. + if (discardedIndex.size()) { + android::Mutex::Autolock lock(m_texturesLock); + for (int i = discardedIndex.size() - 1; i >= 0; i--) + textures.remove(discardedIndex[i]); + + int remainedTextureNumber = textures.size(); + int* countPtr = base ? &m_maxTextureCount : &m_maxLayerTextureCount; + if (remainedTextureNumber < *countPtr) { + XLOG("reset maxTextureCount for %s tiles from %d to %d", + base ? "base" : "layer", *countPtr, remainedTextureNumber); + *countPtr = remainedTextureNumber; + } + + } + + XLOG("Discarded %d %s textures (out of %d %s tiles)", + dealloc, (deallocateGLTextures ? "gl" : ""), + max, base ? "base" : "layer"); } void TilesManager::gatherTexturesNumbers(int* nbTextures, int* nbAllocatedTextures, @@ -221,19 +253,14 @@ void TilesManager::printTextures() x = o->x(); y = o->y(); } - XLOG("[%d] texture %x busy: %d owner: %x (%d, %d) page: %x scale: %.2f", + XLOG("[%d] texture %x owner: %x (%d, %d) page: %x scale: %.2f", i, texture, - texture->busy(), o, x, y, o ? o->page() : 0, o ? o->scale() : 0); + o, x, y, o ? o->page() : 0, o ? o->scale() : 0); } XLOG("------"); #endif // DEBUG } -void TilesManager::addPaintedSurface(PaintedSurface* surface) -{ - m_paintedSurfaces.append(surface); -} - void TilesManager::gatherTextures() { android::Mutex::Autolock lock(m_texturesLock); @@ -274,9 +301,7 @@ BaseTileTexture* TilesManager::getAvailableTexture(BaseTile* owner) // busy anyway // 2. If a tile isn't owned, break with that one // 3. Don't let tiles acquire their front textures - // 4. If we find a tile in the same page with a different scale, - // it's old and not visible. Break with that one - // 5. Otherwise, use the least recently prepared tile, but ignoring tiles + // 4. Otherwise, use the least recently prepared tile, but ignoring tiles // drawn in the last frame to avoid flickering BaseTileTexture* farthestTexture = 0; @@ -285,12 +310,6 @@ BaseTileTexture* TilesManager::getAvailableTexture(BaseTile* owner) for (unsigned int i = 0; i < max; i++) { BaseTileTexture* texture = (*availableTexturePool)[i]; BaseTile* currentOwner = static_cast<BaseTile*>(texture->owner()); - - if (texture->busy()) { - // don't bother, since the acquire() will likely fail - continue; - } - if (!currentOwner) { // unused texture! take it! farthestTexture = texture; @@ -303,14 +322,6 @@ BaseTileTexture* TilesManager::getAvailableTexture(BaseTile* owner) continue; } - if (currentOwner->painter() == owner->painter() && texture->scale() != owner->scale()) { - // if we render the back page with one scale, then another while - // still zooming, we recycle the tiles with the old scale instead of - // taking ones from the front page - farthestTexture = texture; - break; - } - unsigned long long textureDrawCount = currentOwner->drawCount(); if (oldestDrawCount > textureDrawCount) { farthestTexture = texture; @@ -352,6 +363,16 @@ BaseTileTexture* TilesManager::getAvailableTexture(BaseTile* owner) return 0; } +void TilesManager::setHighEndGfx(bool highEnd) +{ + m_highEndGfx = highEnd; +} + +bool TilesManager::highEndGfx() +{ + return m_highEndGfx; +} + int TilesManager::maxTextureCount() { android::Mutex::Autolock lock(m_texturesLock); @@ -390,7 +411,8 @@ void TilesManager::setMaxLayerTextureCount(int max) double secondsSinceLayersUsed = WTF::currentTime() - m_lastTimeLayersUsed; if (secondsSinceLayersUsed > LAYER_TEXTURES_DESTROY_TIMEOUT) { unsigned long long sparedDrawCount = ~0; // by default, spare no textures - deallocateTexturesVector(sparedDrawCount, m_tilesTextures); + bool deleteGLTextures = true; + discardTexturesVector(sparedDrawCount, m_tilesTextures, deleteGLTextures); m_hasLayerTextures = false; } return; @@ -411,6 +433,14 @@ void TilesManager::setMaxLayerTextureCount(int max) m_hasLayerTextures = true; } +TransferQueue* TilesManager::transferQueue() +{ + // To minimize the memory usage, transfer queue can be set to minimal size + // if required. + if (!m_queue) + m_queue = new TransferQueue(m_useMinimalMemory); + return m_queue; +} float TilesManager::tileWidth() { @@ -432,57 +462,6 @@ float TilesManager::layerTileHeight() return LAYER_TILE_HEIGHT; } -void TilesManager::paintedSurfacesCleanup(GLWebViewState* state) -{ - // PaintedSurfaces are created by LayerAndroid with a refcount of 1, - // and just transferred to new (corresponding) layers when a new layer tree - // is received. - // PaintedSurface also keep a reference on the Layer it currently has, so - // when we unref the tree of layer, those layers with a PaintedSurface will - // still be around if we do nothing. - // Here, if the surface does not have any associated layer, it means that we - // received a new layer tree without a corresponding layer (i.e. a layer - // using a texture has been removed by webkit). - // In that case, we remove the PaintedSurface from our list, and unref it. - // If the surface does have a layer, but the GLWebViewState associated to - // that layer is different from the one passed in parameter, it means we can - // also remove the surface (and we also remove/unref any layer that surface - // has). We do this when we deallocate GLWebViewState (i.e. the webview has - // been destroyed) and also when we switch to a page without - // composited layers. - - WTF::Vector<PaintedSurface*> collect; - for (unsigned int i = 0; i < m_paintedSurfaces.size(); i++) { - PaintedSurface* surface = m_paintedSurfaces[i]; - - Layer* drawing = surface->drawingLayer(); - Layer* painting = surface->paintingLayer(); - - XLOG("considering PS %p, drawing %p, painting %p", surface, drawing, painting); - - bool drawingMatchesState = state && drawing && (drawing->state() == state); - bool paintingMatchesState = state && painting && (painting->state() == state); - - if ((!painting && !drawing) || drawingMatchesState || paintingMatchesState) { - XLOG("trying to remove PS %p, painting %p, drawing %p, DMS %d, PMS %d", - surface, painting, drawing, drawingMatchesState, paintingMatchesState); - collect.append(surface); - } - } - for (unsigned int i = 0; i < collect.size(); i++) { - PaintedSurface* surface = collect[i]; - m_paintedSurfaces.remove(m_paintedSurfaces.find(surface)); - SkSafeUnref(surface); - } -} - -void TilesManager::unregisterGLWebViewState(GLWebViewState* state) -{ - // Discard the whole queue b/c we lost GL context already. - // Note the real updateTexImage will still wait for the next draw. - transferQueue()->discardQueue(); -} - TilesManager* TilesManager::instance() { if (!gInstance) { diff --git a/Source/WebCore/platform/graphics/android/TilesManager.h b/Source/WebCore/platform/graphics/android/TilesManager.h index 9782fbb..a0ed9e7 100644 --- a/Source/WebCore/platform/graphics/android/TilesManager.h +++ b/Source/WebCore/platform/graphics/android/TilesManager.h @@ -45,8 +45,6 @@ namespace WebCore { -class PaintedSurface; - class TilesManager { public: static TilesManager* instance(); @@ -78,11 +76,8 @@ public: m_pixmapsGenerationThread->scheduleOperation(operation); } - void swapLayersTextures(LayerAndroid* newTree, LayerAndroid* oldTree); - void addPaintedSurface(PaintedSurface* surface); - ShaderProgram* shader() { return &m_shader; } - TransferQueue* transferQueue() { return &m_queue; } + TransferQueue* transferQueue(); VideoLayerManager* videoLayerManager() { return &m_videoLayerManager; } void gatherLayerTextures(); @@ -106,6 +101,10 @@ public: void resetTextureUsage(TiledPage* page); + // m_highEndGfx is written/read only on UI thread, no need for a lock. + void setHighEndGfx(bool highEnd); + bool highEndGfx(); + int maxTextureCount(); int maxLayerTextureCount(); void setMaxTextureCount(int max); @@ -114,13 +113,11 @@ public: static float tileHeight(); static float layerTileWidth(); static float layerTileHeight(); - void paintedSurfacesCleanup(GLWebViewState* state = 0); - void unregisterGLWebViewState(GLWebViewState* state); void allocateTiles(); - // Called when webview is hidden to discard graphics memory - void deallocateTextures(bool allTextures); + // remove all tiles from textures (and optionally deallocate gl memory) + void discardTextures(bool allTextures, bool glTextures); bool getShowVisualIndicator() { @@ -132,11 +129,6 @@ public: m_showVisualIndicator = showVisualIndicator; } - SharedTextureMode getSharedTextureMode() - { - return SurfaceTextureMode; - } - TilesProfiler* getProfiler() { return &m_profiler; @@ -184,6 +176,19 @@ public: return m_useMinimalMemory; } + void setUseDoubleBuffering(bool useDoubleBuffering) + { + m_useDoubleBuffering = useDoubleBuffering; + } + bool useDoubleBuffering() { return m_useDoubleBuffering; } + + + unsigned int incWebkitContentUpdates() { return m_webkitContentUpdates++; } + + void incContentUpdates() { m_contentUpdates++; } + unsigned int getContentUpdates() { return m_contentUpdates; } + void clearContentUpdates() { m_contentUpdates = 0; } + void incDrawGLCount() { m_drawGLCount++; @@ -194,11 +199,6 @@ public: return m_drawGLCount; } - int getPaintedSurfaceCount() - { - return m_paintedSurfaces.size(); - } - private: TilesManager(); @@ -209,8 +209,9 @@ private: m_generatorReadyCond.wait(m_generatorLock); } - void deallocateTexturesVector(unsigned long long sparedDrawCount, - WTF::Vector<BaseTileTexture*>& textures); + void discardTexturesVector(unsigned long long sparedDrawCount, + WTF::Vector<BaseTileTexture*>& textures, + bool deallocateGLTextures); Vector<BaseTileTexture*> m_textures; Vector<BaseTileTexture*> m_availableTextures; @@ -219,8 +220,7 @@ private: Vector<BaseTileTexture*> m_availableTilesTextures; bool m_layerTexturesRemain; - Vector<PaintedSurface*> m_paintedSurfaces; - + bool m_highEndGfx; int m_maxTextureCount; int m_maxLayerTextureCount; @@ -232,6 +232,10 @@ private: bool m_useMinimalMemory; + bool m_useDoubleBuffering; + unsigned int m_contentUpdates; // nr of successful tiled paints + unsigned int m_webkitContentUpdates; // nr of paints from webkit + sp<TexturesGenerator> m_pixmapsGenerationThread; android::Mutex m_texturesLock; @@ -241,7 +245,7 @@ private: static TilesManager* gInstance; ShaderProgram m_shader; - TransferQueue m_queue; + TransferQueue* m_queue; VideoLayerManager m_videoLayerManager; diff --git a/Source/WebCore/platform/graphics/android/TransferQueue.cpp b/Source/WebCore/platform/graphics/android/TransferQueue.cpp index b20ec7a..0002c2c 100644 --- a/Source/WebCore/platform/graphics/android/TransferQueue.cpp +++ b/Source/WebCore/platform/graphics/android/TransferQueue.cpp @@ -29,7 +29,8 @@ #if USE(ACCELERATED_COMPOSITING) #include "BaseTile.h" -#include "PaintedSurface.h" +#include "GLUtils.h" +#include "TilesManager.h" #include <android/native_window.h> #include <gui/SurfaceTexture.h> #include <gui/SurfaceTextureClient.h> @@ -50,7 +51,10 @@ #endif // DEBUG -#define ST_BUFFER_NUMBER 6 +// For simple webView usage, MINIMAL_SIZE is recommended for memory saving. +// In browser case, EFFICIENT_SIZE is preferred. +#define MINIMAL_SIZE 1 +#define EFFICIENT_SIZE 6 // Set this to 1 if we would like to take the new GpuUpload approach which // relied on the glCopyTexSubImage2D instead of a glDraw call @@ -58,7 +62,7 @@ namespace WebCore { -TransferQueue::TransferQueue() +TransferQueue::TransferQueue(bool useMinimalMem) : m_eglSurface(EGL_NO_SURFACE) , m_transferQueueIndex(0) , m_fboID(0) @@ -69,35 +73,55 @@ TransferQueue::TransferQueue() , m_currentUploadType(DEFAULT_UPLOAD_TYPE) { memset(&m_GLStateBeforeBlit, 0, sizeof(m_GLStateBeforeBlit)); - - m_emptyItemCount = ST_BUFFER_NUMBER; - - m_transferQueue = new TileTransferData[ST_BUFFER_NUMBER]; + m_transferQueueSize = useMinimalMem ? MINIMAL_SIZE : EFFICIENT_SIZE; + m_emptyItemCount = m_transferQueueSize; + m_transferQueue = new TileTransferData[m_transferQueueSize]; } TransferQueue::~TransferQueue() { - glDeleteFramebuffers(1, &m_fboID); - m_fboID = 0; - glDeleteTextures(1, &m_sharedSurfaceTextureId); - m_sharedSurfaceTextureId = 0; - + android::Mutex::Autolock lock(m_transferQueueItemLocks); + cleanupGLResources(); delete[] m_transferQueue; } -void TransferQueue::initSharedSurfaceTextures(int width, int height) +// This should be called within the m_transferQueueItemLocks. +// Now only called by emptyQueue() and destructor. +void TransferQueue::cleanupGLResources() +{ + if (m_sharedSurfaceTexture.get()) { + m_sharedSurfaceTexture->abandon(); + m_sharedSurfaceTexture.clear(); + } + if (m_fboID) { + glDeleteFramebuffers(1, &m_fboID); + m_fboID = 0; + } + if (m_sharedSurfaceTextureId) { + glDeleteTextures(1, &m_sharedSurfaceTextureId); + m_sharedSurfaceTextureId = 0; + } +} + +void TransferQueue::initGLResources(int width, int height) { + android::Mutex::Autolock lock(m_transferQueueItemLocks); if (!m_sharedSurfaceTextureId) { glGenTextures(1, &m_sharedSurfaceTextureId); m_sharedSurfaceTexture = #if GPU_UPLOAD_WITHOUT_DRAW - new android::SurfaceTexture(m_sharedSurfaceTextureId, true, GL_TEXTURE_2D); + new android::SurfaceTexture(m_sharedSurfaceTextureId, true, + GL_TEXTURE_2D, false); #else new android::SurfaceTexture(m_sharedSurfaceTextureId); #endif m_ANW = new android::SurfaceTextureClient(m_sharedSurfaceTexture); m_sharedSurfaceTexture->setSynchronousMode(true); - m_sharedSurfaceTexture->setBufferCount(ST_BUFFER_NUMBER+1); + + int extraBuffersNeeded = 0; + m_ANW->query(m_ANW.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, + &extraBuffersNeeded); + m_sharedSurfaceTexture->setBufferCount(m_transferQueueSize + extraBuffersNeeded); int result = native_window_set_buffers_geometry(m_ANW.get(), width, height, HAL_PIXEL_FORMAT_RGBA_8888); @@ -114,9 +138,9 @@ void TransferQueue::initSharedSurfaceTextures(int width, int height) // When bliting, if the item from the transfer queue is mismatching b/t the // BaseTile and the content, then the item is considered as obsolete, and // the content is discarded. -bool TransferQueue::checkObsolete(int index) +bool TransferQueue::checkObsolete(const TileTransferData* data) { - BaseTile* baseTilePtr = m_transferQueue[index].savedBaseTilePtr; + BaseTile* baseTilePtr = data->savedBaseTilePtr; if (!baseTilePtr) { XLOG("Invalid savedBaseTilePtr , such that the tile is obsolete"); return true; @@ -128,34 +152,50 @@ bool TransferQueue::checkObsolete(int index) return true; } - const TextureTileInfo* tileInfo = &m_transferQueue[index].tileInfo; - - if (tileInfo->m_x != baseTilePtr->x() - || tileInfo->m_y != baseTilePtr->y() - || tileInfo->m_scale != baseTilePtr->scale() - || tileInfo->m_painter != baseTilePtr->painter()) { - XLOG("Mismatching x, y, scale or painter , such that the tile is obsolete"); - return true; - } - return false; } void TransferQueue::blitTileFromQueue(GLuint fboID, BaseTileTexture* destTex, + BaseTileTexture* frontTex, GLuint srcTexId, GLenum srcTexTarget, int index) { #if GPU_UPLOAD_WITHOUT_DRAW glBindFramebuffer(GL_FRAMEBUFFER, fboID); + glBindTexture(GL_TEXTURE_2D, destTex->m_ownTextureId); + + int textureWidth = destTex->getSize().width(); + int textureHeight = destTex->getSize().height(); + + IntRect inval = m_transferQueue[index].invalRect; + bool partialInval = !inval.isEmpty(); + + if (partialInval && frontTex) { + // recopy the previous texture to the new one, as + // the partial update will not cover the entire texture + glFramebufferTexture2D(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, + frontTex->m_ownTextureId, + 0); + glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, + textureWidth, textureHeight); + } + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, srcTexId, 0); - glBindTexture(GL_TEXTURE_2D, destTex->m_ownTextureId); - glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, - destTex->getSize().width(), - destTex->getSize().height()); + + if (!partialInval) { + glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, + textureWidth, textureHeight); + } else { + glCopyTexSubImage2D(GL_TEXTURE_2D, 0, inval.x(), inval.y(), 0, 0, + inval.width(), inval.height()); + } + #else // Then set up the FBO and copy the SurfTex content in. glBindFramebuffer(GL_FRAMEBUFFER, fboID); @@ -256,15 +296,33 @@ void TransferQueue::setHasGLContext(bool hasContext) m_hasGLContext = hasContext; } -// Only called when WebView is destroyed or switching the uploadType. -void TransferQueue::discardQueue() +void TransferQueue::setPendingDiscardWithLock() { android::Mutex::Autolock lock(m_transferQueueItemLocks); + setPendingDiscard(); +} + +void TransferQueue::emptyQueue() +{ + android::Mutex::Autolock lock(m_transferQueueItemLocks); + setPendingDiscard(); + cleanupPendingDiscard(); + cleanupGLResources(); +} - for (int i = 0 ; i < ST_BUFFER_NUMBER; i++) +// Set all the content in the queue to pendingDiscard, after this, there will +// be nothing added to the queue, and this can be called in any thread. +// However, in order to discard the content in the Surface Texture using +// updateTexImage, cleanupPendingDiscard need to be called on the UI thread. +// Must be called within a m_transferQueueItemLocks. +void TransferQueue::setPendingDiscard() +{ + for (int i = 0 ; i < m_transferQueueSize; i++) if (m_transferQueue[i].status == pendingBlit) m_transferQueue[i].status = pendingDiscard; + m_pureColorTileQueue.clear(); + bool GLContextExisted = getHasGLContext(); // Unblock the Tex Gen thread first before Tile Page deletion. // Otherwise, there will be a deadlock while removing operations. @@ -275,28 +333,57 @@ void TransferQueue::discardQueue() m_transferQueueItemCond.signal(); } +void TransferQueue::updatePureColorTiles() +{ + for (unsigned int i = 0 ; i < m_pureColorTileQueue.size(); i++) { + TileTransferData* data = &m_pureColorTileQueue[i]; + if (data->status == pendingBlit) { + BaseTileTexture* destTexture = 0; + bool obsoleteBaseTile = checkObsolete(data); + if (!obsoleteBaseTile) { + destTexture = data->savedBaseTilePtr->backTexture(); + destTexture->setPureColor(data->pureColor); + destTexture->transferComplete(); + } + } else if (data->status == emptyItem || data->status == pendingDiscard) { + // The queue should be clear instead of setting to different status. + XLOG("Warning: Don't expect an emptyItem here."); + } + } + m_pureColorTileQueue.clear(); +} + // Call on UI thread to copy from the shared Surface Texture to the BaseTile's texture. void TransferQueue::updateDirtyBaseTiles() { android::Mutex::Autolock lock(m_transferQueueItemLocks); - cleanupTransportQueue(); + cleanupPendingDiscard(); if (!getHasGLContext()) setHasGLContext(true); + // Check the pure color tile first, since it is simpler. + updatePureColorTiles(); + // Start from the oldest item, we call the updateTexImage to retrive // the texture and blit that into each BaseTile's texture. const int nextItemIndex = getNextTransferQueueIndex(); int index = nextItemIndex; bool usedFboForUpload = false; - for (int k = 0; k < ST_BUFFER_NUMBER ; k++) { + for (int k = 0; k < m_transferQueueSize ; k++) { if (m_transferQueue[index].status == pendingBlit) { - bool obsoleteBaseTile = checkObsolete(index); + bool obsoleteBaseTile = checkObsolete(&m_transferQueue[index]); // Save the needed info, update the Surf Tex, clean up the item in // the queue. Then either move on to next item or copy the content. BaseTileTexture* destTexture = 0; - if (!obsoleteBaseTile) + BaseTileTexture* frontTexture = 0; + if (!obsoleteBaseTile) { destTexture = m_transferQueue[index].savedBaseTilePtr->backTexture(); + // while destTexture is guaranteed to not be null, frontTexture + // might be (first transfer) + frontTexture = m_transferQueue[index].savedBaseTilePtr->frontTexture(); + } + if (m_transferQueue[index].uploadType == GpuUpload) { status_t result = m_sharedSurfaceTexture->updateTexImage(); if (result != OK) @@ -306,7 +393,7 @@ void TransferQueue::updateDirtyBaseTiles() m_transferQueue[index].status = emptyItem; if (obsoleteBaseTile) { XLOG("Warning: the texture is obsolete for this baseTile"); - index = (index + 1) % ST_BUFFER_NUMBER; + index = (index + 1) % m_transferQueueSize; continue; } @@ -315,25 +402,22 @@ void TransferQueue::updateDirtyBaseTiles() if (m_transferQueue[index].uploadType == CpuUpload) { // Here we just need to upload the bitmap content to the GL Texture - GLUtils::updateTextureWithBitmap(destTexture->m_ownTextureId, 0, 0, - *m_transferQueue[index].bitmap); + GLUtils::updateTextureWithBitmap(destTexture->m_ownTextureId, + *m_transferQueue[index].bitmap, + m_transferQueue[index].invalRect); } else { if (!usedFboForUpload) { saveGLState(); usedFboForUpload = true; } - blitTileFromQueue(m_fboID, destTexture, + blitTileFromQueue(m_fboID, destTexture, frontTexture, m_sharedSurfaceTextureId, m_sharedSurfaceTexture->getCurrentTextureTarget(), index); } - // After the base tile copied into the GL texture, we need to - // update the texture's info such that at draw time, readyFor - // will find the latest texture's info - // We don't need a map any more, each texture contains its own - // texturesTileInfo. - destTexture->setOwnTextureTileInfoFromQueue(&m_transferQueue[index].tileInfo); + destTexture->setPure(false); + destTexture->transferComplete(); XLOG("Blit tile x, y %d %d with dest texture %p to destTexture->m_ownTextureId %d", m_transferQueue[index].tileInfo.m_x, @@ -341,7 +425,7 @@ void TransferQueue::updateDirtyBaseTiles() destTexture, destTexture->m_ownTextureId); } - index = (index + 1) % ST_BUFFER_NUMBER; + index = (index + 1) % m_transferQueueSize; } // Clean up FBO setup. Doing this for both CPU/GPU upload can make the @@ -353,14 +437,14 @@ void TransferQueue::updateDirtyBaseTiles() GLUtils::checkGlError("updateDirtyBaseTiles"); } - m_emptyItemCount = ST_BUFFER_NUMBER; + m_emptyItemCount = m_transferQueueSize; m_transferQueueItemCond.signal(); } void TransferQueue::updateQueueWithBitmap(const TileRenderInfo* renderInfo, - int x, int y, const SkBitmap& bitmap) + const SkBitmap& bitmap) { - if (!tryUpdateQueueWithBitmap(renderInfo, x, y, bitmap)) { + if (!tryUpdateQueueWithBitmap(renderInfo, bitmap)) { // failed placing bitmap in queue, discard tile's texture so it will be // re-enqueued (and repainted) BaseTile* tile = renderInfo->baseTile; @@ -370,12 +454,15 @@ void TransferQueue::updateQueueWithBitmap(const TileRenderInfo* renderInfo, } bool TransferQueue::tryUpdateQueueWithBitmap(const TileRenderInfo* renderInfo, - int x, int y, const SkBitmap& bitmap) + const SkBitmap& bitmap) { - m_transferQueueItemLocks.lock(); + // This lock need to cover the full update since it is possible that queue + // will be cleaned up in the middle of this update without the lock. + // The Surface Texture will not block us since the readyForUpdate will check + // availability of the slots in the queue first. + android::Mutex::Autolock lock(m_transferQueueItemLocks); bool ready = readyForUpdate(); TextureUploadType currentUploadType = m_currentUploadType; - m_transferQueueItemLocks.unlock(); if (!ready) { XLOG("Quit bitmap update: not ready! for tile x y %d %d", renderInfo->x, renderInfo->y); @@ -393,13 +480,14 @@ bool TransferQueue::tryUpdateQueueWithBitmap(const TileRenderInfo* renderInfo, return false; uint8_t* img = (uint8_t*)buffer.bits; - int row, col; + int row; int bpp = 4; // Now we only deal with RGBA8888 format. int width = TilesManager::instance()->tileWidth(); int height = TilesManager::instance()->tileHeight(); - if (!x && !y && bitmap.width() == width && bitmap.height() == height) { + if (bitmap.width() == width && bitmap.height() == height) { bitmap.lockPixels(); uint8_t* bitmapOrigin = static_cast<uint8_t*>(bitmap.getPixels()); + if (buffer.stride != bitmap.width()) // Copied line by line since we need to handle the offsets and stride. for (row = 0 ; row < bitmap.height(); row ++) { @@ -411,31 +499,58 @@ bool TransferQueue::tryUpdateQueueWithBitmap(const TileRenderInfo* renderInfo, memcpy(img, bitmapOrigin, bpp * bitmap.width() * bitmap.height()); bitmap.unlockPixels(); - } else { - // TODO: implement the partial invalidate here! - XLOG("ERROR: don't expect to get here yet before we support partial inval"); } ANativeWindow_unlockAndPost(m_ANW.get()); } - m_transferQueueItemLocks.lock(); // b) After update the Surface Texture, now udpate the transfer queue info. addItemInTransferQueue(renderInfo, currentUploadType, &bitmap); - m_transferQueueItemLocks.unlock(); XLOG("Bitmap updated x, y %d %d, baseTile %p", renderInfo->x, renderInfo->y, renderInfo->baseTile); return true; } +void TransferQueue::addItemInPureColorQueue(const TileRenderInfo* renderInfo, Color color) +{ + // The pure color tiles' queue will be read from UI thread and written in + // Tex Gen thread, thus we need to have a lock here. + android::Mutex::Autolock lock(m_transferQueueItemLocks); + TileTransferData data; + addItemCommon(renderInfo, GpuUpload, &data); + data.pureColor = color; + m_pureColorTileQueue.append(data); +} + +// Translates the info from TileRenderInfo and others to TileTransferData. +// This is used by pure color tiles and normal tiles. +void TransferQueue::addItemCommon(const TileRenderInfo* renderInfo, + TextureUploadType type, + TileTransferData* data) +{ + data->savedBaseTileTexturePtr = renderInfo->baseTile->backTexture(); + data->savedBaseTilePtr = renderInfo->baseTile; + data->status = pendingBlit; + data->uploadType = type; + + IntRect inval(0, 0, 0, 0); + if (renderInfo->invalRect) { + inval.setX(renderInfo->invalRect->fLeft); + inval.setY(renderInfo->invalRect->fTop); + inval.setWidth(renderInfo->invalRect->width()); + inval.setHeight(renderInfo->invalRect->height()); + } + data->invalRect = inval; +} + // Note that there should be lock/unlock around this function call. // Currently only called by GLUtils::updateSharedSurfaceTextureWithBitmap. void TransferQueue::addItemInTransferQueue(const TileRenderInfo* renderInfo, TextureUploadType type, const SkBitmap* bitmap) { - m_transferQueueIndex = (m_transferQueueIndex + 1) % ST_BUFFER_NUMBER; + m_transferQueueIndex = (m_transferQueueIndex + 1) % m_transferQueueSize; int index = m_transferQueueIndex; if (m_transferQueue[index].savedBaseTilePtr @@ -443,10 +558,8 @@ void TransferQueue::addItemInTransferQueue(const TileRenderInfo* renderInfo, XLOG("ERROR update a tile which is dirty already @ index %d", index); } - m_transferQueue[index].savedBaseTileTexturePtr = renderInfo->baseTile->backTexture(); - m_transferQueue[index].savedBaseTilePtr = renderInfo->baseTile; - m_transferQueue[index].status = pendingBlit; - m_transferQueue[index].uploadType = type; + TileTransferData* data = &m_transferQueue[index]; + addItemCommon(renderInfo, type, data); if (type == CpuUpload && bitmap) { // Lazily create the bitmap if (!m_transferQueue[index].bitmap) { @@ -458,38 +571,28 @@ void TransferQueue::addItemInTransferQueue(const TileRenderInfo* renderInfo, bitmap->copyTo(m_transferQueue[index].bitmap, bitmap->config()); } - // Now fill the tileInfo. - TextureTileInfo* textureInfo = &m_transferQueue[index].tileInfo; - - textureInfo->m_x = renderInfo->x; - textureInfo->m_y = renderInfo->y; - textureInfo->m_scale = renderInfo->scale; - textureInfo->m_painter = renderInfo->tilePainter; - - textureInfo->m_picture = renderInfo->textureInfo->m_pictureCount; - m_emptyItemCount--; } void TransferQueue::setTextureUploadType(TextureUploadType type) { + android::Mutex::Autolock lock(m_transferQueueItemLocks); if (m_currentUploadType == type) return; - discardQueue(); + setPendingDiscard(); - android::Mutex::Autolock lock(m_transferQueueItemLocks); m_currentUploadType = type; XLOGC("Now we set the upload to %s", m_currentUploadType == GpuUpload ? "GpuUpload" : "CpuUpload"); } -// Note: this need to be called within th lock. -// Only called by updateDirtyBaseTiles() for now -void TransferQueue::cleanupTransportQueue() +// Note: this need to be called within the lock and on the UI thread. +// Only called by updateDirtyBaseTiles() and emptyQueue() for now +void TransferQueue::cleanupPendingDiscard() { int index = getNextTransferQueueIndex(); - for (int i = 0 ; i < ST_BUFFER_NUMBER; i++) { + for (int i = 0 ; i < m_transferQueueSize; i++) { if (m_transferQueue[index].status == pendingDiscard) { // No matter what the current upload type is, as long as there has // been a Surf Tex enqueue operation, this updateTexImage need to @@ -515,7 +618,7 @@ void TransferQueue::cleanupTransportQueue() m_transferQueue[index].savedBaseTileTexturePtr = 0; m_transferQueue[index].status = emptyItem; } - index = (index + 1) % ST_BUFFER_NUMBER; + index = (index + 1) % m_transferQueueSize; } } @@ -524,7 +627,7 @@ void TransferQueue::saveGLState() glGetIntegerv(GL_VIEWPORT, m_GLStateBeforeBlit.viewport); glGetBooleanv(GL_SCISSOR_TEST, m_GLStateBeforeBlit.scissor); glGetBooleanv(GL_DEPTH_TEST, m_GLStateBeforeBlit.depth); -#if DEBUG +#ifdef DEBUG glGetFloatv(GL_COLOR_CLEAR_VALUE, m_GLStateBeforeBlit.clearColor); #endif } @@ -536,7 +639,7 @@ void TransferQueue::setGLStateForCopy(int width, int height) glDisable(GL_SCISSOR_TEST); glDisable(GL_DEPTH_TEST); // Clear the content is only for debug purpose. -#if DEBUG +#ifdef DEBUG glClearColor(0, 0, 0, 0); glClear(GL_COLOR_BUFFER_BIT); #endif @@ -554,7 +657,7 @@ void TransferQueue::restoreGLState() if (m_GLStateBeforeBlit.depth[0]) glEnable(GL_DEPTH_TEST); -#if DEBUG +#ifdef DEBUG glClearColor(m_GLStateBeforeBlit.clearColor[0], m_GLStateBeforeBlit.clearColor[1], m_GLStateBeforeBlit.clearColor[2], @@ -564,7 +667,7 @@ void TransferQueue::restoreGLState() int TransferQueue::getNextTransferQueueIndex() { - return (m_transferQueueIndex + 1) % ST_BUFFER_NUMBER; + return (m_transferQueueIndex + 1) % m_transferQueueSize; } } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/TransferQueue.h b/Source/WebCore/platform/graphics/android/TransferQueue.h index 63455de..b864085 100644 --- a/Source/WebCore/platform/graphics/android/TransferQueue.h +++ b/Source/WebCore/platform/graphics/android/TransferQueue.h @@ -32,6 +32,7 @@ #include "BaseTileTexture.h" #include "ShaderProgram.h" #include "TiledPage.h" +#include <EGL/eglext.h> namespace WebCore { @@ -86,12 +87,15 @@ public: TransferItemStatus status; BaseTile* savedBaseTilePtr; BaseTileTexture* savedBaseTileTexturePtr; - TextureTileInfo tileInfo; + IntRect invalRect; TextureUploadType uploadType; // This is only useful in Cpu upload code path, so it will be dynamically // lazily allocated. SkBitmap* bitmap; + // Specific data to the pure color tiles' queue. + Color pureColor; + // Sync object for GPU fence, this is the only the info passed from UI // thread to Tex Gen thread. The reason of having this is due to the // missing sync mechanism on Surface Texture on some vendor. b/5122031. @@ -104,22 +108,20 @@ public: class TransferQueue { public: - TransferQueue(); + TransferQueue(bool useMinimalMem); ~TransferQueue(); // This will be called by the browser through nativeSetProperty void setTextureUploadType(TextureUploadType type); - + void cleanupGLResources(); void updateDirtyBaseTiles(); - void initSharedSurfaceTextures(int width, int height); + void initGLResources(int width, int height); // insert the bitmap into the queue, mark the tile dirty if failing - void updateQueueWithBitmap(const TileRenderInfo* renderInfo, int x, int y, + void updateQueueWithBitmap(const TileRenderInfo* renderInfo, const SkBitmap& bitmap); - void discardQueue(); - void addItemInTransferQueue(const TileRenderInfo* info, TextureUploadType type, const SkBitmap* bitmap); @@ -132,6 +134,12 @@ public: void lockQueue() { m_transferQueueItemLocks.lock(); } void unlockQueue() { m_transferQueueItemLocks.unlock(); } + void addItemInPureColorQueue(const TileRenderInfo* renderInfo, Color color); + + void setPendingDiscardWithLock(); + void emptyQueue(); + + bool needsInit() { return !m_sharedSurfaceTextureId; } // This queue can be accessed from UI and TexGen thread, therefore, we need // a lock to protect its access TileTransferData* m_transferQueue; @@ -143,7 +151,7 @@ public: private: // return true if successfully inserted into queue - bool tryUpdateQueueWithBitmap(const TileRenderInfo* renderInfo, int x, int y, + bool tryUpdateQueueWithBitmap(const TileRenderInfo* renderInfo, const SkBitmap& bitmap); bool getHasGLContext(); void setHasGLContext(bool hasContext); @@ -156,16 +164,22 @@ private: void restoreGLState(); // Check the current transfer queue item is obsolete or not. - bool checkObsolete(int index); + bool checkObsolete(const TileTransferData* data); + void setPendingDiscard(); // Before each draw call and the blit operation, clean up all the // pendingDiscard items. - void cleanupTransportQueue(); + void cleanupPendingDiscard(); void blitTileFromQueue(GLuint fboID, BaseTileTexture* destTex, + BaseTileTexture* frontTex, GLuint srcTexId, GLenum srcTexTarget, int index); + void addItemCommon(const TileRenderInfo* renderInfo, + TextureUploadType type, TileTransferData* data); + + void updatePureColorTiles(); // Note that the m_transferQueueIndex only changed in the TexGen thread // where we are going to move on to update the next item in the queue. int m_transferQueueIndex; @@ -201,6 +215,14 @@ private: // This should be GpuUpload for production, but for debug purpose or working // around driver/HW issue, we can set it to CpuUpload. TextureUploadType m_currentUploadType; + + // The non-pure-color tile are 1 to 1 mapping with Surface Texture which is + // resource limited. To get better performance, it is better to separate + // the pure color tile into another queue. + WTF::Vector<TileTransferData> m_pureColorTileQueue; + + // The number of items transfer queue can buffer up. + int m_transferQueueSize; }; } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/TreeManager.cpp b/Source/WebCore/platform/graphics/android/TreeManager.cpp deleted file mode 100644 index b7eaacf..0000000 --- a/Source/WebCore/platform/graphics/android/TreeManager.cpp +++ /dev/null @@ -1,331 +0,0 @@ -/* - * Copyright 2011, 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 "TreeManager.h" - -#include "Layer.h" -#include "BaseLayerAndroid.h" -#include "ScrollableLayerAndroid.h" -#include "TilesManager.h" - -#include <cutils/log.h> -#include <wtf/CurrentTime.h> -#include <wtf/text/CString.h> - -#undef XLOGC -#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "TreeManager", __VA_ARGS__) - -#ifdef DEBUG - -#undef XLOG -#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "TreeManager", __VA_ARGS__) - -#else - -#undef XLOG -#define XLOG(...) - -#endif // DEBUG - -namespace WebCore { - -TreeManager::TreeManager() - : m_drawingTree(0) - , m_paintingTree(0) - , m_queuedTree(0) - , m_fastSwapMode(false) -{ -} - -TreeManager::~TreeManager() -{ - clearTrees(); -} - -// the painting tree has finished painting: -// discard the drawing tree -// swap the painting tree in place of the drawing tree -// and start painting the queued tree -void TreeManager::swap() -{ - // swap can't be called unless painting just finished - ASSERT(m_paintingTree); - - android::Mutex::Autolock lock(m_paintSwapLock); - - XLOG("SWAPPING, D %p, P %p, Q %p", m_drawingTree, m_paintingTree, m_queuedTree); - - // if we have a drawing tree, discard it since the painting tree is done - if (m_drawingTree) { - XLOG("destroying drawing tree %p", m_drawingTree); - m_drawingTree->setIsDrawing(false); - SkSafeUnref(m_drawingTree); - } - - // painting tree becomes the drawing tree - XLOG("drawing tree %p", m_paintingTree); - m_paintingTree->setIsDrawing(true); - if (m_paintingTree->countChildren()) - static_cast<LayerAndroid*>(m_paintingTree->getChild(0))->initAnimations(); - - if (m_queuedTree) { - // start painting with the queued tree - XLOG("now painting tree %p", m_queuedTree); - m_queuedTree->setIsPainting(m_paintingTree); - } - m_drawingTree = m_paintingTree; - m_paintingTree = m_queuedTree; - m_queuedTree = 0; - - TilesManager::instance()->paintedSurfacesCleanup(); - - XLOG("SWAPPING COMPLETE, D %p, P %p, Q %p", m_drawingTree, m_paintingTree, m_queuedTree); -} - -// clear all of the content in the three trees held by the tree manager -void TreeManager::clearTrees() -{ - // remove painted surfaces from any tree in this view, and set trees as no - // longer drawing, to clear ptrs from surfaces to layers - GLWebViewState* oldState = 0; - if (m_drawingTree) { - oldState = m_drawingTree->state(); - m_drawingTree->setIsDrawing(false); - } - if (m_paintingTree) { - oldState = m_paintingTree->state(); - m_paintingTree->setIsDrawing(false); - } - - XLOG("TreeManager %p removing PS from state %p", this, oldState); - TilesManager::instance()->paintedSurfacesCleanup(oldState); - - SkSafeUnref(m_drawingTree); - m_drawingTree = 0; - SkSafeUnref(m_paintingTree); - m_paintingTree = 0; - SkSafeUnref(m_queuedTree); - m_queuedTree = 0; -} - -// a new layer tree has arrived, queue it if we're painting something already, -// or start painting it if we aren't -void TreeManager::updateWithTree(Layer* newTree, bool brandNew) -{ - XLOG("updateWithTree - %p, has children %d, has animations %d", - newTree, newTree && newTree->countChildren(), - newTree && newTree->countChildren() - ? static_cast<LayerAndroid*>(newTree->getChild(0))->hasAnimations() : 0); - - // can't have a queued tree unless have a painting tree too - ASSERT(m_paintingTree || !m_queuedTree); - - SkSafeRef(newTree); - - android::Mutex::Autolock lock(m_paintSwapLock); - - if (!newTree || brandNew) { - clearTrees(); - if (brandNew) { - m_paintingTree = newTree; - m_paintingTree->setIsPainting(m_drawingTree); - } - return; - } - - if (m_queuedTree || m_paintingTree) { - // currently painting, so defer this new tree - if (m_queuedTree) { - // have a queued tree, copy over invals so the regions are - // eventually repainted - m_queuedTree->mergeInvalsInto(newTree); - - XLOG("DISCARDING tree - %p, has children %d, has animations %d", - newTree, newTree && newTree->countChildren(), - newTree && newTree->countChildren() - ? static_cast<LayerAndroid*>(newTree->getChild(0))->hasAnimations() : 0); - } - SkSafeUnref(m_queuedTree); - m_queuedTree = newTree; - return; - } - - // don't have painting tree, paint this one! - m_paintingTree = newTree; - m_paintingTree->setIsPainting(m_drawingTree); -} - -void TreeManager::updateScrollableLayerInTree(Layer* tree, int layerId, int x, int y) -{ - LayerAndroid* layer; - if (tree && tree->countChildren()) { - layer = static_cast<LayerAndroid*>(tree->getChild(0))->findById(layerId); - if (layer && layer->contentIsScrollable()) - static_cast<ScrollableLayerAndroid*>(layer)->scrollTo(x, y); - } -} - -void TreeManager::updateScrollableLayer(int layerId, int x, int y) -{ - updateScrollableLayerInTree(m_queuedTree, layerId, x, y); - updateScrollableLayerInTree(m_paintingTree, layerId, x, y); - updateScrollableLayerInTree(m_drawingTree, layerId, x, y); -} - -bool TreeManager::drawGL(double currentTime, IntRect& viewRect, - SkRect& visibleRect, float scale, - bool enterFastSwapMode, bool* treesSwappedPtr, bool* newTreeHasAnimPtr, - TexturesResult* texturesResultPtr) -{ - m_fastSwapMode |= enterFastSwapMode; - - XLOG("drawGL, D %p, P %p, Q %p, fastSwap %d", - m_drawingTree, m_paintingTree, m_queuedTree, m_fastSwapMode); - - bool ret = false; - bool didTreeSwap = false; - if (m_paintingTree) { - XLOG("preparing painting tree %p", m_paintingTree); - - LayerAndroid* laTree = 0; - if (m_paintingTree->countChildren()) { - laTree = static_cast<LayerAndroid*>(m_paintingTree->getChild(0)); - ret |= laTree->evaluateAnimations(currentTime); - } - - ret |= m_paintingTree->prepare(currentTime, viewRect, - visibleRect, scale); - - if (laTree) - laTree->computeTexturesAmount(texturesResultPtr); - - if (/*!m_fastSwapMode && */ m_paintingTree->isReady()) { - XLOG("have painting tree %p ready, swapping!", m_paintingTree); - didTreeSwap = true; - swap(); - if (treesSwappedPtr) - *treesSwappedPtr = true; - if (laTree && newTreeHasAnimPtr) - *newTreeHasAnimPtr = laTree->hasAnimations(); - } - } else if (m_drawingTree) { - XLOG("preparing drawing tree %p", m_drawingTree); - ret |= m_drawingTree->prepare(currentTime, viewRect, - visibleRect, scale); - if (m_drawingTree->countChildren()) { - LayerAndroid* laTree = static_cast<LayerAndroid*>(m_drawingTree->getChild(0)); - laTree->computeTexturesAmount(texturesResultPtr); - } - } - - - if (m_drawingTree) { - bool drawingReady = didTreeSwap || m_drawingTree->isReady(); - - if (didTreeSwap || m_fastSwapMode || (drawingReady && !m_paintingTree)) - m_drawingTree->swapTiles(); - - if (drawingReady) { - // exit fast swap mode, as content is up to date - m_fastSwapMode = false; - } else { - // drawing isn't ready, must redraw - ret = true; - } - - if (m_drawingTree->countChildren()) { - LayerAndroid* laTree = static_cast<LayerAndroid*>(m_drawingTree->getChild(0)); - ret |= laTree->evaluateAnimations(currentTime); - } - XLOG("drawing tree %p", m_drawingTree); - ret |= m_drawingTree->drawGL(viewRect, visibleRect, scale); - } else if (m_paintingTree && m_paintingTree->state()) { - // Dont have a drawing tree, draw white background - Color defaultBackground = Color::white; - m_paintingTree->state()->drawBackground(defaultBackground); - } - - if (m_paintingTree) { - XLOG("still have painting tree %p", m_paintingTree); - return true; - } - - return ret; -} - -int TreeManager::getTotalPaintedSurfaceCount() -{ - return TilesManager::instance()->getPaintedSurfaceCount(); -} - -// draw for base tile - called on TextureGeneration thread -void TreeManager::drawCanvas(SkCanvas* canvas, bool drawLayers) -{ - BaseLayerAndroid* paintingTree = 0; - m_paintSwapLock.lock(); - if (m_paintingTree) - paintingTree = static_cast<BaseLayerAndroid*>(m_paintingTree); - else - paintingTree = static_cast<BaseLayerAndroid*>(m_drawingTree); - SkSafeRef(paintingTree); - m_paintSwapLock.unlock(); - - if (!paintingTree) - return; - - - paintingTree->drawCanvas(canvas); - - if (drawLayers && paintingTree->countChildren()) { - // draw the layers onto the canvas as well - Layer* layers = paintingTree->getChild(0); - static_cast<LayerAndroid*>(layers)->drawCanvas(canvas); - } - - SkSafeUnref(paintingTree); -} - -int TreeManager::baseContentWidth() -{ - if (m_paintingTree) { - return static_cast<BaseLayerAndroid*>(m_paintingTree)->content()->width(); - } else if (m_drawingTree) { - return static_cast<BaseLayerAndroid*>(m_drawingTree)->content()->width(); - } - return 0; -} - -int TreeManager::baseContentHeight() -{ - if (m_paintingTree) { - return static_cast<BaseLayerAndroid*>(m_paintingTree)->content()->height(); - } else if (m_drawingTree) { - return static_cast<BaseLayerAndroid*>(m_drawingTree)->content()->height(); - } - return 0; -} - -} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/VerticalTextMap.cpp b/Source/WebCore/platform/graphics/android/VerticalTextMap.cpp index 6e715e2..42aa385 100644 --- a/Source/WebCore/platform/graphics/android/VerticalTextMap.cpp +++ b/Source/WebCore/platform/graphics/android/VerticalTextMap.cpp @@ -33,28 +33,29 @@ #include <wtf/RefPtr.h> static const UChar vTextCnvTable[][2] = { - // TODO: uncomment mappings once we add glyphs for vertical forms. - // {0x0021, 0xfe15}, // exclamation mark + {0x0021, 0xfe15}, // exclamation mark {0x0028, 0xfe35}, // left paren {0x0029, 0xfe36}, // right paren - // {0x002c, 0xfe10}, // comma + {0x002c, 0xfe10}, // comma + {0x002d, 0xfe32}, // hyphen {0x003a, 0xfe30}, // colon - {0x003b, 0x007c}, // hyphen - // {0x003f, 0xfe16}, // question mark - // {0x005b, 0xfe14}, // semicolon - {0x005d, 0xfe47}, // left square bracket - {0x005f, 0xfe48}, // right square bracket + {0x003b, 0xfe14}, // semicolon + {0x003f, 0xfe16}, // question mark + {0x005b, 0xfe47}, // left square bracket + {0x005d, 0xfe48}, // right square bracket {0x007b, 0xfe37}, // left curly bracket {0x007d, 0xfe38}, // right curly bracket {0x007e, 0x007c}, // tilde to vertical line + {0x00ab, 0xfe3d}, // left pointing double angle quotation mark + {0x00bb, 0xfe3e}, // right pointing double angle quotation mark + {0x2010, 0xfe32}, // hyphen {0x2013, 0xfe32}, // en dash {0x2014, 0xfe31}, // em dash {0x2015, 0xfe31}, // horizontal bar {0x2025, 0xfe30}, // two dot leader - // TODO: change the mapping 0x2026 -> 0xFE19 once Android has the glyph for 0xFE19. - {0x2026, 0xfe30}, // three dot leader - // {0x3001, 0xfe11}, // Ideographic comma - // {0x3002, 0xfe12}, // Ideographic full stop + {0x2026, 0xfe19}, // three dot leader + {0x3001, 0xfe11}, // Ideographic comma + {0x3002, 0xfe12}, // Ideographic full stop {0x3008, 0xfe3f}, // left angle bracket {0x3009, 0xfe40}, // right angle bracket {0x300a, 0xfe3d}, // left double angle bracket @@ -67,19 +68,21 @@ static const UChar vTextCnvTable[][2] = { {0x3011, 0xfe3c}, // right black lenticular bracket {0x3014, 0xfe39}, // left black lenticular bracket {0x3015, 0xfe3a}, // right tortise shell bracket - // {0x3016, 0xfe17}, // left white lenticular bracket - // {0x3017, 0xfe18}, // right white lenticular bracket - // {0x3019, 0xfe19}, // horizontal ellipses + {0x3016, 0xfe17}, // left white lenticular bracket + {0x3017, 0xfe18}, // right white lenticular bracket {0x30fc, 0x3021}, // prolonged sound {0xfe4f, 0xfe34}, // wavy low line {0xff08, 0xfe35}, // full width left paren {0xff09, 0xfe36}, // full width right paren + {0xff0c, 0xfe10}, // full width comma {0xff3b, 0xfe47}, // full width left square bracket {0xff3d, 0xfe48}, // full width right square bracket {0xff5b, 0xfe37}, // full width left curly bracket + {0xff5c, 0xfe31}, // fullwidth vertical line {0xff5d, 0xfe38}, // full width right curly bracket - // {0xff64, 0xfe11}, // halfwidth ideo comma - // {0xff61, 0xfe12}, // halfwidth ideo full stop + {0xff5e, 0x007c}, // tilde to vertical line + {0xff64, 0xfe11}, // halfwidth ideo comma + {0xff61, 0xfe12}, // halfwidth ideo full stop }; namespace WebCore { diff --git a/Source/WebCore/platform/graphics/android/VideoLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/VideoLayerAndroid.cpp index 482d711..e48d36c 100644 --- a/Source/WebCore/platform/graphics/android/VideoLayerAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/VideoLayerAndroid.cpp @@ -26,16 +26,18 @@ #include "config.h" #include "VideoLayerAndroid.h" -#include "RenderSkinMediaButton.h" #include "TilesManager.h" #include <GLES2/gl2.h> +#include <cutils/log.h> #include <gui/SurfaceTexture.h> +#include <wtf/text/CString.h> #if USE(ACCELERATED_COMPOSITING) +#undef XLOGC +#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "VideoLayerAndroid", __VA_ARGS__) + #ifdef DEBUG -#include <cutils/log.h> -#include <wtf/text/CString.h> #undef XLOG #define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "VideoLayerAndroid", __VA_ARGS__) @@ -49,16 +51,8 @@ namespace WebCore { -GLuint VideoLayerAndroid::m_spinnerOuterTextureId = 0; -GLuint VideoLayerAndroid::m_spinnerInnerTextureId = 0; -GLuint VideoLayerAndroid::m_posterTextureId = 0; -GLuint VideoLayerAndroid::m_backgroundTextureId = 0; -bool VideoLayerAndroid::m_createdTexture = false; - double VideoLayerAndroid::m_rotateDegree = 0; -const IntRect VideoLayerAndroid::buttonRect(0, 0, IMAGESIZE, IMAGESIZE); - VideoLayerAndroid::VideoLayerAndroid() : LayerAndroid((RenderLayer*)0) { @@ -87,144 +81,139 @@ void VideoLayerAndroid::setSurfaceTexture(sp<SurfaceTexture> texture, TilesManager::instance()->videoLayerManager()->registerTexture(uniqueId(), textureName); } -GLuint VideoLayerAndroid::createSpinnerInnerTexture() +void VideoLayerAndroid::showPreparingAnimation(const SkRect& rect, + const SkRect innerRect) { - return createTextureFromImage(RenderSkinMediaButton::SPINNER_INNER); + ShaderProgram* shader = TilesManager::instance()->shader(); + VideoLayerManager* manager = TilesManager::instance()->videoLayerManager(); + // Paint the video content's background. + shader->drawLayerQuad(m_drawTransform, rect, 0, 1, true, GL_TEXTURE_2D, + Color(128, 128, 128, 255)); + + TransformationMatrix addReverseRotation; + TransformationMatrix addRotation = m_drawTransform; + addRotation.translate(innerRect.fLeft, innerRect.fTop); + double halfButtonSize = manager->getButtonSize() / 2; + addRotation.translate(halfButtonSize, halfButtonSize); + addReverseRotation = addRotation; + addRotation.rotate(m_rotateDegree); + addRotation.translate(-halfButtonSize, -halfButtonSize); + + SkRect size = SkRect::MakeWH(innerRect.width(), innerRect.height()); + shader->drawLayerQuad(addRotation, size, + manager->getSpinnerOuterTextureId(), 1, true); + + addReverseRotation.rotate(-m_rotateDegree); + addReverseRotation.translate(-halfButtonSize, -halfButtonSize); + + shader->drawLayerQuad(addReverseRotation, size, + manager->getSpinnerInnerTextureId(), 1, true); + + m_rotateDegree += ROTATESTEP; } -GLuint VideoLayerAndroid::createSpinnerOuterTexture() +SkRect VideoLayerAndroid::calVideoRect(const SkRect& rect) { - return createTextureFromImage(RenderSkinMediaButton::SPINNER_OUTER); -} - -GLuint VideoLayerAndroid::createPosterTexture() -{ - return createTextureFromImage(RenderSkinMediaButton::VIDEO); -} - -GLuint VideoLayerAndroid::createTextureFromImage(int buttonType) -{ - SkRect rect = SkRect(buttonRect); - SkBitmap bitmap; - bitmap.setConfig(SkBitmap::kARGB_8888_Config, rect.width(), rect.height()); - bitmap.allocPixels(); - bitmap.eraseColor(0); - - SkCanvas canvas(bitmap); - canvas.drawARGB(0, 0, 0, 0, SkXfermode::kClear_Mode); - RenderSkinMediaButton::Draw(&canvas, buttonRect, buttonType, true); - - GLuint texture; - glGenTextures(1, &texture); - - GLUtils::createTextureWithBitmap(texture, bitmap); - bitmap.reset(); - return texture; -} - -GLuint VideoLayerAndroid::createBackgroundTexture() -{ - GLuint texture; - glGenTextures(1, &texture); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - GLubyte pixels[4 *3] = { - 128, 128, 128, - 128, 128, 128, - 128, 128, 128, - 128, 128, 128 - }; - glBindTexture(GL_TEXTURE_2D, texture); - GLUtils::checkGlError("glBindTexture"); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels); - GLUtils::checkGlError("glTexImage2D"); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - return texture; + SkRect videoRect = rect; + VideoLayerManager* manager = TilesManager::instance()->videoLayerManager(); + float aspectRatio = manager->getAspectRatio(uniqueId()); + float deltaY = rect.height() - rect.width() / aspectRatio; + if (deltaY >= 0) + videoRect.inset(0, deltaY / 2); + else { + float deltaX = rect.width() - rect.height() * aspectRatio; + if (deltaX >= 0) + videoRect.inset(deltaX / 2, 0); + } + return videoRect; } -bool VideoLayerAndroid::drawGL() +bool VideoLayerAndroid::drawGL(bool layerTilesDisabled) { // Lazily allocated the textures. - if (!m_createdTexture) { - m_backgroundTextureId = createBackgroundTexture(); - m_spinnerOuterTextureId = createSpinnerOuterTexture(); - m_spinnerInnerTextureId = createSpinnerInnerTexture(); - m_posterTextureId = createPosterTexture(); - m_createdTexture = true; - } + TilesManager* tilesManager = TilesManager::instance(); + VideoLayerManager* manager = tilesManager->videoLayerManager(); + manager->initGLResourcesIfNeeded(); + + ShaderProgram* shader = tilesManager->shader(); SkRect rect = SkRect::MakeSize(getSize()); GLfloat surfaceMatrix[16]; - SkRect innerRect = SkRect(buttonRect); - if (innerRect.contains(rect)) - innerRect = rect; + // Calculate the video rect based on the aspect ratio and the element rect. + SkRect videoRect = calVideoRect(rect); + if (videoRect != rect) { + // Paint the whole video element with black color when video content + // can't cover the whole area. + shader->drawLayerQuad(m_drawTransform, rect, 0, 1, true, GL_TEXTURE_2D, + Color(0, 0, 0, 255)); + } + + // Inner rect is for the progressing / play / pause animation. + SkRect innerRect = SkRect::MakeWH(manager->getButtonSize(), + manager->getButtonSize()); + if (innerRect.contains(videoRect)) + innerRect = videoRect; + double buttonSize = manager->getButtonSize(); + innerRect.offset(videoRect.fLeft + (videoRect.width() - buttonSize) / 2, + videoRect.fTop + (videoRect.height() - buttonSize) / 2); - innerRect.offset((rect.width() - IMAGESIZE) / 2 , (rect.height() - IMAGESIZE) / 2); + // When we are drawing the animation of the play/pause button in the + // middle of the video, we need to ask for redraw. + bool needRedraw = false; // Draw the poster image, the progressing image or the Video depending // on the player's state. if (m_playerState == PREPARING) { // Show the progressing animation, with two rotating circles - TilesManager::instance()->shader()->drawLayerQuad(m_drawTransform, rect, - m_backgroundTextureId, - 1, true); - - TransformationMatrix addReverseRotation; - TransformationMatrix addRotation = m_drawTransform; - addRotation.translate(innerRect.fLeft, innerRect.fTop); - addRotation.translate(IMAGESIZE / 2, IMAGESIZE / 2); - addReverseRotation = addRotation; - addRotation.rotate(m_rotateDegree); - addRotation.translate(-IMAGESIZE / 2, -IMAGESIZE / 2); - - SkRect size = SkRect::MakeWH(innerRect.width(), innerRect.height()); - TilesManager::instance()->shader()->drawLayerQuad(addRotation, size, - m_spinnerOuterTextureId, - 1, true); - - addReverseRotation.rotate(-m_rotateDegree); - addReverseRotation.translate(-IMAGESIZE / 2, -IMAGESIZE / 2); - - TilesManager::instance()->shader()->drawLayerQuad(addReverseRotation, size, - m_spinnerInnerTextureId, - 1, true); - - m_rotateDegree += ROTATESTEP; - + showPreparingAnimation(videoRect, innerRect); + needRedraw = true; } else if (m_playerState == PLAYING && m_surfaceTexture.get()) { // Show the real video. m_surfaceTexture->updateTexImage(); m_surfaceTexture->getTransformMatrix(surfaceMatrix); - GLuint textureId = - TilesManager::instance()->videoLayerManager()->getTextureId(uniqueId()); - TilesManager::instance()->shader()->drawVideoLayerQuad(m_drawTransform, - surfaceMatrix, - rect, textureId); - TilesManager::instance()->videoLayerManager()->updateMatrix(uniqueId(), - surfaceMatrix); + GLuint textureId = manager->getTextureId(uniqueId()); + shader->drawVideoLayerQuad(m_drawTransform, surfaceMatrix, + videoRect, textureId); + manager->updateMatrix(uniqueId(), surfaceMatrix); + + // Use the scale to control the fading the sizing during animation + double scale = manager->drawIcon(uniqueId(), PlayIcon); + if (scale) { + innerRect.inset(manager->getButtonSize() / 4 * scale, + manager->getButtonSize() / 4 * scale); + shader->drawLayerQuad(m_drawTransform, innerRect, + manager->getPlayTextureId(), scale, true); + needRedraw = true; + } + } else { - GLuint textureId = - TilesManager::instance()->videoLayerManager()->getTextureId(uniqueId()); - GLfloat* matrix = - TilesManager::instance()->videoLayerManager()->getMatrix(uniqueId()); + GLuint textureId = manager->getTextureId(uniqueId()); + GLfloat* matrix = manager->getMatrix(uniqueId()); if (textureId && matrix) { // Show the screen shot for each video. - TilesManager::instance()->shader()->drawVideoLayerQuad(m_drawTransform, - matrix, - rect, textureId); + shader->drawVideoLayerQuad(m_drawTransform, matrix, + videoRect, textureId); } else { // Show the static poster b/c there is no screen shot available. - TilesManager::instance()->shader()->drawLayerQuad(m_drawTransform, rect, - m_backgroundTextureId, - 1, true); - TilesManager::instance()->shader()->drawLayerQuad(m_drawTransform, innerRect, - m_posterTextureId, - 1, true); + shader->drawLayerQuad(m_drawTransform, rect, 0, 1, true, GL_TEXTURE_2D, + Color(128, 128, 128, 255)); + shader->drawLayerQuad(m_drawTransform, innerRect, + manager->getPosterTextureId(), 1, true); + } + + // Use the scale to control the fading and the sizing during animation. + double scale = manager->drawIcon(uniqueId(), PauseIcon); + if (scale) { + innerRect.inset(manager->getButtonSize() / 4 * scale, + manager->getButtonSize() / 4 * scale); + shader->drawLayerQuad(m_drawTransform, innerRect, + manager->getPauseTextureId(), scale, true); + needRedraw = true; } - } - return drawChildrenGL(); + } + return needRedraw; } } diff --git a/Source/WebCore/platform/graphics/android/VideoLayerAndroid.h b/Source/WebCore/platform/graphics/android/VideoLayerAndroid.h index 8a064bb..29b1bdc 100644 --- a/Source/WebCore/platform/graphics/android/VideoLayerAndroid.h +++ b/Source/WebCore/platform/graphics/android/VideoLayerAndroid.h @@ -30,6 +30,7 @@ #include "GLUtils.h" #include "LayerAndroid.h" +#include "ShaderProgram.h" #include <jni.h> namespace android { @@ -56,34 +57,23 @@ public: virtual LayerAndroid* copy() const { return new VideoLayerAndroid(*this); } // The following 3 functions are called in UI thread only. - virtual bool drawGL(); + virtual bool drawGL(bool layerTilesDisabled); void setSurfaceTexture(sp<SurfaceTexture> texture, int textureName, PlayerState playerState); - GLuint createBackgroundTexture(); - GLuint createSpinnerOuterTexture(); - GLuint createSpinnerInnerTexture(); - GLuint createPosterTexture(); private: - GLuint createTextureFromImage(int buttonType); void init(); + void showPreparingAnimation(const SkRect& rect, + const SkRect innerRect); + SkRect calVideoRect(const SkRect& rect); // Surface texture for showing the video is actually allocated in Java side // and passed into this native code. sp<android::SurfaceTexture> m_surfaceTexture; PlayerState m_playerState; - // Texture for showing the static image will be created at native side. - static bool m_createdTexture; - static GLuint m_backgroundTextureId; - static GLuint m_posterTextureId; - static GLuint m_spinnerOuterTextureId; - static GLuint m_spinnerInnerTextureId; - static double m_rotateDegree; static const int ROTATESTEP = 12; - static const int IMAGESIZE = 64; - static const IntRect buttonRect; }; } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/VideoLayerManager.cpp b/Source/WebCore/platform/graphics/android/VideoLayerManager.cpp index cec4d67..f957aed 100644 --- a/Source/WebCore/platform/graphics/android/VideoLayerManager.cpp +++ b/Source/WebCore/platform/graphics/android/VideoLayerManager.cpp @@ -26,11 +26,18 @@ #include "config.h" #include "VideoLayerManager.h" +#include "RenderSkinMediaButton.h" +#include "SkCanvas.h" +#include <cutils/log.h> +#include <wtf/CurrentTime.h> +#include <wtf/text/CString.h> + #if USE(ACCELERATED_COMPOSITING) +#undef XLOGC +#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "VideoLayerManager", __VA_ARGS__) + #ifdef DEBUG -#include <cutils/log.h> -#include <wtf/text/CString.h> #undef XLOG #define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "VideoLayerManager", __VA_ARGS__) @@ -42,6 +49,10 @@ #endif // DEBUG +// The animation of the play/pause icon will last for PLAY_PAUSE_ICON_SHOW_TIME +// seconds. +#define PLAY_PAUSE_ICON_SHOW_TIME 1 + // Define the max sum of all the video's sizes. // Note that video_size = width * height. If there is no compression, then the // maximum memory consumption could be 4 * video_size. @@ -49,11 +60,110 @@ // screenshots would not be above 8M. #define MAX_VIDEOSIZE_SUM 2097152 +// We don't preload the video data, so we don't have the exact size yet. +// Assuming 16:9 by default, this will be corrected after video prepared. +#define DEFAULT_VIDEO_ASPECT_RATIO 1.78 + +#define VIDEO_TEXTURE_NUMBER 5 +#define VIDEO_BUTTON_SIZE 64 + namespace WebCore { VideoLayerManager::VideoLayerManager() + : m_currentTimeStamp(0) + , m_createdTexture(false) + , m_posterTextureId(0) + , m_spinnerOuterTextureId(0) + , m_spinnerInnerTextureId(0) + , m_playTextureId(0) + , m_pauseTextureId(0) + , m_buttonRect(0, 0, VIDEO_BUTTON_SIZE, VIDEO_BUTTON_SIZE) +{ +} + +int VideoLayerManager::getButtonSize() +{ + return VIDEO_BUTTON_SIZE; +} + +GLuint VideoLayerManager::createTextureFromImage(int buttonType) { - m_currentTimeStamp = 0; + SkRect rect = SkRect(m_buttonRect); + SkBitmap bitmap; + bitmap.setConfig(SkBitmap::kARGB_8888_Config, rect.width(), rect.height()); + bitmap.allocPixels(); + bitmap.eraseColor(0); + + SkCanvas canvas(bitmap); + canvas.drawARGB(0, 0, 0, 0, SkXfermode::kClear_Mode); + RenderSkinMediaButton::Draw(&canvas, m_buttonRect, buttonType, true, 0, + false); + + GLuint texture; + glGenTextures(1, &texture); + + GLUtils::createTextureWithBitmap(texture, bitmap); + bitmap.reset(); + return texture; +} + +// Should be called at the VideoLayerAndroid::drawGL to make sure we allocate +// the GL resources lazily. +void VideoLayerManager::initGLResourcesIfNeeded() +{ + if (!m_createdTexture) { + XLOGC("Reinit GLResource for VideoLayer"); + initGLResources(); + } +} + +void VideoLayerManager::initGLResources() +{ + GLUtils::checkGlError("before initGLResources()"); + if (!m_createdTexture) { + m_spinnerOuterTextureId = + createTextureFromImage(RenderSkinMediaButton::SPINNER_OUTER); + m_spinnerInnerTextureId = + createTextureFromImage(RenderSkinMediaButton::SPINNER_INNER); + m_posterTextureId = + createTextureFromImage(RenderSkinMediaButton::VIDEO); + m_playTextureId = createTextureFromImage(RenderSkinMediaButton::PLAY); + m_pauseTextureId = createTextureFromImage(RenderSkinMediaButton::PAUSE); + } + m_createdTexture = !GLUtils::checkGlError("initGLResources()"); + return; +} + +void VideoLayerManager::cleanupGLResources() +{ + if (m_createdTexture) { + GLuint videoTextures[VIDEO_TEXTURE_NUMBER] = { m_spinnerOuterTextureId, + m_spinnerInnerTextureId, m_posterTextureId, m_playTextureId, + m_pauseTextureId }; + + glDeleteTextures(VIDEO_TEXTURE_NUMBER, videoTextures); + m_createdTexture = false; + } + // Delete the texture in retired mode, but have not hit draw call to be + // removed. + deleteUnusedTextures(); + + // Go over the registered GL textures (screen shot textures) and delete them. + android::Mutex::Autolock lock(m_videoLayerInfoMapLock); + InfoIterator end = m_videoLayerInfoMap.end(); + for (InfoIterator it = m_videoLayerInfoMap.begin(); it != end; ++it) { + // The map include every video has been played, so their textureId can + // be deleted already, like hitting onTrimMemory multiple times. + if (it->second->textureId) { + XLOG("delete texture from the map %d", it->second->textureId); + glDeleteTextures(1, &it->second->textureId); + // Set the textureID to 0 to show the video icon. + it->second->textureId = 0; + } + } + + GLUtils::checkGlError("cleanupGLResources()"); + return; } // Getting TextureId for GL draw call, in the UI thread. @@ -66,6 +176,16 @@ GLuint VideoLayerManager::getTextureId(const int layerId) return result; } +// Getting the aspect ratio for GL draw call, in the UI thread. +float VideoLayerManager::getAspectRatio(const int layerId) +{ + android::Mutex::Autolock lock(m_videoLayerInfoMapLock); + float result = 0; + if (m_videoLayerInfoMap.contains(layerId)) + result = m_videoLayerInfoMap.get(layerId)->aspectRatio; + return result; +} + // Getting matrix for GL draw call, in the UI thread. GLfloat* VideoLayerManager::getMatrix(const int layerId) { @@ -103,8 +223,11 @@ void VideoLayerManager::registerTexture(const int layerId, const GLuint textureI pInfo->textureId = textureId; memset(pInfo->surfaceMatrix, 0, sizeof(pInfo->surfaceMatrix)); pInfo->videoSize = 0; + pInfo->aspectRatio = DEFAULT_VIDEO_ASPECT_RATIO; m_currentTimeStamp++; pInfo->timeStamp = m_currentTimeStamp; + pInfo->lastIconShownTime = 0; + pInfo->iconState = Registered; m_videoLayerInfoMap.add(layerId, pInfo); XLOG("GL texture %d regisered for layerId %d", textureId, layerId); @@ -115,13 +238,16 @@ void VideoLayerManager::registerTexture(const int layerId, const GLuint textureI // Only when the video is prepared, we got the video size. So we should update // the size for the video accordingly. // This is called from webcore thread, from MediaPlayerPrivateAndroid. -void VideoLayerManager::updateVideoLayerSize(const int layerId, const int size ) +void VideoLayerManager::updateVideoLayerSize(const int layerId, const int size, + const float ratio) { android::Mutex::Autolock lock(m_videoLayerInfoMapLock); if (m_videoLayerInfoMap.contains(layerId)) { VideoLayerInfo* pInfo = m_videoLayerInfoMap.get(layerId); - if (pInfo) + if (pInfo) { pInfo->videoSize = size; + pInfo->aspectRatio = ratio; + } } // If the memory usage is out of bound, then just delete the oldest ones. @@ -207,6 +333,7 @@ void VideoLayerManager::deleteUnusedTextures() m_retiredTextures.clear(); } m_retiredTexturesLock.unlock(); + GLUtils::checkGlError("deleteUnusedTextures"); return; } @@ -238,5 +365,34 @@ void VideoLayerManager::removeLayerInternal(const int layerId) return; } +double VideoLayerManager::drawIcon(const int layerId, IconType type) +{ + // When ratio 0 is returned, the Icon should not be drawn. + double ratio = 0; + + android::Mutex::Autolock lock(m_videoLayerInfoMapLock); + if (m_videoLayerInfoMap.contains(layerId)) { + VideoLayerInfo* pInfo = m_videoLayerInfoMap.get(layerId); + // If this is state switching moment, reset the time and state + if ((type == PlayIcon && pInfo->iconState != PlayIconShown) + || (type == PauseIcon && pInfo->iconState != PauseIconShown)) { + pInfo->lastIconShownTime = WTF::currentTime(); + pInfo->iconState = (type == PlayIcon) ? PlayIconShown : PauseIconShown; + } + + // After switching the state, we calculate the ratio depending on the + // time interval. + if ((type == PlayIcon && pInfo->iconState == PlayIconShown) + || (type == PauseIcon && pInfo->iconState == PauseIconShown)) { + double delta = WTF::currentTime() - pInfo->lastIconShownTime; + ratio = 1.0 - (delta / PLAY_PAUSE_ICON_SHOW_TIME); + } + } + + if (ratio > 1 || ratio < 0) + ratio = 0; + return ratio; +} + } #endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/VideoLayerManager.h b/Source/WebCore/platform/graphics/android/VideoLayerManager.h index de2dafc..c8e420e 100644 --- a/Source/WebCore/platform/graphics/android/VideoLayerManager.h +++ b/Source/WebCore/platform/graphics/android/VideoLayerManager.h @@ -27,6 +27,7 @@ #define VideoLayerManager_h #include "GLUtils.h" +#include "IntRect.h" #include <wtf/HashMap.h> #include <wtf/Vector.h> @@ -34,13 +35,28 @@ namespace WebCore { +enum IconState { + Registered, + PlayIconShown, + PauseIconShown +}; + +enum IconType { + PlayIcon, + PauseIcon +}; + // Every video layer can use its uniqueId to query VideoLayerManager about such // info globally. struct VideoLayerInfo { GLuint textureId; // GL texture bound with the surface texture. int videoSize; // The size of the video. + float aspectRatio; // The aspect ratio of the video. int timeStamp; // Used to decide which VideoLayerInfo is the oldest one. GLfloat surfaceMatrix[16]; + + double lastIconShownTime; + IconState iconState; }; @@ -54,7 +70,7 @@ public: // Register the texture when we got setSurfaceTexture call. void registerTexture(const int layerId, const GLuint textureId); // Update the size when the video is prepared. - void updateVideoLayerSize(const int layerId, const int size); + void updateVideoLayerSize(const int layerId, const int size, const float ratio); // At draw time, update the matrix for every video frame update. void updateMatrix(const int layerId, const GLfloat* matrix); // Remove the layer info from the mapping. @@ -64,10 +80,24 @@ public: GLuint getTextureId(const int layerId); // Return the matrix for surface texture corresponding to the layerId GLfloat* getMatrix(const int layerId); + // Return the aspect ratio for the video corresponding to the layerId + float getAspectRatio(const int layerId); // Delete the GL textures void deleteUnusedTextures(); + double drawIcon(const int layerId, IconType type); + + GLuint getSpinnerInnerTextureId() { return m_spinnerInnerTextureId; } + GLuint getSpinnerOuterTextureId() { return m_spinnerOuterTextureId; } + GLuint getPosterTextureId() { return m_posterTextureId; } + GLuint getPlayTextureId() { return m_playTextureId; } + GLuint getPauseTextureId() { return m_pauseTextureId; } + + void initGLResourcesIfNeeded(); + void cleanupGLResources(); + + static int getButtonSize(); private: // Get the sum of all the video size stored in m_videoLayerInfoMap. int getTotalMemUsage(); @@ -75,7 +105,7 @@ private: bool recycleTextureMem(); // The private function to remove layer. void removeLayerInternal(const int layerId); - + void initGLResources(); // Indexed by each layer's uniqueId, this map contains the important info // used for showing the video when playing or the screenshot when paused. HashMap<int, VideoLayerInfo*> m_videoLayerInfoMap; @@ -89,6 +119,18 @@ private: // thread, and really get deleted in the UI thread. Vector<GLuint> m_retiredTextures; android::Mutex m_retiredTexturesLock; + + GLuint createTextureFromImage(int buttonType); + + // Texture for showing the static image will be created at native side. + bool m_createdTexture; + GLuint m_posterTextureId; + GLuint m_spinnerOuterTextureId; + GLuint m_spinnerInnerTextureId; + GLuint m_playTextureId; + GLuint m_pauseTextureId; + + IntRect m_buttonRect; }; } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/android_graphics.cpp b/Source/WebCore/platform/graphics/android/android_graphics.cpp deleted file mode 100644 index e88c65d..0000000 --- a/Source/WebCore/platform/graphics/android/android_graphics.cpp +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright 2007, 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 "CachedPrefix.h" -#include "android_graphics.h" -#include "CachedColor.h" -#include "CachedRoot.h" -#include "IntRect.h" -#include "LayerAndroid.h" -#include "SkCanvas.h" -#include "SkCornerPathEffect.h" -#include "SkPath.h" -#include "SkRegion.h" -#include "WebViewCore.h" - -namespace android { - -// The CSS values for the inner and outer widths may be specified as fractions -#define WIDTH_SCALE 0.0625f // 1/16, to offset the scale in CSSStyleSelector - -void CursorRing::draw(SkCanvas* canvas, LayerAndroid* layer, IntRect* inval) -{ - if (!m_lastBounds.isEmpty()) { - *inval = m_lastBounds; - m_lastBounds = IntRect(0, 0, 0, 0); - } -#if USE(ACCELERATED_COMPOSITING) - int layerId = m_node->isInLayer() ? m_frame->layer(m_node)->uniqueId() : -1; - if (layer->uniqueId() != layerId) - return; -#endif - if (canvas->quickReject(m_bounds, SkCanvas::kAA_EdgeType)) { - DBG_NAV_LOGD("canvas->quickReject cursorNode=%d (nodePointer=%p)" - " bounds=(%d,%d,w=%d,h=%d)", m_node->index(), m_node->nodePointer(), - m_bounds.x(), m_bounds.y(), m_bounds.width(), m_bounds.height()); - return; - } - const CachedColor& colors = m_frame->color(m_node); - unsigned rectCount = m_rings.size(); - SkRegion rgn; - SkPath path; - for (unsigned i = 0; i < rectCount; i++) - { - SkRect r(m_rings[i]); - SkIRect ir; - - r.round(&ir); - ir.inset(-colors.outset(), -colors.outset()); - rgn.op(ir, SkRegion::kUnion_Op); - } - rgn.getBoundaryPath(&path); - - SkPaint paint; - paint.setAntiAlias(true); - paint.setPathEffect(new SkCornerPathEffect( - SkIntToScalar(colors.radius())))->unref(); - SkColor outer; - SkColor inner; - if (m_isPressed) { - SkColor pressed; - pressed = colors.fillColor(); - paint.setColor(pressed); - canvas->drawPath(path, paint); - outer = colors.pressedOuterColor(); - inner = colors.pressedInnerColor(); - } else { - outer = colors.selectedOuterColor(); - inner = colors.selectedInnerColor(); - } - paint.setStyle(SkPaint::kStroke_Style); - paint.setStrokeWidth(colors.outerWidth() * WIDTH_SCALE); - paint.setColor(outer); - canvas->drawPath(path, paint); - paint.setStrokeWidth(colors.innerWidth() * WIDTH_SCALE); - paint.setColor(inner); - canvas->drawPath(path, paint); - SkRect localBounds, globalBounds; - localBounds = path.getBounds(); - float width = std::max(colors.innerWidth(), colors.outerWidth()); - width *= WIDTH_SCALE; - localBounds.inset(-width, -width); - const SkMatrix& matrix = canvas->getTotalMatrix(); - matrix.mapRect(&globalBounds, localBounds); - SkIRect globalIBounds; - globalBounds.round(&globalIBounds); - m_lastBounds = globalIBounds; - inval->unite(m_lastBounds); -} - -void CursorRing::setIsButton(const CachedNode* node) -{ - m_isButton = false; -} - -bool CursorRing::setup() -{ - m_node->cursorRings(m_frame, &m_rings); - if (!m_rings.size()) { - DBG_NAV_LOG("!rings.size()"); - m_viewImpl->m_hasCursorBounds = false; - return false; - } - setIsButton(m_node); - m_bounds = m_node->bounds(m_frame); - m_viewImpl->updateCursorBounds(m_root, m_frame, m_node); - - bool useHitBounds = m_node->useHitBounds(); - if (useHitBounds) - m_bounds = m_node->hitBounds(m_frame); - if (useHitBounds || m_node->useBounds()) { - m_rings.clear(); - m_rings.append(m_bounds); - } - m_absBounds = m_node->bounds(m_frame); - const CachedColor& colors = m_frame->color(m_node); - m_bounds.inflate(SkScalarCeil(colors.outerWidth())); - m_absBounds.inflate(SkScalarCeil(colors.outerWidth())); - if (!m_node->hasCursorRing() || (m_node->isPlugin() && m_node->isFocus())) - return false; -#if DEBUG_NAV_UI - const WebCore::IntRect& ring = m_rings[0]; - DBG_NAV_LOGD("cursorNode=%d (nodePointer=%p) pressed=%s rings=%d" - " (%d, %d, %d, %d) isPlugin=%s", - m_node->index(), m_node->nodePointer(), - m_isPressed ? "true" : "false", - m_rings.size(), ring.x(), ring.y(), ring.width(), ring.height(), - m_node->isPlugin() ? "true" : "false"); - DBG_NAV_LOGD("[%d] inner=%d outer=%d outset=%d radius=%d" - " fill=0x%08x pin=0x%08x pout=0x%08x sin=0x%08x sout=0x%08x", - m_node->colorIndex(), colors.innerWidth(), colors.outerWidth(), - colors.outset(), colors.radius(), colors.fillColor(), - colors.pressedInnerColor(), colors.pressedOuterColor(), - colors.selectedInnerColor(), colors.selectedInnerColor()); -#endif - return true; -} - -} diff --git a/Source/WebCore/platform/graphics/android/android_graphics.h b/Source/WebCore/platform/graphics/android/android_graphics.h index 60ac115..7faa781 100644 --- a/Source/WebCore/platform/graphics/android/android_graphics.h +++ b/Source/WebCore/platform/graphics/android/android_graphics.h @@ -26,53 +26,17 @@ #ifndef android_graphics_DEFINED #define android_graphics_DEFINED -#include "DrawExtra.h" -#include "IntRect.h" -#include "SkTypes.h" -#include "wtf/Vector.h" - namespace WebCore { class GraphicsContext; - class GLExtras; } +class SkCanvas; -SkCanvas* android_gc2canvas(GraphicsContext* gc); - -namespace android { - -class CachedFrame; -class CachedNode; -class CachedRoot; -class WebViewCore; - -// Data and methods for cursor rings +// TODO: Move this somewhere else. The implementation for this is actually in +// GraphicsContextAndroid.cpp, but this is used by a handful of other files +SkCanvas* android_gc2canvas(WebCore::GraphicsContext* gc); // used to inflate node cache entry #define CURSOR_RING_HIT_TEST_RADIUS 5 -class CursorRing : public DrawExtra { -public: - CursorRing(WebViewCore* core) : m_viewImpl(core) {} - virtual ~CursorRing() {} - virtual void draw(SkCanvas* , LayerAndroid* , IntRect* ); - void setIsButton(const CachedNode* ); - bool setup(); - WTF::Vector<IntRect>& rings() { return m_rings; } -private: - friend class WebView; - friend class WebCore::GLExtras; - WebViewCore* m_viewImpl; // copy for convenience - WTF::Vector<IntRect> m_rings; - IntRect m_bounds; - IntRect m_absBounds; - IntRect m_lastBounds; - const CachedRoot* m_root; - const CachedFrame* m_frame; - const CachedNode* m_node; - bool m_isButton; - bool m_isPressed; -}; - -} #endif diff --git a/Source/WebCore/platform/network/android/ResourceHandleAndroid.cpp b/Source/WebCore/platform/network/android/ResourceHandleAndroid.cpp index 13a26f0..4bc918b 100644 --- a/Source/WebCore/platform/network/android/ResourceHandleAndroid.cpp +++ b/Source/WebCore/platform/network/android/ResourceHandleAndroid.cpp @@ -96,9 +96,7 @@ void ResourceHandle::platformSetDefersLoading(bool) } // This static method is called to check to see if a POST response is in -// the cache. The JNI call through to the HTTP cache stored on the Java -// side may be slow, but is only used during a navigation to -// a POST response. +// the cache. bool ResourceHandle::willLoadFromCache(ResourceRequest& request, Frame*) { // set the cache policy correctly, copied from diff --git a/Source/WebCore/platform/network/android/ResourceLoaderAndroid.h b/Source/WebCore/platform/network/android/ResourceLoaderAndroid.h index f627d62..5ff2322 100644 --- a/Source/WebCore/platform/network/android/ResourceLoaderAndroid.h +++ b/Source/WebCore/platform/network/android/ResourceLoaderAndroid.h @@ -46,7 +46,6 @@ public: virtual void pauseLoad(bool) = 0; // END ANDROID TODO - // Call to java to find out if this URL is in the cache static bool willLoadFromCache(const WebCore::KURL&, int64_t identifier); protected: ResourceLoaderAndroid() { } diff --git a/Source/WebCore/platform/network/android/ResourceRequestAndroid.cpp b/Source/WebCore/platform/network/android/ResourceRequestAndroid.cpp index 00735f3..1519e9c 100644 --- a/Source/WebCore/platform/network/android/ResourceRequestAndroid.cpp +++ b/Source/WebCore/platform/network/android/ResourceRequestAndroid.cpp @@ -30,17 +30,10 @@ namespace WebCore { unsigned initializeMaximumHTTPConnectionCountPerHost() { -#if USE(CHROME_NETWORK_STACK) // The chromium network stack already handles limiting the number of // parallel requests per host, so there's no need to do it here. Therefore, // this is set to a high value that should never be hit in practice. return 10000; -#else - // This is used by the loader to control the number of parallel load - // requests. Our java framework has 4 threads that can each pipeline up to - // 5 requests. Use 20 as a maximum number. - return 20; -#endif } } // namespace WebCore diff --git a/Source/WebCore/platform/text/android/HyphenationAndroid.cpp b/Source/WebCore/platform/text/android/HyphenationAndroid.cpp index d1bd839..9933715 100644 --- a/Source/WebCore/platform/text/android/HyphenationAndroid.cpp +++ b/Source/WebCore/platform/text/android/HyphenationAndroid.cpp @@ -28,7 +28,7 @@ // For external hyphenation library. #include "hyphen.h" -#include <utils/AssetManager.h> +#include <androidfw/AssetManager.h> #include <wtf/text/CString.h> #include <wtf/text/WTFString.h> diff --git a/Source/WebCore/plugins/PluginView.cpp b/Source/WebCore/plugins/PluginView.cpp index c39ceac..ffefc71 100644 --- a/Source/WebCore/plugins/PluginView.cpp +++ b/Source/WebCore/plugins/PluginView.cpp @@ -830,8 +830,6 @@ PassRefPtr<JSC::Bindings::Instance> PluginView::bindingInstance() } #endif -#if USE(V8) -// This is really JS engine independent NPObject* PluginView::getNPObject() { #if ENABLE(NETSCAPE_PLUGIN_API) if (!m_plugin || !m_plugin->pluginFuncs()->getvalue) @@ -859,7 +857,6 @@ NPObject* PluginView::getNPObject() { return 0; #endif // NETSCAPE_PLUGIN_API } -#endif // V8 void PluginView::disconnectStream(PluginStream* stream) { diff --git a/Source/WebCore/plugins/PluginView.h b/Source/WebCore/plugins/PluginView.h index 976c65c..bf77e51 100644 --- a/Source/WebCore/plugins/PluginView.h +++ b/Source/WebCore/plugins/PluginView.h @@ -202,9 +202,7 @@ namespace WebCore { void (*timerFunc)(NPP, uint32_t timerID)); void unscheduleTimer(NPP, uint32_t timerID); #endif -#if USE(V8) NPObject* getNPObject(); -#endif virtual void invalidateRect(const IntRect&); diff --git a/Source/WebCore/plugins/android/PluginViewAndroid.cpp b/Source/WebCore/plugins/android/PluginViewAndroid.cpp index dba7d3b..315d8a4 100644 --- a/Source/WebCore/plugins/android/PluginViewAndroid.cpp +++ b/Source/WebCore/plugins/android/PluginViewAndroid.cpp @@ -63,10 +63,6 @@ #include "ScriptController.h" #include "Settings.h" -#if USE(JSC) -#include <runtime/JSLock.h> -#endif - #include <wtf/ASCIICType.h> // #include "runtime.h" #include "WebViewCore.h" @@ -484,9 +480,6 @@ void PluginView::setNPWindowIfNeeded() m_npWindow.clipRect.bottom = m_pageRect.y() + m_pageRect.height(); if (m_plugin->pluginFuncs()->setwindow) { -#if USE(JSC) - JSC::JSLock::DropAllLocks dropAllLocks(false); -#endif setCallingPlugin(true); m_plugin->pluginFuncs()->setwindow(m_instance, &m_npWindow); setCallingPlugin(false); diff --git a/Source/WebCore/rendering/InlineTextBox.cpp b/Source/WebCore/rendering/InlineTextBox.cpp index 5815b8b..d5eeeae 100644 --- a/Source/WebCore/rendering/InlineTextBox.cpp +++ b/Source/WebCore/rendering/InlineTextBox.cpp @@ -43,6 +43,7 @@ #include "Text.h" #include "break_lines.h" #include <wtf/AlwaysInline.h> +#include <wtf/text/CString.h> using namespace std; @@ -1069,8 +1070,12 @@ void InlineTextBox::paintTextMatchMarker(GraphicsContext* pt, const FloatPoint& renderer()->theme()->platformInactiveTextSearchHighlightColor(); pt->save(); updateGraphicsContext(pt, color, color, 0, style->colorSpace()); // Don't draw text at all! +#if PLATFORM(ANDROID) + pt->drawHighlightForText(font, run, FloatPoint(boxOrigin.x(), boxOrigin.y() - deltaY), selHeight, color, style->colorSpace(), sPos, ePos, marker.activeMatch); +#else pt->clip(FloatRect(boxOrigin.x(), boxOrigin.y() - deltaY, m_logicalWidth, selHeight)); pt->drawHighlightForText(font, run, FloatPoint(boxOrigin.x(), boxOrigin.y() - deltaY), selHeight, color, style->colorSpace(), sPos, ePos); +#endif pt->restore(); } } diff --git a/Source/WebCore/rendering/RenderArena.cpp b/Source/WebCore/rendering/RenderArena.cpp index 57ed978..e15101f 100644 --- a/Source/WebCore/rendering/RenderArena.cpp +++ b/Source/WebCore/rendering/RenderArena.cpp @@ -136,11 +136,4 @@ void RenderArena::free(size_t size, void* ptr) #endif } -#ifdef ANDROID_INSTRUMENT -size_t RenderArena::reportPoolSize() const -{ - return ReportPoolSize(&m_pool); -} -#endif - } // namespace WebCore diff --git a/Source/WebCore/rendering/RenderArena.h b/Source/WebCore/rendering/RenderArena.h index 5d2559a..e1ff535 100644 --- a/Source/WebCore/rendering/RenderArena.h +++ b/Source/WebCore/rendering/RenderArena.h @@ -53,10 +53,6 @@ public: void* allocate(size_t); void free(size_t, void*); -#ifdef ANDROID_INSTRUMENT - size_t reportPoolSize() const; -#endif - private: // Underlying arena pool ArenaPool m_pool; diff --git a/Source/WebCore/rendering/RenderBlockLineLayout.cpp b/Source/WebCore/rendering/RenderBlockLineLayout.cpp index df20063..a2469a0 100644 --- a/Source/WebCore/rendering/RenderBlockLineLayout.cpp +++ b/Source/WebCore/rendering/RenderBlockLineLayout.cpp @@ -895,6 +895,10 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintLogica m_minPreferredLogicalWidth = min(m_minPreferredLogicalWidth, maxWidth); m_maxPreferredLogicalWidth = min(m_maxPreferredLogicalWidth, maxWidth); + // if overflow isn't visible, block elements may get clipped + // due to the limited content width. disable overflow clipping. + setHasOverflowClip(false); + IntRect overflow = layoutOverflowRect(); if (overflow.width() > maxWidth) { overflow.setWidth(maxWidth); diff --git a/Source/WebCore/rendering/RenderHTMLCanvas.cpp b/Source/WebCore/rendering/RenderHTMLCanvas.cpp index de2a2c1..03b406b 100644 --- a/Source/WebCore/rendering/RenderHTMLCanvas.cpp +++ b/Source/WebCore/rendering/RenderHTMLCanvas.cpp @@ -47,6 +47,13 @@ RenderHTMLCanvas::RenderHTMLCanvas(HTMLCanvasElement* element) bool RenderHTMLCanvas::requiresLayer() const { +#if PLATFORM(ANDROID) + // All Canvas are drawn on their own composited layer + // This improves performances a lot (as this simplify + // the repaint/inval chain dealing with the PictureSet) + return true; +#endif + if (RenderReplaced::requiresLayer()) return true; diff --git a/Source/WebCore/rendering/RenderLayer.cpp b/Source/WebCore/rendering/RenderLayer.cpp index cdc4c05..66aab18 100644 --- a/Source/WebCore/rendering/RenderLayer.cpp +++ b/Source/WebCore/rendering/RenderLayer.cpp @@ -64,6 +64,7 @@ #include "HTMLNames.h" #if ENABLE(ANDROID_OVERFLOW_SCROLL) #include "HTMLTextAreaElement.h" +#include "GraphicsLayerAndroid.h" #endif #include "HitTestRequest.h" #include "HitTestResult.h" @@ -1389,11 +1390,27 @@ void RenderLayer::scrollTo(int x, int y) view->updateWidgetPositions(); } +#if PLATFORM(ANDROID) + GraphicsLayerAndroid* backingLayer = 0; + bool scrollableContent = false; +#endif + #if USE(ACCELERATED_COMPOSITING) if (compositor()->inCompositingMode()) { // Our stacking context is guaranteed to contain all of our descendants that may need // repositioning, so update compositing layers from there. +#if ENABLE(ANDROID_OVERFLOW_SCROLL) + if (view && backing() && backing()->graphicsLayer()) { + backingLayer = static_cast<GraphicsLayerAndroid*>(backing()->graphicsLayer()); + scrollableContent = backingLayer->contentLayer() + && backingLayer->contentLayer()->contentIsScrollable(); + } + // If we have a scrollable content, no need to do this + RenderLayer* compositingAncestor = enclosingCompositingLayer(); + if (!scrollableContent && compositingAncestor) { +#else if (RenderLayer* compositingAncestor = stackingContext()->enclosingCompositingLayer()) { +#endif if (compositor()->compositingConsultsOverlap()) compositor()->updateCompositingLayers(CompositingUpdateOnScroll, compositingAncestor); else { @@ -1422,8 +1439,10 @@ void RenderLayer::scrollTo(int x, int y) #if ENABLE(ANDROID_OVERFLOW_SCROLL) // On android, scrollable areas are put on composited layers, so we // do not need to repaint simply because we are scrolling - if (view && !hasOverflowScroll()) + if (view && !(hasOverflowScroll() || scrollableContent)) renderer()->repaintUsingContainer(repaintContainer, rectForRepaint); + if (backingLayer && (hasOverflowScroll() || scrollableContent)) + backingLayer->updateScrollOffset(); #else if (view) renderer()->repaintUsingContainer(repaintContainer, rectForRepaint); diff --git a/Source/WebCore/rendering/RenderLayer.h b/Source/WebCore/rendering/RenderLayer.h index 02ab8e9..5e421f0 100644 --- a/Source/WebCore/rendering/RenderLayer.h +++ b/Source/WebCore/rendering/RenderLayer.h @@ -498,6 +498,12 @@ public: bool hasOverflowScroll() const { return m_hasOverflowScroll; } bool hasOverflowParent() const; #endif +#if PLATFORM(ANDROID) + bool intrinsicallyComposited() const { return m_intrinsicallyComposited; } + void setIntrinsicallyComposited(bool intrinsicallyComposited) { + m_intrinsicallyComposited = intrinsicallyComposited; + } +#endif private: // The normal operator new is disallowed on all render objects. @@ -751,6 +757,9 @@ protected: bool m_shouldComposite : 1; #endif #endif +#if PLATFORM(ANDROID) + bool m_intrinsicallyComposited : 1; +#endif bool m_containsDirtyOverlayScrollbars : 1; #if ENABLE(ANDROID_OVERFLOW_SCROLL) diff --git a/Source/WebCore/rendering/RenderLayerCompositor.cpp b/Source/WebCore/rendering/RenderLayerCompositor.cpp index 33bf2f7..d7f5c6b 100644 --- a/Source/WebCore/rendering/RenderLayerCompositor.cpp +++ b/Source/WebCore/rendering/RenderLayerCompositor.cpp @@ -92,6 +92,10 @@ struct CompositingState { RenderLayer* m_compositingAncestor; bool m_subtreeIsCompositing; + // m_compositingBounds is only used in computeCompositingRequirements. It can be either the + // ancestor bounds or the bounds for the sibling layers which are above the composited layer. + // It is used to reject creating unnecesary layers. + IntRect m_compositingBounds; #if ENABLE(COMPOSITED_FIXED_ELEMENTS) bool m_fixedSibling; bool m_hasFixedElement; @@ -678,7 +682,12 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, O layer->updateLayerPosition(); layer->updateZOrderLists(); layer->updateNormalFlowList(); - +#if PLATFORM(ANDROID) + RenderObject* renderer = layer->renderer(); + bool intCom = requiresCompositingLayer(layer); + layer->setIntrinsicallyComposited(intCom); +#endif + // Clear the flag layer->setHasCompositingDescendant(false); @@ -693,7 +702,10 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, O if (absBounds.isEmpty()) absBounds.setSize(IntSize(1, 1)); haveComputedBounds = true; - mustOverlapCompositedLayers = overlapsCompositedLayers(*overlapMap, absBounds); + // If the current subtree is not compositing, and the layer is fully inside the current compositing bounnds, + // there is no need to do the overlap test. This reduces the total number of the composited layers. + if (compositingState.m_subtreeIsCompositing || !compositingState.m_compositingBounds.contains(absBounds)) + mustOverlapCompositedLayers = overlapsCompositedLayers(*overlapMap, absBounds); } #if ENABLE(COMPOSITED_FIXED_ELEMENTS) @@ -709,6 +721,10 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, O // a compositing layer among them, so start by inheriting the compositing // ancestor with m_subtreeIsCompositing set to false. CompositingState childState(compositingState.m_compositingAncestor); + if (compositingState.m_subtreeIsCompositing) + childState.m_compositingBounds = absBounds; + else + childState.m_compositingBounds = compositingState.m_compositingBounds; #ifndef NDEBUG ++childState.m_depth; #endif @@ -729,6 +745,7 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, O compositingState.m_subtreeIsCompositing = true; // This layer now acts as the ancestor for kids. childState.m_compositingAncestor = layer; + childState.m_compositingBounds = absBounds; if (overlapMap) addToOverlapMap(*overlapMap, layer, absBounds, haveComputedBounds); } @@ -1398,6 +1415,10 @@ bool RenderLayerCompositor::requiresCompositingForAndroidLayers(const RenderLaye if (layer->isFixed()) return true; #endif + + if (layer->renderer()->isCanvas()) + return true; + return false; } #endif diff --git a/Source/WebCore/rendering/RenderText.cpp b/Source/WebCore/rendering/RenderText.cpp index b35820a..6f4d3b7 100644 --- a/Source/WebCore/rendering/RenderText.cpp +++ b/Source/WebCore/rendering/RenderText.cpp @@ -37,6 +37,7 @@ #include "RenderCombineText.h" #include "RenderLayer.h" #include "RenderView.h" +#include "Settings.h" #include "Text.h" #include "TextBreakIterator.h" #include "TextResourceDecoder.h" @@ -53,6 +54,37 @@ using namespace Unicode; namespace WebCore { +class SecureTextTimer; +typedef HashMap<RenderText*, SecureTextTimer*> SecureTextTimerMap; +static SecureTextTimerMap* gSecureTextTimers = 0; + +class SecureTextTimer : public TimerBase { +public: + SecureTextTimer(RenderText* renderText) + : m_renderText(renderText) + , m_lastTypedCharacterOffset(-1) + { + } + + void restartWithNewText(unsigned lastTypedCharacterOffset) + { + m_lastTypedCharacterOffset = lastTypedCharacterOffset; + startOneShot(m_renderText->document()->settings()->passwordEchoDurationInSeconds()); + } + void invalidate() { m_lastTypedCharacterOffset = -1; } + unsigned lastTypedCharacterOffset() { return m_lastTypedCharacterOffset; } + +private: + virtual void fired() + { + ASSERT(gSecureTextTimers->contains(m_renderText)); + m_renderText->setText(m_renderText->text(), true /* forcing setting text as it may be masked later */); + } + + RenderText* m_renderText; + int m_lastTypedCharacterOffset; +}; + static void makeCapitalized(String* string, UChar previous) { if (string->isNull()) @@ -196,6 +228,9 @@ void RenderText::removeAndDestroyTextBoxes() void RenderText::destroy() { + if (SecureTextTimer* secureTextTimer = gSecureTextTimers ? gSecureTextTimers->take(this) : 0) + delete secureTextTimer; + removeAndDestroyTextBoxes(); RenderObject::destroy(); } @@ -1140,13 +1175,13 @@ void RenderText::setTextInternal(PassRefPtr<StringImpl> text) case TSNONE: break; case TSCIRCLE: - m_text.makeSecure(whiteBullet); + secureText(whiteBullet); break; case TSDISC: - m_text.makeSecure(bullet); + secureText(bullet); break; case TSSQUARE: - m_text.makeSecure(blackSquare); + secureText(blackSquare); } } @@ -1156,6 +1191,28 @@ void RenderText::setTextInternal(PassRefPtr<StringImpl> text) m_isAllASCII = m_text.containsOnlyASCII(); } +void RenderText::secureText(UChar mask) +{ + if (!m_text.length()) + return; + + int lastTypedCharacterOffsetToReveal = -1; + String revealedText; + SecureTextTimer* secureTextTimer = gSecureTextTimers ? gSecureTextTimers->get(this) : 0; + if (secureTextTimer && secureTextTimer->isActive()) { + lastTypedCharacterOffsetToReveal = secureTextTimer->lastTypedCharacterOffset(); + if (lastTypedCharacterOffsetToReveal >= 0) + revealedText.append(m_text[lastTypedCharacterOffsetToReveal]); + } + + m_text.makeSecure(mask); + if (lastTypedCharacterOffsetToReveal >= 0) { + m_text.replace(lastTypedCharacterOffsetToReveal, 1, revealedText); + // m_text may be updated later before timer fires. We invalidate the lastTypedCharacterOffset to avoid inconsistency. + secureTextTimer->invalidate(); + } +} + void RenderText::setText(PassRefPtr<StringImpl> text, bool force) { ASSERT(text); @@ -1590,4 +1647,17 @@ void RenderText::checkConsistency() const #endif +void RenderText::momentarilyRevealLastTypedCharacter(unsigned lastTypedCharacterOffset) +{ + if (!gSecureTextTimers) + gSecureTextTimers = new SecureTextTimerMap; + + SecureTextTimer* secureTextTimer = gSecureTextTimers->get(this); + if (!secureTextTimer) { + secureTextTimer = new SecureTextTimer(this); + gSecureTextTimers->add(this, secureTextTimer); + } + secureTextTimer->restartWithNewText(lastTypedCharacterOffset); +} + } // namespace WebCore diff --git a/Source/WebCore/rendering/RenderText.h b/Source/WebCore/rendering/RenderText.h index 2008dad..f89a762 100644 --- a/Source/WebCore/rendering/RenderText.h +++ b/Source/WebCore/rendering/RenderText.h @@ -117,6 +117,9 @@ public: bool containsReversedText() const { return m_containsReversedText; } + bool isSecure() const { return style()->textSecurity() != TSNONE; } + void momentarilyRevealLastTypedCharacter(unsigned lastTypedCharacterOffset); + InlineTextBox* findNextInlineTextBox(int offset, int& pos) const; bool allowTabs() const { return !style()->collapseWhiteSpace(); } @@ -158,6 +161,7 @@ private: void updateNeedsTranscoding(); inline void transformText(String&) const; + void secureText(UChar mask); float m_minWidth; // here to minimize padding in 64-bit. diff --git a/Source/WebCore/rendering/style/RenderStyle.h b/Source/WebCore/rendering/style/RenderStyle.h index fad5a7b..ea01064 100644 --- a/Source/WebCore/rendering/style/RenderStyle.h +++ b/Source/WebCore/rendering/style/RenderStyle.h @@ -786,19 +786,6 @@ public: ESpeak speak() { return static_cast<ESpeak>(rareInheritedData->speak); } -#ifdef ANDROID_CSS_RING - // called when building nav cache to determine if the ring data is unchanged - const void* ringData() const { return reinterpret_cast<const void*>(rareInheritedData.get()); } - Color ringFillColor() const { return rareInheritedData->ringFillColor; } - Length ringInnerWidth() const { return rareInheritedData->ringInnerWidth; } - Length ringOuterWidth() const { return rareInheritedData->ringOuterWidth; } - Length ringOutset() const { return rareInheritedData->ringOutset; } - Color ringPressedInnerColor() const { return rareInheritedData->ringPressedInnerColor; } - Color ringPressedOuterColor() const { return rareInheritedData->ringPressedOuterColor; } - Length ringRadius() const { return rareInheritedData->ringRadius; } - Color ringSelectedInnerColor() const { return rareInheritedData->ringSelectedInnerColor; } - Color ringSelectedOuterColor() const { return rareInheritedData->ringSelectedOuterColor; } -#endif #ifdef ANDROID_CSS_TAP_HIGHLIGHT_COLOR Color tapHighlightColor() const { return rareInheritedData->tapHighlightColor; } #endif @@ -1142,21 +1129,6 @@ public: void setTextSizeAdjust(bool b) { SET_VAR(rareInheritedData, textSizeAdjust, b); } void setTextSecurity(ETextSecurity aTextSecurity) { SET_VAR(rareInheritedData, textSecurity, aTextSecurity); } -#ifdef ANDROID_CSS_RING - void setRingFillColor(const Color& v) { SET_VAR(rareInheritedData, ringFillColor, v); } - void setRingInnerWidth(Length v) { SET_VAR(rareInheritedData, ringInnerWidth, v); } - void setRingOuterWidth(Length v) { SET_VAR(rareInheritedData, ringOuterWidth, v); } - void setRingOutset(Length v) { SET_VAR(rareInheritedData, ringOutset, v); } - void setRingPressedInnerColor(const Color& v) { - SET_VAR(rareInheritedData, ringPressedInnerColor, v); } - void setRingPressedOuterColor(const Color& v) { - SET_VAR(rareInheritedData, ringPressedOuterColor, v); } - void setRingRadius(Length v) { SET_VAR(rareInheritedData, ringRadius, v); } - void setRingSelectedInnerColor(const Color& v) { - SET_VAR(rareInheritedData, ringSelectedInnerColor, v); } - void setRingSelectedOuterColor(const Color& v) { - SET_VAR(rareInheritedData, ringSelectedOuterColor, v); } -#endif #ifdef ANDROID_CSS_TAP_HIGHLIGHT_COLOR void setTapHighlightColor(const Color& v) { SET_VAR(rareInheritedData, tapHighlightColor, v); } #endif @@ -1359,17 +1331,6 @@ public: static const Vector<StyleDashboardRegion>& noneDashboardRegions(); #endif -#ifdef ANDROID_CSS_RING - static Color initialRingFillColor() { return Color::ringFill; } - static Length initialRingInnerWidth() { return Length(16, Fixed); } // 1.0 - static Length initialRingOuterWidth() { return Length(40, Fixed); } // 2.5 - static Length initialRingOutset() { return Length(3, Fixed); } - static Color initialRingSelectedInnerColor() { return Color::ringSelectedInner; } - static Color initialRingSelectedOuterColor() { return Color::ringSelectedOuter; } - static Color initialRingPressedInnerColor() { return Color::ringPressedInner; } - static Color initialRingPressedOuterColor() { return Color::ringPressedOuter; } - static Length initialRingRadius() { return Length(1, Fixed); } -#endif #ifdef ANDROID_CSS_TAP_HIGHLIGHT_COLOR static Color initialTapHighlightColor() { return Color::tap; } #endif diff --git a/Source/WebCore/rendering/style/StyleRareInheritedData.cpp b/Source/WebCore/rendering/style/StyleRareInheritedData.cpp index 2253d1c..a7acc4a 100644 --- a/Source/WebCore/rendering/style/StyleRareInheritedData.cpp +++ b/Source/WebCore/rendering/style/StyleRareInheritedData.cpp @@ -32,17 +32,6 @@ namespace WebCore { StyleRareInheritedData::StyleRareInheritedData() : textStrokeWidth(RenderStyle::initialTextStrokeWidth()) -#ifdef ANDROID_CSS_RING - , ringFillColor(RenderStyle::initialRingFillColor()) - , ringInnerWidth(RenderStyle::initialRingInnerWidth()) - , ringOuterWidth(RenderStyle::initialRingOuterWidth()) - , ringOutset(RenderStyle::initialRingOutset()) - , ringPressedInnerColor(RenderStyle::initialRingPressedInnerColor()) - , ringPressedOuterColor(RenderStyle::initialRingPressedOuterColor()) - , ringRadius(RenderStyle::initialRingRadius()) - , ringSelectedInnerColor(RenderStyle::initialRingSelectedInnerColor()) - , ringSelectedOuterColor(RenderStyle::initialRingSelectedOuterColor()) -#endif #ifdef ANDROID_CSS_TAP_HIGHLIGHT_COLOR , tapHighlightColor(RenderStyle::initialTapHighlightColor()) #endif @@ -77,18 +66,6 @@ StyleRareInheritedData::StyleRareInheritedData(const StyleRareInheritedData& o) , textStrokeColor(o.textStrokeColor) , textStrokeWidth(o.textStrokeWidth) , textFillColor(o.textFillColor) - , textEmphasisColor(o.textEmphasisColor) -#ifdef ANDROID_CSS_RING - , ringFillColor(o.ringFillColor) - , ringInnerWidth(o.ringInnerWidth) - , ringOuterWidth(o.ringOuterWidth) - , ringOutset(o.ringOutset) - , ringPressedInnerColor(o.ringPressedInnerColor) - , ringPressedOuterColor(o.ringPressedOuterColor) - , ringRadius(o.ringRadius) - , ringSelectedInnerColor(o.ringSelectedInnerColor) - , ringSelectedOuterColor(o.ringSelectedOuterColor) -#endif #ifdef ANDROID_CSS_TAP_HIGHLIGHT_COLOR , tapHighlightColor(o.tapHighlightColor) #endif @@ -157,17 +134,6 @@ bool StyleRareInheritedData::operator==(const StyleRareInheritedData& o) const && nbspMode == o.nbspMode && khtmlLineBreak == o.khtmlLineBreak && textSizeAdjust == o.textSizeAdjust -#ifdef ANDROID_CSS_RING - && ringFillColor == o.ringFillColor - && ringInnerWidth == o.ringInnerWidth - && ringOuterWidth == o.ringOuterWidth - && ringOutset == o.ringOutset - && ringPressedInnerColor == o.ringPressedInnerColor - && ringPressedOuterColor == o.ringPressedOuterColor - && ringRadius == o.ringRadius - && ringSelectedInnerColor == o.ringSelectedInnerColor - && ringSelectedOuterColor == o.ringSelectedOuterColor -#endif #ifdef ANDROID_CSS_TAP_HIGHLIGHT_COLOR && tapHighlightColor == o.tapHighlightColor #endif diff --git a/Source/WebCore/rendering/style/StyleRareInheritedData.h b/Source/WebCore/rendering/style/StyleRareInheritedData.h index 39cfe3c..16fcc5f 100644 --- a/Source/WebCore/rendering/style/StyleRareInheritedData.h +++ b/Source/WebCore/rendering/style/StyleRareInheritedData.h @@ -58,17 +58,6 @@ public: Color textFillColor; Color textEmphasisColor; -#ifdef ANDROID_CSS_RING - Color ringFillColor; - Length ringInnerWidth; - Length ringOuterWidth; - Length ringOutset; - Color ringPressedInnerColor; - Color ringPressedOuterColor; - Length ringRadius; - Color ringSelectedInnerColor; - Color ringSelectedOuterColor; -#endif #ifdef ANDROID_CSS_TAP_HIGHLIGHT_COLOR Color tapHighlightColor; #endif diff --git a/Source/WebCore/storage/AbstractDatabase.h b/Source/WebCore/storage/AbstractDatabase.h index 9279adc..e0a277f 100644 --- a/Source/WebCore/storage/AbstractDatabase.h +++ b/Source/WebCore/storage/AbstractDatabase.h @@ -36,7 +36,7 @@ #include "SQLiteDatabase.h" #include <wtf/Forward.h> #include <wtf/ThreadSafeRefCounted.h> -#ifndef NDEBUG +#if !LOG_DISABLED || !ERROR_DISABLED #include "SecurityOrigin.h" #endif @@ -109,7 +109,7 @@ protected: unsigned long m_estimatedSize; String m_filename; -#ifndef NDEBUG +#if !LOG_DISABLED || !ERROR_DISABLED String databaseDebugName() const { return m_contextThreadSecurityOrigin->toString() + "::" + m_name; } #endif diff --git a/Source/WebCore/storage/DatabaseTask.cpp b/Source/WebCore/storage/DatabaseTask.cpp index 343ae1e..ad744e5 100644 --- a/Source/WebCore/storage/DatabaseTask.cpp +++ b/Source/WebCore/storage/DatabaseTask.cpp @@ -62,7 +62,7 @@ void DatabaseTaskSynchronizer::taskCompleted() DatabaseTask::DatabaseTask(Database* database, DatabaseTaskSynchronizer* synchronizer) : m_database(database) , m_synchronizer(synchronizer) -#ifndef NDEBUG +#if !LOG_DISABLED , m_complete(false) #endif { @@ -70,13 +70,17 @@ DatabaseTask::DatabaseTask(Database* database, DatabaseTaskSynchronizer* synchro DatabaseTask::~DatabaseTask() { +#if !LOG_DISABLED ASSERT(m_complete || !m_synchronizer); +#endif } void DatabaseTask::performTask() { // Database tasks are meant to be used only once, so make sure this one hasn't been performed before. +#if !LOG_DISABLED ASSERT(!m_complete); +#endif LOG(StorageAPI, "Performing %s %p\n", debugTaskName(), this); @@ -86,7 +90,7 @@ void DatabaseTask::performTask() if (m_synchronizer) m_synchronizer->taskCompleted(); -#ifndef NDEBUG +#if !LOG_DISABLED m_complete = true; #endif } @@ -108,7 +112,7 @@ void Database::DatabaseOpenTask::doPerformTask() m_success = database()->performOpenAndVerify(m_setVersionInNewDatabase, m_code); } -#ifndef NDEBUG +#if !LOG_DISABLED const char* Database::DatabaseOpenTask::debugTaskName() const { return "DatabaseOpenTask"; @@ -128,7 +132,7 @@ void Database::DatabaseCloseTask::doPerformTask() database()->close(); } -#ifndef NDEBUG +#if !LOG_DISABLED const char* Database::DatabaseCloseTask::debugTaskName() const { return "DatabaseCloseTask"; @@ -150,7 +154,7 @@ void Database::DatabaseTransactionTask::doPerformTask() m_transaction->database()->inProgressTransactionCompleted(); } -#ifndef NDEBUG +#if !LOG_DISABLED const char* Database::DatabaseTransactionTask::debugTaskName() const { return "DatabaseTransactionTask"; @@ -172,7 +176,7 @@ void Database::DatabaseTableNamesTask::doPerformTask() m_tableNames = database()->performGetTableNames(); } -#ifndef NDEBUG +#if !LOG_DISABLED const char* Database::DatabaseTableNamesTask::debugTaskName() const { return "DatabaseTableNamesTask"; diff --git a/Source/WebCore/storage/DatabaseTask.h b/Source/WebCore/storage/DatabaseTask.h index e1df591..faadc69 100644 --- a/Source/WebCore/storage/DatabaseTask.h +++ b/Source/WebCore/storage/DatabaseTask.h @@ -90,7 +90,7 @@ private: Database* m_database; DatabaseTaskSynchronizer* m_synchronizer; -#ifndef NDEBUG +#if !LOG_DISABLED virtual const char* debugTaskName() const = 0; bool m_complete; #endif @@ -107,7 +107,7 @@ private: DatabaseOpenTask(Database*, bool setVersionInNewDatabase, DatabaseTaskSynchronizer*, ExceptionCode&, bool& success); virtual void doPerformTask(); -#ifndef NDEBUG +#if !LOG_DISABLED virtual const char* debugTaskName() const; #endif @@ -127,7 +127,7 @@ private: DatabaseCloseTask(Database*, DatabaseTaskSynchronizer*); virtual void doPerformTask(); -#ifndef NDEBUG +#if !LOG_DISABLED virtual const char* debugTaskName() const; #endif }; @@ -146,7 +146,7 @@ private: DatabaseTransactionTask(PassRefPtr<SQLTransaction>); virtual void doPerformTask(); -#ifndef NDEBUG +#if !LOG_DISABLED virtual const char* debugTaskName() const; #endif @@ -164,7 +164,7 @@ private: DatabaseTableNamesTask(Database*, DatabaseTaskSynchronizer*, Vector<String>& names); virtual void doPerformTask(); -#ifndef NDEBUG +#if !LOG_DISABLED virtual const char* debugTaskName() const; #endif diff --git a/Source/WebCore/storage/SQLTransaction.cpp b/Source/WebCore/storage/SQLTransaction.cpp index dfcd568..0b1ad25 100644 --- a/Source/WebCore/storage/SQLTransaction.cpp +++ b/Source/WebCore/storage/SQLTransaction.cpp @@ -117,7 +117,7 @@ void SQLTransaction::enqueueStatement(PassRefPtr<SQLStatement> statement) m_statementQueue.append(statement); } -#ifndef NDEBUG +#if !LOG_DISABLED const char* SQLTransaction::debugStepName(SQLTransaction::TransactionStepMethod step) { if (step == &SQLTransaction::acquireLock) diff --git a/Source/WebCore/storage/SQLTransaction.h b/Source/WebCore/storage/SQLTransaction.h index 4c84f91..a0a83ed 100644 --- a/Source/WebCore/storage/SQLTransaction.h +++ b/Source/WebCore/storage/SQLTransaction.h @@ -105,7 +105,7 @@ private: void deliverTransactionErrorCallback(); void cleanupAfterTransactionErrorCallback(); -#ifndef NDEBUG +#if !LOG_DISABLED static const char* debugStepName(TransactionStepMethod); #endif diff --git a/Source/WebCore/svg/SVGFontFaceUriElement.h b/Source/WebCore/svg/SVGFontFaceUriElement.h index ad9ba97..3806315 100644 --- a/Source/WebCore/svg/SVGFontFaceUriElement.h +++ b/Source/WebCore/svg/SVGFontFaceUriElement.h @@ -45,22 +45,6 @@ private: virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0); virtual void insertedIntoDocument(); -#ifdef ANDROID_INSTRUMENT - void* operator new(size_t size) { - return SVGElement::operator new(size); - } - void* operator new[](size_t size) { - return SVGElement::operator new[](size); - } - - void operator delete(void* p, size_t size) { - SVGElement::operator delete(p, size); - } - void operator delete[](void* p, size_t size) { - SVGElement::operator delete[](p, size); - } -#endif - void loadFont(); CachedResourceHandle<CachedFont> m_cachedFont; diff --git a/Source/WebCore/workers/WorkerContext.idl b/Source/WebCore/workers/WorkerContext.idl index e31f5ad..5a6c407 100644 --- a/Source/WebCore/workers/WorkerContext.idl +++ b/Source/WebCore/workers/WorkerContext.idl @@ -126,6 +126,7 @@ module threads { attribute Int32ArrayConstructor Int32Array; // Usable with new operator attribute Uint32ArrayConstructor Uint32Array; // Usable with new operator attribute Float32ArrayConstructor Float32Array; // Usable with new operator + attribute Float64ArrayConstructor Float64Array; // Usable with new operator }; } diff --git a/Source/WebCore/xml/XSLImportRule.h b/Source/WebCore/xml/XSLImportRule.h index 3c5939d..5c0ca8a 100644 --- a/Source/WebCore/xml/XSLImportRule.h +++ b/Source/WebCore/xml/XSLImportRule.h @@ -52,22 +52,6 @@ public: bool isLoading(); void loadSheet(); -#ifdef ANDROID_INSTRUMENT - void* operator new(size_t size) { - return StyleBase::operator new(size); - } - void* operator new[](size_t size) { - return StyleBase::operator new[](size); - } - - void operator delete(void* p, size_t size) { - StyleBase::operator delete(p, size); - } - void operator delete[](void* p, size_t size) { - StyleBase::operator delete[](p, size); - } -#endif - private: XSLImportRule(XSLStyleSheet* parentSheet, const String& href); |