diff options
Diffstat (limited to 'Source/WebCore')
229 files changed, 8387 insertions, 10067 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..6ddf965 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 \ @@ -637,8 +639,11 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \ platform/graphics/android/BaseTile.cpp \ platform/graphics/android/BaseTileTexture.cpp \ platform/graphics/android/BitmapAllocatorAndroid.cpp \ + platform/graphics/android/CanvasLayer.cpp \ + platform/graphics/android/CanvasTexture.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,39 +658,40 @@ 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 \ platform/graphics/android/TilesProfiler.cpp \ - 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 +817,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.cpp b/Source/WebCore/html/HTMLCanvasElement.cpp index 9f51f10..e67cbf9 100644 --- a/Source/WebCore/html/HTMLCanvasElement.cpp +++ b/Source/WebCore/html/HTMLCanvasElement.cpp @@ -45,6 +45,7 @@ #include "MIMETypeRegistry.h" #include "Page.h" #include "RenderHTMLCanvas.h" +#include "RenderLayer.h" #include "Settings.h" #include <math.h> #include <stdio.h> @@ -225,6 +226,11 @@ void HTMLCanvasElement::didDraw(const FloatRect& rect) return; m_dirtyRect.unite(r); +#if PLATFORM(ANDROID) + // We handle invals ourselves and don't want webkit to repaint if we + // have put the canvas on a layer + if (!ro->hasLayer()) +#endif ro->repaintRectangle(enclosingIntRect(m_dirtyRect)); } diff --git a/Source/WebCore/html/HTMLCanvasElement.h b/Source/WebCore/html/HTMLCanvasElement.h index 9eab209..e485835 100644 --- a/Source/WebCore/html/HTMLCanvasElement.h +++ b/Source/WebCore/html/HTMLCanvasElement.h @@ -128,20 +128,8 @@ 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); - } +#if PLATFORM(ANDROID) + void clearDirtyRect() { m_dirtyRect = FloatRect(); } #endif private: 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/CachedResourceLoader.cpp b/Source/WebCore/loader/cache/CachedResourceLoader.cpp index 91c0629..fe25a93 100644 --- a/Source/WebCore/loader/cache/CachedResourceLoader.cpp +++ b/Source/WebCore/loader/cache/CachedResourceLoader.cpp @@ -293,6 +293,8 @@ bool CachedResourceLoader::canRequest(CachedResource::Type type, const KURL& url } #if ENABLE(LINK_PREFETCH) case CachedResource::LinkResource: + if (!m_document->settings()->linkPrefetchEnabled()) + return false; break; #endif } 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..8f2958c 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()) { @@ -1764,6 +1745,11 @@ void FrameView::scheduleRelayout() m_frame->ownerRenderer()->setNeedsLayout(true, true); } +#ifdef ANDROID_FLATTEN_FRAMESET + if (m_frame->ownerRenderer() && m_frame->ownerElement()->hasTagName(frameTag)) + m_frame->ownerRenderer()->setNeedsLayoutAndPrefWidthsRecalc(); +#endif + int delay = m_frame->document()->minimumLayoutDelay(); if (m_layoutTimer.isActive() && m_delayedLayout && !delay) unscheduleRelayout(); diff --git a/Source/WebCore/page/Settings.cpp b/Source/WebCore/page/Settings.cpp index e2312a9..f668f3e 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) @@ -148,6 +149,9 @@ Settings::Settings(Page* page) // they can't use by. Leaving enabled for now to not change existing behavior. , m_downloadableBinaryFontsEnabled(true) , m_xssAuditorEnabled(false) +#if ENABLE(LINK_PREFETCH) + , m_linkPrefetchEnabled(true) +#endif , m_acceleratedCompositingEnabled(true) , m_acceleratedCompositingFor3DTransformsEnabled(true) , m_acceleratedCompositingForVideoEnabled(true) @@ -192,6 +196,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. @@ -817,6 +826,13 @@ void Settings::setXSSAuditorEnabled(bool xssAuditorEnabled) m_xssAuditorEnabled = xssAuditorEnabled; } +#if ENABLE(LINK_PREFETCH) +void Settings::setLinkPrefetchEnabled(bool linkPrefetchEnabled) +{ + m_linkPrefetchEnabled = linkPrefetchEnabled; +} +#endif + void Settings::setAcceleratedCompositingEnabled(bool enabled) { if (m_acceleratedCompositingEnabled == enabled) diff --git a/Source/WebCore/page/Settings.h b/Source/WebCore/page/Settings.h index 31a5ad9..2cf7715 100644 --- a/Source/WebCore/page/Settings.h +++ b/Source/WebCore/page/Settings.h @@ -352,6 +352,11 @@ namespace WebCore { void setXSSAuditorEnabled(bool); bool xssAuditorEnabled() const { return m_xssAuditorEnabled; } +#if ENABLE(LINK_PREFETCH) + void setLinkPrefetchEnabled(bool); + bool linkPrefetchEnabled() const { return m_linkPrefetchEnabled; } +#endif + void setCanvasUsesAcceleratedDrawing(bool); bool canvasUsesAcceleratedDrawing() const { return m_canvasUsesAcceleratedDrawing; } @@ -458,6 +463,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 +522,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; @@ -559,6 +572,9 @@ namespace WebCore { bool m_acceleratedDrawingEnabled : 1; bool m_downloadableBinaryFontsEnabled : 1; bool m_xssAuditorEnabled : 1; +#if ENABLE(LINK_PREFETCH) + bool m_linkPrefetchEnabled : 1; +#endif bool m_acceleratedCompositingEnabled : 1; bool m_acceleratedCompositingFor3DTransformsEnabled : 1; bool m_acceleratedCompositingForVideoEnabled : 1; @@ -617,6 +633,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/GlyphPageTreeNode.cpp b/Source/WebCore/platform/graphics/GlyphPageTreeNode.cpp index 951cf56..126b3b4 100644 --- a/Source/WebCore/platform/graphics/GlyphPageTreeNode.cpp +++ b/Source/WebCore/platform/graphics/GlyphPageTreeNode.cpp @@ -47,12 +47,19 @@ GlyphPageTreeNode* GlyphPageTreeNode::pageZeroRoot = 0; GlyphPageTreeNode* GlyphPageTreeNode::getRoot(unsigned pageNumber) { +#if !PLATFORM(ANDROID) static bool initialized; if (!initialized) { initialized = true; roots = new HashMap<int, GlyphPageTreeNode*>; pageZeroRoot = new GlyphPageTreeNode; } +#else + if (!roots) + roots = new HashMap<int, GlyphPageTreeNode*>; + if (!pageZeroRoot) + pageZeroRoot = new GlyphPageTreeNode; +#endif GlyphPageTreeNode* node = pageNumber ? roots->get(pageNumber) : pageZeroRoot; if (!node) { @@ -68,6 +75,29 @@ GlyphPageTreeNode* GlyphPageTreeNode::getRoot(unsigned pageNumber) return node; } +#if PLATFORM(ANDROID) +void GlyphPageTreeNode::resetRoots() +{ + if (roots) { + HashMap<int, GlyphPageTreeNode*>::iterator end = roots->end(); + for (HashMap<int, GlyphPageTreeNode*>::iterator it = roots->begin(); it != end; ++it) + it->second->resetChildren(); + } + if (pageZeroRoot) { + pageZeroRoot->resetChildren(); + } +} + +void GlyphPageTreeNode::resetChildren() +{ + HashMap<const FontData*, GlyphPageTreeNode*>::const_iterator end = m_children.end(); + for (HashMap<const FontData*, GlyphPageTreeNode*>::const_iterator it = m_children.begin(); it != end; ++it) { + pruneTreeFontData(static_cast<const SimpleFontData*>(it->first)); + pruneTreeCustomFontData(it->first); + } +} +#endif + size_t GlyphPageTreeNode::treeGlyphPageCount() { size_t count = 0; @@ -347,7 +377,11 @@ GlyphPageTreeNode* GlyphPageTreeNode::getChild(const FontData* fontData, unsigne void GlyphPageTreeNode::pruneCustomFontData(const FontData* fontData) { +#if !PLATFORM(ANDROID) if (!fontData || !m_customFontCount) +#else + if (!fontData || !m_customFontCount || fontData == (SimpleFontData*)-1) +#endif return; // Prune any branch that contains this FontData. @@ -371,7 +405,11 @@ void GlyphPageTreeNode::pruneCustomFontData(const FontData* fontData) void GlyphPageTreeNode::pruneFontData(const SimpleFontData* fontData, unsigned level) { ASSERT(fontData); +#if !PLATFORM(ANDROID) if (!fontData) +#else + if (!fontData || fontData == (SimpleFontData*)-1) +#endif return; // Prune any branch that contains this FontData. diff --git a/Source/WebCore/platform/graphics/GlyphPageTreeNode.h b/Source/WebCore/platform/graphics/GlyphPageTreeNode.h index b68c0ed..72a62ea 100644 --- a/Source/WebCore/platform/graphics/GlyphPageTreeNode.h +++ b/Source/WebCore/platform/graphics/GlyphPageTreeNode.h @@ -196,6 +196,11 @@ public: void pruneCustomFontData(const FontData*); void pruneFontData(const SimpleFontData*, unsigned level = 0); +#if PLATFORM(ANDROID) + static void resetRoots(); + void resetChildren(); +#endif + GlyphPageTreeNode* parent() const { return m_parent; } GlyphPageTreeNode* getChild(const FontData*, unsigned pageNumber); diff --git a/Source/WebCore/platform/graphics/Gradient.h b/Source/WebCore/platform/graphics/Gradient.h index 7595896..ec22efe 100644 --- a/Source/WebCore/platform/graphics/Gradient.h +++ b/Source/WebCore/platform/graphics/Gradient.h @@ -58,14 +58,9 @@ typedef QGradient* PlatformGradient; typedef struct _cairo_pattern cairo_pattern_t; typedef cairo_pattern_t* PlatformGradient; #elif USE(SKIA) -#if PLATFORM(ANDROID) -#include "SkShader.h" -typedef class PlatformGradientRec* PlatformGradient; -#else class SkShader; typedef class SkShader* PlatformGradient; typedef class SkShader* PlatformPattern; -#endif #elif PLATFORM(HAIKU) class BGradient; typedef BGradient* PlatformGradient; @@ -116,9 +111,6 @@ namespace WebCore { #if OS(WINCE) && !PLATFORM(QT) const Vector<ColorStop, 2>& getStops() const; #else -#if PLATFORM(ANDROID) - SkShader* getShader(SkShader::TileMode); -#endif PlatformGradient platformGradient(); #endif diff --git a/Source/WebCore/platform/graphics/GraphicsContext.cpp b/Source/WebCore/platform/graphics/GraphicsContext.cpp index 65cc6df..d8ea160 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) { @@ -660,7 +662,7 @@ CompositeOperator GraphicsContext::compositeOperation() const return m_state.compositeOperator; } -#if !(USE(SKIA) && !PLATFORM(ANDROID)) +#if !USE(SKIA) void GraphicsContext::setPlatformFillGradient(Gradient*) { } @@ -686,7 +688,7 @@ void GraphicsContext::setPlatformTextDrawingMode(TextDrawingModeFlags mode) } #endif -#if !PLATFORM(QT) && !USE(CAIRO) && !(USE(SKIA) && !PLATFORM(ANDROID)) && !PLATFORM(HAIKU) && !PLATFORM(OPENVG) +#if !PLATFORM(QT) && !USE(CAIRO) && !USE(SKIA) && !PLATFORM(OPENVG) void GraphicsContext::setPlatformStrokeStyle(StrokeStyle) { } diff --git a/Source/WebCore/platform/graphics/GraphicsContext.h b/Source/WebCore/platform/graphics/GraphicsContext.h index 2b41c2e..5c60e98 100644 --- a/Source/WebCore/platform/graphics/GraphicsContext.h +++ b/Source/WebCore/platform/graphics/GraphicsContext.h @@ -287,8 +287,6 @@ namespace WebCore { #endif #if PLATFORM(ANDROID) - // initialize a paint for bitmaps - void setupBitmapPaint(SkPaint*); // initialize a paint for filling void setupFillPaint(SkPaint*); // initialize a paint for stroking @@ -301,10 +299,6 @@ namespace WebCore { // returns true if there is a valid (non-transparent) stroke color bool willStroke() const; - // may return NULL, since we lazily allocate the path. This is the path - // that is drawn by drawPath() - const SkPath* getCurrPath() const; - /** platform-specific factory method to return a bitmap graphicscontext, called by <canvas> when we need to draw offscreen. Caller is responsible for deleting the context. Use drawOffscreenContext() to draw the context's image @@ -382,7 +376,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/AndroidAnimation.cpp b/Source/WebCore/platform/graphics/android/AndroidAnimation.cpp index 6b22359..0ef84b9 100644 --- a/Source/WebCore/platform/graphics/android/AndroidAnimation.cpp +++ b/Source/WebCore/platform/graphics/android/AndroidAnimation.cpp @@ -14,39 +14,22 @@ * limitations under the License. */ +#define LOG_TAG "AndroidAnimation" +#define LOG_NDEBUG 1 + #include "config.h" #include "AndroidAnimation.h" #if USE(ACCELERATED_COMPOSITING) +#include "AndroidLog.h" #include "Animation.h" #include "GraphicsLayerAndroid.h" - #include "Timer.h" #include "TimingFunction.h" #include "TranslateTransformOperation.h" #include "UnitBezier.h" -#include <wtf/CurrentTime.h> -#include <cutils/log.h> -#include <wtf/text/CString.h> - -#undef XLOGC -#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "AndroidAnimation", __VA_ARGS__) - -#ifdef DEBUG - -#undef XLOG -#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "AndroidAnimation", __VA_ARGS__) - -#else - -#undef XLOG -#define XLOG(...) - -#endif // DEBUG - - namespace WebCore { static int gUniqueId; @@ -251,10 +234,10 @@ void AndroidOpacityAnimation::applyForProgress(LayerAndroid* layer, float progre FloatAnimationValue* fromValue = (FloatAnimationValue*) m_operations->at(from); FloatAnimationValue* toValue = (FloatAnimationValue*) m_operations->at(to); - XLOG("[layer %d] opacity fromValue %x, key %.2f, toValue %x, key %.2f for progress %.2f", - layer->uniqueId(), - fromValue, fromValue->keyTime(), - toValue, toValue->keyTime(), progress); + ALOGV("[layer %d] opacity fromValue %x, key %.2f, toValue %x, key %.2f for progress %.2f", + layer->uniqueId(), + fromValue, fromValue->keyTime(), + toValue, toValue->keyTime(), progress); // We now have the correct two values to work with, let's compute the // progress value @@ -293,10 +276,10 @@ void AndroidTransformAnimation::applyForProgress(LayerAndroid* layer, float prog TransformAnimationValue* fromValue = (TransformAnimationValue*) m_operations->at(from); TransformAnimationValue* toValue = (TransformAnimationValue*) m_operations->at(to); - XLOG("[layer %d] fromValue %x, key %.2f, toValue %x, key %.2f for progress %.2f", - layer->uniqueId(), - fromValue, fromValue->keyTime(), - toValue, toValue->keyTime(), progress); + ALOGV("[layer %d] fromValue %x, key %.2f, toValue %x, key %.2f for progress %.2f", + layer->uniqueId(), + fromValue, fromValue->keyTime(), + toValue, toValue->keyTime(), progress); // We now have the correct two values to work with, let's compute the // progress value @@ -304,8 +287,8 @@ void AndroidTransformAnimation::applyForProgress(LayerAndroid* layer, float prog const TimingFunction* timingFunction = fromValue->timingFunction(); float p = applyTimingFunction(fromValue->keyTime(), toValue->keyTime(), progress, timingFunction); - XLOG("progress %.2f => %.2f from: %.2f to: %.2f", progress, p, fromValue->keyTime(), - toValue->keyTime()); + ALOGV("progress %.2f => %.2f from: %.2f to: %.2f", progress, p, fromValue->keyTime(), + toValue->keyTime()); progress = p; // With both values and the progress, we also need to check out that diff --git a/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp index 9c7716c..7bb632f 100644 --- a/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp @@ -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,368 +23,35 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#define LOG_TAG "BaseLayerAndroid" +#define LOG_NDEBUG 1 + #include "config.h" #include "BaseLayerAndroid.h" -#if USE(ACCELERATED_COMPOSITING) -#include "ClassTracker.h" -#include "GLUtils.h" -#include "ShaderProgram.h" -#include "SkCanvas.h" -#include "TilesManager.h" -#include <GLES2/gl2.h> -#include <wtf/CurrentTime.h> -#endif // USE(ACCELERATED_COMPOSITING) - -#include <cutils/log.h> -#include <wtf/text/CString.h> - -#undef XLOGC -#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "BaseLayerAndroid", __VA_ARGS__) - -#ifdef DEBUG - -#undef XLOG -#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "BaseLayerAndroid", __VA_ARGS__) - -#else - -#undef XLOG -#define XLOG(...) - -#endif // DEBUG - -// TODO: dynamically determine based on DPI -#define PREFETCH_SCALE_MODIFIER 0.3 -#define PREFETCH_OPACITY 1 -#define PREFETCH_X_DIST 0 -#define PREFETCH_Y_DIST 1 +#include "AndroidLog.h" +#include "GLWebViewState.h" +#include "LayerContent.h" namespace WebCore { -using namespace android; - -BaseLayerAndroid::BaseLayerAndroid() -#if USE(ACCELERATED_COMPOSITING) - : m_color(Color::white) - , m_scrollState(NotScrolling) -#endif -{ -#ifdef DEBUG_COUNT - ClassTracker::instance()->increment("BaseLayerAndroid"); -#endif -} - -BaseLayerAndroid::~BaseLayerAndroid() -{ - m_content.clear(); -#ifdef DEBUG_COUNT - ClassTracker::instance()->decrement("BaseLayerAndroid"); -#endif -} -void BaseLayerAndroid::setContent(const PictureSet& src) -{ -#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); - // 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. - // setSize(src.width(), src.height()); -} +// Note: this must match the use of ID 0 specifying the base layer in DrawExtra +#define BASE_UNIQUE_ID 0 -bool BaseLayerAndroid::drawCanvas(SkCanvas* canvas) +BaseLayerAndroid::BaseLayerAndroid(LayerContent* content) + : LayerAndroid((RenderLayer*)0) + , m_color(Color::white) { -#if USE(ACCELERATED_COMPOSITING) - android::Mutex::Autolock lock(m_drawLock); -#endif - if (!m_content.isEmpty()) - m_content.draw(canvas); - return true; + setContent(content); + setSize(content->width(), content->height()); + m_uniqueId = BASE_UNIQUE_ID; } -#if USE(ACCELERATED_COMPOSITING) - -void BaseLayerAndroid::prefetchBasePicture(SkRect& viewport, float currentScale, - TiledPage* prefetchTiledPage, bool draw) +void BaseLayerAndroid::getLocalTransform(SkMatrix* matrix) const { - SkIRect bounds; - float prefetchScale = currentScale * PREFETCH_SCALE_MODIFIER; - - float invTileWidth = (prefetchScale) - / TilesManager::instance()->tileWidth(); - float invTileHeight = (prefetchScale) - / TilesManager::instance()->tileHeight(); - bool goingDown = m_state->goingDown(); - bool goingLeft = m_state->goingLeft(); - - - XLOG("fetch rect %f %f %f %f, scale %f", - viewport.fLeft, - viewport.fTop, - viewport.fRight, - viewport.fBottom, - scale); - - bounds.fLeft = static_cast<int>(floorf(viewport.fLeft * invTileWidth)) - PREFETCH_X_DIST; - bounds.fTop = static_cast<int>(floorf(viewport.fTop * invTileHeight)) - PREFETCH_Y_DIST; - bounds.fRight = static_cast<int>(ceilf(viewport.fRight * invTileWidth)) + PREFETCH_X_DIST; - bounds.fBottom = static_cast<int>(ceilf(viewport.fBottom * invTileHeight)) + PREFETCH_Y_DIST; - - XLOG("prefetch rect %d %d %d %d, scale %f, preparing page %p", - bounds.fLeft, bounds.fTop, - bounds.fRight, bounds.fBottom, - scale * PREFETCH_SCALE, - prefetchTiledPage); - - prefetchTiledPage->setScale(prefetchScale); - prefetchTiledPage->updateTileDirtiness(bounds); - prefetchTiledPage->prepare(goingDown, goingLeft, bounds, - TiledPage::ExpandedBounds); - prefetchTiledPage->swapBuffersIfReady(bounds, - prefetchScale); - if (draw) - prefetchTiledPage->prepareForDrawGL(PREFETCH_OPACITY, bounds); -} - -bool BaseLayerAndroid::isReady() -{ - ZoomManager* zoomManager = m_state->zoomManager(); - if (ZoomManager::kNoScaleRequest != zoomManager->scaleRequestState()) { - XLOG("base layer not ready, still zooming"); - return false; // still zooming - } - - if (!m_state->frontPage()->isReady(m_state->preZoomBounds())) { - XLOG("base layer not ready, front page not done painting"); - 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()); - - m_state->backPage()->swapBuffersIfReady(m_state->preZoomBounds(), - 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) -{ - 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 - - m_state->invalRegion(m_dirtyRegion); - m_dirtyRegion.setEmpty(); -} - -void BaseLayerAndroid::mergeInvalsInto(Layer* replacementTree) -{ - 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); -} - -bool BaseLayerAndroid::prepareBasePictureInGL(SkRect& viewport, float scale, - double currentTime) -{ - ZoomManager* zoomManager = m_state->zoomManager(); - - bool goingDown = m_state->goingDown(); - bool goingLeft = m_state->goingLeft(); - - const SkIRect& viewportTileBounds = m_state->viewportTileBounds(); - XLOG("drawBasePicture, TX: %d, TY: %d scale %.2f", viewportTileBounds.fLeft, - viewportTileBounds.fTop, scale); - - // Query the resulting state from the zoom manager - bool prepareNextTiledPage = zoomManager->needPrepareNextTiledPage(); - - // Display the current page - TiledPage* tiledPage = m_state->frontPage(); - TiledPage* nextTiledPage = m_state->backPage(); - tiledPage->setScale(zoomManager->currentScale()); - - // Let's prepare the page if needed so that it will start painting - if (prepareNextTiledPage) { - nextTiledPage->setScale(scale); - m_state->setFutureViewport(viewportTileBounds); - - // ignore dirtiness return value since while zooming we repaint regardless - nextTiledPage->updateTileDirtiness(viewportTileBounds); - - nextTiledPage->prepare(goingDown, goingLeft, viewportTileBounds, - TiledPage::VisibleBounds); - // Cancel pending paints for the foreground page - TilesManager::instance()->removePaintOperationsForPage(tiledPage, false); - } - - // If we fired a request, let's check if it's ready to use - if (zoomManager->didFireRequest()) { - if (nextTiledPage->swapBuffersIfReady(viewportTileBounds, - zoomManager->futureScale())) - zoomManager->setReceivedRequest(); // transition to received request state - } - - float transparency = 1; - bool doZoomPageSwap = false; - - // If the page is ready, display it. We do a short transition between - // the two pages (current one and future one with the new scale factor) - if (zoomManager->didReceivedRequest()) { - float nextTiledPageTransparency = 1; - m_state->resetFrameworkInval(); - zoomManager->processTransition(currentTime, scale, &doZoomPageSwap, - &nextTiledPageTransparency, &transparency); - nextTiledPage->prepareForDrawGL(nextTiledPageTransparency, viewportTileBounds); - } - - const SkIRect& preZoomBounds = m_state->preZoomBounds(); - - bool zooming = ZoomManager::kNoScaleRequest != zoomManager->scaleRequestState(); - - if (doZoomPageSwap) { - zoomManager->setCurrentScale(scale); - m_state->swapPages(); - } - - bool needsRedraw = zooming; - - // if applied invals mark tiles dirty, need to redraw - needsRedraw |= tiledPage->updateTileDirtiness(preZoomBounds); - - // paint what's needed unless we're zooming, since the new tiles won't - // be relevant soon anyway - if (!zooming) - tiledPage->prepare(goingDown, goingLeft, preZoomBounds, - TiledPage::ExpandedBounds); - - XLOG("scrolling %d, zooming %d, needsRedraw %d", - scrolling, zooming, needsRedraw); - - // prefetch in the nextTiledPage if unused by zooming (even if not scrolling - // since we want the tiles to be ready before they're needed) - bool usePrefetchPage = !zooming; - nextTiledPage->setIsPrefetchPage(usePrefetchPage); - if (usePrefetchPage) { - // if the non-prefetch page isn't missing tiles, don't bother drawing - // prefetch page - bool drawPrefetchPage = tiledPage->hasMissingContent(preZoomBounds); - prefetchBasePicture(viewport, scale, nextTiledPage, drawPrefetchPage); - } - - tiledPage->prepareForDrawGL(transparency, preZoomBounds); - - return needsRedraw; -} - -void BaseLayerAndroid::drawBasePictureInGL() -{ - m_state->backPage()->drawGL(); - m_state->frontPage()->drawGL(); -} - -#endif // USE(ACCELERATED_COMPOSITING) - -void BaseLayerAndroid::updateLayerPositions(SkRect& visibleRect) -{ - LayerAndroid* compositedRoot = static_cast<LayerAndroid*>(getChild(0)); - TransformationMatrix ident; - compositedRoot->updateFixedLayersPositions(visibleRect); - FloatRect clip(0, 0, content()->width(), content()->height()); - compositedRoot->updateGLPositionsAndScale( - ident, clip, 1, m_state->zoomManager()->layersScale()); - -#ifdef DEBUG - compositedRoot->showLayer(0); - XLOG("We have %d layers, %d textured", - compositedRoot->nbLayers(), - compositedRoot->nbTexturedLayers()); -#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; -} - -bool BaseLayerAndroid::drawGL(IntRect& viewRect, SkRect& visibleRect, - float scale) -{ - XLOG("drawing 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; + // base layer doesn't use size in transform calculation + matrix->preConcat(getMatrix()); } } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/BaseLayerAndroid.h b/Source/WebCore/platform/graphics/android/BaseLayerAndroid.h index c5ce52f..0ef39c8 100644 --- a/Source/WebCore/platform/graphics/android/BaseLayerAndroid.h +++ b/Source/WebCore/platform/graphics/android/BaseLayerAndroid.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 @@ -27,65 +27,33 @@ #define BaseLayerAndroid_h #include "Color.h" -#include "GLWebViewState.h" -#include "IntRect.h" -#include "Layer.h" -#include "PictureSet.h" -#include "SkPicture.h" +#include "LayerAndroid.h" namespace WebCore { -class BaseLayerAndroid : public Layer { +class RenderLayerCompositor; + +class BaseLayerAndroid : public LayerAndroid { public: - enum ScrollState { - NotScrolling = 0, - Scrolling = 1, - ScrollingFinishPaint = 2 - }; + BaseLayerAndroid(LayerContent* content); + + virtual ~BaseLayerAndroid() {}; - BaseLayerAndroid(); - virtual ~BaseLayerAndroid(); + virtual SubclassType subclassType() { return LayerAndroid::BaseLayer; } + virtual bool needsTexture() { return true; } -#if USE(ACCELERATED_COMPOSITING) 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; } - // 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); - // rendering asset management - void swapTiles(); - void setIsDrawing(bool isDrawing); - void setIsPainting(Layer* drawingTree); - void mergeInvalsInto(Layer* replacementTree); - bool isReady(); + virtual void getLocalTransform(SkMatrix* matrix) const; + virtual const TransformationMatrix* drawTransform() const { return 0; } private: -#if USE(ACCELERATED_COMPOSITING) - void prefetchBasePicture(SkRect& viewport, float currentScale, - TiledPage* prefetchTiledPage, bool draw); - bool prepareBasePictureInGL(SkRect& viewport, float scale, double currentTime); - void drawBasePictureInGL(); - - android::Mutex m_drawLock; + // TODO: move to SurfaceCollection. Color m_color; -#endif - android::PictureSet m_content; - - ScrollState m_scrollState; }; } // namespace WebCore -#endif // BaseLayerAndroid_h +#endif //BaseLayerAndroid_h diff --git a/Source/WebCore/platform/graphics/android/BaseRenderer.cpp b/Source/WebCore/platform/graphics/android/BaseRenderer.cpp index 57baee8..fba62b7 100644 --- a/Source/WebCore/platform/graphics/android/BaseRenderer.cpp +++ b/Source/WebCore/platform/graphics/android/BaseRenderer.cpp @@ -23,12 +23,15 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#define LOG_TAG "BaseRenderer" +#define LOG_NDEBUG 1 #include "config.h" #include "BaseRenderer.h" #if USE(ACCELERATED_COMPOSITING) +#include "AndroidLog.h" #include "GaneshRenderer.h" #include "GLUtils.h" #include "RasterRenderer.h" @@ -37,24 +40,13 @@ #include "SkCanvas.h" #include "SkDevice.h" #include "SkPicture.h" +#include "SkTypeface.h" #include "TilesManager.h" #include <wtf/text/CString.h> -#ifdef DEBUG - -#include <cutils/log.h> -#include <wtf/CurrentTime.h> - -#undef XLOG -#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "BaseRenderer", __VA_ARGS__) - -#else - -#undef XLOG -#define XLOG(...) - -#endif // DEBUG +#define UPDATE_COUNT_MASK 0xFF // displayed count wraps at 256 +#define UPDATE_COUNT_ALPHA_MASK 0x1F // alpha wraps at 32 namespace WebCore { @@ -79,40 +71,24 @@ void BaseRenderer::swapRendererIfNeeded(BaseRenderer*& renderer) } void BaseRenderer::drawTileInfo(SkCanvas* canvas, - const TileRenderInfo& renderInfo, int pictureCount) + const TileRenderInfo& renderInfo, int updateCount, double renderDuration) { + static SkTypeface* s_typeface = 0; + if (!s_typeface) + s_typeface = SkTypeface::CreateFromName("", SkTypeface::kBold); SkPaint paint; + paint.setTextSize(17); 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); - paint.setARGB(255, 0, 0, 0); - canvas->drawText(str, strlen(str), 0, 10, paint); - paint.setARGB(255, 255, 0, 0); - canvas->drawText(str, strlen(str), 0, 11, paint); - - int tagCount = 0; - const String* tags = getPerformanceTags(tagCount); - - float total = 0; - for (int i = 0; i < tagCount; i++) { - float tagDuration = m_perfMon.getAverageDuration(tags[i]); - total += tagDuration; - snprintf(str, 256, "%s: %.2f", tags[i].utf8().data(), tagDuration); - paint.setARGB(255, 0, 0, 0); - int textY = (i * 12) + 25; - canvas->drawText(str, strlen(str), 0, textY, paint); - paint.setARGB(255, 255, 0, 0); - canvas->drawText(str, strlen(str), 0, textY + 1, paint); - } - snprintf(str, 256, "total: %.2f", total); - paint.setARGB(255, 0, 0, 0); - int textY = (tagCount * 12) + 30; - canvas->drawText(str, strlen(str), 0, textY, paint); + snprintf(str, 256, " (%d,%d) %.2fx %d %.1fms", renderInfo.x, renderInfo.y, + renderInfo.scale, updateCount, renderDuration); + paint.setARGB(128, 255, 255, 255); + canvas->drawRectCoords(0, 0, renderInfo.tileSize.fWidth, 17, paint); paint.setARGB(255, 255, 0, 0); - canvas->drawText(str, strlen(str), 0, textY + 1, paint); + paint.setTypeface(s_typeface); + canvas->drawText(str, strlen(str), 20, 15, paint); } -int BaseRenderer::renderTiledContent(const TileRenderInfo& renderInfo) +void BaseRenderer::renderTiledContent(TileRenderInfo& renderInfo) { const bool visualIndicator = TilesManager::instance()->getShowVisualIndicator(); const SkSize& tileSize = renderInfo.tileSize; @@ -121,45 +97,66 @@ int BaseRenderer::renderTiledContent(const TileRenderInfo& renderInfo) setupCanvas(renderInfo, &canvas); if (!canvas.getDevice()) { - XLOG("Error: No Device"); - return 0; + // TODO: consider ALOGE + ALOGV("Error: No Device"); + return; } - if (visualIndicator) + double before; + if (visualIndicator) { canvas.save(); + before = currentTimeMS(); + } 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 (renderInfo.baseTile && renderInfo.baseTile->backTexture()) + checkForPureColor(renderInfo, &canvas); + else + renderInfo.isPureColor = false; if (visualIndicator) { + double after = currentTimeMS(); 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); + SkPaint paint; + paint.setARGB(color, 0, 255, 0); + if (renderInfo.invalRect) + canvas.drawIRect(*renderInfo.invalRect, paint); + else { + SkIRect rect; + rect.set(0, 0, tileSize.width(), tileSize.height()); + canvas.drawIRect(rect, 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); + } + drawTileInfo(&canvas, renderInfo, updateCount, after - before); // paint the tile boundaries - SkPaint paint; - paint.setARGB(128, 255, 0, 0); + paint.setARGB(64, 255, 0, 0); paint.setStrokeWidth(3); canvas.drawLine(0, 0, tileSize.width(), tileSize.height(), paint); - paint.setARGB(128, 0, 255, 0); + paint.setARGB(64, 0, 255, 0); canvas.drawLine(0, tileSize.height(), tileSize.width(), 0, paint); paint.setARGB(128, 0, 0, 255); - canvas.drawLine(0, 0, tileSize.width(), 0, paint); canvas.drawLine(tileSize.width(), 0, tileSize.width(), tileSize.height(), paint); - - if (renderInfo.measurePerf) - drawTileInfo(&canvas, renderInfo, pictureCount); } - 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..ef1e4c2 100644 --- a/Source/WebCore/platform/graphics/android/BaseRenderer.h +++ b/Source/WebCore/platform/graphics/android/BaseRenderer.h @@ -28,8 +28,9 @@ #if USE(ACCELERATED_COMPOSITING) -#include "PerformanceMonitor.h" +#include "Color.h" #include "SkRect.h" +#include <wtf/text/StringHash.h> class SkCanvas; class SkDevice; @@ -63,8 +64,8 @@ struct TileRenderInfo { // info about the texture that we are to render into TextureInfo* textureInfo; - // specifies whether or not to measure the rendering performance - bool measurePerf; + bool isPureColor; + Color pureColor; }; /** @@ -76,7 +77,7 @@ public: BaseRenderer(RendererType type) : m_type(type) {} virtual ~BaseRenderer() {} - int renderTiledContent(const TileRenderInfo& renderInfo); + void renderTiledContent(TileRenderInfo& renderInfo); RendererType getType() { return m_type; } @@ -90,14 +91,10 @@ protected: virtual void setupCanvas(const TileRenderInfo& renderInfo, SkCanvas* canvas) = 0; virtual void setupPartialInval(const TileRenderInfo& renderInfo, SkCanvas* canvas) {} virtual void renderingComplete(const TileRenderInfo& renderInfo, SkCanvas* canvas) = 0; + virtual void checkForPureColor(TileRenderInfo& renderInfo, SkCanvas* canvas) = 0; void drawTileInfo(SkCanvas* canvas, const TileRenderInfo& renderInfo, - int pictureCount); - - virtual const String* getPerformanceTags(int& tagCount) = 0; - - // Performance tracking - PerformanceMonitor m_perfMon; + int updateCount, double renderDuration); private: RendererType m_type; diff --git a/Source/WebCore/platform/graphics/android/BaseTile.cpp b/Source/WebCore/platform/graphics/android/BaseTile.cpp index 27bd482..ddaf181 100644 --- a/Source/WebCore/platform/graphics/android/BaseTile.cpp +++ b/Source/WebCore/platform/graphics/android/BaseTile.cpp @@ -23,51 +23,38 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#define LOG_TAG "BaseTile" +#define LOG_NDEBUG 1 + #include "config.h" #include "BaseTile.h" #if USE(ACCELERATED_COMPOSITING) +#include "AndroidLog.h" #include "GLUtils.h" #include "RasterRenderer.h" #include "TextureInfo.h" #include "TilesManager.h" -#include <cutils/atomic.h> - -#include <cutils/log.h> -#include <wtf/CurrentTime.h> -#include <wtf/text/CString.h> - -#undef XLOGC -#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "BaseTile", __VA_ARGS__) - -#ifdef DEBUG - -#undef XLOG -#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "BaseTile", __VA_ARGS__) - -#else - -#undef XLOG -#define XLOG(...) - -#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) - : m_glWebViewState(0) - , m_painter(0) - , m_x(-1) + : m_x(-1) , m_y(-1) - , m_page(0) , m_frontTexture(0) , m_backTexture(0) , 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 +63,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 +74,6 @@ BaseTile::~BaseTile() m_frontTexture->release(this); delete m_renderer; - delete[] m_dirtyArea; - delete[] m_fullRepaint; #ifdef DEBUG_COUNT ClassTracker::instance()->decrement("BaseTile"); @@ -111,10 +82,10 @@ BaseTile::~BaseTile() // All the following functions must be called from the main GL thread. -void BaseTile::setContents(TilePainter* painter, int x, int y, float scale) +void BaseTile::setContents(int x, int y, float scale, bool isExpandedPrefetchTile) { - if ((m_painter != painter) - || (m_x != x) + // TODO: investigate whether below check/discard is necessary + if ((m_x != x) || (m_y != y) || (m_scale != scale)) { // neither texture is relevant @@ -122,11 +93,12 @@ void BaseTile::setContents(TilePainter* painter, int x, int y, float scale) } android::AutoMutex lock(m_atomicSync); - m_painter = painter; m_x = x; m_y = y; m_scale = scale; m_drawCount = TilesManager::instance()->getDrawGLCount(); + if (isExpandedPrefetchTile) + m_drawCount--; // deprioritize expanded painting region } void BaseTile::reserveTexture() @@ -135,14 +107,14 @@ void BaseTile::reserveTexture() android::AutoMutex lock(m_atomicSync); if (texture && m_backTexture != texture) { - XLOG("tile %p reserving texture %p, back was %p (front %p)", - this, texture, m_backTexture, m_frontTexture); + ALOGV("tile %p reserving texture %p, back was %p (front %p)", + this, texture, m_backTexture, m_frontTexture); m_state = Unpainted; m_backTexture = texture; } if (m_state == UpToDate) { - XLOG("moving tile %p to unpainted, since it reserved while up to date", this); + ALOGV("moving tile %p to unpainted, since it reserved while up to date", this); m_dirty = true; m_state = Unpainted; } @@ -150,13 +122,13 @@ void BaseTile::reserveTexture() bool BaseTile::removeTexture(BaseTileTexture* texture) { - XLOG("%p removeTexture %p, back %p front %p... page %p", - this, texture, m_backTexture, m_frontTexture, m_page); + ALOGV("%p removeTexture %p, back %p front %p... page %p", + this, texture, m_backTexture, m_frontTexture, m_page); // We update atomically, so paintBitmap() can see the correct value android::AutoMutex lock(m_atomicSync); if (m_frontTexture == texture) { if (m_state == UpToDate) { - XLOG("front texture removed, state was UpToDate, now becoming unpainted, bt is %p", m_backTexture); + ALOGV("front texture removed, state was UpToDate, now becoming unpainted, bt is %p", m_backTexture); m_state = Unpainted; } @@ -174,30 +146,21 @@ 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; SkRegion::Iterator cliperator(dirtyArea); - int tileWidth = TilesManager::instance()->tileWidth(); - int tileHeight = TilesManager::instance()->tileHeight(); - if (m_isLayerTile) { - tileWidth = TilesManager::instance()->layerTileWidth(); - tileHeight = TilesManager::instance()->layerTileHeight(); - } SkRect realTileRect; SkRect dirtyRect; while (!cliperator.done()) { dirtyRect.set(cliperator.rect()); - if (intersectWithRect(m_x, m_y, tileWidth, tileHeight, + if (intersectWithRect(m_x, m_y, TilesManager::tileWidth(), TilesManager::tileHeight(), m_scale, dirtyRect, realTileRect)) { intersect = true; break; @@ -217,7 +180,7 @@ void BaseTile::markAsDirty(int unsigned pictureCount, } else if (m_state != Unpainted) { // TODO: fix it so that they can paint while deferring the markAsDirty // call (or block updates) - XLOG("Warning: tried to mark tile %p at %d, %d islayertile %d as dirty, state %d, page %p", + ALOGV("Warning: tried to mark tile %p at %d, %d islayertile %d as dirty, state %d, page %p", this, m_x, m_y, isLayerTile(), m_state, m_page); // prefetch tiles can be marked dirty while in the process of painting, @@ -244,15 +207,16 @@ void BaseTile::setRepaintPending(bool pending) m_repaintPending = pending; } -void BaseTile::draw(float transparency, SkRect& rect, float scale) +bool BaseTile::drawGL(float opacity, const SkRect& rect, float scale, + const TransformationMatrix* transform) { if (m_x < 0 || m_y < 0 || m_scale != scale) - return; + return false; // No need to mutex protect reads of m_backTexture as it is only written to by // the consumer thread. if (!m_frontTexture) - return; + return false; // Early return if set to un-usable in purpose! m_atomicSync.lock(); @@ -260,27 +224,10 @@ void BaseTile::draw(float transparency, SkRect& rect, float scale) m_atomicSync.unlock(); 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); - } + return false; - m_frontTexture->consumerRelease(); + m_frontTexture->drawGL(isLayerTile(), rect, opacity, transform); + return true; } bool BaseTile::isTileReady() @@ -301,16 +248,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, @@ -342,7 +280,7 @@ bool BaseTile::isTileVisible(const IntRect& viewTileBounds) } // This is called from the texture generation thread -void BaseTile::paintBitmap() +void BaseTile::paintBitmap(TilePainter* painter) { // We acquire the values below atomically. This ensures that we are reading // values correctly across cores. Further, once we have these values they @@ -350,38 +288,31 @@ 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; - TilePainter* painter = m_painter; if (!dirty || !texture) { m_atomicSync.unlock(); return; } if (m_state != Unpainted) { - XLOG("Warning: started painting tile %p, but was at state %d, ft %p bt %p", + ALOGV("Warning: started painting tile %p, but was at state %d, ft %p bt %p", 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 +330,79 @@ 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; - - renderInfo.invalRect = &finalRealRect; - renderInfo.measurePerf = false; - - pictureCount = m_renderer->renderTiledContent(renderInfo); + cliperator.next(); } - cliperator.next(); + if (!fullRepaint) { + renderInfo.invalRect = &totalRect; + m_renderer->renderTiledContent(renderInfo); + } } // Do a full repaint if needed if (fullRepaint) { - SkIRect rect; - rect.set(0, 0, tileWidth, tileHeight); - - renderInfo.invalRect = ▭ - renderInfo.measurePerf = TilesManager::instance()->getShowVisualIndicator(); - - pictureCount = m_renderer->renderTiledContent(renderInfo); + renderInfo.invalRect = 0; + 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,27 +412,19 @@ 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()) + if (!m_dirtyArea.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()) - m_dirty = true; - - XLOG("painted tile %p (%d, %d), texture %p, dirty=%d", this, x, y, texture, m_dirty); + ALOGV("painted tile %p (%d, %d), texture %p, dirty=%d", this, x, y, texture, m_dirty); validatePaint(); } else { - XLOG("tile %p no longer owns texture %p, m_state %d. ft %p bt %p", - this, texture, m_state, m_frontTexture, m_backTexture); + ALOGV("tile %p no longer owns texture %p, m_state %d. ft %p bt %p", + this, texture, m_state, m_frontTexture, m_backTexture); } m_atomicSync.unlock(); @@ -512,8 +432,8 @@ void BaseTile::paintBitmap() void BaseTile::discardTextures() { android::AutoMutex lock(m_atomicSync); - XLOG("%p discarding bt %p, ft %p", - this, m_backTexture, m_frontTexture); + ALOGV("%p discarding bt %p, ft %p", + this, m_backTexture, m_frontTexture); if (m_frontTexture) { m_frontTexture->release(this); m_frontTexture = 0; @@ -522,10 +442,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; } @@ -550,8 +469,8 @@ bool BaseTile::swapTexturesIfNeeded() { m_frontTexture = m_backTexture; m_backTexture = 0; m_state = UpToDate; - XLOG("display texture for %p at %d, %d front is now %p, back is %p", - this, m_x, m_y, m_frontTexture, m_backTexture); + ALOGV("display texture for %p at %d, %d front is now %p, back is %p", + this, m_x, m_y, m_frontTexture, m_backTexture); return true; } @@ -566,8 +485,8 @@ void BaseTile::backTextureTransfer() { m_state = ReadyToSwap; else { // shouldn't have transferred a tile in any other state, log - XLOG("Note: transferred tile %p at %d %d, state wasn't paintingstarted or validated: %d", - this, m_x, m_y, m_state); + ALOGV("Note: transferred tile %p at %d %d, state wasn't paintingstarted or validated: %d", + this, m_x, m_y, m_state); } } @@ -589,10 +508,13 @@ 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 { - XLOG("Note: validated tile %p at %d %d, state wasn't paintingstarted or transferred %d", + } else { + ALOGV("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 // paintBitmap() may have cleared m_dirty) @@ -600,11 +522,11 @@ void BaseTile::validatePaint() { } if (m_deferredDirty) { - XLOG("Note: deferred dirty flag set, possibly a missed paint on tile %p", this); + ALOGV("Note: deferred dirty flag set, possibly a missed paint on tile %p", this); m_deferredDirty = false; } } else { - XLOG("Note: paint was unsuccessful."); + ALOGV("Note: paint was unsuccessful."); m_state = Unpainted; } diff --git a/Source/WebCore/platform/graphics/android/BaseTile.h b/Source/WebCore/platform/graphics/android/BaseTile.h index 685ca43..93ec287 100644 --- a/Source/WebCore/platform/graphics/android/BaseTile.h +++ b/Source/WebCore/platform/graphics/android/BaseTile.h @@ -39,7 +39,6 @@ namespace WebCore { class TextureInfo; -class TiledPage; class BaseTileTexture; class GLWebViewState; @@ -54,7 +53,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. * @@ -94,27 +93,27 @@ public: bool isLayerTile() { return m_isLayerTile; } - void setContents(TilePainter* painter, int x, int y, float scale); - void setPage(TiledPage* page) { m_page = page; } + void setContents(int x, int y, float scale, bool isExpandedPrefetchTile); void reserveTexture(); bool isTileReady(); - void draw(float transparency, SkRect& rect, float scale); + // Return false when real draw didn't happen for any reason. + bool drawGL(float opacity, const SkRect& rect, float scale, + const TransformationMatrix* transform); // the only thread-safe function called by the background thread - void paintBitmap(); + void paintBitmap(TilePainter* painter); bool intersectWithRect(int x, int y, int tileWidth, int tileHeight, float scale, const SkRect& dirtyRect, 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(); + virtual bool isRepaintPending(); void setRepaintPending(bool pending); float scale() const { return m_scale; } TextureState textureState() const { return m_state; } @@ -132,25 +131,15 @@ public: void backTextureTransfer(); void backTextureTransferFail(); - void setGLWebViewState(GLWebViewState* state) { m_glWebViewState = state; } - // TextureOwner implementation virtual bool removeTexture(BaseTileTexture* texture); - virtual TiledPage* page() { return m_page; } - virtual GLWebViewState* state() { return m_glWebViewState; } - TilePainter* painter() { return m_painter; } private: void validatePaint(); - GLWebViewState* m_glWebViewState; - - TilePainter* m_painter; int m_x; int m_y; - TiledPage* m_page; - // The remaining variables can be updated throughout the lifetime of the object BaseTileTexture* m_frontTexture; @@ -166,16 +155,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..f7f9370 100644 --- a/Source/WebCore/platform/graphics/android/BaseTileTexture.cpp +++ b/Source/WebCore/platform/graphics/android/BaseTileTexture.cpp @@ -23,47 +23,27 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#define LOG_TAG "BaseTileTexture" +#define LOG_NDEBUG 1 + #include "config.h" #include "BaseTileTexture.h" +#include "AndroidLog.h" #include "BaseTile.h" #include "ClassTracker.h" -#include "DeleteTextureOperation.h" #include "GLUtils.h" #include "TilesManager.h" -#include <cutils/log.h> -#include <wtf/text/CString.h> - -#undef XLOGC -#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "BaseTileTexture", __VA_ARGS__) - -#ifdef DEBUG - -#undef XLOG -#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "BaseTileTexture", __VA_ARGS__) - -#else - -#undef XLOG -#define XLOG(...) - -#endif // DEBUG - 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 +51,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 +74,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 +84,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); + ALOGV("texture %p releasing tile %p, m_owner %p", this, owner, m_owner); if (m_owner != owner) return false; @@ -213,61 +106,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() +void BaseTileTexture::transferComplete() { - TextureTileInfo* textureInfo = &m_ownTextureTileInfo; - return textureInfo->m_scale; -} - -// This function + TilesManager::addItemInTransferQueue() is replacing the -// setTile(). -void BaseTileTexture::setOwnTextureTileInfoFromQueue(const TextureTileInfo* info) -{ - 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 + ALOGE("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..d8737b3 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,101 +39,57 @@ 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(); - // OpenGL ID of backing texture, 0 when not allocated GLuint m_ownTextureId; // these are used for dynamically (de)allocating backing graphics memory 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/CanvasLayer.cpp b/Source/WebCore/platform/graphics/android/CanvasLayer.cpp new file mode 100644 index 0000000..5409fef --- /dev/null +++ b/Source/WebCore/platform/graphics/android/CanvasLayer.cpp @@ -0,0 +1,218 @@ +/* + * 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. + */ + +#define LOG_TAG "CanvasLayer" +#define LOG_NDEBUG 1 + +#include "config.h" +#include "CanvasLayer.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "AndroidLog.h" +#include "CanvasTexture.h" +#include "Image.h" +#include "ImageBuffer.h" +#include "RenderLayerCompositor.h" +#include "SkBitmap.h" +#include "SkBitmapRef.h" +#include "SkCanvas.h" +#include "TilesManager.h" + +namespace WebCore { + +CanvasLayer::CanvasLayer(RenderLayer* owner, HTMLCanvasElement* canvas) + : LayerAndroid(owner) + , m_canvas(canvas) + , m_dirtyCanvas() + , m_bitmap(0) +{ + init(); + m_canvas->addObserver(this); +} + +CanvasLayer::CanvasLayer(const CanvasLayer& layer) + : LayerAndroid(layer) + , m_canvas(0) + , m_bitmap(0) +{ + init(); + if (!layer.m_canvas) { + // The canvas has already been destroyed - this shouldn't happen + ALOGW("Creating a CanvasLayer for a destroyed canvas!"); + m_contentRect = IntRect(); + m_offsetFromRenderer = IntSize(); + m_texture->setHwAccelerated(false); + return; + } + // We are making a copy for the UI, sync the interesting bits + m_contentRect = layer.contentRect(); + m_offsetFromRenderer = layer.offsetFromRenderer(); + bool previousState = m_texture->hasValidTexture(); + if (!previousState && layer.m_dirtyCanvas.isEmpty()) { + // We were previously in software and don't have anything new to draw, + // so stay in software + m_bitmap = layer.bitmap(); + SkSafeRef(m_bitmap); + } else { + // Attempt to upload to a surface texture + if (!m_texture->uploadImageBuffer(layer.m_canvas->buffer())) { + // Blargh, no surface texture or ImageBuffer - fall back to software + m_bitmap = layer.bitmap(); + SkSafeRef(m_bitmap); + // Merge the canvas invals with the layer's invals to repaint the needed + // tiles. + SkRegion::Iterator iter(layer.m_dirtyCanvas); + const IntPoint& offset = m_contentRect.location(); + for (; !iter.done(); iter.next()) { + SkIRect diff = iter.rect(); + diff.fLeft += offset.x(); + diff.fRight += offset.x(); + diff.fTop += offset.y(); + diff.fBottom += offset.y(); + m_dirtyRegion.op(diff, SkRegion::kUnion_Op); + } + } + if (previousState != m_texture->hasValidTexture()) { + // Need to do a full inval of the canvas content as we are mode switching + m_dirtyRegion.op(m_contentRect.x(), m_contentRect.y(), + m_contentRect.maxX(), m_contentRect.maxY(), SkRegion::kUnion_Op); + } + } +} + +CanvasLayer::~CanvasLayer() +{ + if (m_canvas) + m_canvas->removeObserver(this); + SkSafeUnref(m_bitmap); +} + +void CanvasLayer::init() +{ + m_texture = CanvasTexture::getCanvasTexture(this); +} + +void CanvasLayer::canvasChanged(HTMLCanvasElement*, const FloatRect& changedRect) +{ + if (!m_texture->hasValidTexture()) { + // We only need to track invals if we aren't using a SurfaceTexture. + // If we drop out of hwa, we will do a full inval anyway + SkIRect irect = SkIRect::MakeXYWH(changedRect.x(), changedRect.y(), + changedRect.width(), changedRect.height()); + m_dirtyCanvas.op(irect, SkRegion::kUnion_Op); + } + owningLayer()->compositor()->scheduleLayerFlush(); +} + +void CanvasLayer::canvasResized(HTMLCanvasElement*) +{ + const IntSize& size = m_canvas->size(); + m_dirtyCanvas.setRect(0, 0, size.width(), size.height()); + // If we are smaller than one tile, don't bother using a surface texture + if (size.width() <= TilesManager::tileWidth() + && size.height() <= TilesManager::tileHeight()) + m_texture->setSize(IntSize()); + else + m_texture->setSize(size); +} + +void CanvasLayer::canvasDestroyed(HTMLCanvasElement*) +{ + m_canvas = 0; +} + +void CanvasLayer::clearDirtyRegion() +{ + LayerAndroid::clearDirtyRegion(); + m_dirtyCanvas.setEmpty(); + if (m_canvas) + m_canvas->clearDirtyRect(); +} + +SkBitmapRef* CanvasLayer::bitmap() const +{ + if (!m_canvas || !m_canvas->buffer()) + return 0; + return m_canvas->copiedImage()->nativeImageForCurrentFrame(); +} + +IntRect CanvasLayer::contentRect() const +{ + if (!m_canvas + || !m_canvas->renderer() + || !m_canvas->renderer()->style() + || !m_canvas->inDocument() + || m_canvas->renderer()->style()->visibility() != VISIBLE) + return IntRect(); + return m_canvas->renderBox()->contentBoxRect(); +} + +IntSize CanvasLayer::offsetFromRenderer() const +{ + return m_canvas->renderBox()->layer()->backing()->graphicsLayer()->offsetFromRenderer(); +} + +bool CanvasLayer::needsTexture() +{ + return m_bitmap || LayerAndroid::needsTexture(); +} + +void CanvasLayer::contentDraw(SkCanvas* canvas, PaintStyle style) +{ + LayerAndroid::contentDraw(canvas, style); + if (!m_bitmap) + return; + SkBitmap& bitmap = m_bitmap->bitmap(); + SkRect dst = SkRect::MakeXYWH(m_contentRect.x() - m_offsetFromRenderer.width(), + m_contentRect.y() - m_offsetFromRenderer.height(), + m_contentRect.width(), m_contentRect.height()); + canvas->drawBitmapRect(bitmap, 0, dst, 0); +} + +bool CanvasLayer::drawGL(bool layerTilesDisabled) +{ + bool ret = LayerAndroid::drawGL(layerTilesDisabled); + m_texture->requireTexture(); + if (!m_bitmap && m_texture->updateTexImage()) { + SkRect rect = SkRect::MakeXYWH(m_contentRect.x() - m_offsetFromRenderer.width(), + m_contentRect.y() - m_offsetFromRenderer.height(), + m_contentRect.width(), m_contentRect.height()); + TilesManager::instance()->shader()->drawLayerQuad(m_drawTransform, rect, + m_texture->texture(), 1, true, GL_TEXTURE_EXTERNAL_OES); + } + return ret; +} + +LayerAndroid::InvalidateFlags CanvasLayer::onSetHwAccelerated(bool hwAccelerated) +{ + if (m_texture->setHwAccelerated(hwAccelerated)) + return LayerAndroid::InvalidateLayers; + return LayerAndroid::InvalidateNone; +} + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/TilesTracker.h b/Source/WebCore/platform/graphics/android/CanvasLayer.h index 202d072..532dbf2 100644 --- a/Source/WebCore/platform/graphics/android/TilesTracker.h +++ b/Source/WebCore/platform/graphics/android/CanvasLayer.h @@ -1,5 +1,5 @@ /* - * Copyright 2011, 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,63 +23,59 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef TilesTracker_h -#define TilesTracker_h +#ifndef CanvasLayer_h +#define CanvasLayer_h #if USE(ACCELERATED_COMPOSITING) -#include <cutils/log.h> -#include <wtf/CurrentTime.h> -#include <wtf/text/CString.h> +#include "HTMLCanvasElement.h" +#include "ImageData.h" +#include "LayerAndroid.h" +#include "RenderLayer.h" -#undef XLOG -#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "TilesTracker", __VA_ARGS__) +#include <wtf/RefPtr.h> namespace WebCore { -class TilesTracker { +class CanvasTexture; + +class CanvasLayer : public LayerAndroid, private CanvasObserver { public: - TilesTracker() { - clear(); - } - - void track(bool ready, bool haveTexture) { - m_nbTextures++; - if (ready) - m_nbTexturesReady++; - else - m_nbTexturesNotReady++; - if (haveTexture) - m_nbTexturesUsed++; - } - - void clear() { - m_nbLayers = 0; - m_nbVisibleLayers = 0; - m_nbTextures = 0; - m_nbTexturesReady = 0; - m_nbTexturesNotReady = 0; - m_nbTexturesUsed = 0; - } - - void trackLayer() { m_nbLayers++; } - void trackVisibleLayer() { m_nbVisibleLayers++; } - - void showTrackTextures() { - XLOG("We had %d/%d layers needing %d textures, we had %d, %d were ready, %d were not", - m_nbLayers, m_nbVisibleLayers, m_nbTextures, m_nbTexturesUsed, m_nbTexturesReady, m_nbTexturesNotReady); - } + CanvasLayer(RenderLayer* owner, HTMLCanvasElement* canvas); + CanvasLayer(const CanvasLayer& layer); + virtual ~CanvasLayer(); + + virtual LayerAndroid* copy() const { return new CanvasLayer(*this); } + virtual SubclassType subclassType() { return LayerAndroid::CanvasLayer; } + virtual void clearDirtyRegion(); + + virtual bool drawGL(bool layerTilesDisabled); + virtual void contentDraw(SkCanvas* canvas, PaintStyle style); + virtual bool needsTexture(); + +protected: + virtual InvalidateFlags onSetHwAccelerated(bool hwAccelerated); private: - int m_nbLayers; - int m_nbVisibleLayers; - int m_nbTextures; - int m_nbTexturesReady; - int m_nbTexturesNotReady; - int m_nbTexturesUsed; + virtual void canvasChanged(HTMLCanvasElement*, const FloatRect& changedRect); + virtual void canvasResized(HTMLCanvasElement*); + virtual void canvasDestroyed(HTMLCanvasElement*); + + void init(); + SkBitmapRef* bitmap() const; + IntRect contentRect() const; + IntSize offsetFromRenderer() const; + + HTMLCanvasElement* m_canvas; + IntRect m_contentRect; + IntSize m_offsetFromRenderer; + SkRegion m_dirtyCanvas; + SkBitmapRef* m_bitmap; + RefPtr<CanvasTexture> m_texture; }; } // namespace WebCore #endif // USE(ACCELERATED_COMPOSITING) -#endif // TilesTracker_h + +#endif // CanvasLayer_h diff --git a/Source/WebCore/platform/graphics/android/CanvasTexture.cpp b/Source/WebCore/platform/graphics/android/CanvasTexture.cpp new file mode 100644 index 0000000..e4b2bc6 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/CanvasTexture.cpp @@ -0,0 +1,225 @@ +/* + * 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. + */ + +#define LOG_TAG "CanvasTexture" +#define LOG_NDEBUG 1 + +#include "config.h" +#include "CanvasTexture.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "android_graphics.h" +#include "AndroidLog.h" +#include "GLUtils.h" +#include "Image.h" +#include "ImageBuffer.h" +#include "SkBitmap.h" +#include "SkBitmapRef.h" +#include "SkDevice.h" +#include "SkPixelRef.h" + +#include <android/native_window.h> +#include <gui/SurfaceTexture.h> +#include <gui/SurfaceTextureClient.h> + +namespace WebCore { + +static int s_maxTextureSize = 0; +static HashMap<int, CanvasTexture*> s_textures; +static android::Mutex s_texturesLock; + +/******************************************** + * Called by both threads + ********************************************/ + +PassRefPtr<CanvasTexture> CanvasTexture::getCanvasTexture(CanvasLayer* layer) +{ + android::Mutex::Autolock lock(s_texturesLock); + RefPtr<CanvasTexture> texture = s_textures.get(layer->uniqueId()); + if (texture.get()) + return texture.release(); + return adoptRef(new CanvasTexture(layer->uniqueId())); +} + +bool CanvasTexture::setHwAccelerated(bool hwAccelerated) +{ + android::Mutex::Autolock lock(m_surfaceLock); + if (m_useHwAcceleration == hwAccelerated) + return false; + m_useHwAcceleration = hwAccelerated; + if (!m_ANW.get()) + return false; + destroySurfaceTextureLocked(); + return true; +} + +/******************************************** + * Called by WebKit thread + ********************************************/ + +void CanvasTexture::setSize(const IntSize& size) +{ + android::Mutex::Autolock lock(m_surfaceLock); + if (m_size == size) + return; + m_size = size; + if (m_ANW.get()) { + if (useSurfaceTexture()) { + int result = native_window_set_buffers_dimensions(m_ANW.get(), + m_size.width(), m_size.height()); + GLUtils::checkSurfaceTextureError("native_window_set_buffers_dimensions", result); + if (result != NO_ERROR) + m_useHwAcceleration = false; // On error, drop out of HWA + } + if (!useSurfaceTexture()) + destroySurfaceTextureLocked(); + } +} + +SurfaceTextureClient* CanvasTexture::nativeWindow() +{ + android::Mutex::Autolock lock(m_surfaceLock); + if (m_ANW.get()) + return m_ANW.get(); + if (!m_texture) + return 0; + if (!useSurfaceTexture()) + return 0; + m_surfaceTexture = new android::SurfaceTexture(m_texture, false); + m_ANW = new android::SurfaceTextureClient(m_surfaceTexture); + int result = native_window_set_buffers_format(m_ANW.get(), HAL_PIXEL_FORMAT_RGBA_8888); + GLUtils::checkSurfaceTextureError("native_window_set_buffers_format", result); + if (result == NO_ERROR) { + result = native_window_set_buffers_dimensions(m_ANW.get(), + m_size.width(), m_size.height()); + GLUtils::checkSurfaceTextureError("native_window_set_buffers_dimensions", result); + } + if (result != NO_ERROR) { + m_useHwAcceleration = false; + destroySurfaceTextureLocked(); + return 0; + } + return m_ANW.get(); +} + +bool CanvasTexture::uploadImageBuffer(ImageBuffer* imageBuffer) +{ + m_hasValidTexture = false; + SurfaceTextureClient* anw = nativeWindow(); + if (!anw) + return false; + // Size mismatch, early abort (will fall back to software) + if (imageBuffer->size() != m_size) + return false; + GraphicsContext* gc = imageBuffer ? imageBuffer->context() : 0; + if (!gc) + return false; + const SkBitmap& bitmap = android_gc2canvas(gc)->getDevice()->accessBitmap(false); + if (!GLUtils::updateSharedSurfaceTextureWithBitmap(anw, bitmap)) + return false; + m_hasValidTexture = true; + return true; +} + +/******************************************** + * Called by UI thread WITH GL context + ********************************************/ + +CanvasTexture::~CanvasTexture() +{ + if (m_layerId) { + s_texturesLock.lock(); + s_textures.remove(m_layerId); + s_texturesLock.unlock(); + } + if (m_texture) + GLUtils::deleteTexture(&m_texture); +} + +void CanvasTexture::requireTexture() +{ + android::Mutex::Autolock lock(m_surfaceLock); + if (!m_texture) + glGenTextures(1, &m_texture); + if (!s_maxTextureSize) + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &s_maxTextureSize); +} + +bool CanvasTexture::updateTexImage() +{ + android::Mutex::Autolock lock(m_surfaceLock); + if (!m_surfaceTexture.get()) + return false; + status_t result = m_surfaceTexture->updateTexImage(); + if (result != OK) { + ALOGE("unexpected error: updateTexImage return %d", result); + return false; + } + return true; +} + +/******************************************** + * Called by both threads + ********************************************/ + +void CanvasTexture::destroySurfaceTextureLocked() +{ + if (m_ANW.get()) { + m_ANW.clear(); + m_surfaceTexture->abandon(); + m_surfaceTexture.clear(); + } +} + +/******************************************** + * Called by WebKit thread + ********************************************/ + +CanvasTexture::CanvasTexture(int layerId) + : m_size() + , m_layerId(layerId) + , m_texture(0) + , m_surfaceTexture(0) + , m_ANW(0) + , m_hasValidTexture(false) + , m_useHwAcceleration(true) +{ + s_textures.add(m_layerId, this); +} + +// TODO: Have a global limit as well as a way to react to low memory situations +bool CanvasTexture::useSurfaceTexture() +{ + if (!m_useHwAcceleration) + return false; + if (m_size.isEmpty()) + return false; + return (m_size.width() < s_maxTextureSize) && (m_size.height() < s_maxTextureSize); +} + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/CanvasTexture.h b/Source/WebCore/platform/graphics/android/CanvasTexture.h new file mode 100644 index 0000000..98962a0 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/CanvasTexture.h @@ -0,0 +1,95 @@ +/* + * 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 CanvasTexture_h +#define CanvasTexture_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "CanvasLayer.h" + +#include <wtf/RefPtr.h> +#include <utils/threads.h> + +namespace android { +class SurfaceTexture; +class SurfaceTextureClient; +} + +namespace WebCore { + +class CanvasTexture : public ThreadSafeRefCounted<CanvasTexture> { + +public: + /******************************************** + * Called by both threads + ********************************************/ + static PassRefPtr<CanvasTexture> getCanvasTexture(CanvasLayer* layer); + bool setHwAccelerated(bool hwAccelerated); + + /******************************************** + * Called by WebKit thread + ********************************************/ + void setSize(const IntSize& size); + SurfaceTextureClient* nativeWindow(); + bool uploadImageBuffer(ImageBuffer* imageBuffer); + bool hasValidTexture() { return m_hasValidTexture; } + + /******************************************** + * Called by UI thread WITH GL context + ********************************************/ + virtual ~CanvasTexture(); + void requireTexture(); + GLuint texture() { requireTexture(); return m_texture; } + bool updateTexImage(); + +private: + /******************************************** + * Called by both threads + ********************************************/ + void destroySurfaceTextureLocked(); + + /******************************************** + * Called by WebKit thread + ********************************************/ + CanvasTexture(int layerId); + bool useSurfaceTexture(); + + IntSize m_size; + int m_layerId; + GLuint m_texture; + android::Mutex m_surfaceLock; + sp<android::SurfaceTexture> m_surfaceTexture; + sp<android::SurfaceTextureClient> m_ANW; + bool m_hasValidTexture; + bool m_useHwAcceleration; + +}; + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) + +#endif // CanvasTexture_h diff --git a/Source/WebCore/platform/graphics/android/ClassTracker.cpp b/Source/WebCore/platform/graphics/android/ClassTracker.cpp index eb810a8..98e33d9 100644 --- a/Source/WebCore/platform/graphics/android/ClassTracker.cpp +++ b/Source/WebCore/platform/graphics/android/ClassTracker.cpp @@ -23,19 +23,18 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#define LOG_TAG "ClassTracker" +#define LOG_NDEBUG 1 + #include "config.h" #include "ClassTracker.h" +#include "AndroidLog.h" #include "LayerAndroid.h" #include "TilesManager.h" -#include <cutils/log.h> -#include <wtf/CurrentTime.h> #include <wtf/text/CString.h> -#undef XLOG -#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "ClassTracker", __VA_ARGS__) - #define DEBUG_LAYERS #undef DEBUG_LAYERS @@ -85,12 +84,12 @@ void ClassTracker::remove(LayerAndroid* layer) void ClassTracker::show() { android::Mutex::Autolock lock(m_lock); - XLOG("*** Tracking %d classes ***", m_classes.size()); + ALOGD("*** Tracking %d classes ***", m_classes.size()); for (HashMap<String, int>::iterator iter = m_classes.begin(); iter != m_classes.end(); ++iter) { - XLOG("class %s has %d instances", - iter->first.latin1().data(), iter->second); + ALOGD("class %s has %d instances", + iter->first.latin1().data(), iter->second); } - XLOG("*** %d Layers ***", m_layers.size()); + ALOGD("*** %d Layers ***", m_layers.size()); int nbTextures = 0; int nbAllocatedTextures = 0; int nbLayerTextures = 0; @@ -98,23 +97,23 @@ void ClassTracker::show() float textureSize = 256 * 256 * 4 / 1024.0 / 1024.0; TilesManager::instance()->gatherTexturesNumbers(&nbTextures, &nbAllocatedTextures, &nbLayerTextures, &nbAllocatedLayerTextures); - XLOG("*** textures: %d/%d (%.2f Mb), layer textures: %d/%d (%.2f Mb) : total used %.2f Mb", - nbAllocatedTextures, nbTextures, - nbAllocatedTextures * textureSize, - nbAllocatedLayerTextures, nbLayerTextures, - nbAllocatedLayerTextures * textureSize, - (nbAllocatedTextures + nbAllocatedLayerTextures) * textureSize); + ALOGD("*** textures: %d/%d (%.2f Mb), layer textures: %d/%d (%.2f Mb) : total used %.2f Mb", + nbAllocatedTextures, nbTextures, + nbAllocatedTextures * textureSize, + nbAllocatedLayerTextures, nbLayerTextures, + nbAllocatedLayerTextures * textureSize, + (nbAllocatedTextures + nbAllocatedLayerTextures) * textureSize); #ifdef DEBUG_LAYERS for (unsigned int i = 0; i < m_layers.size(); i++) { LayerAndroid* layer = m_layers[i]; - XLOG("[%d/%d] layer %x (%.2f, %.2f) of type %d, refcount(%d) has texture %x has image ref %x (%x) root: %x parent: %x", - i, m_layers.size(), layer, - layer->getWidth(), layer->getHeight(), - layer->type(), layer->getRefCnt(), - layer->texture(), layer->imageRef(), - layer->imageTexture(), (LayerAndroid*) layer->getRootLayer(), - (LayerAndroid*) layer->getParent()); + ALOGD("[%d/%d] layer %x (%.2f, %.2f) of type %d, refcount(%d) has texture %x has image ref %x (%x) root: %x parent: %x", + i, m_layers.size(), layer, + layer->getWidth(), layer->getHeight(), + layer->type(), layer->getRefCnt(), + layer->texture(), layer->imageRef(), + layer->imageTexture(), (LayerAndroid*) layer->getRootLayer(), + (LayerAndroid*) layer->getParent()); } #endif } 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..989eebd --- /dev/null +++ b/Source/WebCore/platform/graphics/android/FixedPositioning.cpp @@ -0,0 +1,105 @@ +#define LOG_TAG "FixedPositioning" +#define LOG_NDEBUG 1 + +#include "config.h" +#include "FixedPositioning.h" + +#include "AndroidLog.h" +#include "DumpLayer.h" +#include "IFrameLayerAndroid.h" +#include "TilesManager.h" + +#if USE(ACCELERATED_COMPOSITING) + +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..c8b9488 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 @@ -87,6 +88,8 @@ static bool setupForText(SkPaint* paint, GraphicsContext* gc, if (!mode) return false; + paint->setVerticalText(font->platformData().orientation() == Vertical); + FloatSize shadowOffset; float shadowBlur; Color shadowColor; @@ -192,8 +195,6 @@ void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font, const GlyphBufferAdvance* adv = glyphBuffer.advances(from); SkAutoSTMalloc<32, SkPoint> storage(numGlyphs), storage2(numGlyphs), storage3(numGlyphs); SkPoint* pos = storage.get(); - SkPoint* vPosBegin = storage2.get(); - SkPoint* vPosEnd = storage3.get(); SkCanvas* canvas = gc->platformContext()->mCanvas; @@ -201,6 +202,9 @@ void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font, point.xy + [width, height, width, height, ...], so we have to convert */ + if (font->platformData().orientation() == Vertical) + y += SkFloatToScalar(font->fontMetrics().floatAscent(IdeographicBaseline) - font->fontMetrics().floatAscent()); + if (EmojiFont::IsAvailable()) { // set filtering, to make scaled images look nice(r) paint.setFilterBitmap(true); @@ -230,27 +234,25 @@ void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font, localCount * sizeof(uint16_t), &pos[localIndex], paint); } else { - bool isVertical = font->platformData().orientation() == Vertical; for (int i = 0; i < numGlyphs; i++) { pos[i].set(x, y); y += SkFloatToScalar(adv[i].height()); - if (isVertical) { - SkScalar myWidth = SkFloatToScalar(adv[i].width()); - vPosBegin[i].set(x + myWidth, y); - vPosEnd[i].set(x + myWidth, y - myWidth); - x += myWidth; - - SkPath path; - path.reset(); - path.moveTo(vPosBegin[i]); - path.lineTo(vPosEnd[i]); - canvas->drawTextOnPath(glyphs + i, 2, path, 0, paint); - } - else - x += SkFloatToScalar(adv[i].width()); + x += SkFloatToScalar(adv[i].width()); } - if (!isVertical) - canvas->drawPosText(glyphs, numGlyphs * sizeof(uint16_t), pos, paint); + + if (font->platformData().orientation() == Vertical) { + canvas->save(); + canvas->rotate(-90); + SkMatrix rotator; + rotator.reset(); + rotator.setRotate(90); + rotator.mapPoints(pos, numGlyphs); + } + + canvas->drawPosText(glyphs, numGlyphs * sizeof(uint16_t), pos, paint); + + if (font->platformData().orientation() == Vertical) + canvas->restore(); } } @@ -379,7 +381,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 +427,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 +474,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 +487,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 +522,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 +654,7 @@ bool TextRunWalker::nextScriptRun() setupFontForScriptRun(); shapeGlyphs(); - setGlyphXPositions(rtl()); + setGlyphPositions(rtl()); return true; } @@ -737,6 +741,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 +759,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 +770,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 +781,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 +797,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 +817,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 +832,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 +855,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 +902,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 +975,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,16 +1002,16 @@ 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 + } else if (!walker.rtl()) 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 + } else if (!walker.rtl()) to -= numCodePoints; if (!walker.rtl()) @@ -1028,7 +1056,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 +1064,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 +1079,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 +1111,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/FontCacheAndroid.cpp b/Source/WebCore/platform/graphics/android/FontCacheAndroid.cpp index 4fc3b4e..5696a46 100644 --- a/Source/WebCore/platform/graphics/android/FontCacheAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/FontCacheAndroid.cpp @@ -34,7 +34,6 @@ #include "SkPaint.h" #include "SkTypeface.h" #include "SkUtils.h" -#include <wtf/text/CString.h> namespace WebCore { diff --git a/Source/WebCore/platform/graphics/android/FontDataAndroid.cpp b/Source/WebCore/platform/graphics/android/FontDataAndroid.cpp index c6dd174..88822df 100644 --- a/Source/WebCore/platform/graphics/android/FontDataAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/FontDataAndroid.cpp @@ -56,8 +56,12 @@ void SimpleFontData::platformInit() m_fontMetrics.setAscent(a); m_fontMetrics.setDescent(d); m_fontMetrics.setXHeight(SkScalarToFloat(-skiaFontMetrics.fAscent) * 0.56f); // hack I stole from the window's port - m_fontMetrics.setLineSpacing(a + d); - m_fontMetrics.setLineGap(SkScalarToFloat(skiaFontMetrics.fLeading)); + float lineGap = SkScalarToFloat(skiaFontMetrics.fLeading); + if (platformData().orientation() == Vertical && lineGap == 0) { + lineGap = skiaFontMetrics.fAvgCharWidth * 0.56f; + } + m_fontMetrics.setLineGap(lineGap); + m_fontMetrics.setLineSpacing(a + d + lineGap); if (platformData().orientation() == Vertical && !isTextOrientationFallback()) { static const uint32_t vheaTag = SkSetFourByteTag('v', 'h', 'e', 'a'); 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..1676489 100644 --- a/Source/WebCore/platform/graphics/android/GLExtras.cpp +++ b/Source/WebCore/platform/graphics/android/GLExtras.cpp @@ -23,50 +23,24 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#define LOG_TAG "GLExtras" +#define LOG_NDEBUG 1 + #include "config.h" +#include "AndroidLog.h" #include "DrawExtra.h" -#include "FindCanvas.h" #include "GLExtras.h" #include "IntRect.h" #include "TilesManager.h" #include "android_graphics.h" -#include <cutils/log.h> -#include <wtf/text/CString.h> - -#undef XLOGC -#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "GLExtras", __VA_ARGS__) - -#ifdef DEBUG - -#undef XLOG -#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "GLExtras", __VA_ARGS__) - -#else - -#undef XLOG -#define XLOG(...) - -#endif // DEBUG - // 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 +48,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); + ALOGV("drawQuad [%fx%f, %f, %f]", srcRect.fLeft, srcRect.fTop, + srcRect.width(), srcRect.height()); + // 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 +79,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 +120,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 +131,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..beb62db 100644 --- a/Source/WebCore/platform/graphics/android/GLUtils.cpp +++ b/Source/WebCore/platform/graphics/android/GLUtils.cpp @@ -23,6 +23,9 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#define LOG_TAG "GLUtils" +#define LOG_NDEBUG 1 + #include "config.h" #include "GLUtils.h" @@ -31,26 +34,15 @@ #include "ShaderProgram.h" #include "TilesManager.h" -#include <cutils/log.h> +#include <AndroidLog.h> +#include <android/native_window.h> #include <gui/SurfaceTexture.h> #include <wtf/CurrentTime.h> -#include <wtf/text/CString.h> - - -#ifdef DEBUG - -#include <cutils/log.h> -#include <wtf/text/CString.h> -#undef XLOG -#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "GLUtils", __VA_ARGS__) - -#else - -#undef XLOG -#define XLOG(...) - -#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; @@ -116,10 +108,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."); + ALOGE("ERROR: Fatal OOM detected."); CRASH(); } } @@ -127,11 +144,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 + ALOGE("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 + ALOGE("after %s() eglError (0x%x)\n", op, error); crashIfOOM(error); } } @@ -140,7 +163,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 + ALOGE("GL ERROR - after %s() glError (0x%x)\n", op, error); crashIfOOM(error); ret = true; } @@ -151,7 +177,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 + ALOGE("GL ERROR on %x - after %s() glError (0x%x)\n", p, op, error); crashIfOOM(error); ret = true; } @@ -161,7 +190,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 + ALOGE("ERROR at calling %s status is (%d)", functionName, status); } } ///////////////////////////////////////////////////////////////////////////////////////// @@ -237,7 +269,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; } @@ -269,7 +301,7 @@ EGLContext GLUtils::createBackgroundContext(EGLContext sharedContext) EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); checkEglError("eglGetDisplay"); if (display == EGL_NO_DISPLAY) { - XLOG("eglGetDisplay returned EGL_NO_DISPLAY"); + ALOGE("eglGetDisplay returned EGL_NO_DISPLAY"); return EGL_NO_CONTEXT; } @@ -278,7 +310,7 @@ EGLContext GLUtils::createBackgroundContext(EGLContext sharedContext) EGLBoolean returnValue = eglInitialize(display, &majorVersion, &minorVersion); checkEglError("eglInitialize", returnValue); if (returnValue != EGL_TRUE) { - XLOG("eglInitialize failed\n"); + ALOGE("eglInitialize failed\n"); return EGL_NO_CONTEXT; } @@ -292,14 +324,14 @@ EGLContext GLUtils::createBackgroundContext(EGLContext sharedContext) EGLContext context = eglCreateContext(display, config, sharedContext, contextAttribs); checkEglError("eglCreateContext"); if (context == EGL_NO_CONTEXT) { - XLOG("eglCreateContext failed\n"); + ALOGE("eglCreateContext failed\n"); return EGL_NO_CONTEXT; } returnValue = eglMakeCurrent(display, surface, surface, context); checkEglError("eglMakeCurrent", returnValue); if (returnValue != EGL_TRUE) { - XLOG("eglMakeCurrent failed\n"); + ALOGE("eglMakeCurrent failed\n"); return EGL_NO_CONTEXT; } @@ -313,7 +345,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 +403,154 @@ 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]); + ALOGV("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. + if (tileTexture && renderInfo->isPureColor) { + // 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); + + 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::updateQueueWithBitmap(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()); + ALOGV("The bitmap size (%d,%d) does not equal the texture size (%d,%d)", + bitmap.width(), bitmap.height(), + requiredSize.width(), requiredSize.height()); } + GLUtils::updateQueueWithBitmap(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) +void GLUtils::updateQueueWithBitmap(const TileRenderInfo* renderInfo, const SkBitmap& bitmap) { + if (!renderInfo + || !renderInfo->textureInfo + || !renderInfo->baseTile) + return; - 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); + TilesManager::instance()->transferQueue()->updateQueueWithBitmap(renderInfo, bitmap); } -void GLUtils::updateSurfaceTextureWithBitmap(const TileRenderInfo* renderInfo, int x, int y, const SkBitmap& bitmap, GLint filter) +bool GLUtils::updateSharedSurfaceTextureWithBitmap(ANativeWindow* anw, const SkBitmap& bitmap) { - 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; + SkAutoLockPixels alp(bitmap); + if (!bitmap.getPixels()) + return false; + ANativeWindow_Buffer buffer; + if (ANativeWindow_lock(anw, &buffer, 0)) + return false; + if (buffer.width < bitmap.width() || buffer.height < bitmap.height()) { + ALOGW("bitmap (%dx%d) too large for buffer (%dx%d)!", + bitmap.width(), bitmap.height(), + buffer.width, buffer.height); + ANativeWindow_unlockAndPost(anw); + return false; } + uint8_t* img = (uint8_t*)buffer.bits; + int row; + int bpp = 4; // Now we only deal with RGBA8888 format. + bitmap.lockPixels(); + uint8_t* bitmapOrigin = static_cast<uint8_t*>(bitmap.getPixels()); - 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()); + 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 ++) { - uint8_t* dst = &(img[(buf->getStride() * (row + x) + y) * bpp]); + uint8_t* dst = &(img[buffer.stride * row * 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) -{ - if (!renderInfo - || !renderInfo->textureInfo - || !renderInfo->baseTile) - return; + else + memcpy(img, bitmapOrigin, bpp * bitmap.width() * bitmap.height()); - TilesManager::instance()->transferQueue()->updateQueueWithBitmap(renderInfo, x, y, bitmap); + bitmap.unlockPixels(); + ANativeWindow_unlockAndPost(anw); + return true; } void GLUtils::createTextureWithBitmap(GLuint texture, const SkBitmap& bitmap, GLint filter) @@ -505,9 +566,12 @@ 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," - " internalformat 0x%x, type 0x%x, bitmap.getPixels() %p", - bitmap.width(), bitmap.height(), internalformat, type, bitmap.getPixels()); +#ifndef DEBUG + if (allowGLLog()) +#endif + ALOGE("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()); } glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); @@ -523,7 +587,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 +597,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 + ALOGE("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); @@ -571,6 +644,23 @@ void GLUtils::convertToTransformationMatrix(const float* matrix, TransformationM matrix[12], matrix[13], matrix[14], matrix[15]); } +void GLUtils::clearBackgroundIfOpaque(const Color* backgroundColor) +{ + if (!backgroundColor->hasAlpha()) { + if (TilesManager::instance()->invertedScreen()) { + float color = 1.0 - ((((float) backgroundColor->red() / 255.0) + + ((float) backgroundColor->green() / 255.0) + + ((float) backgroundColor->blue() / 255.0)) / 3.0); + glClearColor(color, color, color, 1); + } else { + glClearColor((float)backgroundColor->red() / 255.0, + (float)backgroundColor->green() / 255.0, + (float)backgroundColor->blue() / 255.0, 1); + } + glClear(GL_COLOR_BUFFER_BIT); + } +} + } // namespace WebCore #endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/GLUtils.h b/Source/WebCore/platform/graphics/android/GLUtils.h index 68acbab..f24ea0d 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,22 @@ 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 updateQueueWithBitmap(const TileRenderInfo* , const SkBitmap& bitmap); + static bool updateSharedSurfaceTextureWithBitmap(ANativeWindow* anw, 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 void clearBackgroundIfOpaque(const Color* backgroundColor); + 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..a5080ca 100644 --- a/Source/WebCore/platform/graphics/android/GLWebViewState.cpp +++ b/Source/WebCore/platform/graphics/android/GLWebViewState.cpp @@ -23,11 +23,15 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#define LOG_TAG "GLWebViewState" +#define LOG_NDEBUG 1 + #include "config.h" #include "GLWebViewState.h" #if USE(ACCELERATED_COMPOSITING) +#include "AndroidLog.h" #include "BaseLayerAndroid.h" #include "ClassTracker.h" #include "GLUtils.h" @@ -36,29 +40,10 @@ #include "ScrollableLayerAndroid.h" #include "SkPath.h" #include "TilesManager.h" -#include "TilesTracker.h" -#include "TreeManager.h" -#include <wtf/CurrentTime.h> - +#include "SurfaceCollection.h" +#include "SurfaceCollectionManager.h" #include <pthread.h> - -#include <cutils/log.h> -#include <wtf/text/CString.h> - -#undef XLOGC -#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "GLWebViewState", __VA_ARGS__) - -#ifdef DEBUG - -#undef XLOG -#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "GLWebViewState", __VA_ARGS__) - -#else - -#undef XLOG -#define XLOG(...) - -#endif // DEBUG +#include <wtf/CurrentTime.h> #define FIRST_TILED_PAGE_ID 1 #define SECOND_TILED_PAGE_ID 2 @@ -69,32 +54,28 @@ #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_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(); - m_viewportTileBounds.setEmpty(); - m_preZoomBounds.setEmpty(); - - m_tiledPageA = new TiledPage(FIRST_TILED_PAGE_ID, this); - m_tiledPageB = new TiledPage(SECOND_TILED_PAGE_ID, this); #ifdef DEBUG_COUNT ClassTracker::instance()->increment("GLWebViewState"); @@ -108,39 +89,26 @@ 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. - // Explicitely, currently we need to have the m_paintingBaseLayer around - // in order to complete any pending paint operations (the tiled pages - // will remove any pending operations, and wait if one is underway). - delete m_tiledPageA; - delete m_tiledPageB; #ifdef DEBUG_COUNT ClassTracker::instance()->decrement("GLWebViewState"); #endif } -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 - m_zoomManager.swapPages(); // reset zoom state - m_tiledPageA->discardTextures(); - m_tiledPageB->discardTextures(); + if (!layer || isPictureAfterFirstLayout) m_layersRenderingMode = kAllTextures; - } + + SurfaceCollection* collection = 0; if (layer) { - XLOG("new base layer %p, (inval region empty %d) with child %p", layer, inval.isEmpty(), layer->getChild(0)); + ALOGV("layer tree %p, with child %p", layer, layer->getChild(0)); layer->setState(this); - layer->markAsDirty(inval); // TODO: set in webview.cpp + collection = new SurfaceCollection(layer); } - m_treeManager.updateWithTree(layer, isPictureAfterFirstLayout); + bool queueFull = m_surfaceCollectionManager.updateWithSurfaceCollection( + collection, isPictureAfterFirstLayout); m_glExtras.setDrawExtra(0); #ifdef MEASURES_PERF @@ -150,135 +118,54 @@ 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); - - // TODO: only inval the area of the scrolled layer instead of - // doing a fullInval() - if (m_layersRenderingMode == kSingleSurfaceRendering) - fullInval(); -} - -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() - fullInval(); - return; - } - SkRegion::Iterator iterator(region); - while (!iterator.done()) { - SkIRect r = iterator.rect(); - IntRect ir(r.fLeft, r.fTop, r.width(), r.height()); - inval(ir); - iterator.next(); - } -} - -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); - if (m_frameworkInval.isEmpty()) - m_frameworkInval = rect; - else - m_frameworkInval.unite(rect); - XLOG("intermediate invalRect(%d, %d, %d, %d) after unite with rect %d %d %d %d", m_frameworkInval.x(), - m_frameworkInval.y(), m_frameworkInval.width(), m_frameworkInval.height(), - rect.x(), rect.y(), rect.width(), rect.height()); - } - TilesManager::instance()->getProfiler()->nextInval(rect, zoomManager()->currentScale()); -} - -unsigned int GLWebViewState::paintBaseLayerContent(SkCanvas* canvas) -{ - m_treeManager.drawCanvas(canvas, m_layersRenderingMode == kSingleSurfaceRendering); - return m_currentPictureCounter; -} - -TiledPage* GLWebViewState::sibling(TiledPage* page) -{ - return (page == m_tiledPageA) ? m_tiledPageB : m_tiledPageA; + m_surfaceCollectionManager.updateScrollableLayer(layerId, x, y); } -TiledPage* GLWebViewState::frontPage() +void GLWebViewState::setViewport(const SkRect& viewport, float scale) { - android::Mutex::Autolock lock(m_tiledPageLock); - return m_usePageA ? m_tiledPageA : m_tiledPageB; -} + // allocate max possible number of tiles visible with this viewport / expandedTileBounds + const float invTileContentWidth = scale / TilesManager::tileWidth(); + const float invTileContentHeight = scale / TilesManager::tileHeight(); -TiledPage* GLWebViewState::backPage() -{ - android::Mutex::Autolock lock(m_tiledPageLock); - return m_usePageA ? m_tiledPageB : m_tiledPageA; -} + int viewMaxTileX = static_cast<int>(ceilf((viewport.width()-1) * invTileContentWidth)) + 1; + int viewMaxTileY = static_cast<int>(ceilf((viewport.height()-1) * invTileContentHeight)) + 1; -void GLWebViewState::swapPages() -{ - android::Mutex::Autolock lock(m_tiledPageLock); - m_usePageA ^= true; - TiledPage* oldPage = m_usePageA ? m_tiledPageB : m_tiledPageA; - zoomManager()->swapPages(); - oldPage->discardTextures(); -} + TilesManager* manager = TilesManager::instance(); + int maxTextureCount = viewMaxTileX * viewMaxTileY * (manager->highEndGfx() ? 4 : 2); -int GLWebViewState::baseContentWidth() -{ - return m_treeManager.baseContentWidth(); -} -int GLWebViewState::baseContentHeight() -{ - return m_treeManager.baseContentHeight(); -} + manager->setMaxTextureCount(maxTextureCount); -void GLWebViewState::setViewport(SkRect& viewport, float scale) -{ - if ((m_viewport == viewport) && - (zoomManager()->futureScale() == scale)) + // TODO: investigate whether we can move this return earlier. + if ((m_viewport == viewport) + && (m_scale == scale)) { + // everything below will stay the same, early return. + m_isViewportScrolling = false; return; + } + m_scale = scale; m_goingDown = m_viewport.fTop - viewport.fTop <= 0; m_goingLeft = m_viewport.fLeft - viewport.fLeft >= 0; - m_viewport = viewport; - - XLOG("New VIEWPORT %.2f - %.2f %.2f - %.2f (w: %2.f h: %.2f scale: %.2f currentScale: %.2f futureScale: %.2f)", - m_viewport.fLeft, m_viewport.fTop, m_viewport.fRight, m_viewport.fBottom, - 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); + // detect viewport scrolling from short programmatic scrolls/jumps + m_isViewportScrolling = m_viewport != viewport && SkRect::Intersects(m_viewport, viewport); + m_viewport = viewport; - TilesManager::instance()->setMaxTextureCount(maxTextureCount); - m_tiledPageA->updateBaseTileSize(); - m_tiledPageB->updateBaseTileSize(); + ALOGV("New VIEWPORT %.2f - %.2f %.2f - %.2f (w: %2.f h: %.2f scale: %.2f )", + m_viewport.fLeft, m_viewport.fTop, m_viewport.fRight, m_viewport.fBottom, + m_viewport.width(), m_viewport.height(), scale); } #ifdef MEASURES_PERF void GLWebViewState::dumpMeasures() { for (int i = 0; i < m_timeCounter; i++) { - XLOGC("%d delay: %d ms", m_totalTimeCounter + i, + ALOGD("%d delay: %d ms", m_totalTimeCounter + i, static_cast<int>(m_delayTimes[i]*1000)); m_delayTimes[i] = 0; } @@ -287,14 +174,6 @@ void GLWebViewState::dumpMeasures() } #endif // MEASURES_PERF -void GLWebViewState::resetFrameworkInval() -{ - m_frameworkInval.setX(0); - m_frameworkInval.setY(0); - m_frameworkInval.setWidth(0); - m_frameworkInval.setHeight(0); -} - void GLWebViewState::addDirtyArea(const IntRect& rect) { if (rect.isEmpty()) @@ -316,42 +195,34 @@ void GLWebViewState::resetLayersDirtyArea() m_frameworkLayersInval.setHeight(0); } -void GLWebViewState::drawBackground(Color& backgroundColor) -{ - if (TilesManager::instance()->invertedScreen()) { - float color = 1.0 - ((((float) backgroundColor.red() / 255.0) + - ((float) backgroundColor.green() / 255.0) + - ((float) backgroundColor.blue() / 255.0)) / 3.0); - glClearColor(color, color, color, 1); - } else { - glClearColor((float)backgroundColor.red() / 255.0, - (float)backgroundColor.green() / 255.0, - (float)backgroundColor.blue() / 255.0, 1); - } - 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()) { + ALOGD("Reinit shader"); + shader->initGLResources(); } - shader->setViewport(visibleRect, scale); - shader->setViewRect(viewRect); - shader->setWebViewRect(webViewRect); - shader->setTitleBarHeight(titleBarHeight); - shader->setScreenClip(screenClip); - shader->resetBlending(); + TransferQueue* transferQueue = tilesManager->transferQueue(); + if (transferQueue->needsInit()) { + ALOGD("Reinit transferQueue"); + transferQueue->initGLResources(TilesManager::tileWidth(), + TilesManager::tileHeight()); + } + // TODO: Add the video GL resource re-initialization code here. + shader->setupDrawing(viewRect, visibleRect, webViewRect, + titleBarHeight, screenClip, scale); shader->calculateAnimationDelta(); glViewport(left + shader->getAnimationDeltaX(), @@ -361,7 +232,6 @@ double GLWebViewState::setupDrawing(IntRect& viewRect, SkRect& visibleRect, double currentTime = WTF::currentTime(); setViewport(visibleRect, scale); - m_zoomManager.processNewScale(currentTime, scale); return currentTime; } @@ -409,7 +279,7 @@ bool GLWebViewState::setLayersRenderingMode(TexturesResult& nbTexturesNeeded) if (m_layersRenderingMode != layersRenderingMode) { char* mode[] = { "kAllTextures", "kClippedTextures", "kScrollableAndFixedLayers", "kFixedLayers", "kSingleSurfaceRendering" }; - XLOGC("Change from mode %s to %s -- We need textures: fixed: %d," + ALOGD("Change from mode %s to %s -- We need textures: fixed: %d," " scrollable: %d, clipped: %d, full: %d, max textures: %d", static_cast<char*>(mode[layersRenderingMode]), static_cast<char*>(mode[m_layersRenderingMode]), @@ -427,90 +297,67 @@ bool GLWebViewState::setLayersRenderingMode(TexturesResult& nbTexturesNeeded) m_layersRenderingMode = kSingleSurfaceRendering; // update the base surface if needed - if (m_layersRenderingMode != layersRenderingMode - && invalBase) { - m_tiledPageA->discardTextures(); - m_tiledPageB->discardTextures(); - fullInval(); - return true; - } - return false; -} - -void GLWebViewState::fullInval() -{ - // TODO -- use base layer's size. - IntRect ir(0, 0, 1E6, 1E6); - inval(ir); + // TODO: inval base layergroup when going into single surface mode + return (m_layersRenderingMode != layersRenderingMode && invalBase); } 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) { - m_scale = scale; - TilesManager::instance()->getProfiler()->nextFrame(viewport.fLeft, - viewport.fTop, - viewport.fRight, - viewport.fBottom, - scale); - TilesManager::instance()->incDrawGLCount(); - -#ifdef DEBUG - TilesManager::instance()->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(); - m_expandedTileBoundsX = (useHorzPrefetch) ? TILE_PREFETCH_DISTANCE : 0; - m_expandedTileBoundsY = (useVertPrefetch) ? TILE_PREFETCH_DISTANCE : 0; - - XLOG("drawGL, rect(%d, %d, %d, %d), viewport(%.2f, %.2f, %.2f, %.2f)", - rect.x(), rect.y(), rect.width(), rect.height(), - viewport.fLeft, viewport.fTop, viewport.fRight, viewport.fBottom); + TilesManager* tilesManager = TilesManager::instance(); + tilesManager->getProfiler()->nextFrame(viewport.fLeft, viewport.fTop, + viewport.fRight, viewport.fBottom, + scale); + tilesManager->incDrawGLCount(); + + ALOGV("drawGL, rect(%d, %d, %d, %d), viewport(%.2f, %.2f, %.2f, %.2f)", + rect.x(), rect.y(), rect.width(), rect.height(), + viewport.fLeft, viewport.fTop, viewport.fRight, viewport.fBottom); + + ALOGV("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); resetLayersDirtyArea(); - // 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 - if (scale < MIN_SCALE_WARNING || scale > MAX_SCALE_WARNING) - XLOGC("WARNING, scale seems corrupted before update: %e", scale); + ALOGW("WARNING, scale seems corrupted before update: %e", scale); // 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) - XLOGC("WARNING, scale seems corrupted after update: %e", scale); + if (scale < MIN_SCALE_WARNING || scale > MAX_SCALE_WARNING) { + ALOGW("WARNING, scale seems corrupted after update: %e", scale); + CRASH(); + } // gather the textures we can use - TilesManager::instance()->gatherLayerTextures(); + tilesManager->gatherTextures(); 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); - if (!ret) - resetFrameworkInval(); + m_glExtras.setViewport(viewport); + ret |= m_surfaceCollectionManager.drawGL(currentTime, rect, viewport, + scale, fastSwap, + collectionsSwappedPtr, newCollectionHasAnimPtr, + &nbTexturesNeeded); int nbTexturesForImages = ImagesManager::instance()->nbTextures(); - XLOG("*** We have %d textures for images, %d full, %d clipped, total %d / %d", + ALOGV("*** We have %d textures for images, %d full, %d clipped, total %d / %d", nbTexturesForImages, nbTexturesNeeded.full, nbTexturesNeeded.clipped, nbTexturesNeeded.full + nbTexturesForImages, nbTexturesNeeded.clipped + nbTexturesForImages); @@ -518,45 +365,27 @@ 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(); if (ret) { // ret==true && empty inval region means we've inval'd everything, // but don't have new content. Keep redrawing full view (0,0,0,0) // until tile generation catches up and we swap pages. - bool fullScreenInval = m_frameworkInval.isEmpty(); - - if (TilesManager::instance()->invertedScreenSwitch()) { - fullScreenInval = true; - TilesManager::instance()->setInvertedScreenSwitch(false); - } + bool fullScreenInval = m_frameworkLayersInval.isEmpty(); if (!fullScreenInval) { - FloatRect frameworkInval = TilesManager::instance()->shader()->rectInInvScreenCoord( - m_frameworkInval); - // Inflate the invalidate rect to avoid precision lost. - frameworkInval.inflate(1); - IntRect inval(frameworkInval.x(), frameworkInval.y(), - frameworkInval.width(), frameworkInval.height()); + m_frameworkLayersInval.inflate(1); - inval.unite(m_frameworkLayersInval); + invalRect->setX(m_frameworkLayersInval.x()); + invalRect->setY(m_frameworkLayersInval.y()); + invalRect->setWidth(m_frameworkLayersInval.width()); + invalRect->setHeight(m_frameworkLayersInval.height()); - invalRect->setX(inval.x()); - invalRect->setY(inval.y()); - invalRect->setWidth(inval.width()); - invalRect->setHeight(inval.height()); - - XLOG("invalRect(%d, %d, %d, %d)", inval.x(), - inval.y(), inval.width(), inval.height()); + ALOGV("invalRect(%d, %d, %d, %d)", inval.x(), + inval.y(), inval.width(), inval.height()); if (!invalRect->intersects(rect)) { // invalidate is occurring offscreen, do full inval to guarantee redraw @@ -570,10 +399,28 @@ bool GLWebViewState::drawGL(IntRect& rect, SkRect& viewport, IntRect* invalRect, invalRect->setWidth(0); invalRect->setHeight(0); } - } else { - resetFrameworkInval(); } + showFrameInfo(rect, *collectionsSwappedPtr); + + 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 +429,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..e4b3b3b 100644 --- a/Source/WebCore/platform/graphics/android/GLWebViewState.h +++ b/Source/WebCore/platform/graphics/android/GLWebViewState.h @@ -35,9 +35,7 @@ #include "SkCanvas.h" #include "SkRect.h" #include "SkRegion.h" -#include "TiledPage.h" -#include "TreeManager.h" -#include "ZoomManager.h" +#include "SurfaceCollectionManager.h" #include <utils/threads.h> // Performance measurements probe @@ -51,9 +49,6 @@ // HW limit or save further in the GPU memory consumption. #define TILE_PREFETCH_DISTANCE 1 -// ratio of content to view required for prefetching to enable -#define TILE_PREFETCH_RATIO 1.2 - namespace WebCore { class BaseLayerAndroid; @@ -171,57 +166,26 @@ public: GLWebViewState(); ~GLWebViewState(); - ZoomManager* zoomManager() { return &m_zoomManager; } - 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, + bool setBaseLayer(BaseLayerAndroid* layer, bool showVisualIndicator, bool isPictureAfterFirstLayout); void paintExtras(); GLExtras* glExtras() { return &m_glExtras; } - TiledPage* sibling(TiledPage* page); - TiledPage* frontPage(); - TiledPage* backPage(); - void swapPages(); - - // dimensions of the current base layer - 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; } - - void drawBackground(Color& backgroundColor); - double setupDrawing(IntRect& viewRect, SkRect& visibleRect, - IntRect& webViewRect, int titleBarHeight, - IntRect& screenClip, float scale); + bool isScrolling() { return m_isScrolling || m_isViewportScrolling; } bool setLayersRenderingMode(TexturesResult&); - void fullInval(); 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(); #endif - void resetFrameworkInval(); void addDirtyArea(const IntRect& rect); void resetLayersDirtyArea(); @@ -232,10 +196,6 @@ public: m_goingLeft = goingLeft; } - int expandedTileBoundsX() { return m_expandedTileBoundsX; } - int expandedTileBoundsY() { return m_expandedTileBoundsY; } - void setHighEndGfx(bool highEnd) { m_highEndGfx = highEnd; } - float scale() { return m_scale; } enum LayersRenderingMode { @@ -250,24 +210,17 @@ public: LayersRenderingMode layersRenderingMode() { return m_layersRenderingMode; } void scrollLayer(int layerId, int x, int y); - void invalRegion(const SkRegion& region); - 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; SkRect m_viewport; - SkIRect m_viewportTileBounds; - SkIRect m_futureViewportTileBounds; - SkIRect m_preZoomBounds; - - unsigned int m_currentPictureCounter; - bool m_usePageA; - TiledPage* m_tiledPageA; - TiledPage* m_tiledPageB; - IntRect m_lastInval; - IntRect m_frameworkInval; IntRect m_frameworkLayersInval; #ifdef MEASURES_PERF @@ -279,17 +232,14 @@ 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/GaneshContext.cpp b/Source/WebCore/platform/graphics/android/GaneshContext.cpp index 03e6eb7..620fccf 100644 --- a/Source/WebCore/platform/graphics/android/GaneshContext.cpp +++ b/Source/WebCore/platform/graphics/android/GaneshContext.cpp @@ -23,37 +23,23 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#define LOG_TAG "GaneshContext" +#define LOG_NDEBUG 1 #include "config.h" #include "GaneshContext.h" + +#include "AndroidLog.h" #include "GLUtils.h" #include "android/native_window.h" #if USE(ACCELERATED_COMPOSITING) -#ifdef DEBUG - -#include <cutils/log.h> -#include <wtf/CurrentTime.h> - -#undef XLOG -#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "GaneshContext", __VA_ARGS__) - -#else - -#undef XLOG -#define XLOG(...) - -#endif // DEBUG - namespace WebCore { GaneshContext::GaneshContext() : m_grContext(0) - , m_baseTileDeviceFBO(0) - , m_baseTileFBO(0) - , m_baseTileStencil(0) , m_baseTileDeviceSurface(0) , m_surfaceConfig(0) , m_surfaceContext(EGL_NO_CONTEXT) @@ -90,33 +76,17 @@ SkDevice* GaneshContext::getDeviceForBaseTile(const TileRenderInfo& renderInfo) // reset the Ganesh context to prevent rendering issues. bool contextNeedsReset = false; if (eglGetCurrentContext() != m_surfaceContext) { - XLOG("Warning: EGLContext has Changed! %p, %p", m_surfaceContext, - eglGetCurrentContext()); + ALOGV("Warning: EGLContext has Changed! %p, %p", + m_surfaceContext, eglGetCurrentContext()); contextNeedsReset = true; } - SkDevice* device = 0; - if (renderInfo.textureInfo->getSharedTextureMode() == SurfaceTextureMode) - device = getDeviceForBaseTileSurface(renderInfo); - else if (renderInfo.textureInfo->getSharedTextureMode() == EglImageMode) - device = getDeviceForBaseTileFBO(renderInfo); - - // We must reset the Ganesh context only after we are sure we have - // re-established our EGLContext as the current context. - if (device && contextNeedsReset) - getGrContext()->resetContext(); - - return device; -} - -SkDevice* GaneshContext::getDeviceForBaseTileSurface(const TileRenderInfo& renderInfo) -{ EGLDisplay display; if (!m_surfaceContext) { if(eglGetCurrentContext() != EGL_NO_CONTEXT) { - XLOG("ERROR: should not have a context yet"); + ALOGV("ERROR: should not have a context yet"); } display = eglGetDisplay(EGL_DEFAULT_DISPLAY); @@ -154,7 +124,6 @@ SkDevice* GaneshContext::getDeviceForBaseTileSurface(const TileRenderInfo& rende } TransferQueue* tileQueue = TilesManager::instance()->transferQueue(); - if (tileQueue->m_eglSurface == EGL_NO_SURFACE) { const float tileWidth = renderInfo.tileSize.width(); @@ -170,112 +139,43 @@ SkDevice* GaneshContext::getDeviceForBaseTileSurface(const TileRenderInfo& rende tileQueue->m_eglSurface = eglCreateWindowSurface(display, m_surfaceConfig, anw, NULL); GLUtils::checkEglError("eglCreateWindowSurface"); - XLOG("eglCreateWindowSurface"); + ALOGV("eglCreateWindowSurface"); } EGLBoolean returnValue = eglMakeCurrent(display, tileQueue->m_eglSurface, tileQueue->m_eglSurface, m_surfaceContext); GLUtils::checkEglError("eglMakeCurrent", returnValue); - XLOG("eglMakeCurrent"); + ALOGV("eglMakeCurrent"); if (!m_baseTileDeviceSurface) { - GrPlatformSurfaceDesc surfaceDesc; - surfaceDesc.fSurfaceType = kRenderTarget_GrPlatformSurfaceType; - surfaceDesc.fRenderTargetFlags = kNone_GrPlatformRenderTargetFlagBit; - surfaceDesc.fWidth = TilesManager::tileWidth(); - surfaceDesc.fHeight = TilesManager::tileHeight(); - surfaceDesc.fConfig = kRGBA_8888_GrPixelConfig; - surfaceDesc.fStencilBits = 8; - surfaceDesc.fPlatformRenderTarget = 0; + GrPlatformRenderTargetDesc renderTargetDesc; + renderTargetDesc.fWidth = TilesManager::tileWidth(); + renderTargetDesc.fHeight = TilesManager::tileHeight(); + renderTargetDesc.fConfig = kRGBA_8888_PM_GrPixelConfig; + renderTargetDesc.fSampleCnt = 0; + renderTargetDesc.fStencilBits = 8; + renderTargetDesc.fRenderTargetHandle = 0; GrContext* grContext = getGrContext(); - GrRenderTarget* renderTarget = (GrRenderTarget*) grContext->createPlatformSurface(surfaceDesc); - - SkBitmap bitmap; - bitmap.setConfig(SkBitmap::kARGB_8888_Config, - renderInfo.tileSize.width(), - renderInfo.tileSize.height()); + GrRenderTarget* renderTarget = grContext->createPlatformRenderTarget(renderTargetDesc); - m_baseTileDeviceSurface = new SkGpuDevice(grContext, bitmap, renderTarget); + m_baseTileDeviceSurface = new SkGpuDevice(grContext, renderTarget); renderTarget->unref(); - XLOG("generated device %p", m_baseTileDeviceSurface); + ALOGV("generated device %p", m_baseTileDeviceSurface); } GLUtils::checkGlError("getDeviceForBaseTile"); - return m_baseTileDeviceSurface; -} - -SkDevice* GaneshContext::getDeviceForBaseTileFBO(const TileRenderInfo& renderInfo) -{ - const GLuint textureId = renderInfo.textureInfo->m_textureId; - const float tileWidth = renderInfo.tileSize.width(); - const float tileHeight = renderInfo.tileSize.height(); - - // bind to the current texture - glBindTexture(GL_TEXTURE_2D, textureId); - - // setup the texture if needed - if (renderInfo.textureInfo->m_width != tileWidth - || renderInfo.textureInfo->m_height != tileHeight) { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tileWidth, tileHeight, - 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - renderInfo.textureInfo->m_width = tileWidth; - renderInfo.textureInfo->m_height = tileHeight; - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - } - - if (!m_baseTileFBO) { - glGenFramebuffers(1, &m_baseTileFBO); - XLOG("generated FBO"); - } - - if (!m_baseTileStencil) { - glGenRenderbuffers(1, &m_baseTileStencil); - glBindRenderbuffer(GL_RENDERBUFFER, m_baseTileStencil); - glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, - TilesManager::tileWidth(), - TilesManager::tileHeight()); - glClearStencil(0); - glClear(GL_STENCIL_BUFFER_BIT); - XLOG("generated stencil"); - } - - // bind the FBO and attach the texture and stencil - glBindFramebuffer(GL_FRAMEBUFFER, m_baseTileFBO); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureId, 0); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_baseTileStencil); - - if (!m_baseTileDeviceFBO) { - - GrPlatformSurfaceDesc surfaceDesc; - surfaceDesc.fSurfaceType = kRenderTarget_GrPlatformSurfaceType; - surfaceDesc.fRenderTargetFlags = kNone_GrPlatformRenderTargetFlagBit; - surfaceDesc.fWidth = TilesManager::tileWidth(); - surfaceDesc.fHeight = TilesManager::tileHeight(); - surfaceDesc.fConfig = kRGBA_8888_GrPixelConfig; - surfaceDesc.fStencilBits = 8; - surfaceDesc.fPlatformRenderTarget = m_baseTileFBO; - - GrContext* grContext = getGrContext(); - GrRenderTarget* renderTarget = (GrRenderTarget*) grContext->createPlatformSurface(surfaceDesc); - - SkBitmap bitmap; - bitmap.setConfig(SkBitmap::kARGB_8888_Config, - TilesManager::tileWidth(), TilesManager::tileWidth()); - - m_baseTileDeviceFBO = new SkGpuDevice(grContext, bitmap, renderTarget); - renderTarget->unref(); - XLOG("generated device %p", m_baseTileDeviceFBO); - } + // We must reset the Ganesh context only after we are sure we have + // re-established our EGLContext as the current context. + if (m_baseTileDeviceSurface && contextNeedsReset) + getGrContext()->resetContext(); - GLUtils::checkGlError("getDeviceForBaseTile"); - return m_baseTileDeviceFBO; + return m_baseTileDeviceSurface; } + } // namespace WebCore #endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/GaneshContext.h b/Source/WebCore/platform/graphics/android/GaneshContext.h index 12ea92d..def35e5 100644 --- a/Source/WebCore/platform/graphics/android/GaneshContext.h +++ b/Source/WebCore/platform/graphics/android/GaneshContext.h @@ -48,20 +48,8 @@ private: GaneshContext(); GrContext* getGrContext(); - - // Creates a device for rendering into a SurfaceTexture via an EGLSurface - SkDevice* getDeviceForBaseTileSurface(const TileRenderInfo& renderInfo); - // Creates a device for rendering into a EGLImage via an FBO - SkDevice* getDeviceForBaseTileFBO(const TileRenderInfo& renderInfo); - GrContext* m_grContext; - // FBO specific variables - SkGpuDevice* m_baseTileDeviceFBO; - GLuint m_baseTileFBO; - GLuint m_baseTileStencil; - - // Surface specific variables SkGpuDevice* m_baseTileDeviceSurface; EGLConfig m_surfaceConfig; EGLContext m_surfaceContext; diff --git a/Source/WebCore/platform/graphics/android/GaneshRenderer.cpp b/Source/WebCore/platform/graphics/android/GaneshRenderer.cpp index f4df33a..559af1f 100644 --- a/Source/WebCore/platform/graphics/android/GaneshRenderer.cpp +++ b/Source/WebCore/platform/graphics/android/GaneshRenderer.cpp @@ -23,46 +23,22 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#define LOG_TAG "GaneshRenderer" +#define LOG_NDEBUG 1 #include "config.h" #include "GaneshRenderer.h" #if USE(ACCELERATED_COMPOSITING) +#include "AndroidLog.h" #include "GaneshContext.h" #include "SkCanvas.h" #include "SkGpuDevice.h" #include "TilesManager.h" - -#ifdef DEBUG - -#include <cutils/log.h> -#include <wtf/CurrentTime.h> -#include <wtf/text/CString.h> - -#undef XLOG -#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "GaneshRenderer", __VA_ARGS__) - -#else - -#undef XLOG -#define XLOG(...) - -#endif // DEBUG - namespace WebCore { -static const String TAG_CREATE_FBO = "create_fbo"; -static const String TAG_DRAW_PICTURE = "draw_picture"; -static const String TAG_UPDATE_TEXTURE = "update_texture"; -#define TAG_COUNT 3 -static const String TAGS[] = { - TAG_CREATE_FBO, - TAG_DRAW_PICTURE, - TAG_UPDATE_TEXTURE, -}; - GaneshRenderer::GaneshRenderer() : BaseRenderer(BaseRenderer::Ganesh) { #ifdef DEBUG_COUNT @@ -79,25 +55,18 @@ GaneshRenderer::~GaneshRenderer() void GaneshRenderer::setupCanvas(const TileRenderInfo& renderInfo, SkCanvas* canvas) { - if (renderInfo.measurePerf) - m_perfMon.start(TAG_CREATE_FBO); - GaneshContext* ganesh = GaneshContext::instance(); -#if !DEPRECATED_SURFACE_TEXTURE_MODE - if (renderInfo.textureInfo->getSharedTextureMode() == SurfaceTextureMode) { - TransferQueue* tileQueue = TilesManager::instance()->transferQueue(); + TransferQueue* tileQueue = TilesManager::instance()->transferQueue(); - tileQueue->lockQueue(); + tileQueue->lockQueue(); - bool ready = tileQueue->readyForUpdate(); - if (!ready) { - XLOG("!ready"); - tileQueue->unlockQueue(); - return; - } + bool ready = tileQueue->readyForUpdate(); + if (!ready) { + ALOGV("!ready"); + tileQueue->unlockQueue(); + return; } -#endif SkDevice* device = NULL; if (renderInfo.tileSize.width() == TilesManager::tileWidth() @@ -105,25 +74,13 @@ void GaneshRenderer::setupCanvas(const TileRenderInfo& renderInfo, SkCanvas* can device = ganesh->getDeviceForBaseTile(renderInfo); } else { // TODO support arbitrary sizes for layers - XLOG("ERROR: expected (%d,%d) actual (%d,%d)", - TilesManager::tileWidth(), TilesManager::tileHeight(), - renderInfo.tileSize.width(), renderInfo.tileSize.height()); - } - - if (renderInfo.measurePerf) { - m_perfMon.stop(TAG_CREATE_FBO); - m_perfMon.start(TAG_DRAW_PICTURE); + ALOGV("ERROR: expected (%d,%d) actual (%d,%d)", + TilesManager::tileWidth(), TilesManager::tileHeight(), + renderInfo.tileSize.width(), renderInfo.tileSize.height()); } // set the GPU device to the canvas canvas->setDevice(device); - canvas->setDeviceFactory(device->getDeviceFactory()); - - // 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) @@ -138,34 +95,16 @@ void GaneshRenderer::setupPartialInval(const TileRenderInfo& renderInfo, SkCanva void GaneshRenderer::renderingComplete(const TileRenderInfo& renderInfo, SkCanvas* canvas) { - if (renderInfo.measurePerf) { - m_perfMon.stop(TAG_DRAW_PICTURE); - m_perfMon.start(TAG_UPDATE_TEXTURE); - } - - XLOG("rendered to tile (%d,%d)", renderInfo.x, renderInfo.y); + ALOGV("rendered to tile (%d,%d)", renderInfo.x, renderInfo.y); GaneshContext::instance()->flush(); // 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 - } - - if (renderInfo.measurePerf) - m_perfMon.stop(TAG_UPDATE_TEXTURE); -} - -const String* GaneshRenderer::getPerformanceTags(int& tagCount) -{ - tagCount = TAG_COUNT; - return TAGS; + TransferQueue* tileQueue = TilesManager::instance()->transferQueue(); + eglSwapBuffers(eglGetCurrentDisplay(), tileQueue->m_eglSurface); + tileQueue->addItemInTransferQueue(&renderInfo, GpuUpload, 0); + tileQueue->unlockQueue(); } } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/GaneshRenderer.h b/Source/WebCore/platform/graphics/android/GaneshRenderer.h index 0e1d41e..d7eda24 100644 --- a/Source/WebCore/platform/graphics/android/GaneshRenderer.h +++ b/Source/WebCore/platform/graphics/android/GaneshRenderer.h @@ -49,7 +49,9 @@ protected: virtual void setupCanvas(const TileRenderInfo& renderInfo, SkCanvas* canvas); virtual void setupPartialInval(const TileRenderInfo& renderInfo, SkCanvas* canvas); virtual void renderingComplete(const TileRenderInfo& renderInfo, SkCanvas* canvas); - virtual const String* getPerformanceTags(int& tagCount); + virtual void checkForPureColor(TileRenderInfo& renderInfo, SkCanvas* canvas) { + renderInfo.isPureColor = false; + } }; diff --git a/Source/WebCore/platform/graphics/android/GradientAndroid.cpp b/Source/WebCore/platform/graphics/android/GradientAndroid.cpp index b8dc9dd..7bc69c5 100644 --- a/Source/WebCore/platform/graphics/android/GradientAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/GradientAndroid.cpp @@ -26,7 +26,6 @@ #include "config.h" #include "Gradient.h" -#include "android_graphics.h" #include "CSSParser.h" #include "GraphicsContext.h" #include "NotImplemented.h" @@ -35,16 +34,6 @@ #include "SkGradientShader.h" #include "SkPaint.h" -class PlatformGradientRec { -public: - PlatformGradientRec() : m_shader(NULL) {} - ~PlatformGradientRec() { SkSafeUnref(m_shader); } - - SkShader* m_shader; - SkShader::TileMode m_tileMode; - int m_colorCountWhenShaderWasBuilt; -}; - namespace WebCore { void Gradient::platformDestroy() @@ -58,12 +47,10 @@ static U8CPU F2B(float x) return (int)(x * 255); } -SkShader* Gradient::getShader(SkShader::TileMode mode) +SkShader* Gradient::platformGradient() { - if (NULL == m_gradient) - m_gradient = new PlatformGradientRec; - else if (mode == m_gradient->m_tileMode) - return m_gradient->m_shader; + if (m_gradient) + return m_gradient; // need to ensure that the m_stops array is sorted. We call getColor() // which, as a side effect, does the sort. @@ -73,6 +60,19 @@ SkShader* Gradient::getShader(SkShader::TileMode mode) this->getColor(0, &r, &g, &b, &a); } + SkShader::TileMode mode = SkShader::kClamp_TileMode; + switch (m_spreadMethod) { + case SpreadMethodReflect: + mode = SkShader::kMirror_TileMode; + break; + case SpreadMethodRepeat: + mode = SkShader::kRepeat_TileMode; + break; + case SpreadMethodPad: + mode = SkShader::kClamp_TileMode; + break; + } + SkPoint pts[2] = { m_p0, m_p1 }; // convert to SkPoint const size_t count = m_stops.size(); @@ -88,40 +88,28 @@ SkShader* Gradient::getShader(SkShader::TileMode mode) ++iter; } - SkShader* s; - if (m_radial) - s = SkGradientShader::CreateTwoPointRadial(pts[0], + if (m_radial) { + m_gradient = SkGradientShader::CreateTwoPointRadial(pts[0], SkFloatToScalar(m_r0), pts[1], SkFloatToScalar(m_r1), colors, pos, count, mode); - else - s = SkGradientShader::CreateLinear(pts, colors, pos, count, mode); + } else + m_gradient = SkGradientShader::CreateLinear(pts, colors, pos, count, mode); - if (NULL == s) - s = new SkColorShader(0); + if (!m_gradient) + m_gradient = new SkColorShader(0); - // zap our previous shader, if present - SkSafeUnref(m_gradient->m_shader); - m_gradient->m_shader = s; - m_gradient->m_tileMode = mode; SkMatrix matrix = m_gradientSpaceTransformation; - s->setLocalMatrix(matrix); + m_gradient->setLocalMatrix(matrix); - return s; + return m_gradient; } 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 : - SkShader::kClamp_TileMode; - - paint.setAntiAlias(true); - paint.setShader(this->getShader(mode)); - android_gc2canvas(context)->drawRect(rect, paint); + context->setFillGradient(this); + context->fillRect(rect); } diff --git a/Source/WebCore/platform/graphics/android/GraphicsContextAndroid.cpp b/Source/WebCore/platform/graphics/android/GraphicsContextAndroid.cpp index a490d5f..7d6c809 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" @@ -47,427 +49,36 @@ using namespace std; -#define GC2CANVAS(ctx) (ctx)->m_data->getPlatformGfxCtx()->mCanvas - namespace WebCore { -static int RoundToInt(float x) -{ - return (int)roundf(x); -} - -template <typename T> T* deepCopyPtr(const T* src) -{ - return src ? new T(*src) : 0; -} - -// Set a bitmap shader that mimics dashing by width-on, width-off. -// Returns false if it could not succeed (e.g. there was an existing shader) -static bool setBitmapDash(SkPaint* paint, int width) { - if (width <= 0 || paint->getShader()) - return false; - - SkColor c = paint->getColor(); - - SkBitmap bm; - bm.setConfig(SkBitmap::kARGB_8888_Config, 2, 1); - bm.allocPixels(); - bm.lockPixels(); - - // set the ON pixel - *bm.getAddr32(0, 0) = SkPreMultiplyARGB(0xFF, SkColorGetR(c), - SkColorGetG(c), SkColorGetB(c)); - // set the OFF pixel - *bm.getAddr32(1, 0) = 0; - bm.unlockPixels(); - - SkMatrix matrix; - matrix.setScale(SkIntToScalar(width), SK_Scalar1); - - SkShader* s = SkShader::CreateBitmapShader(bm, SkShader::kRepeat_TileMode, - SkShader::kClamp_TileMode); - s->setLocalMatrix(matrix); - - paint->setShader(s)->unref(); - return true; -} - -// TODO / questions - -// alpha: how does this interact with the alpha in Color? multiply them together? -// mode: do I always respect this? If so, then -// the rgb() & 0xFF000000 check will abort drawing too often -// Is Color premultiplied or not? If it is, then I can't blindly pass it to paint.setColor() - -struct ShadowRec { - SkScalar blur; - SkScalar dx; - SkScalar dy; - SkColor color; // alpha>0 means valid shadow - ShadowRec(SkScalar b = 0, - SkScalar x = 0, - SkScalar y = 0, - SkColor c = 0) // by default, alpha=0, so no shadow - : blur(b), dx(x), dy(y), color(c) - {}; -}; - +// This class just holds onto a PlatformContextSkia for GraphicsContext. class GraphicsContextPlatformPrivate { + WTF_MAKE_NONCOPYABLE(GraphicsContextPlatformPrivate); public: - struct State { - SkPathEffect* pathEffect; - float miterLimit; - float alpha; - float strokeThickness; - SkPaint::Cap lineCap; - SkPaint::Join lineJoin; - SkXfermode::Mode mode; - int dashRatio; // Ratio of the length of a dash to its width - ShadowRec shadow; - 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) - , miterLimit(4) - , alpha(1) - , strokeThickness(0) // Same as default in GraphicsContextPrivate.h - , lineCap(SkPaint::kDefault_Cap) - , lineJoin(SkPaint::kDefault_Join) - , mode(SkXfermode::kSrcOver_Mode) - , dashRatio(3) - , fillColor(SK_ColorBLACK) - , strokeColor(SK_ColorBLACK) - , useAA(true) - { - } - - State(const State& other) - : pathEffect(other.pathEffect) - , miterLimit(other.miterLimit) - , alpha(other.alpha) - , strokeThickness(other.strokeThickness) - , lineCap(other.lineCap) - , lineJoin(other.lineJoin) - , mode(other.mode) - , dashRatio(other.dashRatio) - , shadow(other.shadow) - , fillColor(other.fillColor) - , strokeColor(other.strokeColor) - , useAA(other.useAA) - { - SkSafeRef(pathEffect); - } - - ~State() - { - SkSafeUnref(pathEffect); - } - - void setShadow(int radius, int dx, int dy, SkColor c) - { - // Cut the radius in half, to visually match the effect seen in - // safari browser - shadow.blur = SkScalarHalf(SkIntToScalar(radius)); - shadow.dx = SkIntToScalar(dx); - shadow.dy = SkIntToScalar(dy); - shadow.color = c; - } - - bool setupShadowPaint(GraphicsContext* ctx, SkPaint* paint, SkPoint* offset) - { - paint->setAntiAlias(true); - paint->setDither(true); - paint->setXfermodeMode(mode); - paint->setColor(shadow.color); - offset->set(shadow.dx, shadow.dy); - - // Currently, only GraphicsContexts associated with the - // HTMLCanvasElement have shadows ignore transforms set. This - // allows us to distinguish between CSS and Canvas shadows which - // have different rendering specifications. - uint32_t flags = SkBlurMaskFilter::kHighQuality_BlurFlag; - if (ctx->shadowsIgnoreTransforms()) { - offset->fY = -offset->fY; - flags |= SkBlurMaskFilter::kIgnoreTransform_BlurFlag; - } - - if (shadow.blur > 0) { - paint->setMaskFilter(SkBlurMaskFilter::Create(shadow.blur, - SkBlurMaskFilter::kNormal_BlurStyle))->unref(); - } - return SkColorGetA(shadow.color) && (shadow.blur || shadow.dx || shadow.dy); - } - - SkColor applyAlpha(SkColor c) const - { - int s = RoundToInt(alpha * 256); - if (s >= 256) - return c; - if (s < 0) - return 0; - - int a = SkAlphaMul(SkColorGetA(c), s); - return (c & 0x00FFFFFF) | (a << 24); - } - }; + GraphicsContextPlatformPrivate(PlatformGraphicsContext* platformContext) + : m_context(platformContext) { } + + PlatformGraphicsContext* context() { return m_context; } - GraphicsContextPlatformPrivate(GraphicsContext* gfxCtx, PlatformGraphicsContext* platformGfxCtx) - : m_parentGfxCtx(gfxCtx) - , m_platformGfxCtx(platformGfxCtx) - , m_stateStack(sizeof(State)) - { - State* state = static_cast<State*>(m_stateStack.push_back()); - new (state) State(); - m_state = state; - } - - ~GraphicsContextPlatformPrivate() - { - // We force restores so we don't leak any subobjects owned by our - // stack of State records. - while (m_stateStack.count() > 0) - this->restore(); - - if (m_platformGfxCtx && m_platformGfxCtx->deleteUs()) - delete m_platformGfxCtx; - } - - void save() - { - State* newState = static_cast<State*>(m_stateStack.push_back()); - new (newState) State(*m_state); - m_state = newState; - } - - 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()); - } - - void setFillColor(const Color& c) - { - m_state->fillColor = c.rgb(); - } - - void setStrokeColor(const Color& c) - { - m_state->strokeColor = c.rgb(); - } - - void setStrokeThickness(float f) - { - m_state->strokeThickness = f; - } - - void setupPaintCommon(SkPaint* paint) const - { - paint->setAntiAlias(m_state->useAA); - paint->setDither(true); - paint->setXfermodeMode(m_state->mode); - if (SkColorGetA(m_state->shadow.color) > 0) { - - // Currently, only GraphicsContexts associated with the - // HTMLCanvasElement have shadows ignore transforms set. This - // allows us to distinguish between CSS and Canvas shadows which - // have different rendering specifications. - SkScalar dy = m_state->shadow.dy; - uint32_t flags = SkBlurDrawLooper::kHighQuality_BlurFlag; - if (m_parentGfxCtx->shadowsIgnoreTransforms()) { - dy = -dy; - flags |= SkBlurDrawLooper::kIgnoreTransform_BlurFlag; - flags |= SkBlurDrawLooper::kOverrideColor_BlurFlag; - } - - SkDrawLooper* looper = new SkBlurDrawLooper(m_state->shadow.blur, - m_state->shadow.dx, - dy, - m_state->shadow.color, - flags); - paint->setLooper(looper)->unref(); - } - } - - void setupPaintFill(SkPaint* paint) const - { - this->setupPaintCommon(paint); - paint->setColor(m_state->applyAlpha(m_state->fillColor)); - } - - void setupPaintBitmap(SkPaint* paint) const - { - this->setupPaintCommon(paint); - // We only want the global alpha for bitmaps, - // so just give applyAlpha opaque black - paint->setColor(m_state->applyAlpha(0xFF000000)); - } - - // Sets up the paint for stroking. Returns true if the style is really - // just a dash of squares (the size of the paint's stroke-width. - bool setupPaintStroke(SkPaint* paint, SkRect* rect, bool isHLine = false) - { - this->setupPaintCommon(paint); - paint->setColor(m_state->applyAlpha(m_state->strokeColor)); - - float width = m_state->strokeThickness; - - // This allows dashing and dotting to work properly for hairline strokes - // FIXME: Should we only do this for dashed and dotted strokes? - if (!width) - width = 1; - - paint->setStyle(SkPaint::kStroke_Style); - paint->setStrokeWidth(SkFloatToScalar(width)); - paint->setStrokeCap(m_state->lineCap); - paint->setStrokeJoin(m_state->lineJoin); - paint->setStrokeMiter(SkFloatToScalar(m_state->miterLimit)); - - if (rect && (RoundToInt(width) & 1)) - rect->inset(-SK_ScalarHalf, -SK_ScalarHalf); - - SkPathEffect* pe = m_state->pathEffect; - if (pe) { - paint->setPathEffect(pe); - return false; - } - switch (m_parentGfxCtx->strokeStyle()) { - case NoStroke: - case SolidStroke: - width = 0; - break; - case DashedStroke: - width = m_state->dashRatio * width; - break; - // No break - case DottedStroke: - break; - } - - if (width > 0) { - // Return true if we're basically a dotted dash of squares - bool justSqrs = RoundToInt(width) == RoundToInt(paint->getStrokeWidth()); - - if (justSqrs || !isHLine || !setBitmapDash(paint, width)) { -#if 0 - // this is slow enough that we just skip it for now - // see http://b/issue?id=4163023 - SkScalar intervals[] = { width, width }; - pe = new SkDashPathEffect(intervals, 2, 0); - paint->setPathEffect(pe)->unref(); -#endif - } - return justSqrs; - } - 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; - } - - State* getState() - { - return m_state; - } private: - State* m_state; - GraphicsContext* m_parentGfxCtx; // Back-ptr to our parent - PlatformGraphicsContext* m_platformGfxCtx; - SkDeque m_stateStack; - // Not supported yet - State& operator=(const State&); + // Non-owning pointer to the PlatformContext. + PlatformGraphicsContext* m_context; }; -static SkShader::TileMode SpreadMethod2TileMode(GradientSpreadMethod sm) +static SkShader* extractShader(Pattern* pat, Gradient* grad) { - SkShader::TileMode mode = SkShader::kClamp_TileMode; - - switch (sm) { - case SpreadMethodPad: - mode = SkShader::kClamp_TileMode; - break; - case SpreadMethodReflect: - mode = SkShader::kMirror_TileMode; - break; - case SpreadMethodRepeat: - mode = SkShader::kRepeat_TileMode; - break; - } - return mode; -} - -static void extactShader(SkPaint* paint, Pattern* pat, Gradient* grad) -{ - if (pat) { - // platformPattern() returns a cached obj - paint->setShader(pat->platformPattern(AffineTransform())); - } else if (grad) { - // grad->getShader() returns a cached obj - GradientSpreadMethod sm = grad->spreadMethod(); - paint->setShader(grad->getShader(SpreadMethod2TileMode(sm))); - } + if (pat) + return pat->platformPattern(AffineTransform()); + else if (grad) + return grad->platformGradient(); + return 0; } //////////////////////////////////////////////////////////////////////////////////////////////// GraphicsContext* GraphicsContext::createOffscreenContext(int width, int height) { - PlatformGraphicsContext* pgc = new PlatformGraphicsContext(); + PlatformGraphicsContext* pgc = new PlatformGraphicsContext(new SkCanvas, true); SkBitmap bitmap; @@ -484,7 +95,9 @@ GraphicsContext* GraphicsContext::createOffscreenContext(int width, int height) void GraphicsContext::platformInit(PlatformGraphicsContext* gc) { - m_data = new GraphicsContextPlatformPrivate(this, gc); + if (gc) + gc->setGraphicsContext(this); + m_data = new GraphicsContextPlatformPrivate(gc); setPaintingDisabled(!gc || !gc->mCanvas); } @@ -495,28 +108,26 @@ void GraphicsContext::platformDestroy() void GraphicsContext::savePlatformState() { - // Save our private State - m_data->save(); - // Save our native canvas - GC2CANVAS(this)->save(); + if (paintingDisabled()) + return; + platformContext()->save(); } void GraphicsContext::restorePlatformState() { - // Restore our private State - m_data->restore(); - // Restore our native canvas - GC2CANVAS(this)->restore(); + if (paintingDisabled()) + return; + platformContext()->restore(); } bool GraphicsContext::willFill() const { - return m_data->getState()->fillColor; + return m_state.fillColor.rgb(); } bool GraphicsContext::willStroke() const { - return m_data->getState()->strokeColor; + return m_state.strokeColor.rgb(); } // Draws a filled rectangle with a stroked border. @@ -525,24 +136,7 @@ void GraphicsContext::drawRect(const IntRect& rect) if (paintingDisabled()) return; - SkPaint paint; - SkRect r(rect); - - if (fillColor().alpha()) { - m_data->setupPaintFill(&paint); - GC2CANVAS(this)->drawRect(r, paint); - } - - // According to GraphicsContext.h, stroking inside drawRect always means - // a stroke of 1 inside the rect. - if (strokeStyle() != NoStroke && strokeColor().alpha()) { - paint.reset(); - m_data->setupPaintStroke(&paint, &r); - paint.setPathEffect(0); // No dashing please - paint.setStrokeWidth(SK_Scalar1); // Always just 1.0 width - r.inset(SK_ScalarHalf, SK_ScalarHalf); // Ensure we're "inside" - GC2CANVAS(this)->drawRect(r, paint); - } + platformContext()->drawRect(rect); } // This is only used to draw borders. @@ -551,119 +145,24 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2) if (paintingDisabled()) return; - StrokeStyle style = strokeStyle(); - if (style == NoStroke) - return; - - SkPaint paint; - SkCanvas* canvas = GC2CANVAS(this); - const int idx = SkAbs32(point2.x() - point1.x()); - const int idy = SkAbs32(point2.y() - point1.y()); - - // Special-case horizontal and vertical lines that are really just dots - if (m_data->setupPaintStroke(&paint, 0, !idy) && (!idx || !idy)) { - const SkScalar diameter = paint.getStrokeWidth(); - const SkScalar radius = SkScalarHalf(diameter); - SkScalar x = SkIntToScalar(SkMin32(point1.x(), point2.x())); - SkScalar y = SkIntToScalar(SkMin32(point1.y(), point2.y())); - SkScalar dx, dy; - int count; - SkRect bounds; - - if (!idy) { // Horizontal - bounds.set(x, y - radius, x + SkIntToScalar(idx), y + radius); - x += radius; - dx = diameter * 2; - dy = 0; - count = idx; - } else { // Vertical - bounds.set(x - radius, y, x + radius, y + SkIntToScalar(idy)); - y += radius; - dx = 0; - dy = diameter * 2; - count = idy; - } - - // The actual count is the number of ONs we hit alternating - // ON(diameter), OFF(diameter), ... - { - SkScalar width = SkScalarDiv(SkIntToScalar(count), diameter); - // Now compute the number of cells (ON and OFF) - count = SkScalarRound(width); - // Now compute the number of ONs - count = (count + 1) >> 1; - } - - SkAutoMalloc storage(count * sizeof(SkPoint)); - SkPoint* verts = (SkPoint*)storage.get(); - // Now build the array of vertices to past to drawPoints - for (int i = 0; i < count; i++) { - verts[i].set(x, y); - x += dx; - y += dy; - } - - paint.setStyle(SkPaint::kFill_Style); - paint.setPathEffect(0); - - // Clipping to bounds is not required for correctness, but it does - // allow us to reject the entire array of points if we are completely - // offscreen. This is common in a webpage for android, where most of - // the content is clipped out. If drawPoints took an (optional) bounds - // parameter, that might even be better, as we would *just* use it for - // culling, and not both wacking the canvas' save/restore stack. - canvas->save(SkCanvas::kClip_SaveFlag); - canvas->clipRect(bounds); - canvas->drawPoints(SkCanvas::kPoints_PointMode, count, verts, paint); - canvas->restore(); - } else { - SkPoint pts[2] = { point1, point2 }; - canvas->drawLine(pts[0].fX, pts[0].fY, pts[1].fX, pts[1].fY, paint); - } -} - -static void setrectForUnderline(SkRect* r, GraphicsContext* context, const FloatPoint& point, int yOffset, float width) -{ - float lineThickness = context->strokeThickness(); -#if 0 - if (lineThickness < 1) // Do we really need/want this? - lineThickness = 1; -#endif - r->fLeft = point.x(); - r->fTop = point.y() + yOffset; - r->fRight = r->fLeft + width; - r->fBottom = r->fTop + lineThickness; + platformContext()->drawLine(point1, point2); } -void GraphicsContext::drawLineForText(const FloatPoint& pt, float width, bool) +void GraphicsContext::drawLineForText(const FloatPoint& pt, float width, bool /* printing */) { if (paintingDisabled()) return; - SkRect r; - setrectForUnderline(&r, this, pt, 0, width); - - SkPaint paint; - paint.setAntiAlias(true); - paint.setColor(this->strokeColor().rgb()); - - GC2CANVAS(this)->drawRect(r, paint); + platformContext()->drawLineForText(pt, width); } -// TODO: Should we draw different based on TextCheckingLineStyle? -void GraphicsContext::drawLineForTextChecking(const FloatPoint& pt, float width, TextCheckingLineStyle) +void GraphicsContext::drawLineForTextChecking(const FloatPoint& pt, float width, + TextCheckingLineStyle style) { if (paintingDisabled()) return; - SkRect r; - setrectForUnderline(&r, this, pt, 0, width); - - SkPaint paint; - paint.setAntiAlias(true); - paint.setColor(SK_ColorRED); // Is this specified somewhere? - - GC2CANVAS(this)->drawRect(r, paint); + platformContext()->drawLineForTextChecking(pt, width, style); } // This method is only used to draw the little circles used in lists. @@ -672,28 +171,7 @@ void GraphicsContext::drawEllipse(const IntRect& rect) if (paintingDisabled()) return; - SkPaint paint; - SkRect oval(rect); - - if (fillColor().rgb() & 0xFF000000) { - m_data->setupPaintFill(&paint); - GC2CANVAS(this)->drawOval(oval, paint); - } - if (strokeStyle() != NoStroke) { - paint.reset(); - m_data->setupPaintStroke(&paint, &oval); - GC2CANVAS(this)->drawOval(oval, paint); - } -} - -static inline int fastMod(int value, int max) -{ - int sign = SkExtractSign(value); - - value = SkApplySign(value, sign); - if (value >= max) - value %= max; - return SkApplySign(value, sign); + platformContext()->drawEllipse(rect); } void GraphicsContext::strokeArc(const IntRect& r, int startAngle, int angleSpan) @@ -701,138 +179,43 @@ void GraphicsContext::strokeArc(const IntRect& r, int startAngle, int angleSpan) if (paintingDisabled()) return; - SkPath path; - SkPaint paint; - SkRect oval(r); - - if (strokeStyle() == NoStroke) { - m_data->setupPaintFill(&paint); // We want the fill color - paint.setStyle(SkPaint::kStroke_Style); - paint.setStrokeWidth(SkFloatToScalar(this->strokeThickness())); - } else - m_data->setupPaintStroke(&paint, 0); - - // We do this before converting to scalar, so we don't overflow SkFixed - startAngle = fastMod(startAngle, 360); - angleSpan = fastMod(angleSpan, 360); - - path.addArc(oval, SkIntToScalar(-startAngle), SkIntToScalar(-angleSpan)); - GC2CANVAS(this)->drawPath(path, paint); + platformContext()->strokeArc(r, startAngle, angleSpan); } -void GraphicsContext::drawConvexPolygon(size_t numPoints, const FloatPoint* points, bool shouldAntialias) +void GraphicsContext::drawConvexPolygon(size_t numPoints, const FloatPoint* points, + bool shouldAntialias) { if (paintingDisabled()) return; - if (numPoints <= 1) - return; - - SkPaint paint; - SkPath path; - - path.incReserve(numPoints); - path.moveTo(SkFloatToScalar(points[0].x()), SkFloatToScalar(points[0].y())); - for (size_t i = 1; i < numPoints; i++) - path.lineTo(SkFloatToScalar(points[i].x()), SkFloatToScalar(points[i].y())); - - if (GC2CANVAS(this)->quickReject(path, shouldAntialias ? - SkCanvas::kAA_EdgeType : SkCanvas::kBW_EdgeType)) { - return; - } - - if (fillColor().rgb() & 0xFF000000) { - m_data->setupPaintFill(&paint); - paint.setAntiAlias(shouldAntialias); - GC2CANVAS(this)->drawPath(path, paint); - } - - if (strokeStyle() != NoStroke) { - paint.reset(); - m_data->setupPaintStroke(&paint, 0); - paint.setAntiAlias(shouldAntialias); - GC2CANVAS(this)->drawPath(path, paint); - } + platformContext()->drawConvexPolygon(numPoints, points, shouldAntialias); } void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLeft, const IntSize& topRight, - const IntSize& bottomLeft, const IntSize& bottomRight, const Color& color, ColorSpace) + const IntSize& bottomLeft, const IntSize& bottomRight, + const Color& color, ColorSpace colorSpace) { if (paintingDisabled()) return; - SkPaint paint; - SkPath path; - SkScalar radii[8]; - - radii[0] = SkIntToScalar(topLeft.width()); - radii[1] = SkIntToScalar(topLeft.height()); - radii[2] = SkIntToScalar(topRight.width()); - radii[3] = SkIntToScalar(topRight.height()); - radii[4] = SkIntToScalar(bottomRight.width()); - radii[5] = SkIntToScalar(bottomRight.height()); - radii[6] = SkIntToScalar(bottomLeft.width()); - radii[7] = SkIntToScalar(bottomLeft.height()); - path.addRoundRect(rect, radii); - - m_data->setupPaintFill(&paint); - paint.setColor(color.rgb()); - GC2CANVAS(this)->drawPath(path, paint); + platformContext()->fillRoundedRect(rect, topLeft, topRight, + bottomLeft, bottomRight, color, colorSpace); } void GraphicsContext::fillRect(const FloatRect& rect) { - save(); - SkPaint paint; - - m_data->setupPaintFill(&paint); - - extactShader(&paint, - m_state.fillPattern.get(), - m_state.fillGradient.get()); + if (paintingDisabled()) + return; - GC2CANVAS(this)->drawRect(rect, paint); - restore(); + platformContext()->fillRect(rect); } -void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorSpace) +void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorSpace colorSpace) { if (paintingDisabled()) return; - if (color.rgb() & 0xFF000000) { - save(); - SkPaint paint; - - m_data->setupPaintCommon(&paint); - paint.setColor(color.rgb()); // Punch in the specified color - paint.setShader(0); // In case we had one set - - // Sometimes we record and draw portions of the page, using clips - // for each portion. The problem with this is that webkit, sometimes, - // sees that we're only recording a portion, and they adjust some of - // their rectangle coordinates accordingly (e.g. - // RenderBoxModelObject::paintFillLayerExtended() which calls - // rect.intersect(paintInfo.rect) and then draws the bg with that - // rect. The result is that we end up drawing rects that are meant to - // seam together (one for each portion), but if the rects have - // fractional coordinates (e.g. we are zoomed by a fractional amount) - // we will double-draw those edges, resulting in visual cracks or - // artifacts. - - // The fix seems to be to just turn off antialasing for rects (this - // entry-point in GraphicsContext seems to have been sufficient, - // though perhaps we'll find we need to do this as well in fillRect(r) - // as well.) Currently setupPaintCommon() enables antialiasing. - - // Since we never show the page rotated at a funny angle, disabling - // antialiasing seems to have no real down-side, and it does fix the - // bug when we're zoomed (and drawing portions that need to seam). - paint.setAntiAlias(false); - - GC2CANVAS(this)->drawRect(rect, paint); - restore(); - } + platformContext()->fillRect(rect, color, colorSpace); } void GraphicsContext::clip(const FloatRect& rect) @@ -840,7 +223,7 @@ void GraphicsContext::clip(const FloatRect& rect) if (paintingDisabled()) return; - GC2CANVAS(this)->clipRect(rect); + platformContext()->clip(rect); } void GraphicsContext::clip(const Path& path) @@ -848,7 +231,7 @@ void GraphicsContext::clip(const Path& path) if (paintingDisabled()) return; - m_data->clipPathAntiAliased(*path.platformPath()); + platformContext()->clip(path); } void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness) @@ -856,24 +239,15 @@ void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness if (paintingDisabled()) return; - SkPath path; - SkRect r(rect); - - path.addOval(r, SkPath::kCW_Direction); - // Only perform the inset if we won't invert r - if (2 * thickness < rect.width() && 2 * thickness < rect.height()) { - // Adding one to the thickness doesn't make the border too thick as - // it's painted over afterwards. But without this adjustment the - // border appears a little anemic after anti-aliasing. - r.inset(SkIntToScalar(thickness + 1), SkIntToScalar(thickness + 1)); - path.addOval(r, SkPath::kCCW_Direction); - } - m_data->clipPathAntiAliased(path); + platformContext()->addInnerRoundedRectClip(rect, thickness); } void GraphicsContext::canvasClip(const Path& path) { - clip(path); + if (paintingDisabled()) + return; + + platformContext()->canvasClip(path); } void GraphicsContext::clipOut(const IntRect& r) @@ -881,7 +255,7 @@ void GraphicsContext::clipOut(const IntRect& r) if (paintingDisabled()) return; - GC2CANVAS(this)->clipRect(r, SkRegion::kDifference_Op); + platformContext()->clipOut(r); } #if ENABLE(SVG) @@ -890,9 +264,7 @@ void GraphicsContext::clipPath(const Path& pathToClip, WindRule clipRule) if (paintingDisabled()) return; - SkPath path = *pathToClip.platformPath(); - path.setFillType(clipRule == RULE_EVENODD ? SkPath::kEvenOdd_FillType : SkPath::kWinding_FillType); - GC2CANVAS(this)->clipPath(path); + platformContext()->clipPath(pathToClip, clipRule); } #endif @@ -901,7 +273,7 @@ void GraphicsContext::clipOut(const Path& p) if (paintingDisabled()) return; - GC2CANVAS(this)->clipPath(*p.platformPath(), SkRegion::kDifference_Op); + platformContext()->clipOut(p); } ////////////////////////////////////////////////////////////////////////////////////////////////// @@ -913,20 +285,12 @@ KRenderingDeviceContext* GraphicsContext::createRenderingDeviceContext() } #endif -// These are the flags we need when we call saveLayer for transparency. -// Since it does not appear that webkit intends this to also save/restore -// the matrix or clip, I do not give those flags (for performance) -#define TRANSPARENCY_SAVEFLAGS \ - (SkCanvas::SaveFlags)(SkCanvas::kHasAlphaLayer_SaveFlag | \ - SkCanvas::kFullColorLayer_SaveFlag) - void GraphicsContext::beginTransparencyLayer(float opacity) { if (paintingDisabled()) return; - SkCanvas* canvas = GC2CANVAS(this); - canvas->saveLayerAlpha(0, (int)(opacity * 255), TRANSPARENCY_SAVEFLAGS); + platformContext()->beginTransparencyLayer(opacity); } void GraphicsContext::endTransparencyLayer() @@ -934,44 +298,58 @@ void GraphicsContext::endTransparencyLayer() if (paintingDisabled()) return; - GC2CANVAS(this)->restore(); + platformContext()->endTransparencyLayer(); } /////////////////////////////////////////////////////////////////////////// -void GraphicsContext::setupBitmapPaint(SkPaint* paint) -{ - m_data->setupPaintBitmap(paint); -} - void GraphicsContext::setupFillPaint(SkPaint* paint) { - m_data->setupPaintFill(paint); + if (paintingDisabled()) + return; + platformContext()->setupPaintFill(paint); } void GraphicsContext::setupStrokePaint(SkPaint* paint) { - m_data->setupPaintStroke(paint, 0); + if (paintingDisabled()) + return; + platformContext()->setupPaintStroke(paint, 0); } bool GraphicsContext::setupShadowPaint(SkPaint* paint, SkPoint* offset) { - return m_data->getState()->setupShadowPaint(this, paint, offset); + if (paintingDisabled()) + return false; + return platformContext()->setupPaintShadow(paint, offset); } void GraphicsContext::setPlatformStrokeColor(const Color& c, ColorSpace) { - m_data->setStrokeColor(c); + if (paintingDisabled()) + return; + platformContext()->setStrokeColor(c); } void GraphicsContext::setPlatformStrokeThickness(float f) { - m_data->setStrokeThickness(f); + if (paintingDisabled()) + return; + platformContext()->setStrokeThickness(f); +} + +void GraphicsContext::setPlatformStrokeStyle(StrokeStyle style) +{ + if (paintingDisabled()) + return; + platformContext()->setStrokeStyle(style); } void GraphicsContext::setPlatformFillColor(const Color& c, ColorSpace) { - m_data->setFillColor(c); + if (paintingDisabled()) + return; + platformContext()->setFillColor(c); } void GraphicsContext::setPlatformShadow(const FloatSize& size, float blur, const Color& color, ColorSpace) @@ -987,7 +365,7 @@ void GraphicsContext::setPlatformShadow(const FloatSize& size, float blur, const c = color.rgb(); else c = SkColorSetARGB(0xFF / 3, 0, 0, 0); // "std" Apple shadow color - m_data->getState()->setShadow(blur, size.width(), size.height(), c); + platformContext()->setShadow(blur, size.width(), size.height(), c); } void GraphicsContext::clearPlatformShadow() @@ -995,14 +373,17 @@ void GraphicsContext::clearPlatformShadow() if (paintingDisabled()) return; - m_data->getState()->setShadow(0, 0, 0, 0); + platformContext()->setShadow(0, 0, 0, 0); } /////////////////////////////////////////////////////////////////////////////// -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; + + platformContext()->drawFocusRing(rects, width, offset, color); } void GraphicsContext::drawFocusRing(const Path&, int, int, const Color&) @@ -1013,22 +394,28 @@ void GraphicsContext::drawFocusRing(const Path&, int, int, const Color&) PlatformGraphicsContext* GraphicsContext::platformContext() const { ASSERT(!paintingDisabled()); - return m_data->getPlatformGfxCtx(); + return m_data->context(); } void GraphicsContext::setMiterLimit(float limit) { - m_data->getState()->miterLimit = limit; + if (paintingDisabled()) + return; + platformContext()->setMiterLimit(limit); } void GraphicsContext::setAlpha(float alpha) { - m_data->getState()->alpha = alpha; + if (paintingDisabled()) + return; + platformContext()->setAlpha(alpha); } void GraphicsContext::setPlatformCompositeOperation(CompositeOperator op) { - m_data->getState()->mode = WebCoreCompositeToSkiaComposite(op); + if (paintingDisabled()) + return; + platformContext()->setCompositeOperation(op); } void GraphicsContext::clearRect(const FloatRect& rect) @@ -1036,11 +423,7 @@ void GraphicsContext::clearRect(const FloatRect& rect) if (paintingDisabled()) return; - SkPaint paint; - - m_data->setupPaintFill(&paint); - paint.setXfermodeMode(SkXfermode::kClear_Mode); - GC2CANVAS(this)->drawRect(rect, paint); + platformContext()->clearRect(rect); } void GraphicsContext::strokeRect(const FloatRect& rect, float lineWidth) @@ -1048,29 +431,14 @@ void GraphicsContext::strokeRect(const FloatRect& rect, float lineWidth) if (paintingDisabled()) return; - SkPaint paint; - - m_data->setupPaintStroke(&paint, 0); - paint.setStrokeWidth(SkFloatToScalar(lineWidth)); - GC2CANVAS(this)->drawRect(rect, paint); + platformContext()->strokeRect(rect, lineWidth); } void GraphicsContext::setLineCap(LineCap cap) { - switch (cap) { - case ButtCap: - m_data->getState()->lineCap = SkPaint::kButt_Cap; - break; - case RoundCap: - m_data->getState()->lineCap = SkPaint::kRound_Cap; - break; - case SquareCap: - m_data->getState()->lineCap = SkPaint::kSquare_Cap; - break; - default: - SkDEBUGF(("GraphicsContext::setLineCap: unknown LineCap %d\n", cap)); - break; - } + if (paintingDisabled()) + return; + platformContext()->setLineCap(cap); } #if ENABLE(SVG) @@ -1079,67 +447,43 @@ void GraphicsContext::setLineDash(const DashArray& dashes, float dashOffset) if (paintingDisabled()) return; - size_t dashLength = dashes.size(); - if (!dashLength) - return; - - size_t count = !(dashLength % 2) ? dashLength : dashLength * 2; - SkScalar* intervals = new SkScalar[count]; - - for (unsigned int i = 0; i < count; i++) - intervals[i] = SkFloatToScalar(dashes[i % dashLength]); - SkPathEffect **effectPtr = &m_data->getState()->pathEffect; - SkSafeUnref(*effectPtr); - *effectPtr = new SkDashPathEffect(intervals, count, SkFloatToScalar(dashOffset)); - - delete[] intervals; + platformContext()->setLineDash(dashes, dashOffset); } #endif void GraphicsContext::setLineJoin(LineJoin join) { - switch (join) { - case MiterJoin: - m_data->getState()->lineJoin = SkPaint::kMiter_Join; - break; - case RoundJoin: - m_data->getState()->lineJoin = SkPaint::kRound_Join; - break; - case BevelJoin: - m_data->getState()->lineJoin = SkPaint::kBevel_Join; - break; - default: - SkDEBUGF(("GraphicsContext::setLineJoin: unknown LineJoin %d\n", join)); - break; - } + if (paintingDisabled()) + return; + platformContext()->setLineJoin(join); } void GraphicsContext::scale(const FloatSize& size) { if (paintingDisabled()) return; - GC2CANVAS(this)->scale(SkFloatToScalar(size.width()), SkFloatToScalar(size.height())); + platformContext()->scale(size); } void GraphicsContext::rotate(float angleInRadians) { if (paintingDisabled()) return; - GC2CANVAS(this)->rotate(SkFloatToScalar(angleInRadians * (180.0f / 3.14159265f))); + platformContext()->rotate(angleInRadians); } void GraphicsContext::translate(float x, float y) { if (paintingDisabled()) return; - GC2CANVAS(this)->translate(SkFloatToScalar(x), SkFloatToScalar(y)); + platformContext()->translate(x, y); } void GraphicsContext::concatCTM(const AffineTransform& affine) { if (paintingDisabled()) return; - GC2CANVAS(this)->concat(affine); + platformContext()->concatCTM(affine); } // This is intended to round the rect to device pixels (through the CTM) @@ -1164,39 +508,52 @@ FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& rect, RoundingMo void GraphicsContext::setURLForRect(const KURL& link, const IntRect& destRect) { // Appears to be PDF specific, so we ignore it -#if 0 -if (paintingDisabled()) - return; - -CFURLRef urlRef = link.createCFURL(); -if (urlRef) { - CGContextRef context = platformContext(); - - // Get the bounding box to handle clipping. - CGRect box = CGContextGetClipBoundingBox(context); +} - IntRect intBox((int)box.origin.x, (int)box.origin.y, (int)box.size.width, (int)box.size.height); - IntRect rect = destRect; - rect.intersect(intBox); +void GraphicsContext::setPlatformShouldAntialias(bool useAA) +{ + if (paintingDisabled()) + return; + platformContext()->setShouldAntialias(useAA); +} - CGPDFContextSetURLForRect(context, urlRef, - CGRectApplyAffineTransform(rect, CGContextGetCTM(context))); +void GraphicsContext::setPlatformFillGradient(Gradient* fillGradient) +{ + if (paintingDisabled()) + return; + SkShader* shader = extractShader(0, fillGradient); + platformContext()->setFillShader(shader); +} - CFRelease(urlRef); +void GraphicsContext::setPlatformFillPattern(Pattern* fillPattern) +{ + if (paintingDisabled()) + return; + SkShader* shader = extractShader(fillPattern, 0); + platformContext()->setFillShader(shader); } -#endif + +void GraphicsContext::setPlatformStrokeGradient(Gradient* strokeGradient) +{ + if (paintingDisabled()) + return; + SkShader* shader = extractShader(0, strokeGradient); + platformContext()->setStrokeShader(shader); } -void GraphicsContext::setPlatformShouldAntialias(bool useAA) +void GraphicsContext::setPlatformStrokePattern(Pattern* strokePattern) { if (paintingDisabled()) return; - m_data->getState()->useAA = useAA; + SkShader* shader = extractShader(strokePattern, 0); + platformContext()->setStrokeShader(shader); } AffineTransform GraphicsContext::getCTM() const { - const SkMatrix& m = GC2CANVAS(this)->getTotalMatrix(); + if (paintingDisabled()) + return AffineTransform(); + const SkMatrix& m = platformContext()->getTotalMatrix(); return AffineTransform(SkScalarToDouble(m.getScaleX()), // a SkScalarToDouble(m.getSkewY()), // b SkScalarToDouble(m.getSkewX()), // c @@ -1218,43 +575,18 @@ void GraphicsContext::setCTM(const AffineTransform& transform) void GraphicsContext::fillPath(const Path& pathToFill) { - SkPath* path = pathToFill.platformPath(); - if (paintingDisabled() || !path) + if (paintingDisabled()) return; - switch (this->fillRule()) { - case RULE_NONZERO: - path->setFillType(SkPath::kWinding_FillType); - break; - case RULE_EVENODD: - path->setFillType(SkPath::kEvenOdd_FillType); - break; - } - - SkPaint paint; - m_data->setupPaintFill(&paint); - - extactShader(&paint, - m_state.fillPattern.get(), - m_state.fillGradient.get()); - - GC2CANVAS(this)->drawPath(*path, paint); + platformContext()->fillPath(pathToFill, fillRule()); } void GraphicsContext::strokePath(const Path& pathToStroke) { - const SkPath* path = pathToStroke.platformPath(); - if (paintingDisabled() || !path) + if (paintingDisabled()) return; - SkPaint paint; - m_data->setupPaintStroke(&paint, 0); - - extactShader(&paint, - m_state.strokePattern.get(), - m_state.strokeGradient.get()); - - GC2CANVAS(this)->drawPath(*path, paint); + platformContext()->strokePath(pathToStroke); } InterpolationQuality GraphicsContext::imageInterpolationQuality() const @@ -1280,7 +612,8 @@ void GraphicsContext::setImageInterpolationQuality(InterpolationQuality mode) // Certainly safe to do nothing for the present. } -void GraphicsContext::clipConvexPolygon(size_t numPoints, const FloatPoint*, bool antialias) +void GraphicsContext::clipConvexPolygon(size_t numPoints, const FloatPoint*, + bool antialias) { if (paintingDisabled()) return; @@ -1291,6 +624,19 @@ 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; + + platformContext()->drawHighlightForText(font, run, point, h, backgroundColor, + colorSpace, from, to, isActive); +} + } // namespace WebCore /////////////////////////////////////////////////////////////////////////////// diff --git a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp index 567b54b..fa620e0 100644 --- a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp @@ -14,20 +14,29 @@ * limitations under the License. */ +#define LOG_TAG "GraphicsLayerAndroid" +#define LOG_NDEBUG 1 + #include "config.h" #include "GraphicsLayerAndroid.h" #if USE(ACCELERATED_COMPOSITING) #include "AndroidAnimation.h" +#include "AndroidLog.h" #include "Animation.h" +#include "CanvasLayer.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" @@ -40,23 +49,9 @@ #include "TransformationMatrix.h" #include "TranslateTransformOperation.h" -#include <cutils/log.h> #include <wtf/CurrentTime.h> #include <wtf/text/CString.h> -#undef LOG -#define LOG(...) android_printLog(ANDROID_LOG_DEBUG, "GraphicsLayer", __VA_ARGS__) -#define MLOG(...) android_printLog(ANDROID_LOG_DEBUG, "GraphicsLayer", __VA_ARGS__) -#define TLOG(...) android_printLog(ANDROID_LOG_DEBUG, "GraphicsLayer", __VA_ARGS__) - -#undef LOG -#define LOG(...) -#undef MLOG -#define MLOG(...) -#undef TLOG -#define TLOG(...) -#undef LAYER_DEBUG - using namespace std; static bool gPaused; @@ -125,7 +120,11 @@ GraphicsLayerAndroid::GraphicsLayerAndroid(GraphicsLayerClient* client) : m_foregroundClipLayer(0) { RenderLayer* renderLayer = renderLayerFromClient(m_client); - m_contentLayer = new LayerAndroid(renderLayer); + if (renderLayer && renderLayer->renderer()->isCanvas()) { + m_contentLayer = new CanvasLayer(renderLayer, + static_cast<HTMLCanvasElement*>(renderLayer->renderer()->node())); + } else + m_contentLayer = new LayerAndroid(renderLayer); m_dirtyRegion.setEmpty(); gDebugGraphicsLayerAndroidInstances++; } @@ -148,7 +147,7 @@ void GraphicsLayerAndroid::setName(const String& name) NativeLayer GraphicsLayerAndroid::nativeLayer() const { - LOG("(%x) nativeLayer", this); + ALOGV("(%x) nativeLayer", this); return 0; } @@ -167,7 +166,7 @@ void GraphicsLayerAndroid::addChild(GraphicsLayer* childLayer) { #ifndef NDEBUG const String& name = childLayer->name(); - LOG("(%x) addChild: %x (%s)", this, childLayer, name.latin1().data()); + ALOGV("(%x) addChild: %x (%s)", this, childLayer, name.latin1().data()); #endif GraphicsLayer::addChild(childLayer); m_needsSyncChildren = true; @@ -176,7 +175,7 @@ void GraphicsLayerAndroid::addChild(GraphicsLayer* childLayer) void GraphicsLayerAndroid::addChildAtIndex(GraphicsLayer* childLayer, int index) { - LOG("(%x) addChild %x AtIndex %d", this, childLayer, index); + ALOGV("(%x) addChild %x AtIndex %d", this, childLayer, index); GraphicsLayer::addChildAtIndex(childLayer, index); m_needsSyncChildren = true; askForSync(); @@ -184,7 +183,7 @@ void GraphicsLayerAndroid::addChildAtIndex(GraphicsLayer* childLayer, int index) void GraphicsLayerAndroid::addChildBelow(GraphicsLayer* childLayer, GraphicsLayer* sibling) { - LOG("(%x) addChild %x Below %x", this, childLayer, sibling); + ALOGV("(%x) addChild %x Below %x", this, childLayer, sibling); GraphicsLayer::addChildBelow(childLayer, sibling); m_needsSyncChildren = true; askForSync(); @@ -192,7 +191,7 @@ void GraphicsLayerAndroid::addChildBelow(GraphicsLayer* childLayer, GraphicsLaye void GraphicsLayerAndroid::addChildAbove(GraphicsLayer* childLayer, GraphicsLayer* sibling) { - LOG("(%x) addChild %x Above %x", this, childLayer, sibling); + ALOGV("(%x) addChild %x Above %x", this, childLayer, sibling); GraphicsLayer::addChildAbove(childLayer, sibling); m_needsSyncChildren = true; askForSync(); @@ -200,7 +199,7 @@ void GraphicsLayerAndroid::addChildAbove(GraphicsLayer* childLayer, GraphicsLaye bool GraphicsLayerAndroid::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild) { - LOG("(%x) replaceChild %x by %x", this, oldChild, newChild); + ALOGV("(%x) replaceChild %x by %x", this, oldChild, newChild); bool ret = GraphicsLayer::replaceChild(oldChild, newChild); if (ret) { m_needsSyncChildren = true; @@ -211,7 +210,7 @@ bool GraphicsLayerAndroid::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* void GraphicsLayerAndroid::removeFromParent() { - LOG("(%x) removeFromParent()", this); + ALOGV("(%x) removeFromParent()", this); GraphicsLayerAndroid* parent = static_cast<GraphicsLayerAndroid*>(m_parent); GraphicsLayer::removeFromParent(); // Update the parent's children. @@ -221,7 +220,7 @@ void GraphicsLayerAndroid::removeFromParent() } } -void GraphicsLayerAndroid::updateFixedPosition() +void GraphicsLayerAndroid::updatePositionedLayers() { RenderLayer* renderLayer = renderLayerFromClient(m_client); if (!renderLayer) @@ -232,10 +231,15 @@ 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) { + m_contentLayer->setAbsolutePosition(false); // We need to get the passed CSS properties for the element SkLength left, top, right, bottom; left = convertLength(view->style()->left()); @@ -264,11 +268,23 @@ 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 (view->isPositioned() && view->style()->position() == AbsolutePosition) { + m_contentLayer->setAbsolutePosition(true); + } else { + m_contentLayer->setFixedPosition(0); + m_contentLayer->setAbsolutePosition(false); } } @@ -280,7 +296,7 @@ void GraphicsLayerAndroid::setPosition(const FloatPoint& point) GraphicsLayer::setPosition(point); #ifdef LAYER_DEBUG_2 - LOG("(%x) setPosition(%.2f,%.2f) pos(%.2f, %.2f) anchor(%.2f,%.2f) size(%.2f, %.2f)", + ALOGV("(%x) setPosition(%.2f,%.2f) pos(%.2f, %.2f) anchor(%.2f,%.2f) size(%.2f, %.2f)", this, point.x(), point.y(), m_position.x(), m_position.y(), m_anchorPoint.x(), m_anchorPoint.y(), m_size.width(), m_size.height()); #endif @@ -312,7 +328,7 @@ void GraphicsLayerAndroid::setSize(const FloatSize& size) { if (size == m_size) return; - MLOG("(%x) setSize (%.2f,%.2f)", this, size.width(), size.height()); + ALOGV("(%x) setSize (%.2f,%.2f)", this, size.width(), size.height()); GraphicsLayer::setSize(size); // If it is a media layer the size may have changed as a result of the media @@ -323,8 +339,8 @@ void GraphicsLayerAndroid::setSize(const FloatSize& size) RenderBox* box = layer->renderBox(); int outline = box->view()->maximalOutlineSize(); static_cast<MediaLayer*>(m_contentLayer)->setOutlineSize(outline); - LOG("Media Outline: %d %p %p %p", outline, m_client, layer, box); - LOG("Media Size: %g,%g", size.width(), size.height()); + ALOGV("Media Outline: %d %p %p %p", outline, m_client, layer, box); + ALOGV("Media Size: %g,%g", size.width(), size.height()); } m_contentLayer->setSize(size.width(), size.height()); @@ -356,7 +372,7 @@ void GraphicsLayerAndroid::setChildrenTransform(const TransformationMatrix& t) { if (t == m_childrenTransform) return; - LOG("(%x) setChildrenTransform", this); + ALOGV("(%x) setChildrenTransform", this); GraphicsLayer::setChildrenTransform(t); m_contentLayer->setChildrenTransform(t); @@ -405,7 +421,7 @@ void GraphicsLayerAndroid::setBackgroundColor(const Color& color) { if (color == m_backgroundColor && m_backgroundColorSet) return; - LOG("(%x) setBackgroundColor", this); + ALOGV("(%x) setBackgroundColor", this); GraphicsLayer::setBackgroundColor(color); SkColor c = SkColorSetARGB(color.alpha(), color.red(), color.green(), color.blue()); m_contentLayer->setBackgroundColor(c); @@ -418,7 +434,7 @@ void GraphicsLayerAndroid::clearBackgroundColor() if (!m_backgroundColorSet) return; - LOG("(%x) clearBackgroundColor", this); + ALOGV("(%x) clearBackgroundColor", this); GraphicsLayer::clearBackgroundColor(); askForSync(); } @@ -427,7 +443,7 @@ void GraphicsLayerAndroid::setContentsOpaque(bool opaque) { if (opaque == m_contentsOpaque) return; - LOG("(%x) setContentsOpaque (%d)", this, opaque); + ALOGV("(%x) setContentsOpaque (%d)", this, opaque); GraphicsLayer::setContentsOpaque(opaque); m_haveContents = true; askForSync(); @@ -435,13 +451,13 @@ void GraphicsLayerAndroid::setContentsOpaque(bool opaque) void GraphicsLayerAndroid::setOpacity(float opacity) { - LOG("(%x) setOpacity: %.2f", this, opacity); + ALOGV("(%x) setOpacity: %.2f", this, opacity); float clampedOpacity = max(0.0f, min(opacity, 1.0f)); if (clampedOpacity == m_opacity) return; - MLOG("(%x) setFinalOpacity: %.2f=>%.2f (%.2f)", this, + ALOGV("(%x) setFinalOpacity: %.2f=>%.2f (%.2f)", this, opacity, clampedOpacity, m_opacity); GraphicsLayer::setOpacity(clampedOpacity); m_contentLayer->setOpacity(clampedOpacity); @@ -450,7 +466,7 @@ void GraphicsLayerAndroid::setOpacity(float opacity) void GraphicsLayerAndroid::setNeedsDisplay() { - LOG("(%x) setNeedsDisplay()", this); + ALOGV("(%x) setNeedsDisplay()", this); FloatRect rect(0, 0, m_size.width(), m_size.height()); setNeedsDisplayInRect(rect); } @@ -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,10 +573,25 @@ 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) ", - this, gPaused, m_needsRepaint, m_haveContents); + ALOGV("(%x) repaint(), gPaused(%d) m_needsRepaint(%d) m_haveContents(%d) ", + this, gPaused, m_needsRepaint, m_haveContents); if (!gPaused && m_haveContents && m_needsRepaint && !m_image) { // with SkPicture, we request the entire layer's content. @@ -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,32 +657,33 @@ 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()); + ALOGV("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()); } } - LOG("(%x) repaint() on (%.2f,%.2f) contentlayer(%.2f,%.2f,%.2f,%.2f)paintGraphicsLayer called!", - this, m_size.width(), m_size.height(), - m_contentLayer->getPosition().fX, - m_contentLayer->getPosition().fY, - m_contentLayer->getSize().width(), - m_contentLayer->getSize().height()); + ALOGV("(%x) repaint() on (%.2f,%.2f) contentlayer(%.2f,%.2f,%.2f,%.2f)paintGraphicsLayer called!", + this, m_size.width(), m_size.height(), + m_contentLayer->getPosition().fX, + m_contentLayer->getPosition().fY, + m_contentLayer->getSize().width(), + m_contentLayer->getSize().height()); 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; } @@ -683,8 +734,8 @@ void GraphicsLayerAndroid::setNeedsDisplayInRect(const FloatRect& rect) // rect is in the render object coordinates if (!m_image && !drawsContent()) { - LOG("(%x) setNeedsDisplay(%.2f,%.2f,%.2f,%.2f) doesn't have content, bypass...", - this, rect.x(), rect.y(), rect.width(), rect.height()); + ALOGV("(%x) setNeedsDisplay(%.2f,%.2f,%.2f,%.2f) doesn't have content, bypass...", + this, rect.x(), rect.y(), rect.width(), rect.height()); return; } @@ -736,20 +787,20 @@ bool GraphicsLayerAndroid::createAnimationFromKeyframes(const KeyframeValueList& const Animation* animation, const String& keyframesName, double beginTime) { bool isKeyframe = valueList.size() > 2; - TLOG("createAnimationFromKeyframes(%d), name(%s) beginTime(%.2f)", - isKeyframe, keyframesName.latin1().data(), beginTime); + ALOGV("createAnimationFromKeyframes(%d), name(%s) beginTime(%.2f)", + isKeyframe, keyframesName.latin1().data(), beginTime); switch (valueList.property()) { case AnimatedPropertyInvalid: break; case AnimatedPropertyWebkitTransform: break; case AnimatedPropertyBackgroundColor: break; case AnimatedPropertyOpacity: { - MLOG("ANIMATEDPROPERTYOPACITY"); + ALOGV("ANIMATEDPROPERTYOPACITY"); 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); @@ -785,13 +836,13 @@ bool GraphicsLayerAndroid::createTransformAnimationsFromKeyframes(const Keyframe const IntSize& boxSize) { ASSERT(valueList.property() == AnimatedPropertyWebkitTransform); - TLOG("createTransformAnimationFromKeyframes, name(%s) beginTime(%.2f)", - keyframesName.latin1().data(), beginTime); + ALOGV("createTransformAnimationFromKeyframes, name(%s) beginTime(%.2f)", + keyframesName.latin1().data(), beginTime); 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); @@ -816,36 +867,36 @@ bool GraphicsLayerAndroid::createTransformAnimationsFromKeyframes(const Keyframe void GraphicsLayerAndroid::removeAnimationsForProperty(AnimatedPropertyID anID) { - TLOG("NRO removeAnimationsForProperty(%d)", anID); + ALOGV("NRO removeAnimationsForProperty(%d)", anID); m_contentLayer->removeAnimationsForProperty(anID); askForSync(); } void GraphicsLayerAndroid::removeAnimationsForKeyframes(const String& keyframesName) { - TLOG("NRO removeAnimationsForKeyframes(%s)", keyframesName.latin1().data()); + ALOGV("NRO removeAnimationsForKeyframes(%s)", keyframesName.latin1().data()); m_contentLayer->removeAnimationsForKeyframes(keyframesName); askForSync(); } void GraphicsLayerAndroid::pauseAnimation(const String& keyframesName) { - TLOG("NRO pauseAnimation(%s)", keyframesName.latin1().data()); + ALOGV("NRO pauseAnimation(%s)", keyframesName.latin1().data()); } void GraphicsLayerAndroid::suspendAnimations(double time) { - TLOG("NRO suspendAnimations(%.2f)", time); + ALOGV("NRO suspendAnimations(%.2f)", time); } void GraphicsLayerAndroid::resumeAnimations() { - TLOG("NRO resumeAnimations()"); + ALOGV("NRO resumeAnimations()"); } void GraphicsLayerAndroid::setContentsToImage(Image* image) { - TLOG("(%x) setContentsToImage", this, image); + ALOGV("(%x) setContentsToImage", this, image); if (image && image != m_image) { image->ref(); if (m_image) @@ -899,7 +950,7 @@ void GraphicsLayerAndroid::setContentsToMedia(PlatformLayer* mediaLayer) PlatformLayer* GraphicsLayerAndroid::platformLayer() const { - LOG("platformLayer"); + ALOGV("platformLayer"); return m_contentLayer; } @@ -917,7 +968,7 @@ void GraphicsLayerAndroid::setZPosition(float position) { if (position == m_zPosition) return; - LOG("(%x) setZPosition: %.2f", this, position); + ALOGV("(%x) setZPosition: %.2f", this, position); GraphicsLayer::setZPosition(position); askForSync(); } @@ -988,8 +1039,14 @@ 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(); + updatePositionedLayers(); syncChildren(); syncMask(); diff --git a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.h b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.h index e6d75b0..27dfde2 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(); @@ -132,14 +137,14 @@ private: void syncChildren(); void syncMask(); - void updateFixedPosition(); + void updatePositionedLayers(); void updateScrollingLayers(); // with SkPicture, we always repaint the entire layer's content. 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..dadb13d --- /dev/null +++ b/Source/WebCore/platform/graphics/android/IFrameContentLayerAndroid.cpp @@ -0,0 +1,42 @@ +#define LOG_TAG "IFrameContentLayerAndroid" +#define LOG_NDEBUG 1 + +#include "config.h" +#include "IFrameContentLayerAndroid.h" + +#include "AndroidLog.h" + +#if USE(ACCELERATED_COMPOSITING) + +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..3532542 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/IFrameLayerAndroid.cpp @@ -0,0 +1,40 @@ +#define LOG_TAG "IFrameLayerAndroid" +#define LOG_NDEBUG 1 + +#include "config.h" +#include "IFrameLayerAndroid.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "AndroidLog.h" +#include "DumpLayer.h" + +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..08f72e0 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 @@ -172,20 +172,7 @@ static void round_scaled(SkIRect* dst, const WebCore::FloatRect& src, SkScalarRound(SkFloatToScalar((src.y() + src.height()) * sy))); } -static inline void fixPaintForBitmapsThatMaySeam(SkPaint* paint) { - /* Bitmaps may be drawn to seem next to other images. If we are drawn - zoomed, or at fractional coordinates, we may see cracks/edges if - we antialias, because that will cause us to draw the same pixels - more than once (e.g. from the left and right bitmaps that share - an edge). - - Disabling antialiasing fixes this, and since so far we are never - rotated at non-multiple-of-90 angles, this seems to do no harm - */ - paint->setAntiAlias(false); -} - -void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dstRect, +void BitmapImage::draw(GraphicsContext* gc, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace, CompositeOperator compositeOp) { @@ -222,14 +209,7 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dstRect, return; } - SkCanvas* canvas = ctxt->platformContext()->mCanvas; - SkPaint paint; - - ctxt->setupBitmapPaint(&paint); // need global alpha among other things - paint.setFilterBitmap(true); - paint.setXfermodeMode(WebCoreCompositeToSkiaComposite(compositeOp)); - fixPaintForBitmapsThatMaySeam(&paint); - canvas->drawBitmapRect(bitmap, &srcR, dstR, &paint); + gc->platformContext()->drawBitmapRect(bitmap, &srcR, dstR, compositeOp); #ifdef TRACE_SUBSAMPLED_BITMAPS if (bitmap.width() != image->origWidth() || @@ -248,26 +228,19 @@ void BitmapImage::setURL(const String& str) /////////////////////////////////////////////////////////////////////////////// -void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& srcRect, +void Image::drawPattern(GraphicsContext* gc, const FloatRect& srcRect, const AffineTransform& patternTransform, const FloatPoint& phase, ColorSpace, CompositeOperator compositeOp, const FloatRect& destRect) { SkBitmapRef* image = this->nativeImageForCurrentFrame(); - if (!image) { // If it's too early we won't have an image yet. + if (!image || destRect.isEmpty()) return; - } // in case we get called with an incomplete bitmap const SkBitmap& origBitmap = image->bitmap(); - if (origBitmap.getPixels() == NULL && origBitmap.pixelRef() == NULL) { + if (origBitmap.getPixels() == NULL && origBitmap.pixelRef() == NULL) return; - } - - SkRect dstR(destRect); - if (dstR.isEmpty()) { - return; - } SkIRect srcR; // we may have to scale if the image has been subsampled (so save RAM) @@ -278,11 +251,9 @@ void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& srcRect, if (imageIsSubSampled) { scaleX = (float)image->origWidth() / origBitmap.width(); scaleY = (float)image->origHeight() / origBitmap.height(); -// SkDebugf("----- subsampled %g %g\n", scaleX, scaleY); round_scaled(&srcR, srcRect, 1 / scaleX, 1 / scaleY); - } else { + } else round(&srcR, srcRect); - } // now extract the proper subset of the src image SkBitmap bitmap; @@ -291,19 +262,6 @@ void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& srcRect, return; } - SkCanvas* canvas = ctxt->platformContext()->mCanvas; - SkPaint paint; - ctxt->setupBitmapPaint(&paint); // need global alpha among other things - - SkShader* shader = SkShader::CreateBitmapShader(bitmap, - SkShader::kRepeat_TileMode, - SkShader::kRepeat_TileMode); - paint.setShader(shader)->unref(); - // now paint is the only owner of shader - paint.setXfermodeMode(WebCoreCompositeToSkiaComposite(compositeOp)); - paint.setFilterBitmap(true); - fixPaintForBitmapsThatMaySeam(&paint); - SkMatrix matrix(patternTransform); if (imageIsSubSampled) { @@ -316,26 +274,8 @@ void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& srcRect, float tx = phase.x() + srcRect.x() * patternTransform.a(); float ty = phase.y() + srcRect.y() * patternTransform.d(); matrix.postTranslate(SkFloatToScalar(tx), SkFloatToScalar(ty)); - shader->setLocalMatrix(matrix); -#if 0 - SkDebugf("--- drawPattern: src [%g %g %g %g] dst [%g %g %g %g] transform [%g %g %g %g %g %g] matrix [%g %g %g %g %g %g]\n", - srcRect.x(), srcRect.y(), srcRect.width(), srcRect.height(), - destRect.x(), destRect.y(), destRect.width(), destRect.height(), - patternTransform.a(), patternTransform.b(), patternTransform.c(), - patternTransform.d(), patternTransform.e(), patternTransform.f(), - matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]); -#endif - canvas->drawRect(dstR, paint); -#ifdef TRACE_SUBSAMPLED_BITMAPS - if (bitmap.width() != image->origWidth() || - bitmap.height() != image->origHeight()) { - SkDebugf("--- Image::drawPattern [%d %d] orig [%d %d] dst [%g %g]\n", - bitmap.width(), bitmap.height(), - image->origWidth(), image->origHeight(), - SkScalarToFloat(dstR.width()), SkScalarToFloat(dstR.height())); - } -#endif + gc->platformContext()->drawBitmapPattern(bitmap, matrix, compositeOp, destRect); } // missingImage, textAreaResizeCorner diff --git a/Source/WebCore/platform/graphics/android/ImageBufferAndroid.cpp b/Source/WebCore/platform/graphics/android/ImageBufferAndroid.cpp index 691fbca..f148881 100644 --- a/Source/WebCore/platform/graphics/android/ImageBufferAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/ImageBufferAndroid.cpp @@ -36,6 +36,7 @@ #include "SkBitmapRef.h" #include "SkCanvas.h" #include "SkColorPriv.h" +#include "SkData.h" #include "SkDevice.h" #include "SkImageEncoder.h" #include "SkStream.h" @@ -195,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()); @@ -207,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()); @@ -241,7 +242,9 @@ String ImageBuffer::toDataURL(const String&, const double*) const // Convert it into base64. Vector<char> pngEncodedData; - pngEncodedData.append(pngStream.getStream(), pngStream.getOffset()); + SkData* streamData = pngStream.copyToData(); + pngEncodedData.append((char*)streamData->data(), streamData->size()); + streamData->unref(); Vector<char> base64EncodedData; base64Encode(pngEncodedData, base64EncodedData); // Append with a \0 so that it's a valid string. diff --git a/Source/WebCore/platform/graphics/android/ImageTexture.cpp b/Source/WebCore/platform/graphics/android/ImageTexture.cpp index 23e3899..7d3f2b8 100644 --- a/Source/WebCore/platform/graphics/android/ImageTexture.cpp +++ b/Source/WebCore/platform/graphics/android/ImageTexture.cpp @@ -23,9 +23,13 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#define LOG_TAG "ImageTexture" +#define LOG_NDEBUG 1 + #include "config.h" #include "ImageTexture.h" +#include "AndroidLog.h" #include "ImagesManager.h" #include "LayerAndroid.h" #include "SkDevice.h" @@ -33,25 +37,6 @@ #include "TilesManager.h" #include "TiledTexture.h" -#include <cutils/log.h> -#include <wtf/CurrentTime.h> -#include <wtf/text/CString.h> - -#undef XLOGC -#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "ImageTexture", __VA_ARGS__) - -#ifdef DEBUG - -#undef XLOG -#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "ImageTexture", __VA_ARGS__) - -#else - -#undef XLOG -#define XLOG(...) - -#endif // DEBUG - namespace WebCore { // CRC computation adapted from Tools/DumpRenderTree/CyclicRedundancyCheck.cpp @@ -126,7 +111,7 @@ SkBitmap* ImageTexture::convertBitmap(SkBitmap* bitmap) // Create a copy of the image img->setConfig(SkBitmap::kARGB_8888_Config, w, h); img->allocPixels(); - SkDevice* device = new SkDevice(NULL, *img, false); + SkDevice* device = new SkDevice(*img); SkCanvas canvas; canvas.setDevice(device); device->unref(); @@ -166,7 +151,7 @@ int ImageTexture::nbTextures() // a list of the clients layer, etc.) IntRect visibleArea(0, 0, m_image->width(), m_image->height()); int nbTextures = m_texture->nbTextures(visibleArea, 1.0); - XLOG("ImageTexture %p, %d x %d needs %d textures", + ALOGV("ImageTexture %p, %d x %d needs %d textures", this, m_image->width(), m_image->height(), nbTextures); return nbTextures; @@ -188,18 +173,19 @@ bool ImageTexture::prepareGL(GLWebViewState* state) return false; if (!m_texture && m_picture) { - m_texture = new TiledTexture(this); + bool isLayerTile = true; + m_texture = new TiledTexture(isLayerTile); 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()) { + IntRect unclippedArea(0, 0, m_image->width(), m_image->height()); + m_texture->prepareGL(state, 1.0, unclippedArea, unclippedArea, this); + if (m_texture->isReady()) { m_texture->swapTiles(); return false; } @@ -230,7 +216,20 @@ float ImageTexture::opacity() return m_layer->drawOpacity(); } -void ImageTexture::drawGL(LayerAndroid* layer) +bool ImageTexture::paint(BaseTile* tile, SkCanvas* canvas) +{ + if (!m_picture) { + ALOGV("IT %p COULDNT PAINT, NO PICTURE", this); + return false; + } + + ALOGV("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 +239,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/ImagesManager.cpp b/Source/WebCore/platform/graphics/android/ImagesManager.cpp index 65c41d1..8452503 100644 --- a/Source/WebCore/platform/graphics/android/ImagesManager.cpp +++ b/Source/WebCore/platform/graphics/android/ImagesManager.cpp @@ -23,33 +23,18 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#define LOG_TAG "ImagesManager" +#define LOG_NDEBUG 1 + #include "config.h" #include "ImagesManager.h" +#include "AndroidLog.h" #include "SkCanvas.h" #include "SkDevice.h" #include "SkRefCnt.h" #include "ImageTexture.h" -#include <cutils/log.h> -#include <wtf/CurrentTime.h> -#include <wtf/text/CString.h> - -#undef XLOGC -#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "ImagesManager", __VA_ARGS__) - -#ifdef DEBUG - -#undef XLOG -#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "ImagesManager", __VA_ARGS__) - -#else - -#undef XLOG -#define XLOG(...) - -#endif // DEBUG - namespace WebCore { ImagesManager* ImagesManager::instance() diff --git a/Source/WebCore/platform/graphics/android/ImagesManager.h b/Source/WebCore/platform/graphics/android/ImagesManager.h index a3ea859..b915a46 100644 --- a/Source/WebCore/platform/graphics/android/ImagesManager.h +++ b/Source/WebCore/platform/graphics/android/ImagesManager.h @@ -32,6 +32,8 @@ #include "SkRefCnt.h" #include "Vector.h" +#include <utils/threads.h> + namespace WebCore { class ImageTexture; diff --git a/Source/WebCore/platform/graphics/android/InspectorCanvas.cpp b/Source/WebCore/platform/graphics/android/InspectorCanvas.cpp new file mode 100644 index 0000000..f9edb74 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/InspectorCanvas.cpp @@ -0,0 +1,133 @@ +/* + * 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. + */ + +#define LOG_TAG "InspectorCanvas" +#define LOG_NDEBUG 1 + +#include "config.h" +#include "InspectorCanvas.h" + +#include "AndroidLog.h" +#include "SkPicture.h" + +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(); + } + ALOGV("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..48e36fc 100644 --- a/Source/WebCore/platform/graphics/android/Layer.cpp +++ b/Source/WebCore/platform/graphics/android/Layer.cpp @@ -1,5 +1,10 @@ +#define LOG_TAG "Layer" +#define LOG_NDEBUG 1 + #include "config.h" #include "Layer.h" + +#include "AndroidLog.h" #include "SkCanvas.h" //#define DEBUG_DRAW_LAYER_BOUNDS @@ -158,13 +163,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 +194,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 +214,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..996547b 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); @@ -140,7 +120,7 @@ public: This does not include the childrenMatrix, since that is only applied after this layer draws (but before its children draw). */ - void getLocalTransform(SkMatrix* matrix) const; + virtual void getLocalTransform(SkMatrix* matrix) const; /** Return, in matrix, the concatenation of transforms that are applied from this layer's root parent to the layer itself. @@ -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..b40e00a 100644 --- a/Source/WebCore/platform/graphics/android/LayerAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/LayerAndroid.cpp @@ -1,44 +1,40 @@ +#define LOG_TAG "LayerAndroid" +#define LOG_NDEBUG 1 + #include "config.h" #include "LayerAndroid.h" #if USE(ACCELERATED_COMPOSITING) +#include "AndroidLog.h" #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" #include "TilesManager.h" #include <wtf/CurrentTime.h> -#include <math.h> - -#define LAYER_DEBUG // Add diagonals for debugging -#undef LAYER_DEBUG - -#include <cutils/log.h> #include <wtf/text/CString.h> -#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "LayerAndroid", __VA_ARGS__) - -#ifdef DEBUG - -#undef XLOG -#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "LayerAndroid", __VA_ARGS__) - -#else +#include <math.h> -#undef XLOG -#define XLOG(...) +#define DISABLE_LAYER_MERGE +#undef DISABLE_LAYER_MERGE -#endif // DEBUG +#define LAYER_GROUPING_DEBUG +#undef LAYER_GROUPING_DEBUG namespace WebCore { @@ -55,112 +51,30 @@ 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_uniqueId(++gUniqueId), 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_uniqueId(++gUniqueId), - m_texture(0), + m_isPositionAbsolute(false), + m_fixedPosition(0), + m_zValue(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"); @@ -169,110 +83,101 @@ LayerAndroid::LayerAndroid(RenderLayer* owner) : Layer(), } LayerAndroid::LayerAndroid(const LayerAndroid& layer) : Layer(layer), - m_haveClip(layer.m_haveClip), - m_isIframe(layer.m_isIframe), m_uniqueId(layer.m_uniqueId), - m_texture(0), + m_haveClip(layer.m_haveClip), + m_isPositionAbsolute(layer.m_isPositionAbsolute), + m_fixedPosition(0), + m_zValue(layer.m_zValue), 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; - for (int i = 0; i < layer.countChildren(); i++) - addChild(layer.getChild(i)->copy())->unref(); + // If we have absolute elements, we may need to reorder them if they + // are followed by another layer that is not also absolutely positioned. + // (as absolutely positioned elements are out of the normal flow) + bool hasAbsoluteChildren = false; + bool hasOnlyAbsoluteFollowers = true; + for (int i = 0; i < layer.countChildren(); i++) { + if (layer.getChild(i)->isPositionAbsolute()) { + hasAbsoluteChildren = true; + continue; + } + if (hasAbsoluteChildren + && !layer.getChild(i)->isPositionAbsolute()) { + hasOnlyAbsoluteFollowers = false; + break; + } + } + + if (hasAbsoluteChildren && !hasOnlyAbsoluteFollowers) { + Vector<LayerAndroid*> normalLayers; + Vector<LayerAndroid*> absoluteLayers; + for (int i = 0; i < layer.countChildren(); i++) { + LayerAndroid* child = layer.getChild(i); + if (child->isPositionAbsolute() + || child->isPositionFixed()) + absoluteLayers.append(child); + else + normalLayers.append(child); + } + for (unsigned int i = 0; i < normalLayers.size(); i++) + addChild(normalLayers[i]->copy())->unref(); + for (unsigned int i = 0; i < absoluteLayers.size(); i++) + addChild(absoluteLayers[i]->copy())->unref(); + } else { + for (int i = 0; i < layer.countChildren(); i++) + addChild(layer.getChild(i)->copy())->unref(); + } KeyframesMap::const_iterator end = layer.m_animations.end(); for (KeyframesMap::const_iterator it = layer.m_animations.begin(); it != end; ++it) { 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_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_backgroundColor = 0; - SkSafeRef(m_recordingPicture); - m_iframeOffset.set(0,0); - m_dirtyRegion.setEmpty(); -#ifdef DEBUG_COUNT - ClassTracker::instance()->increment("LayerAndroid - from picture"); - ClassTracker::instance()->add(this); -#endif -} - 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); @@ -280,11 +185,14 @@ LayerAndroid::~LayerAndroid() ClassTracker::instance()->decrement("LayerAndroid"); else if (m_type == LayerAndroid::UILayer) ClassTracker::instance()->decrement("LayerAndroid - recopy (UI)"); - else if (m_type == LayerAndroid::NavCacheLayer) - ClassTracker::instance()->decrement("LayerAndroid - from picture"); #endif } +bool LayerAndroid::hasText() +{ + return m_content && m_content->hasText(); +} + static int gDebugNbAnims = 0; bool LayerAndroid::evaluateAnimations() @@ -395,8 +303,6 @@ void LayerAndroid::setBackgroundColor(SkColor color) m_backgroundColor = color; } -static int gDebugChildLevel; - FloatPoint LayerAndroid::translation() const { TransformationMatrix::DecomposedType tDecomp; @@ -454,216 +360,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; - } + ALOGV("updating fixed positions, using viewport %fx%f - %fx%f", + viewport.fLeft, viewport.fTop, + viewport.width(), viewport.height()); - 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 (!isPositionFixed()) { // turn our fields into a matrix. // // FIXME: this should happen in the caller, and we should remove these @@ -685,13 +413,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 (!isPositionFixed()) localMatrix = parentMatrix; localMatrix.translate3d(originX + position.x(), originY + position.y(), @@ -708,9 +434,9 @@ void LayerAndroid::updateGLPositionsAndScale(const TransformationMatrix& parentM // that layers (defined in content coordinates) will align to display/view pixels float desiredContentX = round(m_drawTransform.m41() * scale) / scale; float desiredContentY = round(m_drawTransform.m42() * scale) / scale; - XLOG("fudging translation from %f, %f to %f, %f", - m_drawTransform.m41(), m_drawTransform.m42(), - desiredContentX, desiredContentY); + ALOGV("fudging translation from %f, %f to %f, %f", + m_drawTransform.m41(), m_drawTransform.m42(), + desiredContentX, desiredContentY); m_drawTransform.setM41(desiredContentX); m_drawTransform.setM42(desiredContentY); } @@ -733,6 +459,9 @@ void LayerAndroid::updateGLPositionsAndScale(const TransformationMatrix& parentM } else { setDrawClip(clipping); } + ALOGV("%s - %d %f %f %f %f", + subclassType() == BaseLayer ? "BASE" : "nonbase", + m_haveClip, m_clippingRect.x(), m_clippingRect.y(), m_clippingRect.width(), m_clippingRect.height()); if (!m_backfaceVisibility && m_drawTransform.inverse().m33() < 0) { @@ -759,13 +488,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 +518,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 +559,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]; @@ -836,9 +567,9 @@ void LayerAndroid::showLayer(int indent) spaces[i] = ' '; if (!indent) { - XLOGC("\n\n--- LAYERS TREE ---"); + ALOGD("\n\n--- LAYERS TREE ---"); IntRect documentViewport(TilesManager::instance()->shader()->documentViewport()); - XLOGC("documentViewport(%d, %d, %d, %d)", + ALOGD("documentViewport(%d, %d, %d, %d)", documentViewport.x(), documentViewport.y(), documentViewport.width(), documentViewport.height()); } @@ -848,87 +579,36 @@ 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, + ALOGD("%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(), visible.x(), visible.y(), visible.width(), visible.height(), 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); + isPositionFixed() ? "FIXED" : "", + 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,43 +646,115 @@ 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) +{ +#ifdef 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) + // isolate intrinsically composited layers + if (m_intrinsicallyComposited || lastLayer->m_intrinsicallyComposited) + return false; + + // TODO: investigate potential for combining transformed layers + if (!m_drawTransform.isIdentityOrTranslation() + || !lastLayer->m_drawTransform.isIdentityOrTranslation()) + return false; + + // 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::assignGroups(LayerMergeState* mergeState) { - return a->zValue() > b->zValue(); + // 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 + ALOGD("%*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, + isPositionFixed(), m_animations.size() != 0, + m_intrinsicallyComposited, + m_haveClip, + contentIsScrollable()); +#endif + + mergeState->currentLayerGroup->addLayer(this, m_drawTransform); + m_layerGroup = mergeState->currentLayerGroup; + + if (m_haveClip || contentIsScrollable() || isPositionFixed()) { + // 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(getChild(i)); + + // 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--; + } + + if (m_haveClip || contentIsScrollable() || isPositionFixed()) { + // re-enable joining + mergeState->nonMergeNestedLevel--; + + // disallow layers painting after to join with this group + mergeState->currentLayerGroup = 0; + } } // We call this in WebViewCore, when copying the tree of layers. @@ -1018,26 +770,14 @@ void LayerAndroid::clearDirtyRegion() m_dirtyRegion.setEmpty(); } -void LayerAndroid::prepare() +int LayerAndroid::setHwAccelerated(bool hwAccelerated) { - XLOG("LA %p preparing, m_texture %p", this, m_texture); - + int flags = InvalidateNone; 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); - - // iterate in reverse so top layers get textures first - for (int i = count-1; i >= 0; i--) - sublayers[i]->prepare(); - } + for (int i = 0; i < count; i++) + flags |= this->getChild(i)->setHwAccelerated(hwAccelerated); - if (m_texture) - m_texture->prepare(m_state); + return flags | onSetHwAccelerated(hwAccelerated); } IntRect LayerAndroid::unclippedArea() @@ -1072,7 +812,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 +831,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 +847,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 +882,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); - } + + canvas->drawLine(0, 0, 0, h-1, paint); + canvas->drawLine(0, h-1, w-1, h-1, paint); + canvas->drawLine(w-1, h-1, w-1, 0, paint); + canvas->drawLine(w-1, 0, 0, 0, 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 +929,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 +949,23 @@ void LayerAndroid::onDraw(SkCanvas* canvas, SkScalar opacity) } ImagesManager::instance()->releaseImage(m_imageCRC); } - contentDraw(canvas); + contentDraw(canvas, style); + if (extra) + extra->draw(canvas, this); } -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 LayerAndroid::setFixedPosition(FixedPositioning* position) { + if (m_fixedPosition && m_fixedPosition != position) + delete m_fixedPosition; + m_fixedPosition = position; } -void writeIndent(FILE* file, int indentLevel) +void LayerAndroid::dumpLayer(FILE* file, int indentLevel) const { - 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); -} - -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::dumpLayers(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", isPositionFixed()); writeFloatVal(file, indentLevel + 1, "opacity", getOpacity()); writeSize(file, indentLevel + 1, "size", getSize()); @@ -1417,22 +976,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..c7028c5 100644 --- a/Source/WebCore/platform/graphics/android/LayerAndroid.h +++ b/Source/WebCore/platform/graphics/android/LayerAndroid.h @@ -48,54 +48,29 @@ 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; class TexturesResult { @@ -115,15 +90,35 @@ public: class TEST_EXPORT LayerAndroid : public Layer { public: - enum LayerType { UndefinedLayer, WebCoreLayer, UILayer, NavCacheLayer }; + typedef enum { UndefinedLayer, WebCoreLayer, UILayer } LayerType; + typedef enum { StandardLayer, ScrollableLayer, + IFrameLayer, IFrameContentLayer, + CanvasLayer, BaseLayer } SubclassType; + typedef enum { InvalidateNone = 0, InvalidateLayers } InvalidateFlags; + + String subclassName() + { + switch (subclassType()) { + case LayerAndroid::StandardLayer: + return "StandardLayer"; + case LayerAndroid::ScrollableLayer: + return "ScrollableLayer"; + case LayerAndroid::IFrameLayer: + return "IFrameLayer"; + case LayerAndroid::IFrameContentLayer: + return "IFrameContentLayer"; + case LayerAndroid::CanvasLayer: + return "CanvasLayer"; + case LayerAndroid::BaseLayer: + return "BaseLayer"; + } + return "Undefined"; + } LayerAndroid(RenderLayer* owner); LayerAndroid(const LayerAndroid& layer); - LayerAndroid(SkPicture*); virtual ~LayerAndroid(); - virtual TiledPage* page() { return 0; } - void setBackfaceVisibility(bool value) { m_backfaceVisibility = value; } void setTransform(const TransformationMatrix& matrix) { m_transform = matrix; } FloatPoint translation() const; @@ -139,30 +134,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; } @@ -170,35 +158,13 @@ public: void setAnchorPointZ(float z) { m_anchorPointZ = z; } float anchorPointZ() { return m_anchorPointZ; } void setDrawTransform(const TransformationMatrix& transform) { m_drawTransform = transform; } - const TransformationMatrix* drawTransform() const { return &m_drawTransform; } + virtual const TransformationMatrix* drawTransform() const { return &m_drawTransform; } void setChildrenTransform(const TransformationMatrix& t) { m_childrenTransform = t; } 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 +173,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 +185,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 +195,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 +219,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 +232,68 @@ public: virtual LayerAndroid* copy() const { return new LayerAndroid(*this); } - void needsRepaint() { m_pictureUsed++; } - unsigned int pictureUsed() { return m_pictureUsed; } - - void clearDirtyRegion(); + virtual void clearDirtyRegion(); - void contentDraw(SkCanvas*); + virtual void contentDraw(SkCanvas* canvas, PaintStyle style); virtual bool isMedia() const { return false; } virtual bool isVideo() const { return false; } + virtual bool isIFrame() const { return false; } + virtual bool isIFrameContent() const { return false; } + + bool isPositionFixed() const { return m_fixedPosition; } + void setAbsolutePosition(bool isAbsolute) { m_isPositionAbsolute = isAbsolute; } + bool isPositionAbsolute() { return m_isPositionAbsolute; } + 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; } + + int setHwAccelerated(bool hwAccelerated); + +protected: + virtual void onDraw(SkCanvas*, SkScalar opacity, android::DrawExtra* extra, PaintStyle style); + virtual InvalidateFlags onSetHwAccelerated(bool hwAccelerated) { return InvalidateNone; } + IntPoint m_offset; TransformationMatrix m_drawTransform; + int m_uniqueId; 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 +302,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 +313,8 @@ 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; + bool m_isPositionAbsolute; + FixedPositioning* m_fixedPosition; typedef HashMap<pair<String, int>, RefPtr<AndroidAnimation> > KeyframesMap; KeyframesMap m_animations; @@ -379,19 +326,19 @@ 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 +355,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..97bc32a --- /dev/null +++ b/Source/WebCore/platform/graphics/android/LayerContent.h @@ -0,0 +1,56 @@ +/* + * 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" +#include <utils/threads.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; + +protected: + // used to prevent parallel draws, as both SkPicture and PictureSet don't support them + android::Mutex m_drawLock; +}; + +} // 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..7bdbd11 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/LayerGroup.cpp @@ -0,0 +1,345 @@ +/* + * 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. + */ + +#define LOG_TAG "LayerGroup" +#define LOG_NDEBUG 1 + +#include "config.h" +#include "LayerGroup.h" + +#include "AndroidLog.h" +#include "ClassTracker.h" +#include "LayerAndroid.h" +#include "TiledTexture.h" +#include "TilesManager.h" + +// 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); + + ALOGV("%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); + ALOGV("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; +} + +IntRect LayerGroup::unclippedArea() +{ + if (singleLayer()) + return getFirstLayer()->unclippedArea(); + return m_unclippedArea; +} + +bool LayerGroup::useAggressiveRendering() +{ + // When the background is translucent, 0 < alpha < 255, we had to turn off + // low res to avoid artifacts from double drawing. + // TODO: avoid double drawing for low res tiles. + return isBase() + && (!m_background.alpha() + || !m_background.hasAlpha()); +} + +void LayerGroup::prepareGL(bool layerTilesDisabled) +{ + bool tilesDisabled = layerTilesDisabled && !isBase(); + if (!m_dualTiledTexture) { + ALOGV("prepareGL on LG %p, no DTT, needsTexture? %d", + this, m_dualTiledTexture, needsTexture()); + + if (!needsTexture()) + return; + + m_dualTiledTexture = new DualTiledTexture(isBase()); + } + + if (tilesDisabled) { + m_dualTiledTexture->discardTextures(); + } else { + bool allowZoom = hasText(); // only allow for scale > 1 if painting vectors + IntRect prepareArea = computePrepareArea(); + IntRect fullArea = unclippedArea(); + + ALOGV("prepareGL on LG %p with DTT %p, %d layers", + this, m_dualTiledTexture, m_layers.size()); + + m_dualTiledTexture->prepareGL(getFirstLayer()->state(), allowZoom, + prepareArea, fullArea, + this, useAggressiveRendering()); + } +} + +bool LayerGroup::drawGL(bool layerTilesDisabled) +{ + bool tilesDisabled = layerTilesDisabled && !isBase(); + if (!getFirstLayer()->visible()) + return false; + + if (!isBase()) { + // TODO: why are clipping regions wrong for base layer? + FloatRect drawClip = getFirstLayer()->drawClip(); + FloatRect clippingRect = TilesManager::instance()->shader()->rectInScreenCoord(drawClip); + TilesManager::instance()->shader()->clip(clippingRect); + } + + bool askRedraw = false; + if (m_dualTiledTexture && !tilesDisabled) { + ALOGV("drawGL on LG %p with DTT %p", this, m_dualTiledTexture); + + // TODO: why this visibleArea is different from visibleRect at zooming for base? + IntRect drawArea = visibleArea(); + askRedraw |= m_dualTiledTexture->drawGL(drawArea, opacity(), + drawTransform(), useAggressiveRendering(), + background()); + } + + // draw member layers (draws image textures, glextras) + for (unsigned int i = 0; i < m_layers.size(); i++) + askRedraw |= m_layers[i]->drawGL(tilesDisabled); + + 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() + && !isBase() + && getFirstLayer()->state()->layersRenderingMode() == GLWebViewState::kAllTextures) { + + area = 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 || isBase()) + return; + + m_dualTiledTexture->computeTexturesAmount(result, getFirstLayer()); +} + +bool LayerGroup::isBase() +{ + // base layer group + // - doesn't use layer tiles (disables blending, doesn't compute textures amount) + // - ignores clip rects + // - only prepares clippedArea + return getFirstLayer()->subclassType() == LayerAndroid::BaseLayer; +} + +bool LayerGroup::paint(BaseTile* tile, SkCanvas* canvas) +{ + if (singleLayer()) { + getFirstLayer()->contentDraw(canvas, Layer::UnmergedLayers); + + // TODO: double buffer by disabling SurfaceCollection swaps and position + // updates until painting complete + + // In single surface mode, draw layer content onto the base layer + if (isBase() + && getFirstLayer()->countChildren() + && getFirstLayer()->state()->layersRenderingMode() > GLWebViewState::kClippedTextures) + getFirstLayer()->getChild(0)->drawCanvas(canvas, true, Layer::FlattenedLayers); + } 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()->drawOpacity(); + return 1.0; +} + +Color* LayerGroup::background() +{ + if (!isBase() || !m_background.isValid()) + return 0; + return &m_background; +} + +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..8e9608d --- /dev/null +++ b/Source/WebCore/platform/graphics/android/LayerGroup.h @@ -0,0 +1,115 @@ +/* + * 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 "Color.h" +#include "IntRect.h" +#include "TilePainter.h" +#include "Vector.h" + +class SkCanvas; +class SkRegion; + +namespace WebCore { + +class BaseTile; +class DualTiledTexture; +class LayerAndroid; +class TexturesResult; + +class LayerGroup : public TilePainter { +public: + LayerGroup(); + virtual ~LayerGroup(); + + bool tryUpdateLayerGroup(LayerGroup* oldLayerGroup); + + void addLayer(LayerAndroid* layer, const TransformationMatrix& transform); + void prepareGL(bool layerTilesDisabled); + bool drawGL(bool layerTilesDisabled); + void swapTiles(); + bool isReady(); + + void computeTexturesAmount(TexturesResult* result); + + LayerAndroid* getFirstLayer() { return m_layers[0]; } + bool needsTexture() { return m_needsTexture; } + bool hasText() { return m_hasText; } + bool isBase(); + void setBackground(Color background) { m_background = background; } + + // TilePainter methods + virtual bool paint(BaseTile* tile, SkCanvas* canvas); + virtual float opacity(); + virtual Color* background(); + +private: + IntRect computePrepareArea(); + IntRect visibleArea(); + IntRect unclippedArea(); + bool singleLayer() { return m_layers.size() == 1; } + void updateBackground(const Color& background); + bool useAggressiveRendering(); + + const TransformationMatrix* drawTransform(); + IntRect m_unclippedArea; + TransformationMatrix m_drawTransform; + + DualTiledTexture* m_dualTiledTexture; + bool m_needsTexture; + bool m_hasText; + Vector<LayerAndroid*> m_layers; + + Color m_background; +}; + +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..6227ea4 100644 --- a/Source/WebCore/platform/graphics/android/MediaLayer.cpp +++ b/Source/WebCore/platform/graphics/android/MediaLayer.cpp @@ -13,41 +13,29 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +#define LOG_TAG "MediaLayer" +#define LOG_NDEBUG 1 + #include "config.h" #include "MediaLayer.h" + +#include "AndroidLog.h" #include "MediaTexture.h" #include "TilesManager.h" #if USE(ACCELERATED_COMPOSITING) -#define LAYER_DEBUG -#undef LAYER_DEBUG - -#ifdef DEBUG - -#include <cutils/log.h> -#include <wtf/text/CString.h> - -#undef XLOG -#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "MediaLayer", __VA_ARGS__) - -#else - -#undef XLOG -#define XLOG(...) - -#endif // DEBUG - namespace WebCore { -MediaLayer::MediaLayer(jobject webViewRef) : LayerAndroid((RenderLayer*) NULL) +MediaLayer::MediaLayer(jobject webViewRef, jobject webViewCoreRef) : LayerAndroid((RenderLayer*) NULL) { - m_mediaTexture = new MediaTexture(webViewRef); + m_mediaTexture = new MediaTexture(webViewRef, webViewCoreRef); m_mediaTexture->incStrong(this); m_isCopy = false; m_outlineSize = 0; - XLOG("Creating Media Layer %p", this); + ALOGV("Creating Media Layer %p", this); } MediaLayer::MediaLayer(const MediaLayer& layer) : LayerAndroid(layer) @@ -57,16 +45,16 @@ MediaLayer::MediaLayer(const MediaLayer& layer) : LayerAndroid(layer) m_isCopy = true; m_outlineSize = layer.m_outlineSize; - XLOG("Creating Media Layer Copy %p -> %p", &layer, this); + ALOGV("Creating Media Layer Copy %p -> %p", &layer, this); } MediaLayer::~MediaLayer() { - XLOG("Deleting Media Layer"); + ALOGV("Deleting Media Layer"); 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 +80,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..2f39d74 100644 --- a/Source/WebCore/platform/graphics/android/MediaLayer.h +++ b/Source/WebCore/platform/graphics/android/MediaLayer.h @@ -32,11 +32,11 @@ namespace WebCore { class MediaLayer : public LayerAndroid { public: - MediaLayer(jobject webViewRef); + MediaLayer(jobject webViewRef, jobject webViewCoreRef); 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/MediaListener.h b/Source/WebCore/platform/graphics/android/MediaListener.h index 5fcbbb2..2dfc08b 100644 --- a/Source/WebCore/platform/graphics/android/MediaListener.h +++ b/Source/WebCore/platform/graphics/android/MediaListener.h @@ -26,21 +26,6 @@ #include "MediaTexture.h" #include "WebCoreJni.h" -#ifdef DEBUG - -#include <cutils/log.h> -#include <wtf/text/CString.h> - -#undef XLOG -#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "MediaListener", __VA_ARGS__) - -#else - -#undef XLOG -#define XLOG(...) - -#endif // DEBUG - namespace WebCore { class MediaListener : public android::SurfaceTexture::FrameAvailableListener { 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..faa20a1 100644 --- a/Source/WebCore/platform/graphics/android/MediaTexture.cpp +++ b/Source/WebCore/platform/graphics/android/MediaTexture.cpp @@ -13,8 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +#define LOG_TAG "MediaTexture" +#define LOG_NDEBUG 1 + #include "config.h" #include "MediaTexture.h" + +#include "AndroidLog.h" #include "TilesManager.h" #include "GLUtils.h" #include "MediaListener.h" @@ -24,28 +30,9 @@ #include <android/native_window.h> #include <gui/SurfaceTexture.h> #include <gui/SurfaceTextureClient.h> -#include <wtf/CurrentTime.h> #include <JNIUtility.h> #include "WebCoreJni.h" -#define LAYER_DEBUG -#undef LAYER_DEBUG - -#ifdef DEBUG - -#include <cutils/log.h> -#include <wtf/text/CString.h> - -#undef XLOG -#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "MediaTexture", __VA_ARGS__) - -#else - -#undef XLOG -#define XLOG(...) - -#endif // DEBUG - // Limits the number of ANativeWindows that can be allocated for video playback. // The limit is currently set to 2 as that is the current max number of // simultaneous HW decodes that our OMX implementation allows. This forces the @@ -54,14 +41,11 @@ namespace WebCore { -MediaTexture::MediaTexture(jobject webViewRef) : android::LightRefBase<MediaTexture>() +MediaTexture::MediaTexture(jobject webViewRef, jobject webViewCoreRef) : android::LightRefBase<MediaTexture>() { - if (webViewRef) { - JNIEnv* env = JSC::Bindings::getJNIEnv(); - m_weakWebViewRef = env->NewWeakGlobalRef(webViewRef); - } else { - m_weakWebViewRef = 0; - } + JNIEnv* env = JSC::Bindings::getJNIEnv(); + m_weakWebViewRef = env->NewWeakGlobalRef(webViewRef); + m_weakWebViewCoreRef = env->NewWeakGlobalRef(webViewCoreRef); m_contentTexture = 0; m_isContentInverted = false; @@ -76,10 +60,9 @@ MediaTexture::~MediaTexture() deleteTexture(m_videoTextures[i], true); } - if (m_weakWebViewRef) { - JNIEnv* env = JSC::Bindings::getJNIEnv(); - env->DeleteWeakGlobalRef(m_weakWebViewRef); - } + JNIEnv* env = JSC::Bindings::getJNIEnv(); + env->DeleteWeakGlobalRef(m_weakWebViewRef); + env->DeleteWeakGlobalRef(m_weakWebViewCoreRef); } bool MediaTexture::isContentInverted() @@ -111,16 +94,16 @@ void MediaTexture::initNativeWindowIfNeeded() m_contentTexture = createTexture(); // send a message to the WebKit thread to notify the plugin that it can draw - if (m_weakWebViewRef) { + if (m_weakWebViewCoreRef) { JNIEnv* env = JSC::Bindings::getJNIEnv(); - jobject localWebViewRef = env->NewLocalRef(m_weakWebViewRef); - if (localWebViewRef) { - jclass wvClass = env->GetObjectClass(localWebViewRef); + jobject localWebViewCoreRef = env->NewLocalRef(m_weakWebViewCoreRef); + if (localWebViewCoreRef) { + jclass wvClass = env->GetObjectClass(localWebViewCoreRef); jmethodID sendPluginDrawMsg = env->GetMethodID(wvClass, "sendPluginDrawMsg", "()V"); - env->CallVoidMethod(localWebViewRef, sendPluginDrawMsg); + env->CallVoidMethod(localWebViewCoreRef, sendPluginDrawMsg); env->DeleteLocalRef(wvClass); - env->DeleteLocalRef(localWebViewRef); + env->DeleteLocalRef(localWebViewCoreRef); } checkException(env); } @@ -171,7 +154,7 @@ void MediaTexture::draw(const TransformationMatrix& contentMatrix, #ifdef DEBUG if (!mediaBounds.contains(dimensions)) { - XLOG("The video exceeds is parent's bounds."); + ALOGV("The video exceeds is parent's bounds."); } #endif // DEBUG @@ -191,8 +174,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 +265,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/MediaTexture.h b/Source/WebCore/platform/graphics/android/MediaTexture.h index 97bb530..9ea7be2 100644 --- a/Source/WebCore/platform/graphics/android/MediaTexture.h +++ b/Source/WebCore/platform/graphics/android/MediaTexture.h @@ -40,7 +40,7 @@ class MediaListener; class MediaTexture : public android::LightRefBase<MediaTexture> { public: - MediaTexture(jobject webViewRef); + MediaTexture(jobject webViewRef, jobject webViewCoreRef); ~MediaTexture(); bool isContentInverted(); @@ -83,6 +83,7 @@ private: sp<ANativeWindow> m_newWindow; jobject m_weakWebViewRef; + jobject m_weakWebViewCoreRef; android::Mutex m_mediaLock; android::Condition m_newMediaRequestCond; diff --git a/Source/WebCore/platform/graphics/android/PaintTileOperation.cpp b/Source/WebCore/platform/graphics/android/PaintTileOperation.cpp index 2d69706..4ae1f31 100644 --- a/Source/WebCore/platform/graphics/android/PaintTileOperation.cpp +++ b/Source/WebCore/platform/graphics/android/PaintTileOperation.cpp @@ -23,23 +23,30 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#define LOG_TAG "PaintTileOperation" +#define LOG_NDEBUG 1 + #include "config.h" #include "PaintTileOperation.h" + +#include "AndroidLog.h" #include "ImageTexture.h" #include "ImagesManager.h" #include "LayerAndroid.h" -#include "PaintedSurface.h" +#include "TilesManager.h" namespace WebCore { -PaintTileOperation::PaintTileOperation(BaseTile* tile, SurfacePainter* surface) - : QueuedOperation(QueuedOperation::PaintTile, tile->page()) - , m_tile(tile) - , m_surface(surface) +PaintTileOperation::PaintTileOperation(BaseTile* tile, TilePainter* painter, + GLWebViewState* state, bool isLowResPrefetch) + : m_tile(tile) + , m_painter(painter) + , m_state(state) + , m_isLowResPrefetch(isLowResPrefetch) { if (m_tile) m_tile->setRepaintPending(true); - SkSafeRef(m_surface); + SkSafeRef(m_painter); } PaintTileOperation::~PaintTileOperation() @@ -49,18 +56,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; } @@ -68,7 +73,7 @@ bool PaintTileOperation::operator==(const QueuedOperation* operation) void PaintTileOperation::run() { if (m_tile) { - m_tile->paintBitmap(); + m_tile->paintBitmap(m_painter); m_tile->setRepaintPending(false); m_tile = 0; } @@ -81,14 +86,9 @@ int PaintTileOperation::priority() int priority = 200000; - // if scrolling, prioritize the prefetch page, otherwise deprioritize - TiledPage* page = m_tile->page(); - if (page && page->isPrefetchPage()) { - if (page->glWebViewState()->isScrolling()) - priority = 0; - else - priority = 400000; - } + // prioritize low res while scrolling + if (m_isLowResPrefetch) + priority = m_state->isScrolling() ? 0 : 400000; // prioritize higher draw count unsigned long long currentDraw = TilesManager::instance()->getDrawGLCount(); @@ -101,7 +101,7 @@ int PaintTileOperation::priority() // for base tiles, prioritize based on position if (!m_tile->isLayerTile()) { - bool goingDown = m_tile->page()->scrollingDown(); + bool goingDown = m_state->goingDown(); priority += m_tile->x(); if (goingDown) diff --git a/Source/WebCore/platform/graphics/android/PaintTileOperation.h b/Source/WebCore/platform/graphics/android/PaintTileOperation.h index bc74d03..afd2fc1 100644 --- a/Source/WebCore/platform/graphics/android/PaintTileOperation.h +++ b/Source/WebCore/platform/graphics/android/PaintTileOperation.h @@ -33,41 +33,40 @@ 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, + GLWebViewState* state, bool isLowResPrefetch); virtual ~PaintTileOperation(); virtual bool operator==(const QueuedOperation* operation); virtual void run(); // returns a rendering priority for m_tile, lower values are processed faster virtual int priority(); - TilePainter* painter() { return m_tile->painter(); } + TilePainter* painter() { return m_painter; } float scale() { return m_tile->scale(); } private: BaseTile* m_tile; - SurfacePainter* m_surface; + TilePainter* m_painter; + GLWebViewState* m_state; + bool m_isLowResPrefetch; }; 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 +76,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 deleted file mode 100644 index 241cbef..0000000 --- a/Source/WebCore/platform/graphics/android/PerformanceMonitor.cpp +++ /dev/null @@ -1,104 +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 "PerformanceMonitor.h" - -#include <wtf/text/CString.h> - -#include <wtf/CurrentTime.h> -#include <cutils/log.h> -#include <wtf/text/CString.h> -#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "PerformanceMonitor", __VA_ARGS__) - -namespace WebCore { - -PerformanceMonitor::PerformanceMonitor() -{ -} - -PerformanceMonitor::~PerformanceMonitor() -{ -} - -void PerformanceMonitor::start(const String &tag) -{ - if (tag.isEmpty()) - return; - PerfItem *item; - if (m_tags.contains(tag)) - item = m_tags.get(tag); - else { - item = new PerfItem(); - m_tags.set(tag, item); - } - gettimeofday(&(item->start_time), NULL); -} - -void PerformanceMonitor::stop(const String &tag) -{ - if (!m_tags.contains(tag)) - return; - PerfItem *item = m_tags.get(tag); - struct timeval end; - gettimeofday(&end, NULL); - long seconds, useconds; - seconds = end.tv_sec - item->start_time.tv_sec; - useconds = end.tv_usec - item->start_time.tv_usec; - - float mtime = (seconds * 1000.0) + (useconds/1000.0); - - float avg = 0; - if (item->average_ms) { - item->average_ms = (item->average_ms + mtime) / 2; - } else - item->average_ms = mtime; -} - -float PerformanceMonitor::getAverageDuration(const String &tag) -{ - if (tag.isEmpty() || !m_tags.contains(tag)) - return 0; - return m_tags.get(tag)->average_ms; -} - -void PerformanceMonitor::display(int limit) -{ - bool shown = false; - HashMap<String, PerfItem*, StringHash>::iterator end = m_tags.end(); - for (HashMap<String, PerfItem*, StringHash>::iterator it = m_tags.begin(); it != end; ++it) { - PerfItem* item = it->second; - if (item->average_ms > limit) { - if (!shown) { - XLOGC("=== DISPLAY MONITOR ===="); - shown = true; - } - XLOGC("item %s took longer than %d ms: %.2f", it->first.latin1().data(), limit, item->average_ms); - } - } - if (shown) - XLOGC("=== END DISPLAY MONITOR ===="); -} - -} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/PictureLayerContent.cpp b/Source/WebCore/platform/graphics/android/PictureLayerContent.cpp new file mode 100644 index 0000000..4398146 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/PictureLayerContent.cpp @@ -0,0 +1,106 @@ +#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; + + android::Mutex::Autolock lock(m_drawLock); + SkRect r = SkRect::MakeWH(width(), height()); + canvas->clipRect(r); + 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/PerformanceMonitor.h b/Source/WebCore/platform/graphics/android/PictureLayerContent.h index 4ebbf6a..94bdfac 100644 --- a/Source/WebCore/platform/graphics/android/PerformanceMonitor.h +++ b/Source/WebCore/platform/graphics/android/PictureLayerContent.h @@ -1,5 +1,5 @@ /* - * Copyright 2011, 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,37 +23,33 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef PerformanceMonitor_h -#define PerformanceMonitor_h +#ifndef PictureLayerContent_h +#define PictureLayerContent_h -#include "config.h" - -#include <wtf/HashMap.h> -#include <wtf/text/StringHash.h> -#include <sys/time.h> -#include <unistd.h> +#include "LayerContent.h" namespace WebCore { -struct PerfItem { - PerfItem() : average_ms(0), start_time() {} - float average_ms; - struct timeval start_time; -}; - -class PerformanceMonitor { +class PictureLayerContent : public LayerContent { public: - PerformanceMonitor(); - virtual ~PerformanceMonitor(); - void start(const String &tag); - void stop(const String &tag); - float getAverageDuration(const String &tag); - void display(int limit); + 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: - HashMap<String, PerfItem*, StringHash> m_tags; + SkPicture* m_picture; + bool m_checkedContent; + bool m_hasText; }; -} +} // WebCore -#endif // PerformanceMonitor_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..8b72b0a --- /dev/null +++ b/Source/WebCore/platform/graphics/android/PictureSetLayerContent.cpp @@ -0,0 +1,41 @@ +#include "config.h" +#include "PictureSetLayerContent.h" + +#include "SkCanvas.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()) + return; + + android::Mutex::Autolock lock(m_drawLock); + SkRect r = SkRect::MakeWH(width(), height()); + canvas->clipRect(r); + 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/DeleteTextureOperation.h b/Source/WebCore/platform/graphics/android/PictureSetLayerContent.h index f3cb57c..61fc3f4 100644 --- a/Source/WebCore/platform/graphics/android/DeleteTextureOperation.h +++ b/Source/WebCore/platform/graphics/android/PictureSetLayerContent.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,31 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef DeleteTextureOperation_h -#define DeleteTextureOperation_h +#ifndef PictureSetLayerContent_h +#define PictureSetLayerContent_h -#include "GLUtils.h" -#include "QueuedOperation.h" +#include "LayerContent.h" +#include "PictureSet.h" namespace WebCore { -class DeleteTextureOperation : public QueuedOperation { +class PictureSetLayerContent : 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); - } + 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: - GLuint m_textureId; - EGLImageKHR m_eglImage; + android::PictureSet m_pictureSet; }; -} +} // WebCore -#endif // DeleteTextureOperation_h +#endif // PictureLayerContent_h diff --git a/Source/WebCore/platform/graphics/android/PlatformGraphicsContext.cpp b/Source/WebCore/platform/graphics/android/PlatformGraphicsContext.cpp index 098534c..3c8ea3c 100644 --- a/Source/WebCore/platform/graphics/android/PlatformGraphicsContext.cpp +++ b/Source/WebCore/platform/graphics/android/PlatformGraphicsContext.cpp @@ -24,28 +24,1025 @@ */ #include "config.h" -#include "Node.h" #include "PlatformGraphicsContext.h" + +#include "AffineTransform.h" +#include "Font.h" +#include "Gradient.h" +#include "GraphicsContext.h" +#include "Node.h" +#include "NotImplemented.h" +#include "Path.h" +#include "Pattern.h" +#include "SkBitmapRef.h" +#include "SkBlurDrawLooper.h" +#include "SkBlurMaskFilter.h" #include "SkCanvas.h" +#include "SkColorPriv.h" +#include "SkCornerPathEffect.h" +#include "SkDashPathEffect.h" +#include "SkDevice.h" +#include "SkGradientShader.h" +#include "SkPaint.h" +#include "SkString.h" +#include "SkiaUtils.h" +#include "TransformationMatrix.h" +#include "android_graphics.h" namespace WebCore { -PlatformGraphicsContext::PlatformGraphicsContext(SkCanvas* canvas) - : mCanvas(canvas), m_deleteCanvas(false) +// These are the flags we need when we call saveLayer for transparency. +// Since it does not appear that webkit intends this to also save/restore +// the matrix or clip, I do not give those flags (for performance) +#define TRANSPARENCY_SAVEFLAGS \ + (SkCanvas::SaveFlags)(SkCanvas::kHasAlphaLayer_SaveFlag | \ + SkCanvas::kFullColorLayer_SaveFlag) + +//************************************** +// Helper functions +//************************************** + +static int RoundToInt(float x) +{ + return (int)roundf(x); +} + +template <typename T> T* deepCopyPtr(const T* src) +{ + return src ? new T(*src) : 0; +} + +// Set a bitmap shader that mimics dashing by width-on, width-off. +// Returns false if it could not succeed (e.g. there was an existing shader) +static bool setBitmapDash(SkPaint* paint, int width) { + if (width <= 0 || paint->getShader()) + return false; + + SkColor c = paint->getColor(); + + SkBitmap bm; + bm.setConfig(SkBitmap::kARGB_8888_Config, 2, 1); + bm.allocPixels(); + bm.lockPixels(); + + // set the ON pixel + *bm.getAddr32(0, 0) = SkPreMultiplyARGB(0xFF, SkColorGetR(c), + SkColorGetG(c), SkColorGetB(c)); + // set the OFF pixel + *bm.getAddr32(1, 0) = 0; + bm.unlockPixels(); + + SkMatrix matrix; + matrix.setScale(SkIntToScalar(width), SK_Scalar1); + + SkShader* s = SkShader::CreateBitmapShader(bm, SkShader::kRepeat_TileMode, + SkShader::kClamp_TileMode); + s->setLocalMatrix(matrix); + + paint->setShader(s)->unref(); + return true; +} + +static void setrectForUnderline(SkRect* r, float lineThickness, + const FloatPoint& point, int yOffset, float width) +{ +#if 0 + if (lineThickness < 1) // Do we really need/want this? + lineThickness = 1; +#endif + r->fLeft = point.x(); + r->fTop = point.y() + yOffset; + r->fRight = r->fLeft + width; + r->fBottom = r->fTop + lineThickness; +} + +static inline int fastMod(int value, int max) +{ + int sign = SkExtractSign(value); + + value = SkApplySign(value, sign); + if (value >= max) + value %= max; + return SkApplySign(value, sign); +} + +static inline void fixPaintForBitmapsThatMaySeam(SkPaint* paint) { + /* Bitmaps may be drawn to seem next to other images. If we are drawn + zoomed, or at fractional coordinates, we may see cracks/edges if + we antialias, because that will cause us to draw the same pixels + more than once (e.g. from the left and right bitmaps that share + an edge). + + Disabling antialiasing fixes this, and since so far we are never + rotated at non-multiple-of-90 angles, this seems to do no harm + */ + paint->setAntiAlias(false); +} + +//************************************** +// State structs +//************************************** + +struct ShadowRec { + SkScalar blur; + SkScalar dx; + SkScalar dy; + SkColor color; // alpha>0 means valid shadow + ShadowRec(SkScalar b = 0, + SkScalar x = 0, + SkScalar y = 0, + SkColor c = 0) // by default, alpha=0, so no shadow + : blur(b), dx(x), dy(y), color(c) + {}; +}; + +struct PlatformGraphicsContext::State { + SkPathEffect* pathEffect; + float miterLimit; + float alpha; + float strokeThickness; + SkPaint::Cap lineCap; + SkPaint::Join lineJoin; + SkXfermode::Mode mode; + int dashRatio; // Ratio of the length of a dash to its width + ShadowRec shadow; + SkColor fillColor; + SkShader* fillShader; + SkColor strokeColor; + SkShader* strokeShader; + bool useAA; + StrokeStyle strokeStyle; + + State() + : pathEffect(0) + , miterLimit(4) + , alpha(1) + , strokeThickness(0) // Same as default in GraphicsContextPrivate.h + , lineCap(SkPaint::kDefault_Cap) + , lineJoin(SkPaint::kDefault_Join) + , mode(SkXfermode::kSrcOver_Mode) + , dashRatio(3) + , fillColor(SK_ColorBLACK) + , fillShader(0) + , strokeColor(SK_ColorBLACK) + , strokeShader(0) + , useAA(true) + , strokeStyle(SolidStroke) + { + } + + State(const State& other) + : pathEffect(other.pathEffect) + , miterLimit(other.miterLimit) + , alpha(other.alpha) + , strokeThickness(other.strokeThickness) + , lineCap(other.lineCap) + , lineJoin(other.lineJoin) + , mode(other.mode) + , dashRatio(other.dashRatio) + , shadow(other.shadow) + , fillColor(other.fillColor) + , fillShader(other.fillShader) + , strokeColor(other.strokeColor) + , strokeShader(other.strokeShader) + , useAA(other.useAA) + , strokeStyle(other.strokeStyle) + { + SkSafeRef(pathEffect); + SkSafeRef(fillShader); + SkSafeRef(strokeShader); + } + + ~State() + { + SkSafeUnref(pathEffect); + SkSafeUnref(fillShader); + SkSafeUnref(strokeShader); + } + + void setShadow(int radius, int dx, int dy, SkColor c) + { + // Cut the radius in half, to visually match the effect seen in + // safari browser + shadow.blur = SkScalarHalf(SkIntToScalar(radius)); + shadow.dx = SkIntToScalar(dx); + shadow.dy = SkIntToScalar(dy); + shadow.color = c; + } + + bool setupShadowPaint(SkPaint* paint, SkPoint* offset, + bool shadowsIgnoreTransforms) + { + paint->setAntiAlias(true); + paint->setDither(true); + paint->setXfermodeMode(mode); + paint->setColor(shadow.color); + offset->set(shadow.dx, shadow.dy); + + // Currently, only GraphicsContexts associated with the + // HTMLCanvasElement have shadows ignore transforms set. This + // allows us to distinguish between CSS and Canvas shadows which + // have different rendering specifications. + uint32_t flags = SkBlurMaskFilter::kHighQuality_BlurFlag; + if (shadowsIgnoreTransforms) { + offset->fY = -offset->fY; + flags |= SkBlurMaskFilter::kIgnoreTransform_BlurFlag; + } + + if (shadow.blur > 0) { + paint->setMaskFilter(SkBlurMaskFilter::Create(shadow.blur, + SkBlurMaskFilter::kNormal_BlurStyle))->unref(); + } + return SkColorGetA(shadow.color) && (shadow.blur || shadow.dx || shadow.dy); + } + + SkColor applyAlpha(SkColor c) const + { + int s = RoundToInt(alpha * 256); + if (s >= 256) + return c; + if (s < 0) + return 0; + + int a = SkAlphaMul(SkColorGetA(c), s); + return (c & 0x00FFFFFF) | (a << 24); + } + + PlatformGraphicsContext::State cloneInheritedProperties(); +private: + // Not supported. + void operator=(const State&); +}; + +// Returns a new State with all of this object's inherited properties copied. +PlatformGraphicsContext::State PlatformGraphicsContext::State::cloneInheritedProperties() { + return PlatformGraphicsContext::State(*this); } -PlatformGraphicsContext::PlatformGraphicsContext() - : mCanvas(new SkCanvas), m_deleteCanvas(true) +//************************************** +// PlatformGraphicsContext +//************************************** + +PlatformGraphicsContext::PlatformGraphicsContext(SkCanvas* canvas, + bool takeCanvasOwnership) + : mCanvas(canvas) + , m_deleteCanvas(takeCanvasOwnership) + , m_stateStack(sizeof(State)) + , m_gc(0) { + m_stateStack.append(State()); + m_state = &m_stateStack.last(); } PlatformGraphicsContext::~PlatformGraphicsContext() { - if (m_deleteCanvas) { -// printf("-------------------- deleting offscreen canvas\n"); + if (m_deleteCanvas) delete mCanvas; +} + +//************************************** +// State management +//************************************** + +void PlatformGraphicsContext::beginTransparencyLayer(float opacity) +{ + SkCanvas* canvas = mCanvas; + canvas->saveLayerAlpha(0, (int)(opacity * 255), TRANSPARENCY_SAVEFLAGS); +} + +void PlatformGraphicsContext::endTransparencyLayer() +{ + mCanvas->restore(); +} + +void PlatformGraphicsContext::save() +{ + m_stateStack.append(m_state->cloneInheritedProperties()); + m_state = &m_stateStack.last(); + + // Save our native canvas. + mCanvas->save(); +} + +void PlatformGraphicsContext::restore() +{ + m_stateStack.removeLast(); + m_state = &m_stateStack.last(); + + // Restore our native canvas. + mCanvas->restore(); +} + +//************************************** +// State setters +//************************************** + +void PlatformGraphicsContext::setAlpha(float alpha) +{ + m_state->alpha = alpha; +} + +void PlatformGraphicsContext::setCompositeOperation(CompositeOperator op) +{ + m_state->mode = WebCoreCompositeToSkiaComposite(op); +} + +void PlatformGraphicsContext::setFillColor(const Color& c) +{ + m_state->fillColor = c.rgb(); + setFillShader(0); +} + +void PlatformGraphicsContext::setFillShader(SkShader* fillShader) +{ + if (fillShader) + m_state->fillColor = Color::black; + + if (fillShader != m_state->fillShader) { + SkSafeUnref(m_state->fillShader); + m_state->fillShader = fillShader; + SkSafeRef(m_state->fillShader); + } +} + +void PlatformGraphicsContext::setLineCap(LineCap cap) +{ + switch (cap) { + case ButtCap: + m_state->lineCap = SkPaint::kButt_Cap; + break; + case RoundCap: + m_state->lineCap = SkPaint::kRound_Cap; + break; + case SquareCap: + m_state->lineCap = SkPaint::kSquare_Cap; + break; + default: + SkDEBUGF(("PlatformGraphicsContext::setLineCap: unknown LineCap %d\n", cap)); + break; + } +} + +void PlatformGraphicsContext::setLineDash(const DashArray& dashes, float dashOffset) +{ + size_t dashLength = dashes.size(); + if (!dashLength) + return; + + size_t count = !(dashLength % 2) ? dashLength : dashLength * 2; + SkScalar* intervals = new SkScalar[count]; + + for (unsigned int i = 0; i < count; i++) + intervals[i] = SkFloatToScalar(dashes[i % dashLength]); + SkPathEffect **effectPtr = &m_state->pathEffect; + SkSafeUnref(*effectPtr); + *effectPtr = new SkDashPathEffect(intervals, count, SkFloatToScalar(dashOffset)); + + delete[] intervals; +} + +void PlatformGraphicsContext::setLineJoin(LineJoin join) +{ + switch (join) { + case MiterJoin: + m_state->lineJoin = SkPaint::kMiter_Join; + break; + case RoundJoin: + m_state->lineJoin = SkPaint::kRound_Join; + break; + case BevelJoin: + m_state->lineJoin = SkPaint::kBevel_Join; + break; + default: + SkDEBUGF(("PlatformGraphicsContext::setLineJoin: unknown LineJoin %d\n", join)); + break; + } +} + +void PlatformGraphicsContext::setMiterLimit(float limit) +{ + m_state->miterLimit = limit; +} + +void PlatformGraphicsContext::setShadow(int radius, int dx, int dy, SkColor c) +{ + m_state->setShadow(radius, dx, dy, c); +} + +void PlatformGraphicsContext::setShouldAntialias(bool useAA) +{ + m_state->useAA = useAA; +} + +void PlatformGraphicsContext::setStrokeColor(const Color& c) +{ + m_state->strokeColor = c.rgb(); + setStrokeShader(0); +} + +void PlatformGraphicsContext::setStrokeShader(SkShader* strokeShader) +{ + if (strokeShader) + m_state->strokeColor = Color::black; + + if (strokeShader != m_state->strokeShader) { + SkSafeUnref(m_state->strokeShader); + m_state->strokeShader = strokeShader; + SkSafeRef(m_state->strokeShader); + } +} + +void PlatformGraphicsContext::setStrokeStyle(StrokeStyle style) +{ + m_state->strokeStyle = style; +} + +void PlatformGraphicsContext::setStrokeThickness(float f) +{ + m_state->strokeThickness = f; +} + +//************************************** +// Paint setup +//************************************** + +void PlatformGraphicsContext::setupPaintCommon(SkPaint* paint) const +{ + paint->setAntiAlias(m_state->useAA); + paint->setDither(true); + paint->setXfermodeMode(m_state->mode); + if (SkColorGetA(m_state->shadow.color) > 0) { + + // Currently, only GraphicsContexts associated with the + // HTMLCanvasElement have shadows ignore transforms set. This + // allows us to distinguish between CSS and Canvas shadows which + // have different rendering specifications. + SkScalar dy = m_state->shadow.dy; + uint32_t flags = SkBlurDrawLooper::kHighQuality_BlurFlag; + if (shadowsIgnoreTransforms()) { + dy = -dy; + flags |= SkBlurDrawLooper::kIgnoreTransform_BlurFlag; + flags |= SkBlurDrawLooper::kOverrideColor_BlurFlag; + } + + SkDrawLooper* looper = new SkBlurDrawLooper(m_state->shadow.blur, + m_state->shadow.dx, + dy, + m_state->shadow.color, + flags); + paint->setLooper(looper)->unref(); + } + paint->setFilterBitmap(true); +} + +void PlatformGraphicsContext::setupPaintFill(SkPaint* paint) const +{ + this->setupPaintCommon(paint); + paint->setColor(m_state->applyAlpha(m_state->fillColor)); + paint->setShader(m_state->fillShader); +} + +bool PlatformGraphicsContext::setupPaintShadow(SkPaint* paint, SkPoint* offset) const +{ + return m_state->setupShadowPaint(paint, offset, shadowsIgnoreTransforms()); +} + +bool PlatformGraphicsContext::setupPaintStroke(SkPaint* paint, SkRect* rect, + bool isHLine) +{ + this->setupPaintCommon(paint); + paint->setColor(m_state->applyAlpha(m_state->strokeColor)); + paint->setShader(m_state->strokeShader); + + float width = m_state->strokeThickness; + + // This allows dashing and dotting to work properly for hairline strokes + // FIXME: Should we only do this for dashed and dotted strokes? + if (!width) + width = 1; + + paint->setStyle(SkPaint::kStroke_Style); + paint->setStrokeWidth(SkFloatToScalar(width)); + paint->setStrokeCap(m_state->lineCap); + paint->setStrokeJoin(m_state->lineJoin); + paint->setStrokeMiter(SkFloatToScalar(m_state->miterLimit)); + + if (rect && (RoundToInt(width) & 1)) + rect->inset(-SK_ScalarHalf, -SK_ScalarHalf); + + SkPathEffect* pe = m_state->pathEffect; + if (pe) { + paint->setPathEffect(pe); + return false; + } + switch (m_state->strokeStyle) { + case NoStroke: + case SolidStroke: + width = 0; + break; + case DashedStroke: + width = m_state->dashRatio * width; + break; + // No break + case DottedStroke: + break; + } + + if (width > 0) { + // Return true if we're basically a dotted dash of squares + bool justSqrs = RoundToInt(width) == RoundToInt(paint->getStrokeWidth()); + + if (justSqrs || !isHLine || !setBitmapDash(paint, width)) { +#if 0 + // this is slow enough that we just skip it for now + // see http://b/issue?id=4163023 + SkScalar intervals[] = { width, width }; + pe = new SkDashPathEffect(intervals, 2, 0); + paint->setPathEffect(pe)->unref(); +#endif + } + return justSqrs; + } + return false; +} + +//************************************** +// Matrix operations +//************************************** + +void PlatformGraphicsContext::concatCTM(const AffineTransform& affine) +{ + mCanvas->concat(affine); +} + +void PlatformGraphicsContext::rotate(float angleInRadians) +{ + mCanvas->rotate(SkFloatToScalar(angleInRadians * (180.0f / 3.14159265f))); +} + +void PlatformGraphicsContext::scale(const FloatSize& size) +{ + mCanvas->scale(SkFloatToScalar(size.width()), SkFloatToScalar(size.height())); +} + +void PlatformGraphicsContext::translate(float x, float y) +{ + mCanvas->translate(SkFloatToScalar(x), SkFloatToScalar(y)); +} + +//************************************** +// Clipping +//************************************** + +void PlatformGraphicsContext::addInnerRoundedRectClip(const IntRect& rect, + int thickness) +{ + SkPath path; + SkRect r(rect); + + path.addOval(r, SkPath::kCW_Direction); + // Only perform the inset if we won't invert r + if (2 * thickness < rect.width() && 2 * thickness < rect.height()) { + // Adding one to the thickness doesn't make the border too thick as + // it's painted over afterwards. But without this adjustment the + // border appears a little anemic after anti-aliasing. + r.inset(SkIntToScalar(thickness + 1), SkIntToScalar(thickness + 1)); + path.addOval(r, SkPath::kCCW_Direction); + } + mCanvas->clipPath(path, SkRegion::kIntersect_Op, true); +} + +void PlatformGraphicsContext::canvasClip(const Path& path) +{ + clip(path); +} + +void PlatformGraphicsContext::clip(const FloatRect& rect) +{ + mCanvas->clipRect(rect); +} + +void PlatformGraphicsContext::clip(const Path& path) +{ + mCanvas->clipPath(*path.platformPath(), SkRegion::kIntersect_Op, true); +} + +void PlatformGraphicsContext::clipConvexPolygon(size_t numPoints, + const FloatPoint*, bool antialias) +{ + if (numPoints <= 1) + return; + + // This is only used if HAVE_PATH_BASED_BORDER_RADIUS_DRAWING is defined + // in RenderObject.h which it isn't for us. TODO: Support that :) +} + +void PlatformGraphicsContext::clipOut(const IntRect& r) +{ + mCanvas->clipRect(r, SkRegion::kDifference_Op); +} + +void PlatformGraphicsContext::clipOut(const Path& p) +{ + mCanvas->clipPath(*p.platformPath(), SkRegion::kDifference_Op); +} + +void PlatformGraphicsContext::clipPath(const Path& pathToClip, WindRule clipRule) +{ + SkPath path = *pathToClip.platformPath(); + path.setFillType(clipRule == RULE_EVENODD + ? SkPath::kEvenOdd_FillType : SkPath::kWinding_FillType); + mCanvas->clipPath(path); +} +void PlatformGraphicsContext::clearRect(const FloatRect& rect) +{ + SkPaint paint; + + setupPaintFill(&paint); + paint.setXfermodeMode(SkXfermode::kClear_Mode); + mCanvas->drawRect(rect, paint); +} + +//************************************** +// Drawing +//************************************** + +void PlatformGraphicsContext::drawBitmapPattern( + const SkBitmap& bitmap, const SkMatrix& matrix, + CompositeOperator compositeOp, const FloatRect& destRect) +{ + SkShader* shader = SkShader::CreateBitmapShader(bitmap, + SkShader::kRepeat_TileMode, + SkShader::kRepeat_TileMode); + shader->setLocalMatrix(matrix); + SkPaint paint; + setupPaintFill(&paint); + paint.setShader(shader); + paint.setXfermodeMode(WebCoreCompositeToSkiaComposite(compositeOp)); + fixPaintForBitmapsThatMaySeam(&paint); + mCanvas->drawRect(destRect, paint); +} + +void PlatformGraphicsContext::drawBitmapRect(const SkBitmap& bitmap, + const SkIRect* src, const SkRect& dst, + CompositeOperator op) +{ + SkPaint paint; + setupPaintFill(&paint); + paint.setXfermodeMode(WebCoreCompositeToSkiaComposite(op)); + fixPaintForBitmapsThatMaySeam(&paint); + mCanvas->drawBitmapRect(bitmap, src, dst, &paint); +} + +void PlatformGraphicsContext::drawConvexPolygon(size_t numPoints, + const FloatPoint* points, + bool shouldAntialias) +{ + if (numPoints <= 1) + return; + + SkPaint paint; + SkPath path; + + path.incReserve(numPoints); + path.moveTo(SkFloatToScalar(points[0].x()), SkFloatToScalar(points[0].y())); + for (size_t i = 1; i < numPoints; i++) + path.lineTo(SkFloatToScalar(points[i].x()), SkFloatToScalar(points[i].y())); + + if (mCanvas->quickReject(path, shouldAntialias ? + SkCanvas::kAA_EdgeType : SkCanvas::kBW_EdgeType)) { + return; + } + + if (m_state->fillColor & 0xFF000000) { + setupPaintFill(&paint); + paint.setAntiAlias(shouldAntialias); + mCanvas->drawPath(path, paint); + } + + if (m_state->strokeStyle != NoStroke) { + paint.reset(); + setupPaintStroke(&paint, 0); + paint.setAntiAlias(shouldAntialias); + mCanvas->drawPath(path, paint); + } +} + +void PlatformGraphicsContext::drawEllipse(const IntRect& rect) +{ + SkPaint paint; + SkRect oval(rect); + + if (m_state->fillColor & 0xFF000000) { + setupPaintFill(&paint); + mCanvas->drawOval(oval, paint); + } + if (m_state->strokeStyle != NoStroke) { + paint.reset(); + setupPaintStroke(&paint, &oval); + mCanvas->drawOval(oval, paint); + } +} + +void PlatformGraphicsContext::drawFocusRing(const Vector<IntRect>& rects, + int /* width */, int /* offset */, + const Color& color) +{ + 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); + mCanvas->drawPath(path, paint); +} + +void PlatformGraphicsContext::drawHighlightForText( + const Font& font, const TextRun& run, const FloatPoint& point, int h, + const Color& backgroundColor, ColorSpace colorSpace, int from, + int to, bool isActive) +{ + 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); + } +} + +void PlatformGraphicsContext::drawLine(const IntPoint& point1, + const IntPoint& point2) +{ + StrokeStyle style = m_state->strokeStyle; + if (style == NoStroke) + return; + + SkPaint paint; + SkCanvas* canvas = mCanvas; + const int idx = SkAbs32(point2.x() - point1.x()); + const int idy = SkAbs32(point2.y() - point1.y()); + + // Special-case horizontal and vertical lines that are really just dots + if (setupPaintStroke(&paint, 0, !idy) && (!idx || !idy)) { + const SkScalar diameter = paint.getStrokeWidth(); + const SkScalar radius = SkScalarHalf(diameter); + SkScalar x = SkIntToScalar(SkMin32(point1.x(), point2.x())); + SkScalar y = SkIntToScalar(SkMin32(point1.y(), point2.y())); + SkScalar dx, dy; + int count; + SkRect bounds; + + if (!idy) { // Horizontal + bounds.set(x, y - radius, x + SkIntToScalar(idx), y + radius); + x += radius; + dx = diameter * 2; + dy = 0; + count = idx; + } else { // Vertical + bounds.set(x - radius, y, x + radius, y + SkIntToScalar(idy)); + y += radius; + dx = 0; + dy = diameter * 2; + count = idy; + } + + // The actual count is the number of ONs we hit alternating + // ON(diameter), OFF(diameter), ... + { + SkScalar width = SkScalarDiv(SkIntToScalar(count), diameter); + // Now compute the number of cells (ON and OFF) + count = SkScalarRound(width); + // Now compute the number of ONs + count = (count + 1) >> 1; + } + + SkAutoMalloc storage(count * sizeof(SkPoint)); + SkPoint* verts = (SkPoint*)storage.get(); + // Now build the array of vertices to past to drawPoints + for (int i = 0; i < count; i++) { + verts[i].set(x, y); + x += dx; + y += dy; + } + + paint.setStyle(SkPaint::kFill_Style); + paint.setPathEffect(0); + + // Clipping to bounds is not required for correctness, but it does + // allow us to reject the entire array of points if we are completely + // offscreen. This is common in a webpage for android, where most of + // the content is clipped out. If drawPoints took an (optional) bounds + // parameter, that might even be better, as we would *just* use it for + // culling, and not both wacking the canvas' save/restore stack. + canvas->save(SkCanvas::kClip_SaveFlag); + canvas->clipRect(bounds); + canvas->drawPoints(SkCanvas::kPoints_PointMode, count, verts, paint); + canvas->restore(); + } else { + SkPoint pts[2] = { point1, point2 }; + canvas->drawLine(pts[0].fX, pts[0].fY, pts[1].fX, pts[1].fY, paint); + } +} + +void PlatformGraphicsContext::drawLineForText(const FloatPoint& pt, float width) +{ + SkRect r; + setrectForUnderline(&r, m_state->strokeThickness, pt, 0, width); + + SkPaint paint; + paint.setAntiAlias(true); + paint.setColor(m_state->strokeColor); + + mCanvas->drawRect(r, paint); +} + +void PlatformGraphicsContext::drawLineForTextChecking(const FloatPoint& pt, + float width, GraphicsContext::TextCheckingLineStyle) +{ + // TODO: Should we draw different based on TextCheckingLineStyle? + SkRect r; + setrectForUnderline(&r, m_state->strokeThickness, pt, 0, width); + + SkPaint paint; + paint.setAntiAlias(true); + paint.setColor(SK_ColorRED); // Is this specified somewhere? + + mCanvas->drawRect(r, paint); +} + +void PlatformGraphicsContext::drawRect(const IntRect& rect) +{ + SkPaint paint; + SkRect r(rect); + + if (m_state->fillColor & 0xFF000000) { + setupPaintFill(&paint); + mCanvas->drawRect(r, paint); + } + + // According to GraphicsContext.h, stroking inside drawRect always means + // a stroke of 1 inside the rect. + if (m_state->strokeStyle != NoStroke && (m_state->strokeColor & 0xFF000000)) { + paint.reset(); + setupPaintStroke(&paint, &r); + paint.setPathEffect(0); // No dashing please + paint.setStrokeWidth(SK_Scalar1); // Always just 1.0 width + r.inset(SK_ScalarHalf, SK_ScalarHalf); // Ensure we're "inside" + mCanvas->drawRect(r, paint); + } +} + +void PlatformGraphicsContext::fillPath(const Path& pathToFill, WindRule fillRule) +{ + SkPath* path = pathToFill.platformPath(); + if (!path) + return; + + switch (fillRule) { + case RULE_NONZERO: + path->setFillType(SkPath::kWinding_FillType); + break; + case RULE_EVENODD: + path->setFillType(SkPath::kEvenOdd_FillType); + break; + } + + SkPaint paint; + setupPaintFill(&paint); + + mCanvas->drawPath(*path, paint); +} + +void PlatformGraphicsContext::fillRect(const FloatRect& rect) +{ + SkPaint paint; + setupPaintFill(&paint); + mCanvas->drawRect(rect, paint); +} + +void PlatformGraphicsContext::fillRect(const FloatRect& rect, + const Color& color, ColorSpace) +{ + if (color.rgb() & 0xFF000000) { + SkPaint paint; + + setupPaintCommon(&paint); + paint.setColor(color.rgb()); // Punch in the specified color + paint.setShader(0); // In case we had one set + + // Sometimes we record and draw portions of the page, using clips + // for each portion. The problem with this is that webkit, sometimes, + // sees that we're only recording a portion, and they adjust some of + // their rectangle coordinates accordingly (e.g. + // RenderBoxModelObject::paintFillLayerExtended() which calls + // rect.intersect(paintInfo.rect) and then draws the bg with that + // rect. The result is that we end up drawing rects that are meant to + // seam together (one for each portion), but if the rects have + // fractional coordinates (e.g. we are zoomed by a fractional amount) + // we will double-draw those edges, resulting in visual cracks or + // artifacts. + + // The fix seems to be to just turn off antialasing for rects (this + // entry-point in GraphicsContext seems to have been sufficient, + // though perhaps we'll find we need to do this as well in fillRect(r) + // as well.) Currently setupPaintCommon() enables antialiasing. + + // Since we never show the page rotated at a funny angle, disabling + // antialiasing seems to have no real down-side, and it does fix the + // bug when we're zoomed (and drawing portions that need to seam). + paint.setAntiAlias(false); + + mCanvas->drawRect(rect, paint); } } +void PlatformGraphicsContext::fillRoundedRect( + const IntRect& rect, const IntSize& topLeft, const IntSize& topRight, + const IntSize& bottomLeft, const IntSize& bottomRight, + const Color& color, ColorSpace) +{ + SkPaint paint; + SkPath path; + SkScalar radii[8]; + + radii[0] = SkIntToScalar(topLeft.width()); + radii[1] = SkIntToScalar(topLeft.height()); + radii[2] = SkIntToScalar(topRight.width()); + radii[3] = SkIntToScalar(topRight.height()); + radii[4] = SkIntToScalar(bottomRight.width()); + radii[5] = SkIntToScalar(bottomRight.height()); + radii[6] = SkIntToScalar(bottomLeft.width()); + radii[7] = SkIntToScalar(bottomLeft.height()); + path.addRoundRect(rect, radii); + + setupPaintFill(&paint); + paint.setColor(color.rgb()); + mCanvas->drawPath(path, paint); +} + +void PlatformGraphicsContext::strokeArc(const IntRect& r, int startAngle, + int angleSpan) +{ + SkPath path; + SkPaint paint; + SkRect oval(r); + + if (m_state->strokeStyle == NoStroke) { + setupPaintFill(&paint); // We want the fill color + paint.setStyle(SkPaint::kStroke_Style); + paint.setStrokeWidth(SkFloatToScalar(m_state->strokeThickness)); + } else + setupPaintStroke(&paint, 0); + + // We do this before converting to scalar, so we don't overflow SkFixed + startAngle = fastMod(startAngle, 360); + angleSpan = fastMod(angleSpan, 360); + + path.addArc(oval, SkIntToScalar(-startAngle), SkIntToScalar(-angleSpan)); + mCanvas->drawPath(path, paint); +} + +void PlatformGraphicsContext::strokePath(const Path& pathToStroke) +{ + const SkPath* path = pathToStroke.platformPath(); + if (!path) + return; + + SkPaint paint; + setupPaintStroke(&paint, 0); + + mCanvas->drawPath(*path, paint); +} + +void PlatformGraphicsContext::strokeRect(const FloatRect& rect, float lineWidth) +{ + SkPaint paint; + + setupPaintStroke(&paint, 0); + paint.setStrokeWidth(SkFloatToScalar(lineWidth)); + mCanvas->drawRect(rect, paint); +} + } // WebCore diff --git a/Source/WebCore/platform/graphics/android/PlatformGraphicsContext.h b/Source/WebCore/platform/graphics/android/PlatformGraphicsContext.h index d22dbd8..ce126a4 100644 --- a/Source/WebCore/platform/graphics/android/PlatformGraphicsContext.h +++ b/Source/WebCore/platform/graphics/android/PlatformGraphicsContext.h @@ -27,31 +27,123 @@ #define platform_graphics_context_h #include "IntRect.h" +#include "GraphicsContext.h" #include "RenderSkinAndroid.h" -#include "RenderSkinButton.h" #include "SkCanvas.h" #include "SkPicture.h" #include "SkTDArray.h" +#include <wtf/Vector.h> class SkCanvas; namespace WebCore { - - class GraphicsContext; class PlatformGraphicsContext { public: - PlatformGraphicsContext(); - // Pass in a recording canvas, and an array of button information to be - // updated. - PlatformGraphicsContext(SkCanvas* canvas); + PlatformGraphicsContext(SkCanvas* canvas, bool takeCanvasOwnership = false); ~PlatformGraphicsContext(); - + + void setGraphicsContext(GraphicsContext* gc) { m_gc = gc; } + + // FIXME: Make mCanvas private SkCanvas* mCanvas; - + // FIXME: This is used by ImageBufferAndroid, which should really be + // managing the canvas lifecycle itself bool deleteUs() const { return m_deleteCanvas; } + + // State management + void beginTransparencyLayer(float opacity); + void endTransparencyLayer(); + void save(); + void restore(); + + // State values + void setAlpha(float alpha); + void setCompositeOperation(CompositeOperator op); + void setFillColor(const Color& c); + void setFillShader(SkShader* fillShader); + void setLineCap(LineCap cap); + void setLineDash(const DashArray& dashes, float dashOffset); + void setLineJoin(LineJoin join); + void setMiterLimit(float limit); + void setShadow(int radius, int dx, int dy, SkColor c); + void setShouldAntialias(bool useAA); + void setStrokeColor(const Color& c); + void setStrokeShader(SkShader* strokeShader); + void setStrokeStyle(StrokeStyle style); + void setStrokeThickness(float f); + + // FIXME: These setupPaint* should be private, but + // they are used by FontAndroid currently + void setupPaintFill(SkPaint* paint) const; + bool setupPaintShadow(SkPaint* paint, SkPoint* offset) const; + // Sets up the paint for stroking. Returns true if the style is really + // just a dash of squares (the size of the paint's stroke-width. + bool setupPaintStroke(SkPaint* paint, SkRect* rect, bool isHLine = false); + + // Matrix operations + void concatCTM(const AffineTransform& affine); + void rotate(float angleInRadians); + void scale(const FloatSize& size); + void translate(float x, float y); + const SkMatrix& getTotalMatrix() { return mCanvas->getTotalMatrix(); } + + // Clipping + void addInnerRoundedRectClip(const IntRect& rect, int thickness); + void canvasClip(const Path& path); + void clip(const FloatRect& rect); + void clip(const Path& path); + void clipConvexPolygon(size_t numPoints, const FloatPoint*, bool antialias); + void clipOut(const IntRect& r); + void clipOut(const Path& p); + void clipPath(const Path& pathToClip, WindRule clipRule); + + // Drawing + void clearRect(const FloatRect& rect); + void drawBitmapPattern(const SkBitmap& bitmap, const SkMatrix& matrix, + CompositeOperator compositeOp, const FloatRect& destRect); + void drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src, + const SkRect& dst, CompositeOperator op); + void drawConvexPolygon(size_t numPoints, const FloatPoint* points, + bool shouldAntialias); + void drawEllipse(const IntRect& rect); + void drawFocusRing(const Vector<IntRect>& rects, int /* width */, + int /* offset */, const Color& color); + void drawHighlightForText(const Font& font, const TextRun& run, + const FloatPoint& point, int h, + const Color& backgroundColor, ColorSpace colorSpace, + int from, int to, bool isActive); + void drawLine(const IntPoint& point1, const IntPoint& point2); + void drawLineForText(const FloatPoint& pt, float width); + void drawLineForTextChecking(const FloatPoint& pt, float width, + GraphicsContext::TextCheckingLineStyle); + void drawRect(const IntRect& rect); + void fillPath(const Path& pathToFill, WindRule fillRule); + void fillRect(const FloatRect& rect); + void fillRect(const FloatRect& rect, const Color& color, ColorSpace); + void fillRoundedRect(const IntRect& rect, const IntSize& topLeft, + const IntSize& topRight, const IntSize& bottomLeft, + const IntSize& bottomRight, const Color& color, + ColorSpace); + void strokeArc(const IntRect& r, int startAngle, int angleSpan); + void strokePath(const Path& pathToStroke); + void strokeRect(const FloatRect& rect, float lineWidth); + private: - bool m_deleteCanvas; + + // shadowsIgnoreTransforms is only true for canvas's ImageBuffer, which will + // have a GraphicsContext + bool shadowsIgnoreTransforms() const { + return m_gc && m_gc->shadowsIgnoreTransforms(); + } + + void setupPaintCommon(SkPaint* paint) const; + + bool m_deleteCanvas; + struct State; + WTF::Vector<State> m_stateStack; + State* m_state; + GraphicsContext* m_gc; // Back-ptr to our parent }; } diff --git a/Source/WebCore/platform/graphics/android/QueuedOperation.h b/Source/WebCore/platform/graphics/android/QueuedOperation.h index 1a83f65..f98efcd 100644 --- a/Source/WebCore/platform/graphics/android/QueuedOperation.h +++ b/Source/WebCore/platform/graphics/android/QueuedOperation.h @@ -28,23 +28,12 @@ namespace WebCore { -class TiledPage; - class QueuedOperation { public: - enum OperationType { Undefined, PaintTile, PaintLayer, DeleteTexture }; - QueuedOperation(OperationType type, TiledPage* page) - : m_type(type) - , 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; + virtual int priority() = 0; }; class OperationFilter { @@ -53,33 +42,6 @@ public: virtual bool check(QueuedOperation* operation) = 0; }; -class PageFilter : public OperationFilter { -public: - PageFilter(TiledPage* page) : m_page(page) {} - virtual bool check(QueuedOperation* operation) - { - if (operation->page() == m_page) - return true; - return false; - } -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 0c92de4..a012c8b 100644 --- a/Source/WebCore/platform/graphics/android/RasterRenderer.cpp +++ b/Source/WebCore/platform/graphics/android/RasterRenderer.cpp @@ -23,12 +23,15 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#define LOG_TAG "RasterRenderer" +#define LOG_NDEBUG 1 #include "config.h" #include "RasterRenderer.h" #if USE(ACCELERATED_COMPOSITING) +#include "AndroidLog.h" #include "GLUtils.h" #include "SkBitmap.h" #include "SkBitmapRef.h" @@ -36,35 +39,8 @@ #include "SkDevice.h" #include "TilesManager.h" -#include <wtf/text/CString.h> - -#ifdef DEBUG - -#include <cutils/log.h> -#include <wtf/CurrentTime.h> - -#undef XLOG -#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "RasterRenderer", __VA_ARGS__) - -#else - -#undef XLOG -#define XLOG(...) - -#endif // DEBUG - namespace WebCore { -static const String TAG_CREATE_BITMAP = "create_bitmap"; -static const String TAG_DRAW_PICTURE = "draw_picture"; -static const String TAG_UPDATE_TEXTURE = "update_texture"; -#define TAG_COUNT 3 -static const String TAGS[] = { - TAG_CREATE_BITMAP, - TAG_DRAW_PICTURE, - TAG_UPDATE_TEXTURE, -}; - SkBitmap* RasterRenderer::g_bitmap = 0; RasterRenderer::RasterRenderer() : BaseRenderer(BaseRenderer::Raster) @@ -90,51 +66,47 @@ RasterRenderer::~RasterRenderer() void RasterRenderer::setupCanvas(const TileRenderInfo& renderInfo, SkCanvas* canvas) { - if (renderInfo.measurePerf) - m_perfMon.start(TAG_CREATE_BITMAP); - if (renderInfo.baseTile->isLayerTile()) { g_bitmap->setIsOpaque(false); g_bitmap->eraseARGB(0, 0, 0, 0); } else { - g_bitmap->setIsOpaque(true); - g_bitmap->eraseARGB(255, 255, 255, 255); + Color defaultBackground = Color::white; + Color* background = renderInfo.tilePainter->background(); + if (!background) { + ALOGV("No background color for base layer!"); + background = &defaultBackground; + } + ALOGV("setupCanvas use background on Base Layer %x", background->rgb()); + g_bitmap->setIsOpaque(!background->hasAlpha()); + g_bitmap->eraseARGB(background->alpha(), background->red(), + background->green(), background->blue()); } - SkDevice* device = new SkDevice(NULL, *g_bitmap, false); - - if (renderInfo.measurePerf) { - m_perfMon.stop(TAG_CREATE_BITMAP); - m_perfMon.start(TAG_DRAW_PICTURE); - } + SkDevice* device = new SkDevice(*g_bitmap); canvas->setDevice(device); 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) { - if (renderInfo.measurePerf) { - m_perfMon.stop(TAG_DRAW_PICTURE); - m_perfMon.start(TAG_UPDATE_TEXTURE); - } - const SkBitmap& bitmap = canvas->getDevice()->accessBitmap(false); - GLUtils::paintTextureWithBitmap(&renderInfo, bitmap); - - if (renderInfo.measurePerf) - m_perfMon.stop(TAG_UPDATE_TEXTURE); } -const String* RasterRenderer::getPerformanceTags(int& tagCount) +void RasterRenderer::checkForPureColor(TileRenderInfo& renderInfo, SkCanvas* canvas) { - tagCount = TAG_COUNT; - return TAGS; + renderInfo.isPureColor = GLUtils::isPureColorBitmap(*g_bitmap, renderInfo.pureColor); } } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/RasterRenderer.h b/Source/WebCore/platform/graphics/android/RasterRenderer.h index 96b3f58..39e00f2 100644 --- a/Source/WebCore/platform/graphics/android/RasterRenderer.h +++ b/Source/WebCore/platform/graphics/android/RasterRenderer.h @@ -49,7 +49,7 @@ protected: virtual void setupCanvas(const TileRenderInfo& renderInfo, SkCanvas* canvas); virtual void renderingComplete(const TileRenderInfo& renderInfo, SkCanvas* canvas); - virtual const String* getPerformanceTags(int& tagCount); + virtual void checkForPureColor(TileRenderInfo& renderInfo, SkCanvas* canvas); private: static SkBitmap* g_bitmap; diff --git a/Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.cpp index 3c2ced5..f28c31d 100644 --- a/Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.cpp @@ -1,3 +1,6 @@ +#define LOG_TAG "ScrollableLayerAndroid" +#define LOG_NDEBUG 1 + #include "config.h" #include "ScrollableLayerAndroid.h" @@ -5,31 +8,40 @@ #if USE(ACCELERATED_COMPOSITING) +#include "AndroidLog.h" + 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..257e68f 100644 --- a/Source/WebCore/platform/graphics/android/ShaderProgram.cpp +++ b/Source/WebCore/platform/graphics/android/ShaderProgram.cpp @@ -23,23 +23,21 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#define LOG_TAG "ShaderProgram" +#define LOG_NDEBUG 1 + #include "config.h" #include "ShaderProgram.h" #if USE(ACCELERATED_COMPOSITING) +#include "AndroidLog.h" #include "FloatPoint3D.h" #include "GLUtils.h" #include "TilesManager.h" #include <GLES2/gl2.h> #include <GLES2/gl2ext.h> -#include <cutils/log.h> -#include <wtf/CurrentTime.h> -#include <wtf/text/CString.h> - -#undef XLOG -#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "ShaderProgram", __VA_ARGS__) namespace WebCore { @@ -62,6 +60,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 +158,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); + ALOGE("could not compile shader %d:\n%s\n", shaderType, buf); free(buf); } glDeleteShader(shader); @@ -151,17 +169,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!"); + ALOGE("couldn't load the vertex shader!"); return -1; } GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pFragmentSource); if (!pixelShader) { - XLOG("couldn't load the pixel shader!"); + ALOGE("couldn't load the pixel shader!"); return -1; } @@ -181,7 +199,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); + ALOGE("could not link program:\n%s\n", buf); free(buf); } } @@ -189,6 +207,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 +218,101 @@ ShaderProgram::ShaderProgram() , m_contrast(1) , m_alphaLayer(false) , m_currentScale(1.0f) + , m_needsInit(true) { - init(); } -void ShaderProgram::init() +void ShaderProgram::cleanupGLResources() { - m_program = createProgram(gVertexShader, gFragmentShader); - m_programInverted = createProgram(gVertexShader, gFragmentShaderInverted); - m_videoProgram = createProgram(gVideoVertexShader, gVideoFragmentShader); - m_surfTexOESProgram = + 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() +{ + // 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 +325,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 +360,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 +438,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 || pureColor.hasAlpha()); + drawQuadInternal(type, finalMatrix, textureId, opacity, textureTarget, + texFilter, pureColor); + } + GLUtils::checkGlError("drawQuad"); } // This function transform a clip rect extracted from the current layer @@ -465,24 +553,15 @@ 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) { if (clip == m_clipRect) return; + ALOGV("--clipping rect %f %f, %f x %f", + clip.x(), clip.y(), clip.width(), clip.height()); + // we should only call glScissor in this function, so that we can easily // track the current clipping rect. @@ -530,40 +609,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 +662,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 +687,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 +696,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..78c3fbb --- /dev/null +++ b/Source/WebCore/platform/graphics/android/SurfaceCollection.cpp @@ -0,0 +1,218 @@ +/* + * 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. + */ + +#define LOG_TAG "SurfaceCollection" +#define LOG_NDEBUG 1 + +#include "config.h" +#include "SurfaceCollection.h" + +#include "AndroidLog.h" +#include "BaseLayerAndroid.h" +#include "ClassTracker.h" +#include "GLWebViewState.h" +#include "LayerAndroid.h" +#include "LayerGroup.h" +#include "ScrollableLayerAndroid.h" +#include "TilesManager.h" + +namespace WebCore { + +//////////////////////////////////////////////////////////////////////////////// +// TILED PAINTING / GROUPS // +//////////////////////////////////////////////////////////////////////////////// + +SurfaceCollection::SurfaceCollection(LayerAndroid* layer) + : m_compositedRoot(layer) +{ + // layer must be non-null. + SkSafeRef(m_compositedRoot); + + // calculate draw transforms and z values + SkRect visibleRect = SkRect::MakeLTRB(0, 0, 1, 1); + m_compositedRoot->updateLayerPositions(visibleRect); + // TODO: updateGLPositionsAndScale? + + // allocate groups for layers, merging where possible + ALOGV("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); + if (m_layerGroups[i]->isBase()) + m_layerGroups[i]->setBackground(getBackground()); + } + +#ifdef DEBUG_COUNT + ClassTracker::instance()->increment("SurfaceCollection"); +#endif +} + +SurfaceCollection::~SurfaceCollection() +{ + SkSafeUnref(m_compositedRoot); + 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) +{ + 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) +{ +#ifdef DEBUG_COUNT + ClassTracker::instance()->show(); +#endif + + bool needsRedraw = false; + 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; +} + +Color SurfaceCollection::getBackground() +{ + return static_cast<BaseLayerAndroid*>(m_compositedRoot)->getBackgroundColor(); +} + +void SurfaceCollection::swapTiles() +{ + for (unsigned int i = 0; i < m_layerGroups.size(); i++) + m_layerGroups[i]->swapTiles(); +} + +bool SurfaceCollection::isReady() +{ + // 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()) { + ALOGV("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); +} + +//////////////////////////////////////////////////////////////////////////////// +// RECURSIVE ANIMATION / INVALS / LAYERS // +//////////////////////////////////////////////////////////////////////////////// + +void SurfaceCollection::setIsPainting(SurfaceCollection* drawingSurface) +{ + 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() +{ + m_compositedRoot->initAnimations(); +} + +void SurfaceCollection::mergeInvalsInto(SurfaceCollection* replacementSurface) +{ + m_compositedRoot->mergeInvalsInto(replacementSurface->m_compositedRoot); +} + +void SurfaceCollection::evaluateAnimations(double currentTime) +{ + m_compositedRoot->evaluateAnimations(currentTime); +} + +bool SurfaceCollection::hasCompositedLayers() +{ + return m_compositedRoot->countChildren(); +} + +bool SurfaceCollection::hasCompositedAnimations() +{ + return m_compositedRoot->hasAnimations(); +} + +void SurfaceCollection::updateScrollableLayer(int layerId, int x, int y) +{ + LayerAndroid* layer = m_compositedRoot->findById(layerId); + if (layer && layer->contentIsScrollable()) + static_cast<ScrollableLayerAndroid*>(layer)->scrollTo(x, y); +} + +void SurfaceCollection::updateLayerPositions(const SkRect& visibleRect) +{ + TransformationMatrix ident; + m_compositedRoot->updateLayerPositions(visibleRect); + FloatRect clip(0, 0, 1e10, 1e10); + m_compositedRoot->updateGLPositionsAndScale( + ident, clip, 1, m_compositedRoot->state()->scale()); + +#ifdef DEBUG + m_compositedRoot->showLayer(0); + ALOGV("We have %d layers, %d textured", + m_compositedRoot->nbLayers(), + m_compositedRoot->nbTexturedLayers()); +#endif +} + +} // 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..e73ec9a --- /dev/null +++ b/Source/WebCore/platform/graphics/android/SurfaceCollection.h @@ -0,0 +1,75 @@ +/* + * 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 "Color.h" +#include "SkRect.h" +#include "SkRefCnt.h" +#include "Vector.h" + +class SkCanvas; +class SkRegion; + +namespace WebCore { + +class LayerAndroid; +class LayerGroup; +class TexturesResult; + +class SurfaceCollection : public SkRefCnt { +// TODO: investigate webkit threadsafe ref counting +public: + SurfaceCollection(LayerAndroid* compositedRoot); + virtual ~SurfaceCollection(); + + // Tiled painting methods (executed on groups) + void prepareGL(const SkRect& visibleRect); + bool drawGL(const SkRect& visibleRect); + Color getBackground(); + void swapTiles(); + bool isReady(); + void computeTexturesAmount(TexturesResult* result); + + // Recursive tree methods (animations, invals, etc) + void setIsPainting(SurfaceCollection* drawingSurfaceCollection); + void setIsDrawing(); + void mergeInvalsInto(SurfaceCollection* replacementSurfaceCollection); + void evaluateAnimations(double currentTime); + + bool hasCompositedLayers(); + bool hasCompositedAnimations(); + void updateScrollableLayer(int layerId, int x, int y); + +private: + void updateLayerPositions(const SkRect& visibleRect); + 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..c3c4bda --- /dev/null +++ b/Source/WebCore/platform/graphics/android/SurfaceCollectionManager.cpp @@ -0,0 +1,245 @@ +/* + * 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. + */ + +#define LOG_TAG "SurfaceCollectionManager" +#define LOG_NDEBUG 1 + +#include "config.h" +#include "SurfaceCollectionManager.h" + +#include "AndroidLog.h" +#include "LayerGroup.h" +#include "TilesManager.h" +#include "SurfaceCollection.h" + +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); + + ALOGV("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) { + ALOGV("destroying drawing collection %p", m_drawingCollection); + SkSafeUnref(m_drawingCollection); + } + + // painting collection becomes the drawing collection + ALOGV("drawing collection %p", m_paintingCollection); + m_paintingCollection->setIsDrawing(); // initialize animations + + if (m_queuedCollection) { + // start painting with the queued collection + ALOGV("now painting collection %p", m_queuedCollection); + m_queuedCollection->setIsPainting(m_paintingCollection); + } + m_drawingCollection = m_paintingCollection; + m_paintingCollection = m_queuedCollection; + m_queuedCollection = 0; + + ALOGV("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() +{ + ALOGV("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) +{ + // 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; + } + + ALOGV("updateWithSurfaceCollection - %p, has children %d, has animations %d", + newCollection, newCollection->hasCompositedLayers(), + newCollection->hasCompositedAnimations()); + + 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(); + } + + ALOGV("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_paintingCollection && 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; + + ALOGV("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) { + ALOGV("preparing painting collection %p", m_paintingCollection); + + m_paintingCollection->evaluateAnimations(currentTime); + + m_paintingCollection->prepareGL(visibleRect); + m_paintingCollection->computeTexturesAmount(texturesResultPtr); + + if (!TilesManager::instance()->useDoubleBuffering() || m_paintingCollection->isReady()) { + ALOGV("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) { + ALOGV("preparing drawing collection %p", m_drawingCollection); + m_drawingCollection->prepareGL(visibleRect); + m_drawingCollection->computeTexturesAmount(texturesResultPtr); + } + + // Don't have a drawing collection, draw white background + Color background = Color::white; + 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); + + ALOGV("drawing collection %p", m_drawingCollection); + background = m_drawingCollection->getBackground(); + } else if (m_paintingCollection) { + // Use paintingCollection background color while tiles are not done painting. + background = m_paintingCollection->getBackground(); + } + + // Start doing the actual GL drawing. + ALOGV("background is %x", background.rgb()); + // If background is opaque, we can safely and efficiently clear it here. + // Otherwise, we have to calculate all the missing tiles and blend the background. + GLUtils::clearBackgroundIfOpaque(&background); + if (m_drawingCollection) + ret |= m_drawingCollection->drawGL(visibleRect); + + if (m_paintingCollection) { + ALOGV("still have painting collection %p", m_paintingCollection); + return true; + } + + return ret; +} + +} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/TreeManager.h b/Source/WebCore/platform/graphics/android/SurfaceCollectionManager.h index 83d5300..304d57f 100644 --- a/Source/WebCore/platform/graphics/android/TreeManager.h +++ b/Source/WebCore/platform/graphics/android/SurfaceCollectionManager.h @@ -23,61 +23,52 @@ * 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 5356dcb..f5c8b02 100644 --- a/Source/WebCore/platform/graphics/android/TextureInfo.cpp +++ b/Source/WebCore/platform/graphics/android/TextureInfo.cpp @@ -35,15 +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_eglSurface = EGL_NO_SURFACE; - 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 1c48937..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,39 +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 - // TODO: Delete this after the Ganesh code path get fixed. - sp<ANativeWindow> m_ANW; - // The EGLSurface wraps the m_ANW to enable direct OpenGL rendering (e.g. Ganesh) - EGLSurface m_eglSurface; - - int m_pictureCount; -private: - SharedTextureMode m_sharedTextureMode; }; } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/TextureOwner.h b/Source/WebCore/platform/graphics/android/TextureOwner.h index 5434dbf..4f9e6ef 100644 --- a/Source/WebCore/platform/graphics/android/TextureOwner.h +++ b/Source/WebCore/platform/graphics/android/TextureOwner.h @@ -31,7 +31,6 @@ class Layer; namespace WebCore { -class TiledPage; class BaseTileTexture; class GLWebViewState; @@ -39,8 +38,6 @@ class TextureOwner { public: virtual ~TextureOwner() { } virtual bool removeTexture(BaseTileTexture* texture) = 0; - virtual TiledPage* page() = 0; - virtual GLWebViewState* state() = 0; virtual bool samePageAs(Layer* root) { return false; } virtual bool isRepaintPending() = 0; virtual unsigned long long drawCount() = 0; diff --git a/Source/WebCore/platform/graphics/android/TexturesGenerator.cpp b/Source/WebCore/platform/graphics/android/TexturesGenerator.cpp index bccb99b..3279ec2 100644 --- a/Source/WebCore/platform/graphics/android/TexturesGenerator.cpp +++ b/Source/WebCore/platform/graphics/android/TexturesGenerator.cpp @@ -23,32 +23,19 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#define LOG_TAG "TexturesGenerator" +#define LOG_NDEBUG 1 + #include "config.h" #include "TexturesGenerator.h" #if USE(ACCELERATED_COMPOSITING) -#include "BaseLayerAndroid.h" +#include "AndroidLog.h" #include "GLUtils.h" #include "PaintTileOperation.h" #include "TilesManager.h" -#ifdef DEBUG - -#include <cutils/log.h> -#include <wtf/CurrentTime.h> -#include <wtf/text/CString.h> - -#undef XLOG -#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "TexturesGenerator", __VA_ARGS__) - -#else - -#undef XLOG -#define XLOG(...) - -#endif // DEBUG - namespace WebCore { void TexturesGenerator::scheduleOperation(QueuedOperation* operation) @@ -60,21 +47,6 @@ void TexturesGenerator::scheduleOperation(QueuedOperation* operation) mRequestedOperationsCond.signal(); } -void TexturesGenerator::removeOperationsForPage(TiledPage* page) -{ - removeOperationsForFilter(new PageFilter(page)); -} - -void TexturesGenerator::removePaintOperationsForPage(TiledPage* page, bool waitForRunning) -{ - removeOperationsForFilter(new PagePaintFilter(page), waitForRunning); -} - -void TexturesGenerator::removeOperationsForFilter(OperationFilter* filter) -{ - removeOperationsForFilter(filter, true); -} - void TexturesGenerator::removeOperationsForFilter(OperationFilter* filter, bool waitForRunning) { if (!filter) @@ -104,7 +76,7 @@ void TexturesGenerator::removeOperationsForFilter(OperationFilter* filter, bool // The solution is use this as a flag to tell Tex Gen thread that // UI thread is waiting now, Tex Gen thread should not wait for the // queue any more. - TilesManager::instance()->transferQueue()->interruptTransferQueue(true); + m_tilesManager->transferQueue()->interruptTransferQueue(true); } delete filter; @@ -122,8 +94,7 @@ void TexturesGenerator::removeOperationsForFilter(OperationFilter* filter, bool status_t TexturesGenerator::readyToRun() { - TilesManager::instance()->markGeneratorAsReady(); - XLOG("Thread ready to run"); + ALOGV("Thread ready to run"); return NO_ERROR; } @@ -167,20 +138,21 @@ bool TexturesGenerator::threadLoop() while (!mRequestedOperations.size()) mRequestedOperationsCond.wait(mRequestedOperationsLock); - XLOG("threadLoop, got signal"); + ALOGV("threadLoop, got signal"); mRequestedOperationsLock.unlock(); m_currentOperation = 0; bool stop = false; while (!stop) { mRequestedOperationsLock.lock(); - XLOG("threadLoop, %d operations in the queue", mRequestedOperations.size()); + ALOGV("threadLoop, %d operations in the queue", mRequestedOperations.size()); if (mRequestedOperations.size()) m_currentOperation = popNext(); mRequestedOperationsLock.unlock(); if (m_currentOperation) { - XLOG("threadLoop, painting the request with priority %d", m_currentOperation->priority()); + ALOGV("threadLoop, painting the request with priority %d", + m_currentOperation->priority()); m_currentOperation->run(); } @@ -192,14 +164,14 @@ bool TexturesGenerator::threadLoop() stop = true; if (m_waitForCompletion) { m_waitForCompletion = false; - TilesManager::instance()->transferQueue()->interruptTransferQueue(false); + m_tilesManager->transferQueue()->interruptTransferQueue(false); mRequestedOperationsCond.signal(); } mRequestedOperationsLock.unlock(); if (oldOperation) delete oldOperation; // delete outside lock } - XLOG("threadLoop empty"); + ALOGV("threadLoop empty"); return true; } diff --git a/Source/WebCore/platform/graphics/android/TexturesGenerator.h b/Source/WebCore/platform/graphics/android/TexturesGenerator.h index 2e3b6b4..35a3386 100644 --- a/Source/WebCore/platform/graphics/android/TexturesGenerator.h +++ b/Source/WebCore/platform/graphics/android/TexturesGenerator.h @@ -29,29 +29,27 @@ #if USE(ACCELERATED_COMPOSITING) #include "QueuedOperation.h" -#include "TiledPage.h" #include "TilePainter.h" +#include "Vector.h" + #include <utils/threads.h> namespace WebCore { using namespace android; -class BaseLayerAndroid; -class LayerAndroid; +class TilesManager; class TexturesGenerator : public Thread { public: - TexturesGenerator() : Thread(false) + TexturesGenerator(TilesManager* instance) : Thread(false) , m_waitForCompletion(false) - , m_currentOperation(0) { } + , m_currentOperation(0) + , m_tilesManager(instance) { } virtual ~TexturesGenerator() { } virtual status_t readyToRun(); - void removeOperationsForPage(TiledPage* page); - void removePaintOperationsForPage(TiledPage* page, bool waitForRunning); - void removeOperationsForFilter(OperationFilter* filter); - void removeOperationsForFilter(OperationFilter* filter, bool waitForRunning); + void removeOperationsForFilter(OperationFilter* filter, bool waitForRunning = true); void scheduleOperation(QueuedOperation* operation); @@ -63,6 +61,7 @@ private: android::Condition mRequestedOperationsCond; bool m_waitForCompletion; QueuedOperation* m_currentOperation; + TilesManager* m_tilesManager; }; } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/TilePainter.h b/Source/WebCore/platform/graphics/android/TilePainter.h index 4d0f5dc..a5dafa9 100644 --- a/Source/WebCore/platform/graphics/android/TilePainter.h +++ b/Source/WebCore/platform/graphics/android/TilePainter.h @@ -34,21 +34,23 @@ class SkCanvas; namespace WebCore { class BaseTile; +class Color; -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; } -}; - -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; } + 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; } + virtual Color* background() { return 0; } + + 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 deleted file mode 100644 index 31a0593..0000000 --- a/Source/WebCore/platform/graphics/android/TiledPage.cpp +++ /dev/null @@ -1,413 +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 "TiledPage.h" - -#if USE(ACCELERATED_COMPOSITING) - -#include "GLUtils.h" -#include "IntRect.h" -#include "PaintTileOperation.h" -#include "SkPaint.h" -#include "SkPaintFlagsDrawFilter.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, "TiledPage", __VA_ARGS__) - -#ifdef DEBUG - -#undef XLOG -#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "TiledPage", __VA_ARGS__) - -#else - -#undef XLOG -#define XLOG(...) - -#endif // DEBUG - -namespace WebCore { - -using namespace android; - -TiledPage::TiledPage(int id, GLWebViewState* state) - : m_baseTiles(0) - , m_baseTileSize(0) - , m_id(id) - , m_scale(1) - , m_invScale(1) - , m_glWebViewState(state) - , m_latestPictureInval(0) - , m_prepare(false) - , m_isPrefetchPage(false) - , m_willDraw(false) -{ - m_baseTiles = new BaseTile[TilesManager::getMaxTextureAllocation() + 1]; -#ifdef DEBUG_COUNT - ClassTracker::instance()->increment("TiledPage"); -#endif -} - -void TiledPage::updateBaseTileSize() -{ - // This value must be at least 1 greater than the max number of allowed - // textures. This is because prepare() asks for a tile before it reserves - // a texture for that tile. If all textures are currently in use by the - // page then there will be no available tile and having the extra tile - // ensures that this does not happen. After claiming the extra tile the call - // to reserveTexture() will cause some other tile in the page to lose it's - // texture and become available, thus ensuring that we always have at least - // one tile that is available. - int baseTileSize = TilesManager::instance()->maxTextureCount() + 1; - if (baseTileSize > m_baseTileSize) - m_baseTileSize = baseTileSize; -} - -TiledPage::~TiledPage() -{ - // 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); - delete[] m_baseTiles; -#ifdef DEBUG_COUNT - ClassTracker::instance()->decrement("TiledPage"); -#endif -} - -BaseTile* TiledPage::getBaseTile(int x, int y) const -{ - // TODO: replace loop over array with HashMap indexing - for (int j = 0; j < m_baseTileSize; j++) { - BaseTile& tile = m_baseTiles[j]; - if (tile.x() == x && tile.y() == y) - return &tile; - } - return 0; -} - -void TiledPage::discardTextures() -{ - for (int j = 0; j < m_baseTileSize; j++) { - BaseTile& tile = m_baseTiles[j]; - tile.discardTextures(); - } - return; -} - -void TiledPage::invalidateRect(const IntRect& inval, const unsigned int pictureCount) -{ - // 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(); - - const int firstDirtyTileX = static_cast<int>(floorf(inval.x() * invTileContentWidth)); - const int firstDirtyTileY = static_cast<int>(floorf(inval.y() * invTileContentHeight)); - const int lastDirtyTileX = static_cast<int>(ceilf(inval.maxX() * invTileContentWidth)); - const int lastDirtyTileY = static_cast<int>(ceilf(inval.maxY() * invTileContentHeight)); - - XLOG("Marking X %d-%d and Y %d-%d dirty", firstDirtyTileX, lastDirtyTileX, firstDirtyTileY, lastDirtyTileY); - // 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; -} - -void TiledPage::prepareRow(bool goingLeft, int tilesInRow, int firstTileX, int y, const SkIRect& tileBounds) -{ - for (int i = 0; i < tilesInRow; i++) { - int x = firstTileX; - - // If we are goingLeft, we want to schedule the tiles starting from the - // right (and to the left if not). This is because tiles are appended to - // the list and the texture uploader goes through the set front to back. - if (goingLeft) - x += (tilesInRow - 1) - i; - else - x += i; - - BaseTile* currentTile = 0; - BaseTile* availableTile = 0; - for (int j = 0; j < m_baseTileSize; j++) { - BaseTile& tile = m_baseTiles[j]; - if (tile.x() == x && tile.y() == y) { - currentTile = &tile; - break; - } - - if (!availableTile || (tile.drawCount() < availableTile->drawCount())) - availableTile = &tile; - } - - if (!currentTile && availableTile) { - XLOG("STEALING tile %d, %d (draw count %llu) for tile %d, %d", - availableTile->x(), availableTile->y(), availableTile->drawCount(), x, y); - availableTile->discardTextures(); // don't wait for textures to be stolen - currentTile = availableTile; - } - - if (!currentTile) { - XLOG("ERROR: No tile available for tile %d %d", x, y); - } - - if (currentTile) { - currentTile->setGLWebViewState(m_glWebViewState); - currentTile->setPage(this); - - currentTile->setContents(this, x, y, m_scale); - - // TODO: move below (which is largely the same for layers / tiled - // page) into prepare() function - - // ensure there is a texture associated with the tile and then check to - // see if the texture is dirty and in need of repainting - if (currentTile->isDirty() || !currentTile->frontTexture()) - currentTile->reserveTexture(); - if (currentTile->backTexture() - && currentTile->isDirty() - && !currentTile->isRepaintPending()) { - PaintTileOperation *operation = new PaintTileOperation(currentTile); - TilesManager::instance()->scheduleOperation(operation); - } - } - } -} - -bool TiledPage::updateTileDirtiness(const SkIRect& tileBounds) -{ - if (!m_glWebViewState || tileBounds.isEmpty()) { - m_invalRegion.setEmpty(); - m_invalTilesRegion.setEmpty(); - return false; - } - - bool visibleTileIsDirty = false; - for (int x = 0; x < m_baseTileSize; x++) { - - 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; - } - } - - // 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) -{ - if (!m_glWebViewState) - return; - - TilesManager::instance()->gatherTextures(); - m_scrollingDown = goingDown; - - int firstTileX = tileBounds.fLeft; - int firstTileY = tileBounds.fTop; - 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(); - int expandY = m_glWebViewState->expandedTileBoundsY(); - - firstTileX -= expandX; - nbTilesWidth += expandX * 2; - - firstTileY -= expandY; - nbTilesHeight += expandY * 2; - } - - // crop the tile bounds in each dimension to the larger of the base layer or viewport - float maxBaseX = m_glWebViewState->baseContentWidth() * m_scale / TilesManager::tileWidth(); - float maxBaseY = m_glWebViewState->baseContentHeight() * m_scale / TilesManager::tileHeight(); - int maxX = std::max(static_cast<int>(ceilf(maxBaseX)), - m_glWebViewState->viewportTileBounds().width()); - int maxY = std::max(static_cast<int>(ceilf(maxBaseY)), - m_glWebViewState->viewportTileBounds().height()); - - // adjust perimeter to not go outside cropped region - if (firstTileX < 0) { - nbTilesWidth += firstTileX; - firstTileX = 0; - } - if (firstTileY < 0) { - nbTilesHeight += firstTileY; - firstTileY = 0; - } - nbTilesWidth = std::min(nbTilesWidth, maxX - firstTileX); - nbTilesHeight = std::min(nbTilesHeight, maxY - firstTileY); - - // check against corrupted scale values giving bad height/width (use float to avoid overflow) - float numTiles = static_cast<float>(nbTilesHeight) * static_cast<float>(nbTilesWidth); - if (numTiles > TilesManager::getMaxTextureAllocation() || nbTilesHeight < 1 || nbTilesWidth < 1) - { - XLOGC("ERROR: We don't have enough tiles for this page!" - " nbTilesHeight %d nbTilesWidth %d", nbTilesHeight, nbTilesWidth); - return; - } - for (int i = 0; i < nbTilesHeight; i++) - prepareRow(goingLeft, nbTilesWidth, firstTileX, firstTileY + i, tileBounds); - - m_prepare = true; -} - -bool TiledPage::hasMissingContent(const SkIRect& tileBounds) -{ - int neededTiles = tileBounds.width() * tileBounds.height(); - for (int j = 0; j < m_baseTileSize; j++) { - BaseTile& tile = m_baseTiles[j]; - if (tileBounds.contains(tile.x(), tile.y())) { - if (tile.frontTexture()) - neededTiles--; - } - } - return neededTiles > 0; -} - -bool TiledPage::isReady(const SkIRect& tileBounds) -{ - int neededTiles = tileBounds.width() * tileBounds.height(); - XLOG("tiled page %p needs %d ready tiles", this, neededTiles); - for (int j = 0; j < m_baseTileSize; j++) { - BaseTile& tile = m_baseTiles[j]; - if (tileBounds.contains(tile.x(), tile.y())) { - if (tile.isTileReady()) - neededTiles--; - } - } - XLOG("tiled page %p still needs %d ready tiles", this, neededTiles); - return neededTiles == 0; -} - -bool TiledPage::swapBuffersIfReady(const SkIRect& tileBounds, float scale) -{ - if (!m_glWebViewState) - return false; - - if (!m_invalRegion.isEmpty() && !m_prepare) - return false; - - if (m_scale != scale) - return false; - - int swaps = 0; - bool fullSwap = true; - for (int x = tileBounds.fLeft; x < tileBounds.fRight; x++) { - for (int y = tileBounds.fTop; y < tileBounds.fBottom; y++) { - BaseTile* t = getBaseTile(x, y); - if (!t || !t->isTileReady()) - fullSwap = false; - } - } - - // swap every tile on page (even if off screen) - for (int j = 0; j < m_baseTileSize; j++) { - BaseTile& tile = m_baseTiles[j]; - if (tile.swapTexturesIfNeeded()) - swaps++; - } - - XLOG("%p greedy swapped %d textures, returning true", this, swaps); - return fullSwap; -} - -void TiledPage::prepareForDrawGL(float transparency, const SkIRect& tileBounds) -{ - m_willDraw = true; - m_transparency = transparency; - m_tileBounds = tileBounds; -} - -void TiledPage::drawGL() -{ - if (!m_glWebViewState || m_transparency == 0 || !m_willDraw) - return; - - const float tileWidth = TilesManager::tileWidth() * m_invScale; - const float tileHeight = TilesManager::tileHeight() * m_invScale; - - for (int j = 0; j < m_baseTileSize; j++) { - BaseTile& tile = m_baseTiles[j]; - bool tileInView = m_tileBounds.contains(tile.x(), tile.y()); - if (tileInView) { - SkRect rect; - rect.fLeft = tile.x() * tileWidth; - rect.fTop = tile.y() * tileHeight; - rect.fRight = rect.fLeft + tileWidth; - rect.fBottom = rect.fTop + tileHeight; - - tile.draw(m_transparency, rect, m_scale); - } - - TilesManager::instance()->getProfiler()->nextTile(tile, m_invScale, tileInView); - } - m_willDraw = false; // don't redraw until re-prepared -} - -bool TiledPage::paint(BaseTile* tile, SkCanvas* canvas, unsigned int* pictureUsed) -{ - static SkPaintFlagsDrawFilter prefetchFilter(SkPaint::kAllFlags, - SkPaint::kAntiAlias_Flag); - - if (!m_glWebViewState) - return false; - - if (isPrefetchPage()) - canvas->setDrawFilter(&prefetchFilter); - - *pictureUsed = m_glWebViewState->paintBaseLayerContent(canvas); - return true; -} - -TiledPage* TiledPage::sibling() -{ - if (!m_glWebViewState) - return 0; - return m_glWebViewState->sibling(this); -} - -} // namespace WebCore - -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/TiledPage.h b/Source/WebCore/platform/graphics/android/TiledPage.h deleted file mode 100644 index 791e1f6..0000000 --- a/Source/WebCore/platform/graphics/android/TiledPage.h +++ /dev/null @@ -1,141 +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 TiledPage_h -#define TiledPage_h - -#if USE(ACCELERATED_COMPOSITING) - -#include "BaseTile.h" -#include "SkCanvas.h" -#include "SkRegion.h" - -#include "TilePainter.h" - -namespace WebCore { - -class GLWebViewState; -class IntRect; - -/** - * The TiledPage represents a map of BaseTiles covering the viewport. Each - * GLWebViewState contains two TiledPages, one to display the page at the - * current scale factor, and another in the background that we use to paint the - * page at a different scale factor. For instance, when we zoom using one - * TiledPage its tiles are scaled in hardware and therefore are subject to a - * loss of quality. To address this when the user finishes zooming we paint the - * background TilePage at the new scale factor. When the background TilePage is - * ready, we swap it with the currently displaying TiledPage. - */ -class TiledPage : public TilePainter { -public: - enum PrepareBounds { - ExpandedBounds = 0, - VisibleBounds = 1 - }; - - TiledPage(int id, GLWebViewState* state); - ~TiledPage(); - - // returns the other TiledPage who shares the same GLWebViewState - TiledPage* sibling(); - - // 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); - - // returns true if the page can't draw the entire region (may still be stale) - bool hasMissingContent(const SkIRect& tileBounds); - - bool isReady(const SkIRect& tileBounds); - - // 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); - // 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*); - - // used by individual tiles to get the information about the current picture - GLWebViewState* glWebViewState() { return m_glWebViewState; } - - float scale() const { return m_scale; } - - //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 discardTextures(); - void updateBaseTileSize(); - bool scrollingDown() { return m_scrollingDown; } - bool isPrefetchPage() { return m_isPrefetchPage; } - void setIsPrefetchPage(bool isPrefetch) { m_isPrefetchPage = isPrefetch; } - -private: - void prepareRow(bool goingLeft, int tilesInRow, int firstTileX, int y, const SkIRect& tileBounds); - - BaseTile* getBaseTile(int x, int y) const; - - // array of tiles used to compose a page. The tiles are allocated in the - // constructor to prevent them from potentially being allocated on the stack - BaseTile* m_baseTiles; - // stores the number of tiles in the m_baseTiles array. This enables us to - // quickly iterate over the array without have to check it's size - int m_baseTileSize; - int m_id; - float m_scale; - 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; - bool m_prepare; - bool m_scrollingDown; - bool m_isPrefetchPage; - - // info saved in prepare, used in drawGL() - bool m_willDraw; - SkIRect m_tileBounds; - float m_transparency; -}; - -} // namespace WebCore - -#endif // USE(ACCELERATED_COMPOSITING) -#endif // TiledPage_h diff --git a/Source/WebCore/platform/graphics/android/TiledTexture.cpp b/Source/WebCore/platform/graphics/android/TiledTexture.cpp index d538416..11cf906 100644 --- a/Source/WebCore/platform/graphics/android/TiledTexture.cpp +++ b/Source/WebCore/platform/graphics/android/TiledTexture.cpp @@ -23,48 +23,35 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#define LOG_TAG "TiledTexture" +#define LOG_NDEBUG 1 + #include "config.h" #include "TiledTexture.h" -#include "TilesManager.h" -#include "TilesTracker.h" - -#include "PaintedSurface.h" +#include "AndroidLog.h" #include "PaintTileOperation.h" #include "SkCanvas.h" #include "SkPicture.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, "TiledTexture", __VA_ARGS__) -#ifdef DEBUG - -#undef XLOG -#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "TiledTexture", __VA_ARGS__) - -#else - -#undef XLOG -#define XLOG(...) - -#endif // DEBUG +#define LOW_RES_PREFETCH_SCALE_MODIFIER 0.3f +#define EXPANDED_BOUNDS_INFLATE 1 +#define EXPANDED_PREFETCH_BOUNDS_Y_INFLATE 1 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; @@ -82,32 +69,40 @@ bool TiledTexture::ready() // in order to unblock the zooming process. // FIXME: have a better system -- maybe keeping the last scale factor // able to fully render everything - XLOG("TT %p, ready %d, visible %d, texturesRemain %d", - this, tilesAllReady, tilesVisible, - TilesManager::instance()->layerTexturesRemain()); + ALOGV("TT %p, ready %d, visible %d, texturesRemain %d", + this, tilesAllReady, tilesVisible, + TilesManager::instance()->layerTexturesRemain()); return !TilesManager::instance()->layerTexturesRemain() || !tilesVisible || tilesAllReady; } +bool TiledTexture::isMissingContent() +{ + for (unsigned int i = 0; i < m_tiles.size(); i++) + if (m_tiles[i]->isTileVisible(m_area) && !m_tiles[i]->frontTexture()) + return true; + return false; +} + void TiledTexture::swapTiles() { int swaps = 0; for (unsigned int i = 0; i < m_tiles.size(); i++) if (m_tiles[i]->swapTexturesIfNeeded()) swaps++; - XLOG("TT %p swapping, swaps = %d", this, swaps); + ALOGV("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()); + ALOGV("TT %p prepare, scale %f, area %d x %d", this, scale, area.width(), area.height()); if (area.width() == 0 && area.height() == 0) { computedArea.setWidth(0); @@ -115,8 +110,8 @@ IntRect TiledTexture::computeTilesArea(IntRect& visibleArea, float scale) return computedArea; } - int tileWidth = TilesManager::instance()->layerTileWidth(); - int tileHeight = TilesManager::instance()->layerTileHeight(); + int tileWidth = TilesManager::tileWidth(); + int tileHeight = TilesManager::tileHeight(); computedArea.setX(area.x() / tileWidth); computedArea.setY(area.y() / tileHeight); @@ -127,87 +122,111 @@ 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, const IntRect& unclippedArea, + TilePainter* painter, bool isLowResPrefetch, bool useExpandPrefetch) { - 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 " - " %d, %d - %d x %d, corresponding to %d, %d x - %d x %d tiles", - this, scale, - visibleArea.x(), visibleArea.y(), - visibleArea.width(), visibleArea.height(), - m_area.x(), m_area.y(), - m_area.width(), m_area.height()); + ALOGV("prepare TiledTexture %p with scale %.2f, prepareArea " + " %d, %d - %d x %d, corresponding to %d, %d x - %d x %d tiles", + this, scale, + prepareArea.x(), prepareArea.y(), + prepareArea.width(), prepareArea.height(), + m_area.x(), m_area.y(), + m_area.width(), m_area.height()); bool goingDown = m_prevTileY < m_area.y(); m_prevTileY = m_area.y(); if (scale != m_scale) - TilesManager::instance()->removeOperationsForFilter(new ScaleFilter(this, scale)); + TilesManager::instance()->removeOperationsForFilter(new ScaleFilter(painter, m_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); + + // log inval region for the base surface + if (m_isBaseSurface && TilesManager::instance()->getProfiler()->enabled()) { + SkRegion::Iterator iterator(m_dirtyRegion); + while (!iterator.done()) { + SkIRect r = iterator.rect(); + TilesManager::instance()->getProfiler()->nextInval(r, scale); + iterator.next(); + } } + m_dirtyRegion.setEmpty(); } - m_dirtyRegion.setEmpty(); + // prepare standard bounds (clearing ExpandPrefetch flag) 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, state, isLowResPrefetch, false); } 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, state, isLowResPrefetch, false); } } + + // prepare expanded bounds + if (useExpandPrefetch) { + IntRect fullArea = computeTilesArea(unclippedArea, scale); + IntRect expandedArea = m_area; + expandedArea.inflate(EXPANDED_BOUNDS_INFLATE); + + if (isLowResPrefetch) + expandedArea.inflate(EXPANDED_PREFETCH_BOUNDS_Y_INFLATE); + + // clip painting area to content + expandedArea.intersect(fullArea); + + for (int i = expandedArea.x(); i < expandedArea.maxX(); i++) + for (int j = expandedArea.y(); j < expandedArea.maxY(); j++) + if (!m_area.contains(i, j)) + prepareTile(i, j, painter, state, isLowResPrefetch, true); + } } -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); + ALOGV("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, + GLWebViewState* state, bool isLowResPrefetch, bool isExpandPrefetch) { BaseTile* tile = getTile(x, y); if (!tile) { - tile = new BaseTile(true); + bool isLayerTile = !m_isBaseSurface; + tile = new BaseTile(isLayerTile); 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); + ALOGV("preparing tile %p at %d, %d, painter is %p", tile, x, y, painter); + + tile->setContents(x, y, m_scale, isExpandPrefetch); // 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()) { + ALOGV("painting TT %p's tile %d %d for LG %p", this, x, y, painter); + PaintTileOperation *operation = new PaintTileOperation(tile, painter, + state, isLowResPrefetch); TilesManager::instance()->scheduleOperation(operation); } } @@ -239,79 +258,94 @@ int TiledTexture::nbTextures(IntRect& area, float scale) return numberTextures; } -bool TiledTexture::draw() +bool TiledTexture::drawGL(const IntRect& visibleArea, float opacity, + const TransformationMatrix* transform, + const Color* background) { - 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; -#ifdef DEBUG - TilesManager::instance()->getTilesTracker()->trackVisibleLayer(); -#endif - - float m_invScale = 1 / m_scale; - const float tileWidth = TilesManager::layerTileWidth() * m_invScale; - const float tileHeight = TilesManager::layerTileHeight() * m_invScale; + float invScale = 1 / m_scale; + const float tileWidth = TilesManager::tileWidth() * invScale; + const float tileHeight = TilesManager::tileHeight() * invScale; + int drawn = 0; bool askRedraw = false; + + SkRegion missingRegion; + bool translucentBaseSurface = + background ? (background->hasAlpha() && background->alpha() > 0) : false; + if (translucentBaseSurface) { + SkIRect totalArea = SkIRect::MakeXYWH(m_area.x(), m_area.y(), + m_area.width(), m_area.height()); + missingRegion = SkRegion(totalArea); + } + for (unsigned int i = 0; i < m_tiles.size(); i++) { BaseTile* tile = m_tiles[i]; - if (tile->isTileVisible(m_area)) { + bool tileInView = tile->isTileVisible(m_area); + if (tileInView) { askRedraw |= !tile->isTileReady(); SkRect rect; rect.fLeft = tile->x() * tileWidth; 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(), - tile->scale(), m_scale, tile->isTileReady(), tile->isDirty()); - tile->draw(m_surface->opacity(), rect, m_scale); -#ifdef DEBUG - TilesManager::instance()->getTilesTracker()->track(tile->isTileReady(), tile->backTexture()); -#endif + ALOGV("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()); + + bool success = tile->drawGL(opacity, rect, m_scale, transform); + if (translucentBaseSurface && success) { + // Cut the successful drawn tile area from the missing region. + missingRegion.op(SkIRect::MakeXYWH(tile->x(), tile->y(), 1, 1), + SkRegion::kDifference_Op); + } + if (tile->frontTexture()) + drawn++; } - } - - // 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; + if (translucentBaseSurface) + TilesManager::instance()->getProfiler()->nextTile(tile, invScale, tileInView); } - XLOG("TT %p painting tile %d, %d with picture %p", this, tile->x(), tile->y(), picture); - - canvas->drawPicture(*picture); + // Draw missing Regions with blend turned on + if (translucentBaseSurface) + drawMissingRegion(missingRegion, opacity, background); - SkSafeUnref(picture); + ALOGV("TT %p drew %d tiles, redraw due to notready %d, scale %f", + this, drawn, askRedraw, m_scale); - return true; + // need to redraw if some visible tile wasn't ready + return askRedraw; } -const TransformationMatrix* TiledTexture::transform() +void TiledTexture::drawMissingRegion(const SkRegion& region, float opacity, + const Color* background) { - if (!m_surface) - return 0; - return m_surface->transform(); + SkRegion::Iterator iterator(region); + const float tileWidth = TilesManager::tileWidth() / m_scale; + const float tileHeight = TilesManager::tileHeight() / m_scale; + ShaderProgram* shader = TilesManager::instance()->shader(); + while (!iterator.done()) { + SkIRect r = iterator.rect(); + SkRect rect; + rect.fLeft = r.x() * tileWidth; + rect.fTop = r.y() * tileHeight; + rect.fRight = rect.fLeft + tileWidth * r.width(); + rect.fBottom = rect.fTop + tileHeight * r.height(); + ALOGV("draw tile x y, %d %d (%d %d) opacity %f", r.x(), r.y(), + r.width(), r.height(), opacity); + // Skia is using pre-multiplied color. + Color postAlpha = Color(background->red() * background->alpha() / 255, + background->green() * background->alpha() / 255, + background->blue() * background->alpha() / 255, + background->alpha() ); + shader->drawQuad(rect, 0, opacity, postAlpha); + iterator.next(); + } } void TiledTexture::removeTiles() @@ -324,28 +358,15 @@ void TiledTexture::removeTiles() void TiledTexture::discardTextures() { + ALOGV("TT %p discarding textures", this); for (unsigned int i = 0; i < m_tiles.size(); i++) m_tiles[i]->discardTextures(); } -bool TiledTexture::owns(BaseTileTexture* texture) -{ - for (unsigned int i = 0; i < m_tiles.size(); i++) { - BaseTile* tile = m_tiles[i]; - if (tile->frontTexture() == texture) - return true; - if (tile->backTexture() == texture) - return true; - } - return false; -} - -DualTiledTexture::DualTiledTexture(SurfacePainter* surface) +DualTiledTexture::DualTiledTexture(bool isBaseSurface) { - m_textureA = new TiledTexture(surface); - m_textureB = new TiledTexture(surface); - m_frontTexture = m_textureA; - m_backTexture = m_textureB; + m_frontTexture = new TiledTexture(isBaseSurface); + m_backTexture = new TiledTexture(isBaseSurface); m_scale = -1; m_futureScale = -1; m_zooming = false; @@ -353,17 +374,22 @@ DualTiledTexture::DualTiledTexture(SurfacePainter* surface) DualTiledTexture::~DualTiledTexture() { - delete m_textureA; - delete m_textureB; + delete m_frontTexture; + delete m_backTexture; } -void DualTiledTexture::prepare(GLWebViewState* state, float scale, bool repaint, - bool startFastSwap, IntRect& visibleArea) +void DualTiledTexture::prepareGL(GLWebViewState* state, bool allowZoom, + const IntRect& prepareArea, const IntRect& unclippedArea, + TilePainter* painter, bool aggressiveRendering) { - // 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; + 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,43 +397,55 @@ 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); + bool useExpandPrefetch = aggressiveRendering; + ALOGV("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_zooming) { + m_frontTexture->prepareGL(state, m_scale, + prepareArea, unclippedArea, painter, false, useExpandPrefetch); + if (aggressiveRendering) { + // prepare the back tiled texture to render content in low res + float lowResPrefetchScale = m_scale * LOW_RES_PREFETCH_SCALE_MODIFIER; + m_backTexture->prepareGL(state, lowResPrefetchScale, + prepareArea, unclippedArea, painter, true, useExpandPrefetch); + m_backTexture->swapTiles(); + } + } else if (m_zoomUpdateTime < WTF::currentTime()) { + m_backTexture->prepareGL(state, m_futureScale, + prepareArea, unclippedArea, painter, false, useExpandPrefetch); + if (m_backTexture->isReady()) { + // zooming completed, swap the textures and new front tiles + swapTiledTextures(); - if (m_scale > 0) - m_frontTexture->prepare(state, m_scale, repaint, startFastSwap, m_preZoomVisibleArea); + m_frontTexture->swapTiles(); + m_backTexture->discardTextures(); - // 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->swapTiles(); - swap(); + m_scale = m_futureScale; m_zooming = false; } } } -void DualTiledTexture::swap() +bool DualTiledTexture::drawGL(const IntRect& visibleArea, float opacity, + const TransformationMatrix* transform, + bool aggressiveRendering, const Color* background) { - m_frontTexture = m_frontTexture == m_textureA ? m_textureB : m_textureA; - m_backTexture = m_backTexture == m_textureA ? m_textureB : m_textureA; - m_scale = m_futureScale; - m_backTexture->discardTextures(); -} + // draw low res prefetch page, if needed + if (aggressiveRendering && !m_zooming && m_frontTexture->isMissingContent()) + m_backTexture->drawGL(visibleArea, opacity, transform); -bool DualTiledTexture::draw() -{ - bool needsRepaint = m_frontTexture->draw(); + bool needsRepaint = m_frontTexture->drawGL(visibleArea, opacity, transform, background); 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() @@ -416,11 +454,46 @@ void DualTiledTexture::swapTiles() m_frontTexture->swapTiles(); } -bool DualTiledTexture::owns(BaseTileTexture* texture) +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->isPositionFixed()) + result->fixed += nbTexturesClipped; + + // Set kScrollableAndFixedLayers level + if (layer->contentIsScrollable() + || layer->isPositionFixed()) + result->scrollable += nbTexturesClipped; + + // Set kClippedTextures level + result->clipped += nbTexturesClipped; + + // Set kAllTextures level + if (layer->contentIsScrollable()) + result->full += nbTexturesClipped; + else + result->full += nbTexturesUnclipped; +} + +void DualTiledTexture::swapTiledTextures() { - bool owns = m_textureA->owns(texture); - owns |= m_textureB->owns(texture); - return owns; + TiledTexture* temp = m_frontTexture; + m_frontTexture = m_backTexture; + m_backTexture = temp; } } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/TiledTexture.h b/Source/WebCore/platform/graphics/android/TiledTexture.h index 444ab14..2e19cea 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,15 +40,12 @@ class SkCanvas; namespace WebCore { -class TiledTexture : public TilePainter { +class TiledTexture { public: - TiledTexture(SurfacePainter* surface) - : m_paintingPicture(0) - , m_surface(surface) - , m_prevTileX(0) - , m_prevTileY(0) + TiledTexture(bool isBaseSurface) + : m_prevTileY(0) , m_scale(1) - , m_swapWhateverIsReady(false) + , m_isBaseSurface(isBaseSurface) { m_dirtyRegion.setEmpty(); #ifdef DEBUG_COUNT @@ -57,69 +55,66 @@ public: virtual ~TiledTexture(); - IntRect computeTilesArea(IntRect& visibleArea, float scale); + static 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, const IntRect& unclippedArea, + TilePainter* painter, bool isLowResPrefetch = false, + bool useExpandPrefetch = false); void swapTiles(); - bool draw(); + bool drawGL(const IntRect& visibleArea, float opacity, + const TransformationMatrix* transform, const Color* background = 0); - void prepareTile(bool repaint, int x, int y); - void update(const SkRegion& dirtyArea, SkPicture* picture); + void prepareTile(int x, int y, TilePainter* painter, + GLWebViewState* state, bool isLowResPrefetch, bool isExpandPrefetch); + void markAsDirty(const SkRegion& dirtyArea); BaseTile* getTile(int x, int y); void removeTiles(); 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(); + bool isMissingContent(); 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; + void drawMissingRegion(const SkRegion& region, float opacity, const Color* tileBackground); Vector<BaseTile*> m_tiles; - // tile coordinates in viewport, set in prepare() IntRect m_area; SkRegion m_dirtyRegion; - int m_prevTileX; int m_prevTileY; float m_scale; - bool m_swapWhateverIsReady; + bool m_isBaseSurface; }; -class DualTiledTexture { +class DualTiledTexture : public SkRefCnt { +// TODO: investigate webkit threadsafe ref counting public: - DualTiledTexture(SurfacePainter* surface); + DualTiledTexture(bool isBaseSurface); ~DualTiledTexture(); - void prepare(GLWebViewState* state, float scale, bool repaint, - bool startFastSwap, IntRect& area); + void prepareGL(GLWebViewState* state, bool allowZoom, + const IntRect& prepareArea, const IntRect& unclippedArea, + TilePainter* painter, bool aggressiveRendering); void swapTiles(); - void swap(); - bool draw(); - void update(const SkRegion& dirtyArea, SkPicture* picture); - bool owns(BaseTileTexture* texture); + bool drawGL(const IntRect& visibleArea, float opacity, + const TransformationMatrix* transform, bool aggressiveRendering, + const Color* background); + void markAsDirty(const SkRegion& dirtyArea); + void computeTexturesAmount(TexturesResult* result, LayerAndroid* layer); + void discardTextures() + { + m_frontTexture->discardTextures(); + m_backTexture->discardTextures(); + } bool isReady() { - return !m_zooming && m_frontTexture->ready(); + return !m_zooming && m_frontTexture->isReady(); } int nbTextures(IntRect& area, float scale) @@ -131,18 +126,17 @@ public: } private: + void swapTiledTextures(); + // Delay before we schedule a new tile at the new scale factor static const double s_zoomUpdateDelay = 0.2; // 200 ms TiledTexture* m_frontTexture; TiledTexture* m_backTexture; - TiledTexture* m_textureA; - TiledTexture* m_textureB; float m_scale; float m_futureScale; double m_zoomUpdateTime; bool m_zooming; - IntRect m_preZoomVisibleArea; }; } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/TilesManager.cpp b/Source/WebCore/platform/graphics/android/TilesManager.cpp index 62324d7..eeedc07 100644 --- a/Source/WebCore/platform/graphics/android/TilesManager.cpp +++ b/Source/WebCore/platform/graphics/android/TilesManager.cpp @@ -23,13 +23,16 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#define LOG_TAG "TilesManager" +#define LOG_NDEBUG 1 + #include "config.h" #include "TilesManager.h" #if USE(ACCELERATED_COMPOSITING) +#include "AndroidLog.h" #include "BaseTile.h" -#include "PaintedSurface.h" #include "SkCanvas.h" #include "SkDevice.h" #include "SkPaint.h" @@ -37,26 +40,7 @@ #include <cutils/atomic.h> #include <gui/SurfaceTexture.h> #include <gui/SurfaceTextureClient.h> - - -#include <cutils/log.h> #include <wtf/CurrentTime.h> -#include <wtf/text/CString.h> - -#undef XLOGC -#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "TilesManager", __VA_ARGS__) - -#ifdef DEBUG - -#undef XLOG -#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "TilesManager", __VA_ARGS__) - -#else - -#undef XLOG -#define XLOG(...) - -#endif // DEBUG // Important: We need at least twice as many textures as is needed to cover // one viewport, otherwise the allocation may stall. @@ -72,8 +56,6 @@ #define MAX_TEXTURE_ALLOCATION ((6+TILE_PREFETCH_DISTANCE*2)*(5+TILE_PREFETCH_DISTANCE*2)*4) #define TILE_WIDTH 256 #define TILE_HEIGHT 256 -#define LAYER_TILE_WIDTH 256 -#define LAYER_TILE_HEIGHT 256 #define BYTES_PER_PIXEL 4 // 8888 config @@ -96,30 +78,34 @@ int TilesManager::getMaxTextureAllocation() TilesManager::TilesManager() : m_layerTexturesRemain(true) + , m_highEndGfx(false) , m_maxTextureCount(0) , m_maxLayerTextureCount(0) , m_generatorReady(false) , m_showVisualIndicator(false) , 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) { - XLOG("TilesManager ctor"); + ALOGV("TilesManager ctor"); m_textures.reserveCapacity(MAX_TEXTURE_ALLOCATION); m_availableTextures.reserveCapacity(MAX_TEXTURE_ALLOCATION); m_tilesTextures.reserveCapacity(MAX_TEXTURE_ALLOCATION); m_availableTilesTextures.reserveCapacity(MAX_TEXTURE_ALLOCATION); - m_pixmapsGenerationThread = new TexturesGenerator(); + m_pixmapsGenerationThread = new TexturesGenerator(this); m_pixmapsGenerationThread->run("TexturesGenerator"); } void TilesManager::allocateTiles() { int nbTexturesToAllocate = m_maxTextureCount - m_textures.size(); - XLOG("%d tiles to allocate (%d textures planned)", nbTexturesToAllocate, m_maxTextureCount); + ALOGV("%d tiles to allocate (%d textures planned)", nbTexturesToAllocate, m_maxTextureCount); int nbTexturesAllocated = 0; for (int i = 0; i < nbTexturesToAllocate; i++) { BaseTileTexture* texture = new BaseTileTexture( @@ -134,12 +120,12 @@ void TilesManager::allocateTiles() } int nbLayersTexturesToAllocate = m_maxLayerTextureCount - m_tilesTextures.size(); - XLOG("%d layers tiles to allocate (%d textures planned)", - nbLayersTexturesToAllocate, m_maxLayerTextureCount); + ALOGV("%d layers tiles to allocate (%d textures planned)", + nbLayersTexturesToAllocate, m_maxLayerTextureCount); int nbLayersTexturesAllocated = 0; for (int i = 0; i < nbLayersTexturesToAllocate; i++) { BaseTileTexture* texture = new BaseTileTexture( - layerTileWidth(), layerTileHeight()); + tileWidth(), tileHeight()); // the atomic load ensures that the texture has been fully initialized // before we pass a pointer for other threads to operate on BaseTileTexture* loadedTexture = @@ -148,14 +134,14 @@ void TilesManager::allocateTiles() m_tilesTextures.append(loadedTexture); nbLayersTexturesAllocated++; } - XLOG("allocated %d textures for base (total: %d, %d Mb), %d textures for layers (total: %d, %d Mb)", - nbTexturesAllocated, m_textures.size(), - m_textures.size() * TILE_WIDTH * TILE_HEIGHT * 4 / 1024 / 1024, - nbLayersTexturesAllocated, m_tilesTextures.size(), - m_tilesTextures.size() * LAYER_TILE_WIDTH * LAYER_TILE_HEIGHT * 4 / 1024 / 1024); + ALOGV("allocated %d textures for base (total: %d, %d Mb), %d textures for layers (total: %d, %d Mb)", + nbTexturesAllocated, m_textures.size(), + m_textures.size() * TILE_WIDTH * TILE_HEIGHT * 4 / 1024 / 1024, + nbLayersTexturesAllocated, m_tilesTextures.size(), + m_tilesTextures.size() * tileWidth() * tileHeight() * 4 / 1024 / 1024); } -void TilesManager::deallocateTextures(bool allTextures) +void TilesManager::discardTextures(bool allTextures, bool glTextures) { const unsigned int max = m_textures.size(); @@ -169,24 +155,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) { + ALOGV("reset maxTextureCount for %s tiles from %d to %d", + base ? "base" : "layer", *countPtr, remainedTextureNumber); + *countPtr = remainedTextureNumber; + } + + } + + ALOGV("Discarded %d %s textures (out of %d %s tiles)", + dealloc, (deallocateGLTextures ? "gl" : ""), + max, base ? "base" : "layer"); } void TilesManager::gatherTexturesNumbers(int* nbTextures, int* nbAllocatedTextures, @@ -209,7 +223,7 @@ void TilesManager::gatherTexturesNumbers(int* nbTextures, int* nbAllocatedTextur void TilesManager::printTextures() { #ifdef DEBUG - XLOG("++++++"); + ALOGV("++++++"); for (unsigned int i = 0; i < m_textures.size(); i++) { BaseTileTexture* texture = m_textures[i]; BaseTile* o = 0; @@ -221,28 +235,18 @@ void TilesManager::printTextures() x = o->x(); y = o->y(); } - XLOG("[%d] texture %x busy: %d owner: %x (%d, %d) page: %x scale: %.2f", - i, texture, - texture->busy(), o, x, y, o ? o->page() : 0, o ? o->scale() : 0); + ALOGV("[%d] texture %x owner: %x (%d, %d) page: %x scale: %.2f", + i, texture, + o, x, y, o ? o->page() : 0, o ? o->scale() : 0); } - XLOG("------"); + ALOGV("------"); #endif // DEBUG } -void TilesManager::addPaintedSurface(PaintedSurface* surface) -{ - m_paintedSurfaces.append(surface); -} - void TilesManager::gatherTextures() { android::Mutex::Autolock lock(m_texturesLock); m_availableTextures = m_textures; -} - -void TilesManager::gatherLayerTextures() -{ - android::Mutex::Autolock lock(m_texturesLock); m_availableTilesTextures = m_tilesTextures; m_layerTexturesRemain = true; } @@ -253,8 +257,8 @@ BaseTileTexture* TilesManager::getAvailableTexture(BaseTile* owner) // Sanity check that the tile does not already own a texture if (owner->backTexture() && owner->backTexture()->owner() == owner) { - XLOG("same owner (%d, %d), getAvailableBackTexture(%x) => texture %x", - owner->x(), owner->y(), owner, owner->backTexture()); + ALOGV("same owner (%d, %d), getAvailableBackTexture(%x) => texture %x", + owner->x(), owner->y(), owner, owner->backTexture()); if (owner->isLayerTile()) m_availableTilesTextures.remove(m_availableTilesTextures.find(owner->backTexture())); else @@ -274,9 +278,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 +287,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 +299,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; @@ -324,11 +312,11 @@ BaseTileTexture* TilesManager::getAvailableTexture(BaseTile* owner) if (previousOwner) { previousOwner->removeTexture(farthestTexture); - XLOG("%s texture %p stolen from tile %d, %d for %d, %d, drawCount was %llu (now %llu)", - owner->isLayerTile() ? "LAYER" : "BASE", - farthestTexture, previousOwner->x(), previousOwner->y(), - owner->x(), owner->y(), - oldestDrawCount, getDrawGLCount()); + ALOGV("%s texture %p stolen from tile %d, %d for %d, %d, drawCount was %llu (now %llu)", + owner->isLayerTile() ? "LAYER" : "BASE", + farthestTexture, previousOwner->x(), previousOwner->y(), + owner->x(), owner->y(), + oldestDrawCount, getDrawGLCount()); } availableTexturePool->remove(availableTexturePool->find(farthestTexture)); @@ -343,7 +331,7 @@ BaseTileTexture* TilesManager::getAvailableTexture(BaseTile* owner) } } - XLOG("Couldn't find an available texture for %s tile %x (%d, %d) out of %d available", + ALOGV("Couldn't find an available texture for %s tile %x (%d, %d) out of %d available", owner->isLayerTile() ? "LAYER" : "BASE", owner, owner->x(), owner->y(), max); #ifdef DEBUG @@ -352,6 +340,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); @@ -366,7 +364,7 @@ int TilesManager::maxLayerTextureCount() void TilesManager::setMaxTextureCount(int max) { - XLOG("setMaxTextureCount: %d (current: %d, total:%d)", + ALOGV("setMaxTextureCount: %d (current: %d, total:%d)", max, m_maxTextureCount, MAX_TEXTURE_ALLOCATION); if (m_maxTextureCount == MAX_TEXTURE_ALLOCATION || max <= m_maxTextureCount) @@ -384,13 +382,14 @@ void TilesManager::setMaxTextureCount(int max) void TilesManager::setMaxLayerTextureCount(int max) { - XLOG("setMaxLayerTextureCount: %d (current: %d, total:%d)", + ALOGV("setMaxLayerTextureCount: %d (current: %d, total:%d)", max, m_maxLayerTextureCount, MAX_TEXTURE_ALLOCATION); if (!max && m_hasLayerTextures) { 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 +410,15 @@ void TilesManager::setMaxLayerTextureCount(int max) m_hasLayerTextures = true; } +TransferQueue* TilesManager::transferQueue() +{ + // m_queue will be created on the UI thread, although it may + // be accessed from the TexturesGenerator. However, that can only happen after + // a previous transferQueue() call due to a prepare. + if (!m_queue) + m_queue = new TransferQueue(m_useMinimalMemory); + return m_queue; +} float TilesManager::tileWidth() { @@ -422,75 +430,11 @@ float TilesManager::tileHeight() return TILE_HEIGHT; } -float TilesManager::layerTileWidth() -{ - return LAYER_TILE_WIDTH; -} - -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) { gInstance = new TilesManager(); - XLOG("instance(), new gInstance is %x", gInstance); - XLOG("Waiting for the generator..."); - gInstance->waitForGenerator(); - XLOG("Generator ready!"); + ALOGV("instance(), new gInstance is %x", gInstance); } return gInstance; } diff --git a/Source/WebCore/platform/graphics/android/TilesManager.h b/Source/WebCore/platform/graphics/android/TilesManager.h index 9782fbb..05fc1af 100644 --- a/Source/WebCore/platform/graphics/android/TilesManager.h +++ b/Source/WebCore/platform/graphics/android/TilesManager.h @@ -35,9 +35,7 @@ #include "ShaderProgram.h" #include "SkBitmapRef.h" #include "TexturesGenerator.h" -#include "TiledPage.h" #include "TilesProfiler.h" -#include "TilesTracker.h" #include "TransferQueue.h" #include "VideoLayerManager.h" #include <utils/threads.h> @@ -45,10 +43,9 @@ namespace WebCore { -class PaintedSurface; - class TilesManager { public: + // May only be called from the UI thread static TilesManager* instance(); static GLint getMaxTextureSize(); static int getMaxTextureAllocation(); @@ -63,29 +60,15 @@ public: m_pixmapsGenerationThread->removeOperationsForFilter(filter, waitForRunning); } - void removeOperationsForPage(TiledPage* page) - { - m_pixmapsGenerationThread->removeOperationsForPage(page); - } - - void removePaintOperationsForPage(TiledPage* page, bool waitForCompletion) - { - m_pixmapsGenerationThread->removePaintOperationsForPage(page, waitForCompletion); - } - void scheduleOperation(QueuedOperation* operation) { 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(); void gatherTextures(); bool layerTexturesRemain() { return m_layerTexturesRemain; } void gatherTexturesNumbers(int* nbTextures, int* nbAllocatedTextures, @@ -93,18 +76,11 @@ public: BaseTileTexture* getAvailableTexture(BaseTile* owner); - void markGeneratorAsReady() - { - { - android::Mutex::Autolock lock(m_generatorLock); - m_generatorReady = true; - } - m_generatorReadyCond.signal(); - } - void printTextures(); - 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(); @@ -112,15 +88,11 @@ public: void setMaxLayerTextureCount(int max); static float tileWidth(); 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,43 +104,21 @@ public: m_showVisualIndicator = showVisualIndicator; } - SharedTextureMode getSharedTextureMode() - { - return SurfaceTextureMode; - } - TilesProfiler* getProfiler() { return &m_profiler; } - TilesTracker* getTilesTracker() - { - return &m_tilesTracker; - } - bool invertedScreen() { return m_invertedScreen; } - bool invertedScreenSwitch() - { - return m_invertedScreenSwitch; - } - void setInvertedScreen(bool invert) { - if (m_invertedScreen != invert) - m_invertedScreenSwitch = true; m_invertedScreen = invert; } - void setInvertedScreenSwitch(bool invertedSwitch) - { - m_invertedScreenSwitch = invertedSwitch; - } - void setInvertedScreenContrast(float contrast) { m_shader.setContrast(contrast); @@ -184,6 +134,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,23 +157,12 @@ public: return m_drawGLCount; } - int getPaintedSurfaceCount() - { - return m_paintedSurfaces.size(); - } - private: TilesManager(); - void waitForGenerator() - { - android::Mutex::Autolock lock(m_generatorLock); - while (!m_generatorReady) - 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 +171,7 @@ private: Vector<BaseTileTexture*> m_availableTilesTextures; bool m_layerTexturesRemain; - Vector<PaintedSurface*> m_paintedSurfaces; - + bool m_highEndGfx; int m_maxTextureCount; int m_maxLayerTextureCount; @@ -228,25 +179,25 @@ private: bool m_showVisualIndicator; bool m_invertedScreen; - bool m_invertedScreenSwitch; 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; - android::Mutex m_generatorLock; - android::Condition m_generatorReadyCond; static TilesManager* gInstance; ShaderProgram m_shader; - TransferQueue m_queue; + TransferQueue* m_queue; VideoLayerManager m_videoLayerManager; TilesProfiler m_profiler; - TilesTracker m_tilesTracker; unsigned long long m_drawGLCount; double m_lastTimeLayersUsed; bool m_hasLayerTextures; diff --git a/Source/WebCore/platform/graphics/android/TilesProfiler.cpp b/Source/WebCore/platform/graphics/android/TilesProfiler.cpp index 0271ee3..2cc6873 100644 --- a/Source/WebCore/platform/graphics/android/TilesProfiler.cpp +++ b/Source/WebCore/platform/graphics/android/TilesProfiler.cpp @@ -23,29 +23,18 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#define LOG_TAG "TilesProfiler" +#define LOG_NDEBUG 1 + #include "config.h" #include "TilesProfiler.h" #if USE(ACCELERATED_COMPOSITING) +#include "AndroidLog.h" #include "TilesManager.h" #include <wtf/CurrentTime.h> -#ifdef DEBUG - -#include <cutils/log.h> -#include <wtf/text/CString.h> - -#undef XLOG -#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "TilesProfiler", __VA_ARGS__) - -#else - -#undef XLOG -#define XLOG(...) - -#endif // DEBUG - // Hard limit on amount of frames (and thus memory) profiling can take #define MAX_PROF_FRAMES 400 #define INVAL_CODE -2 @@ -63,19 +52,19 @@ void TilesProfiler::start() m_badTiles = 0; m_records.clear(); m_time = currentTimeMS(); - XLOG("initializing tileprofiling"); + ALOGV("initializing tileprofiling"); } float TilesProfiler::stop() { m_enabled = false; - XLOG("completed tile profiling, observed %d frames", m_records.size()); + ALOGV("completed tile profiling, observed %d frames", m_records.size()); return (1.0 * m_goodTiles) / (m_goodTiles + m_badTiles); } void TilesProfiler::clear() { - XLOG("clearing tile profiling of its %d frames", m_records.size()); + ALOGV("clearing tile profiling of its %d frames", m_records.size()); m_records.clear(); } @@ -90,8 +79,8 @@ void TilesProfiler::nextFrame(int left, int top, int right, int bottom, float sc #ifdef DEBUG if (m_records.size() != 0) { - XLOG("completed tile profiling frame, observed %d tiles. %f ms since last", - m_records[0].size(), timeDelta); + ALOGD("completed tile profiling frame, observed %d tiles. %f ms since last", + m_records[0].size(), timeDelta); } #endif // DEBUG @@ -103,14 +92,14 @@ void TilesProfiler::nextFrame(int left, int top, int right, int bottom, float sc scale, true, (int)(timeDelta * 1000))); } -void TilesProfiler::nextTile(BaseTile& tile, float scale, bool inView) +void TilesProfiler::nextTile(BaseTile* tile, float scale, bool inView) { if (!m_enabled || (m_records.size() > MAX_PROF_FRAMES) || (m_records.size() == 0)) return; - bool isReady = tile.isTileReady(); - int left = tile.x() * TilesManager::tileWidth(); - int top = tile.y() * TilesManager::tileWidth(); + bool isReady = tile->isTileReady(); + int left = tile->x() * TilesManager::tileWidth(); + int top = tile->y() * TilesManager::tileWidth(); int right = left + TilesManager::tileWidth(); int bottom = top + TilesManager::tileWidth(); @@ -122,20 +111,20 @@ void TilesProfiler::nextTile(BaseTile& tile, float scale, bool inView) } m_records.last().append(TileProfileRecord( left, top, right, bottom, - scale, isReady, (int)tile.drawCount())); - XLOG("adding tile %d %d %d %d, scale %f", left, top, right, bottom, scale); + scale, isReady, (int)tile->drawCount())); + ALOGV("adding tile %d %d %d %d, scale %f", left, top, right, bottom, scale); } -void TilesProfiler::nextInval(const IntRect& rect, float scale) +void TilesProfiler::nextInval(const SkIRect& rect, float scale) { if (!m_enabled || (m_records.size() > MAX_PROF_FRAMES) || (m_records.size() == 0)) return; m_records.last().append(TileProfileRecord( rect.x(), rect.y(), - rect.maxX(), rect.maxY(), scale, false, INVAL_CODE)); - XLOG("adding inval region %d %d %d %d, scale %f", rect.x(), rect.y(), - rect.maxX(), rect.maxY(), scale); + rect.right(), rect.bottom(), scale, false, INVAL_CODE)); + ALOGV("adding inval region %d %d %d %d, scale %f", rect.x(), rect.y(), + rect.right(), rect.bottom(), scale); } } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/TilesProfiler.h b/Source/WebCore/platform/graphics/android/TilesProfiler.h index 286d350..a13d471 100644 --- a/Source/WebCore/platform/graphics/android/TilesProfiler.h +++ b/Source/WebCore/platform/graphics/android/TilesProfiler.h @@ -58,8 +58,8 @@ public: float stop(); void clear(); void nextFrame(int left, int top, int right, int bottom, float scale); - void nextTile(BaseTile& tile, float scale, bool inView); - void nextInval(const IntRect& rect, float scale); + void nextTile(BaseTile* tile, float scale, bool inView); + void nextInval(const SkIRect& rect, float scale); int numFrames() { return m_records.size(); }; @@ -72,6 +72,8 @@ public: return &m_records[frame][tile]; } + bool enabled() { return m_enabled; } + private: bool m_enabled; unsigned int m_goodTiles; diff --git a/Source/WebCore/platform/graphics/android/TransferQueue.cpp b/Source/WebCore/platform/graphics/android/TransferQueue.cpp index 73cc570..a3552ac 100644 --- a/Source/WebCore/platform/graphics/android/TransferQueue.cpp +++ b/Source/WebCore/platform/graphics/android/TransferQueue.cpp @@ -23,35 +23,26 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#define LOG_TAG "TransferQueue" +#define LOG_NDEBUG 1 + #include "config.h" #include "TransferQueue.h" #if USE(ACCELERATED_COMPOSITING) +#include "AndroidLog.h" #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> -#include <cutils/log.h> -#include <cutils/properties.h> -#include <wtf/text/CString.h> -#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "TransferQueue", __VA_ARGS__) - -#ifdef DEBUG - -#undef XLOG -#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "TransferQueue", __VA_ARGS__) - -#else - -#undef XLOG -#define XLOG(...) - -#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 @@ -59,7 +50,7 @@ namespace WebCore { -TransferQueue::TransferQueue() +TransferQueue::TransferQueue(bool useMinimalMem) : m_eglSurface(EGL_NO_SURFACE) , m_transferQueueIndex(0) , m_fboID(0) @@ -70,43 +61,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]; - - // Two bugs made the GPU upload path unreliable on the GPU-accelerated - // emulator. The bugs are being fixed in later branches, but the fixes are - // too risky for this branch. Default to the CpuUpload path for now. - char qemuProp[PROPERTY_VALUE_MAX + 1]; - property_get("ro.kernel.qemu", qemuProp, "0"); - if (atoi(qemuProp) == 1) - m_currentUploadType = CpuUpload; + 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); @@ -123,27 +126,18 @@ 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"); + ALOGV("Invalid savedBaseTilePtr , such that the tile is obsolete"); return true; } BaseTileTexture* baseTileTexture = baseTilePtr->backTexture(); - if (!baseTileTexture) { - XLOG("Invalid baseTileTexture , such that the tile is obsolete"); - 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"); + if (!baseTileTexture || baseTileTexture != data->savedBaseTileTexturePtr) { + ALOGV("Invalid baseTileTexture %p (vs expected %p), such that the tile is obsolete", + baseTileTexture, data->savedBaseTileTexturePtr); return true; } @@ -151,20 +145,46 @@ bool TransferQueue::checkObsolete(int index) } 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); @@ -177,7 +197,7 @@ void TransferQueue::blitTileFromQueue(GLuint fboID, BaseTileTexture* destTex, destTex->getSize().height()); GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); if (status != GL_FRAMEBUFFER_COMPLETE) { - XLOG("Error: glCheckFramebufferStatus failed"); + ALOGV("Error: glCheckFramebufferStatus failed"); glBindFramebuffer(GL_FRAMEBUFFER, 0); return; } @@ -265,15 +285,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. @@ -284,38 +322,67 @@ 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. + ALOGV("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) - XLOGC("unexpected error: updateTexImage return %d", result); + ALOGE("unexpected error: updateTexImage return %d", result); } m_transferQueue[index].savedBaseTilePtr = 0; m_transferQueue[index].status = emptyItem; if (obsoleteBaseTile) { - XLOG("Warning: the texture is obsolete for this baseTile"); - index = (index + 1) % ST_BUFFER_NUMBER; + ALOGV("Warning: the texture is obsolete for this baseTile"); + index = (index + 1) % m_transferQueueSize; continue; } @@ -324,33 +391,29 @@ 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); - - XLOG("Blit tile x, y %d %d with dest texture %p to destTexture->m_ownTextureId %d", - m_transferQueue[index].tileInfo.m_x, - m_transferQueue[index].tileInfo.m_y, - destTexture, - destTexture->m_ownTextureId); + destTexture->setPure(false); + destTexture->transferComplete(); + + ALOGV("Blit tile x, y %d %d with dest texture %p to destTexture->m_ownTextureId %d", + m_transferQueue[index].savedBaseTilePtr, + 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 @@ -362,14 +425,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; @@ -379,83 +442,87 @@ 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); + ALOGV("Quit bitmap update: not ready! for tile x y %d %d", + renderInfo->x, renderInfo->y); return false; } if (currentUploadType == GpuUpload) { // a) Dequeue the Surface Texture and write into the buffer if (!m_ANW.get()) { - XLOG("ERROR: ANW is null"); + ALOGV("ERROR: ANW is null"); return false; } - ANativeWindow_Buffer buffer; - if (ANativeWindow_lock(m_ANW.get(), &buffer, 0)) + if (!GLUtils::updateSharedSurfaceTextureWithBitmap(m_ANW.get(), bitmap)) return false; - - uint8_t* img = (uint8_t*)buffer.bits; - int row, col; - 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) { - 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 ++) { - uint8_t* dst = &(img[buffer.stride * row * bpp]); - uint8_t* src = &(bitmapOrigin[bitmap.width() * row * bpp]); - memcpy(dst, src, bpp * bitmap.width()); - } - else - 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); + ALOGV("Bitmap updated x, y %d %d, baseTile %p", + renderInfo->x, renderInfo->y, renderInfo->baseTile); return true; } +void TransferQueue::addItemInPureColorQueue(const TileRenderInfo* renderInfo) +{ + // 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 = renderInfo->pureColor; + 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 || m_transferQueue[index].status != emptyItem) { - XLOG("ERROR update a tile which is dirty already @ index %d", index); + ALOGV("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) { @@ -467,38 +534,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"); + ALOGD("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 @@ -506,7 +563,7 @@ void TransferQueue::cleanupTransportQueue() if (m_transferQueue[index].uploadType == GpuUpload) { status_t result = m_sharedSurfaceTexture->updateTexImage(); if (result != OK) - XLOGC("unexpected error: updateTexImage return %d", result); + ALOGE("unexpected error: updateTexImage return %d", result); } // since tiles in the queue may be from another webview, remove @@ -517,14 +574,14 @@ void TransferQueue::cleanupTransportQueue() // since tile destruction removes textures on the UI thread, the // texture->owner ptr guarantees the tile is valid tile->discardBackTexture(); - XLOG("transfer queue discarded tile %p, removed texture", tile); + ALOGV("transfer queue discarded tile %p, removed texture", tile); } m_transferQueue[index].savedBaseTilePtr = 0; m_transferQueue[index].savedBaseTileTexturePtr = 0; m_transferQueue[index].status = emptyItem; } - index = (index + 1) % ST_BUFFER_NUMBER; + index = (index + 1) % m_transferQueueSize; } } @@ -533,7 +590,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 } @@ -545,7 +602,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 @@ -563,7 +620,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], @@ -573,7 +630,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..b00ea17 100644 --- a/Source/WebCore/platform/graphics/android/TransferQueue.h +++ b/Source/WebCore/platform/graphics/android/TransferQueue.h @@ -31,7 +31,7 @@ #include "BaseTile.h" #include "BaseTileTexture.h" #include "ShaderProgram.h" -#include "TiledPage.h" +#include <EGL/eglext.h> namespace WebCore { @@ -86,12 +86,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 +107,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 +133,12 @@ public: void lockQueue() { m_transferQueueItemLocks.lock(); } void unlockQueue() { m_transferQueueItemLocks.unlock(); } + void addItemInPureColorQueue(const TileRenderInfo* renderInfo); + + 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 +150,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 +163,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 +214,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..756bf28 100644 --- a/Source/WebCore/platform/graphics/android/VideoLayerAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/VideoLayerAndroid.cpp @@ -23,42 +23,23 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#define LOG_TAG "VideoLayerAndroid" +#define LOG_NDEBUG 1 + #include "config.h" #include "VideoLayerAndroid.h" -#include "RenderSkinMediaButton.h" +#include "AndroidLog.h" #include "TilesManager.h" #include <GLES2/gl2.h> #include <gui/SurfaceTexture.h> #if USE(ACCELERATED_COMPOSITING) -#ifdef DEBUG -#include <cutils/log.h> -#include <wtf/text/CString.h> - -#undef XLOG -#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "VideoLayerAndroid", __VA_ARGS__) - -#else - -#undef XLOG -#define XLOG(...) - -#endif // DEBUG - 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 +68,139 @@ void VideoLayerAndroid::setSurfaceTexture(sp<SurfaceTexture> texture, TilesManager::instance()->videoLayerManager()->registerTexture(uniqueId(), textureName); } -GLuint VideoLayerAndroid::createSpinnerInnerTexture() -{ - return createTextureFromImage(RenderSkinMediaButton::SPINNER_INNER); -} - -GLuint VideoLayerAndroid::createSpinnerOuterTexture() -{ - return createTextureFromImage(RenderSkinMediaButton::SPINNER_OUTER); -} - -GLuint VideoLayerAndroid::createPosterTexture() -{ - return createTextureFromImage(RenderSkinMediaButton::VIDEO); -} - -GLuint VideoLayerAndroid::createTextureFromImage(int buttonType) +void VideoLayerAndroid::showPreparingAnimation(const SkRect& rect, + const SkRect innerRect) { - 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; + 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::createBackgroundTexture() +SkRect VideoLayerAndroid::calVideoRect(const SkRect& rect) { - 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..6501f98 100644 --- a/Source/WebCore/platform/graphics/android/VideoLayerManager.cpp +++ b/Source/WebCore/platform/graphics/android/VideoLayerManager.cpp @@ -23,24 +23,22 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#define LOG_TAG "VideoLayerManager" +#define LOG_NDEBUG 1 + #include "config.h" #include "VideoLayerManager.h" -#if USE(ACCELERATED_COMPOSITING) - -#ifdef DEBUG -#include <cutils/log.h> -#include <wtf/text/CString.h> - -#undef XLOG -#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "VideoLayerManager", __VA_ARGS__) - -#else +#include "AndroidLog.h" +#include "RenderSkinMediaButton.h" +#include "SkCanvas.h" +#include <wtf/CurrentTime.h> -#undef XLOG -#define XLOG(...) +#if USE(ACCELERATED_COMPOSITING) -#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 @@ -49,11 +47,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) { + ALOGD("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) { + ALOGV("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 +163,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,11 +210,14 @@ 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); + ALOGV("GL texture %d regisered for layerId %d", textureId, layerId); return; } @@ -115,13 +225,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. @@ -146,7 +259,7 @@ void VideoLayerManager::updateMatrix(const int layerId, const GLfloat* matrix) return; memcpy(pInfo->surfaceMatrix, matrix, sizeof(pInfo->surfaceMatrix)); } else { - XLOG("Error: should not reach here, the layerId %d should exist!", layerId); + ALOGV("Error: should not reach here, the layerId %d should exist!", layerId); ASSERT(false); } return; @@ -164,10 +277,10 @@ bool VideoLayerManager::recycleTextureMem() InfoIterator end = m_videoLayerInfoMap.end(); #ifdef DEBUG - XLOG("VideoLayerManager::recycleTextureMem m_videoLayerInfoMap contains"); + ALOGV("VideoLayerManager::recycleTextureMem m_videoLayerInfoMap contains"); for (InfoIterator it = m_videoLayerInfoMap.begin(); it != end; ++it) - XLOG(" layerId %d, textureId %d, videoSize %d, timeStamp %d ", - it->first, it->second->textureId, it->second->videoSize, it->second->timeStamp); + ALOGV(" layerId %d, textureId %d, videoSize %d, timeStamp %d ", + it->first, it->second->textureId, it->second->videoSize, it->second->timeStamp); #endif for (InfoIterator it = m_videoLayerInfoMap.begin(); it != end; ++it) { if (it->second->timeStamp < oldestTimeStamp) { @@ -199,7 +312,7 @@ void VideoLayerManager::deleteUnusedTextures() if (textureName) { textureNames[index] = textureName; index++; - XLOG("GL texture %d will be deleted", textureName); + ALOGV("GL texture %d will be deleted", textureName); } } glDeleteTextures(size, textureNames); @@ -207,6 +320,7 @@ void VideoLayerManager::deleteUnusedTextures() m_retiredTextures.clear(); } m_retiredTexturesLock.unlock(); + GLUtils::checkGlError("deleteUnusedTextures"); return; } @@ -238,5 +352,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/ZoomManager.cpp b/Source/WebCore/platform/graphics/android/ZoomManager.cpp deleted file mode 100644 index 2cf9f06..0000000 --- a/Source/WebCore/platform/graphics/android/ZoomManager.cpp +++ /dev/null @@ -1,201 +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 "ZoomManager.h" - -#include "GLWebViewState.h" - -#if USE(ACCELERATED_COMPOSITING) - -#include <wtf/CurrentTime.h> - -#include <cutils/log.h> -#include <wtf/text/CString.h> - -#undef XLOGC -#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "ZoomManager", __VA_ARGS__) - -#ifdef DEBUG - -#undef XLOG -#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "ZoomManager", __VA_ARGS__) - -#else - -#undef XLOG -#define XLOG(...) - -#endif // DEBUG - -namespace WebCore { - -using namespace android; - -ZoomManager::ZoomManager(GLWebViewState* state) - : m_scaleRequestState(kNoScaleRequest) - , m_currentScale(-1) - , m_futureScale(-1) - , m_layersScale(-1) - , m_updateTime(-1) - , m_transitionTime(-1) - , m_glWebViewState(state) -{ -} - -void ZoomManager::scheduleUpdate(const double& currentTime, - const SkIRect& viewport, float scale) -{ - // if no update time, set it - if (updateTime() == -1) { - m_scaleRequestState = kWillScheduleRequest; - setUpdateTime(currentTime + s_updateInitialDelay); - setFutureScale(scale); - m_glWebViewState->setFutureViewport(viewport); - return; - } - - if (currentTime < updateTime()) - return; - - // we reached the scheduled update time, check if we can update - if (futureScale() == scale) { - // we are still with the previous scale, let's go - // with the update - m_scaleRequestState = kRequestNewScale; - setUpdateTime(-1); - } else { - // we reached the update time, but the planned update was for - // a different scale factor -- meaning the user is still probably - // in the process of zooming. Let's push the update time a bit. - setUpdateTime(currentTime + s_updateDelay); - setFutureScale(scale); - m_glWebViewState->setFutureViewport(viewport); - } -} - -double ZoomManager::zoomInTransitionTime(double currentTime) -{ - if (m_transitionTime == -1) - m_transitionTime = currentTime + s_zoomInTransitionDelay; - return m_transitionTime; -} - -double ZoomManager::zoomOutTransitionTime(double currentTime) -{ - if (m_transitionTime == -1) - m_transitionTime = currentTime + s_zoomOutTransitionDelay; - return m_transitionTime; -} - -float ZoomManager::zoomInTransparency(double currentTime) -{ - float t = zoomInTransitionTime(currentTime) - currentTime; - t *= s_invZoomInTransitionDelay; - return fmin(1, fmax(0, t)); -} - -float ZoomManager::zoomOutTransparency(double currentTime) -{ - float t = zoomOutTransitionTime(currentTime) - currentTime; - t *= s_invZoomOutTransitionDelay; - return fmin(1, fmax(0, t)); -} - -bool ZoomManager::swapPages() -{ - bool reset = m_scaleRequestState != kNoScaleRequest; - m_scaleRequestState = kNoScaleRequest; - return reset; -} - -void ZoomManager::processNewScale(double currentTime, float scale) -{ - m_prepareNextTiledPage = false; - m_zooming = false; - const SkIRect& viewportTileBounds = m_glWebViewState->viewportTileBounds(); - - if (scale == m_currentScale - || m_glWebViewState->preZoomBounds().isEmpty()) - m_glWebViewState->setPreZoomBounds(viewportTileBounds); - - // If we have a different scale than the current one, we have to - // decide what to do. The current behaviour is to delay an update, - // so that we do not slow down zooming unnecessarily. - if ((m_currentScale != scale - && (m_scaleRequestState == ZoomManager::kNoScaleRequest - || m_futureScale != scale)) - || m_scaleRequestState == ZoomManager::kWillScheduleRequest) { - - // schedule the new Zoom request - scheduleUpdate(currentTime, viewportTileBounds, scale); - - // If it's a new request, we will have to prepare the page. - if (m_scaleRequestState == ZoomManager::kRequestNewScale) - m_prepareNextTiledPage = true; - } - - // If the viewport has changed since we scheduled the request, we also need - // to prepare. - if ((m_scaleRequestState == ZoomManager::kRequestNewScale - || m_scaleRequestState == ZoomManager::kReceivedNewScale) - && m_glWebViewState->futureViewport() != viewportTileBounds) - m_prepareNextTiledPage = true; - - // Checking if we are zooming... - if (m_scaleRequestState != ZoomManager::kNoScaleRequest) { - m_prepareNextTiledPage = true; - m_zooming = true; - } - - // Get the current scale; if we are zooming, we don't change the scale - // factor immediately (see BaseLayerAndroid::drawBasePictureInGL()), but - // we change the scaleRequestState. When the state is kReceivedNewScale - // (see setReceivedRequest()), we can use the future scale instead of - // the current scale to request new textures. After a transition time, - // the scaleRequestState will be reset and the current scale will be set - // to the future scale. - m_layersScale = m_currentScale; -} - -void ZoomManager::processTransition(double currentTime, float scale, - bool* doSwap, float* backPageTransparency, - float* frontPageTransparency) -{ - if (scale < m_currentScale) - *backPageTransparency = 1 - zoomOutTransparency(currentTime); - else - *frontPageTransparency = zoomInTransparency(currentTime); - - // The transition between the two page is finished - if (currentTime > transitionTime(currentTime, scale)) { - resetTransitionTime(); - *doSwap = true; - } -} - -} // namespace WebCore - -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/ZoomManager.h b/Source/WebCore/platform/graphics/android/ZoomManager.h deleted file mode 100644 index dd04c5d..0000000 --- a/Source/WebCore/platform/graphics/android/ZoomManager.h +++ /dev/null @@ -1,118 +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 ZoomManager_h -#define ZoomManager_h - -#if USE(ACCELERATED_COMPOSITING) - -#include "SkRect.h" - -namespace WebCore { - -class GLWebViewState; - -class ZoomManager { -public: - enum GLScaleStates { - kNoScaleRequest = 0, - kWillScheduleRequest = 1, - kRequestNewScale = 2, - kReceivedNewScale = 3 - }; - typedef int32_t GLScaleState; - - ZoomManager(GLWebViewState* state); - - void scheduleUpdate(const double& currentTime, const SkIRect& viewport, float scale); - - GLScaleState scaleRequestState() const { return m_scaleRequestState; } - void setScaleRequestState(GLScaleState state) { m_scaleRequestState = state; } - float currentScale() const { return m_currentScale; } - void setCurrentScale(float scale) { m_currentScale = scale; } - float futureScale() const { return m_futureScale; } - void setFutureScale(float scale) { m_futureScale = scale; } - float layersScale() const { return m_layersScale; } - double zoomInTransitionTime(double currentTime); - double zoomOutTransitionTime(double currentTime); - float zoomInTransparency(double currentTime); - float zoomOutTransparency(double currentTime); - void resetTransitionTime() { m_transitionTime = -1; } - double updateTime() const { return m_updateTime; } - void setUpdateTime(double value) { m_updateTime = value; } - - // state used by BaseLayerAndroid - bool needPrepareNextTiledPage() { return m_prepareNextTiledPage; } - bool zooming() { return m_zooming; } - - bool didFireRequest() { return m_scaleRequestState == ZoomManager::kRequestNewScale; } - void setReceivedRequest() { - m_scaleRequestState = ZoomManager::kReceivedNewScale; - m_layersScale = m_futureScale; - } - bool didReceivedRequest() { return m_scaleRequestState == ZoomManager::kReceivedNewScale; } - - double transitionTime(double currentTime, float scale) { - return (scale < m_currentScale) ? zoomOutTransitionTime(currentTime) - : zoomInTransitionTime(currentTime); - } - void processTransition(double currentTime, float scale, bool* doSwap, - float* backPageTransparency, float* frontPageTransparency); - - bool swapPages(); - - void processNewScale(double currentTime, float scale); - -private: - // Delay between scheduling a new page when the scale - // factor changes (i.e. zooming in or out) - static const double s_updateInitialDelay = 0.3; // 300 ms - // If the scale factor continued to change and we completed - // the original delay, we push back the update by this value - static const double s_updateDelay = 0.1; // 100 ms - - // Delay for the transition between the two pages - static const double s_zoomInTransitionDelay = 0.1; // 100 ms - static const double s_invZoomInTransitionDelay = 10; - static const double s_zoomOutTransitionDelay = 0.2; // 200 ms - static const double s_invZoomOutTransitionDelay = 5; - - GLScaleState m_scaleRequestState; - float m_currentScale; - float m_futureScale; - float m_layersScale; - double m_updateTime; - double m_transitionTime; - - bool m_prepareNextTiledPage; - bool m_zooming; - - GLWebViewState* m_glWebViewState; -}; - -} // namespace WebCore - -#endif // USE(ACCELERATED_COMPOSITING) -#endif // ZoomManager_h 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/RenderFrame.cpp b/Source/WebCore/rendering/RenderFrame.cpp index 4b1444b..0ae6eda 100644 --- a/Source/WebCore/rendering/RenderFrame.cpp +++ b/Source/WebCore/rendering/RenderFrame.cpp @@ -64,7 +64,12 @@ void RenderFrame::layout() { FrameView* view = static_cast<FrameView*>(widget()); RenderView* root = view ? view->frame()->contentRenderer() : 0; + + // Do not expand frames which has zero width or height if (!width() || !height() || !root) { + updateWidgetPosition(); + if (view) + view->layout(); setNeedsLayout(false); return; } @@ -75,14 +80,17 @@ void RenderFrame::layout() return; } - int layoutWidth = width(); + // Update the dimensions to get the correct width and height + updateWidgetPosition(); + if (root->preferredLogicalWidthsDirty()) + root->computePreferredLogicalWidths(); + // Expand the frame by setting frame height = content height setWidth(max(view->contentsWidth() + borderAndPaddingWidth(), width())); setHeight(max(view->contentsHeight() + borderAndPaddingHeight(), height())); - // Trigger a layout of the FrameView which will schedule a relayout of this RenderFrame. - if (layoutWidth < width()) - view->layout(); + // Update one more time + updateWidgetPosition(); setNeedsLayout(false); } 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..733a418 100644 --- a/Source/WebCore/rendering/RenderLayerCompositor.cpp +++ b/Source/WebCore/rendering/RenderLayerCompositor.cpp @@ -78,7 +78,7 @@ struct CompositingState { : m_compositingAncestor(compAncestor) , m_subtreeIsCompositing(false) #if ENABLE(COMPOSITED_FIXED_ELEMENTS) - , m_fixedSibling(false) + , m_positionedSibling(false) , m_hasFixedElement(false) #endif #if ENABLE(ANDROID_OVERFLOW_SCROLL) @@ -92,8 +92,12 @@ 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_positionedSibling; bool m_hasFixedElement; #endif #if ENABLE(ANDROID_OVERFLOW_SCROLL) @@ -347,7 +351,11 @@ bool RenderLayerCompositor::updateBacking(RenderLayer* layer, CompositingChangeR { bool layerChanged = false; +#if ENABLE(ANDROID_OVERFLOW_SCROLL) + if (needsToBeComposited(layer) || layer->shouldComposite()) { +#else if (needsToBeComposited(layer)) { +#endif enableCompositingMode(); // 3D transforms turn off the testing of overlap. @@ -613,23 +621,49 @@ bool RenderLayerCompositor::overlapsCompositedLayers(OverlapMap& overlapMap, con #if ENABLE(COMPOSITED_FIXED_ELEMENTS) -// to properly support z-index with composited fixed elements, we need to turn -// layers following a fixed layer into compositing mode; but if a layer is fully -// contained into a previous layer already composited (that is not the fixed -// layer), we don't need to composite it. This saves up quite a bit on the -// number of layers we have to composite. -// -bool RenderLayerCompositor::checkForFixedLayers(Vector<RenderLayer*>* list, bool stopAtFixedLayer) +bool RenderLayerCompositor::checkForPositionedElements(Vector<RenderLayer*>* list) { int listSize = list->size(); int haveFixedLayer = -1; bool fixedSibling = false; + bool positionedSibling = false; + + // For absolute positioned elements, we need to check if they are followed + // by a composited element; if so, they also need to be composited, as the + // layer display rendering might be incorrect (absolute elements being + // removed from the flow). + for (int i = 0; i < listSize; ++i) { + RenderLayer* currentLayer = list->at(i); + if (!needsToBeComposited(currentLayer) + && !currentLayer->shouldComposite() + && currentLayer->renderer()->isPositioned()) { + positionedSibling = true; + // check if there is a composited layer later, if so we should be + // composited. + for (int j = i + 1; j < listSize; ++j) { + RenderLayer* layer = list->at(j); + if (needsToBeComposited(layer)) { + currentLayer->setShouldComposite(true); + break; + } + } + break; + } + } + + // If we find a fixed layer, let's mark all the following layers as being + // composited. The layers' surfaces will be merged if needed UI-side. for (int j = 0; j < listSize; ++j) { RenderLayer* currentLayer = list->at(j); + if (currentLayer->shouldComposite()) + continue; + if (currentLayer->isFixed() && needsToBeComposited(currentLayer)) { haveFixedLayer = j; fixedSibling = true; } + + // Bypass fixed layers with a width or height or 1 or less... IntRect currentLayerBounds = currentLayer->renderer()->localToAbsoluteQuad( FloatRect(currentLayer->localBoundingBox())).enclosingBoundingBox(); if ((currentLayerBounds.width() <= 1 @@ -638,28 +672,11 @@ bool RenderLayerCompositor::checkForFixedLayers(Vector<RenderLayer*>* list, bool haveFixedLayer = -1; fixedSibling = false; } - if (haveFixedLayer != -1 && haveFixedLayer != j) { - bool needComposite = true; - int stop = 0; - if (stopAtFixedLayer) - stop = haveFixedLayer + 1; - - for (int k = j - 1; k >= stop; --k) { - RenderLayer* aLayer = list->at(k); - if (aLayer && aLayer->renderer()) { - IntRect bounds = aLayer->renderer()->localToAbsoluteQuad( - FloatRect(aLayer->localBoundingBox())).enclosingBoundingBox(); - if (bounds.contains(currentLayerBounds) - && needsToBeComposited(aLayer) && aLayer->isStackingContext()) { - needComposite = false; - break; - } - } - } - currentLayer->setShouldComposite(needComposite); - } + + if (haveFixedLayer != -1 && haveFixedLayer != j) + currentLayer->setShouldComposite(true); } - return fixedSibling; + return positionedSibling || fixedSibling; } #endif @@ -678,7 +695,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,28 +715,33 @@ 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) - if (compositingState.m_fixedSibling) - layer->setMustOverlapCompositedLayers(layer->shouldComposite()); - else - layer->setMustOverlapCompositedLayers(mustOverlapCompositedLayers); -#else + layer->setMustOverlapCompositedLayers(mustOverlapCompositedLayers); -#endif - + // The children of this layer don't need to composite, unless there is // 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 bool willBeComposited = needsToBeComposited(layer); +#if ENABLE(COMPOSITED_FIXED_ELEMENTS) + willBeComposited |= layer->shouldComposite(); + layer->setMustOverlapCompositedLayers(layer->shouldComposite()); +#endif + #if ENABLE(ANDROID_OVERFLOW_SCROLL) // tell the parent it has scrollable descendants. if (layer->hasOverflowScroll()) @@ -729,6 +756,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); } @@ -746,9 +774,9 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, O if (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) { size_t listSize = negZOrderList->size(); #if ENABLE(COMPOSITED_FIXED_ELEMENTS) - childState.m_fixedSibling = compositingState.m_fixedSibling; - if (checkForFixedLayers(negZOrderList, false)) - childState.m_fixedSibling = true; + childState.m_positionedSibling = compositingState.m_positionedSibling; + if (checkForPositionedElements(negZOrderList)) + childState.m_positionedSibling = true; #endif for (size_t i = 0; i < listSize; ++i) { RenderLayer* curLayer = negZOrderList->at(i); @@ -783,9 +811,9 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, O if (Vector<RenderLayer*>* normalFlowList = layer->normalFlowList()) { size_t listSize = normalFlowList->size(); #if ENABLE(COMPOSITED_FIXED_ELEMENTS) - childState.m_fixedSibling = compositingState.m_fixedSibling; - if (checkForFixedLayers(normalFlowList, true)) - childState.m_fixedSibling = true; + childState.m_positionedSibling = compositingState.m_positionedSibling; + if (checkForPositionedElements(normalFlowList)) + childState.m_positionedSibling = true; #endif for (size_t i = 0; i < listSize; ++i) { RenderLayer* curLayer = normalFlowList->at(i); @@ -797,9 +825,9 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, O if (Vector<RenderLayer*>* posZOrderList = layer->posZOrderList()) { size_t listSize = posZOrderList->size(); #if ENABLE(COMPOSITED_FIXED_ELEMENTS) - childState.m_fixedSibling = compositingState.m_fixedSibling; - if (checkForFixedLayers(posZOrderList, true)) - childState.m_fixedSibling = true; + childState.m_positionedSibling = compositingState.m_positionedSibling; + if (checkForPositionedElements(posZOrderList)) + childState.m_positionedSibling = true; #endif for (size_t i = 0; i < listSize; ++i) { RenderLayer* curLayer = posZOrderList->at(i); @@ -1398,6 +1426,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/RenderLayerCompositor.h b/Source/WebCore/rendering/RenderLayerCompositor.h index 813e265..2de1037 100644 --- a/Source/WebCore/rendering/RenderLayerCompositor.h +++ b/Source/WebCore/rendering/RenderLayerCompositor.h @@ -219,7 +219,7 @@ private: void updateCompositingLayersTimerFired(Timer<RenderLayerCompositor>*); #if ENABLE(COMPOSITED_FIXED_ELEMENTS) - bool checkForFixedLayers(Vector<RenderLayer*>* list, bool stopAtFixedLayer); + bool checkForPositionedElements(Vector<RenderLayer*>* list); #endif // Returns true if any layer's compositing changed 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); |