summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnders Edenbrandt <anders.edenbrandt@sonyericsson.com>2011-12-29 14:13:33 (GMT)
committerPierre-Antoine LaFayette <plafayet@codeaurora.org>2012-05-14 18:41:23 (GMT)
commitc72ff2aa562941d94ceb51ba685d60809ca882a6 (patch)
treedf42534f5b1568ad6739b338e8eb8617116f8611
parentdd8d1267ac633130bfef6d125e1bd14269a80513 (diff)
WebGL implementation for Android
Implementation of WebGL in Android WebKit. Exposes a low level 3D graphics API based on OpenGL ES 2.0 to JavaScript. WebGL is not compiled by default. It can be enabled by setting ENABLE_WEBGL = true in your device BoardConfig.mk or directly in external/webkit/Android.mk. It is also disabled by default (in WebSettings.cpp) as required by Khronos until it reaches 100% conformance. -- From: Anders Edenbrandt <anders.edenbrandt@sonyericsson.com> Date: Thu, 26 Jan 2012 11:48:41 +0100 WebGL bug fixes and updates Some updates: - stability fixes - image decoder - redesign of how the FBOs are used - other bug fixes -- From: Anders Edenbrandt <anders.edenbrandt@sonyericsson.com> Date: Tue, 31 Jan 2012 17:20:13 +0100 WebGL code cleanup and bug fixes -- From: Anders Edenbrandt <anders.edenbrandt@sonyericsson.com> Date: Thu Mar 15 10:15:33 2012 +0100 More improvements and bug fixes Updates: - cleaned up buffer handling, allowing for arbitrary number of buffers - removed rect from invalidation - removed screen update request from drawGL - releasing buffers when the browser is paused - added missing method 'slice' for typed arrays - fixed bug in bindFramebuffer Change-Id: If1bf1f53f8050889a22959288e9e3874ea823dd2
-rw-r--r--Android.mk39
-rw-r--r--Source/JavaScriptCore/wtf/Platform.h4
-rw-r--r--Source/ThirdParty/ANGLE/Android.mk70
-rw-r--r--Source/WebCore/Android.derived.v8bindings.mk8
-rw-r--r--Source/WebCore/Android.mk36
-rw-r--r--Source/WebCore/Android.v8bindings.mk6
-rw-r--r--Source/WebCore/bindings/v8/custom/V8ArrayBufferViewCustom.h10
-rw-r--r--Source/WebCore/dom/Document.cpp30
-rw-r--r--Source/WebCore/dom/Document.h16
-rw-r--r--Source/WebCore/dom/Element.h7
-rw-r--r--Source/WebCore/history/PageCache.cpp4
-rw-r--r--Source/WebCore/html/HTMLCanvasElement.cpp50
-rw-r--r--Source/WebCore/html/HTMLCanvasElement.h8
-rw-r--r--Source/WebCore/html/canvas/ArrayBuffer.cpp38
-rw-r--r--Source/WebCore/html/canvas/ArrayBuffer.h10
-rw-r--r--Source/WebCore/html/canvas/ArrayBuffer.idl3
-rw-r--r--Source/WebCore/html/canvas/WebGLRenderingContext.cpp223
-rw-r--r--Source/WebCore/html/canvas/WebGLRenderingContext.h27
-rw-r--r--Source/WebCore/html/canvas/WebGLRenderingContext.idl4
-rw-r--r--Source/WebCore/html/canvas/WebKitLoseContext.cpp9
-rw-r--r--Source/WebCore/html/canvas/WebKitLoseContext.h2
-rw-r--r--Source/WebCore/html/canvas/WebKitLoseContext.idl2
-rw-r--r--Source/WebCore/platform/graphics/ANGLEWebKitBridge.h3
-rw-r--r--Source/WebCore/platform/graphics/GraphicsContext3D.cpp7
-rw-r--r--Source/WebCore/platform/graphics/GraphicsContext3D.h30
-rw-r--r--Source/WebCore/platform/graphics/android/Extensions3DAndroid.cpp101
-rw-r--r--Source/WebCore/platform/graphics/android/Extensions3DAndroid.h63
-rw-r--r--Source/WebCore/platform/graphics/android/GraphicsContext3DAndroid.cpp1368
-rw-r--r--Source/WebCore/platform/graphics/android/GraphicsContext3DInternal.cpp1013
-rw-r--r--Source/WebCore/platform/graphics/android/GraphicsContext3DInternal.h221
-rw-r--r--Source/WebCore/platform/graphics/android/GraphicsContext3DProxy.cpp98
-rw-r--r--Source/WebCore/platform/graphics/android/GraphicsContext3DProxy.h64
-rw-r--r--Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp54
-rw-r--r--Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.h12
-rw-r--r--Source/WebCore/platform/graphics/android/WebGLLayer.cpp84
-rw-r--r--Source/WebCore/platform/graphics/android/WebGLLayer.h60
-rw-r--r--Source/WebCore/platform/image-decoders/ImageDecoder.cpp8
-rw-r--r--Source/WebCore/rendering/RenderLayerBacking.cpp12
-rw-r--r--Source/WebCore/rendering/RenderLayerCompositor.cpp13
-rw-r--r--Source/WebKit/android/jni/WebSettings.cpp5
-rwxr-xr-xSource/WebKit/android/jni/WebViewCore.cpp12
41 files changed, 3747 insertions, 87 deletions
diff --git a/Android.mk b/Android.mk
index dbd19a2..2af0701 100644
--- a/Android.mk
+++ b/Android.mk
@@ -23,6 +23,11 @@
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
##
+# Control WebGL compiling in webkit.
+ifneq ($(ENABLE_WEBGL),true)
+ ENABLE_WEBGL = false
+endif
+
# Control SVG compiling in webkit.
# Default is true unless explictly disabled.
ifneq ($(ENABLE_SVG),false)
@@ -162,6 +167,10 @@ LOCAL_C_INCLUDES := \
frameworks/base/core/jni/android/graphics \
frameworks/base/include
+ifeq ($(ENABLE_WEBGL),true)
+LOCAL_C_INCLUDES += external/libpng
+endif
+
# Add Source/ for the include of <JavaScriptCore/config.h> from WebCore/config.h
LOCAL_C_INCLUDES := $(LOCAL_C_INCLUDES) \
$(SOURCE_PATH)
@@ -282,6 +291,9 @@ LOCAL_C_INCLUDES := $(LOCAL_C_INCLUDES) \
LOCAL_CFLAGS := $(LOCAL_CFLAGS) \
-DLOG_TAG_NODE=\"webkit-node\"
endif
+# Needed for ANGLE
+LOCAL_C_INCLUDES := $(LOCAL_C_INCLUDES) \
+ $(SOURCE_PATH)/ThirdParty/ANGLE/include/GLSLANG
ifeq ($(JAVASCRIPT_ENGINE),v8)
# Include WTF source file.
@@ -394,6 +406,10 @@ ifeq ($(WEBCORE_FPS_DISPLAY),true)
LOCAL_CFLAGS += -DENABLE_FPS_DISPLAY
endif
+ifeq ($(ENABLE_WEBGL),true)
+LOCAL_CFLAGS += -DENABLE_WEBGL
+endif
+
# LOCAL_LDLIBS is used in simulator builds only and simulator builds are only
# valid on Linux
LOCAL_LDLIBS += -lpthread -ldl
@@ -443,6 +459,10 @@ endif
# Build the list of static libraries
LOCAL_STATIC_LIBRARIES := libxml2 libxslt libhyphenation libskiagpu
+ifeq ($(ENABLE_WEBGL),true)
+LOCAL_STATIC_LIBRARIES += libpng
+endif
+
# Linkage to v8, node
ifeq ($(JAVASCRIPT_ENGINE),v8)
ifeq ($(DYNAMIC_SHARED_LIBV8SO),true)
@@ -514,6 +534,24 @@ LOCAL_C_INCLUDES := $(WEBKIT_C_INCLUDES) \
include $(BUILD_STATIC_LIBRARY)
endif # JAVASCRIPT_ENGINE == jsc
+# Build ANGLE as a static library.
+include $(CLEAR_VARS)
+LOCAL_MODULE := libangle
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE_TAGS := optional
+ANGLE_PATH := $(SOURCE_PATH)/ThirdParty/ANGLE
+LOCAL_SHARED_LIBRARIES := $(WEBKIT_SHARED_LIBRARIES)
+include $(ANGLE_PATH)/Android.mk
+# Redefine LOCAL_SRC_FILES with the correct prefix
+LOCAL_SRC_FILES := $(addprefix Source/ThirdParty/ANGLE/src/compiler/,$(LOCAL_SRC_FILES))
+# Append angle intermediate include paths to the WebKit include list.
+LOCAL_C_INCLUDES := $(WEBKIT_C_INCLUDES) \
+ $(ANGLE_PATH)/include \
+ $(ANGLE_PATH)/src
+LOCAL_CFLAGS += -Wno-error=non-virtual-dtor
+# Build libangle
+include $(BUILD_STATIC_LIBRARY)
+
# Now build the shared library using only the exported jni entry point. This
# will strip out any unused code from the entry point.
include $(CLEAR_VARS)
@@ -528,6 +566,7 @@ LOCAL_STATIC_LIBRARIES := libwebcore $(WEBKIT_STATIC_LIBRARIES)
ifeq ($(JAVASCRIPT_ENGINE),jsc)
LOCAL_STATIC_LIBRARIES += libjs
endif
+LOCAL_STATIC_LIBRARIES += libangle
LOCAL_LDFLAGS := -fvisibility=hidden
LOCAL_CFLAGS := $(WEBKIT_CFLAGS)
LOCAL_CPPFLAGS := $(WEBKIT_CPPFLAGS)
diff --git a/Source/JavaScriptCore/wtf/Platform.h b/Source/JavaScriptCore/wtf/Platform.h
index e92af89..47575c5 100644
--- a/Source/JavaScriptCore/wtf/Platform.h
+++ b/Source/JavaScriptCore/wtf/Platform.h
@@ -2,6 +2,7 @@
* Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
* Copyright (C) 2007-2009 Torch Mobile, Inc.
* Copyright (C) Research In Motion Limited 2010. All rights reserved.
+ * Copyright (C) 2011, Sony Ericsson Mobile Communications AB
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -706,6 +707,9 @@
#define ENABLE_SVG 0
#endif
#define ENABLE_VIDEO 1
+#if defined(ENABLE_WEBGL)
+#define ENABLE_WEBGL 1
+#endif
#if ENABLE_SVG
#if !defined(ENABLE_SVG_ANIMATION)
#define ENABLE_SVG_ANIMATION 0
diff --git a/Source/ThirdParty/ANGLE/Android.mk b/Source/ThirdParty/ANGLE/Android.mk
new file mode 100644
index 0000000..8469f68
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/Android.mk
@@ -0,0 +1,70 @@
+#
+# Copyright (C) 2011, 2012, Sony Ericsson Mobile Communications AB
+# All rights reserved.
+#
+# 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.
+# * Neither the name of the Sony Ericsson Mobile Communications AB nor the
+# names of its contributors may be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 SONY ERICSSON MOBILE COMMUNICATIONS AB 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.
+#
+
+# Compiler src
+LOCAL_SRC_FILES := \
+ Compiler.cpp \
+ InfoSink.cpp \
+ Initialize.cpp \
+ InitializeDll.cpp \
+ IntermTraverse.cpp \
+ Intermediate.cpp \
+ ParseHelper.cpp \
+ PoolAlloc.cpp \
+ QualifierAlive.cpp \
+ RemoveTree.cpp \
+ ShaderLang.cpp \
+ SymbolTable.cpp \
+ ValidateLimitations.cpp \
+ VariableInfo.cpp \
+ debug.cpp \
+ intermOut.cpp \
+ ossource_posix.cpp \
+ parseConst.cpp \
+ util.cpp
+
+# Code generator
+LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \
+ CodeGenGLSL.cpp \
+ OutputGLSL.cpp \
+ TranslatorGLSL.cpp \
+ VersionGLSL.cpp
+
+# Generated files
+LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \
+ glslang_lex.cpp \
+ glslang_tab.cpp
+
+# Preprocessor
+LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \
+ preprocessor/atom.c \
+ preprocessor/cpp.c \
+ preprocessor/cppstruct.c \
+ preprocessor/memory.c \
+ preprocessor/scanner.c \
+ preprocessor/symbols.c \
+ preprocessor/tokens.c
diff --git a/Source/WebCore/Android.derived.v8bindings.mk b/Source/WebCore/Android.derived.v8bindings.mk
index e57998d..e19d55c 100644
--- a/Source/WebCore/Android.derived.v8bindings.mk
+++ b/Source/WebCore/Android.derived.v8bindings.mk
@@ -1,5 +1,6 @@
##
## Copyright 2009, The Android Open Source Project
+## Copyright (C) 2011, Sony Ericsson Mobile Communications AB
##
## Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions
@@ -334,6 +335,13 @@ GEN := \
$(intermediates)/bindings/V8WebGLUniformLocation.h \
$(intermediates)/bindings/V8WebGLVertexArrayObjectOES.h
+ifeq ($(ENABLE_WEBGL), true)
+GEN += \
+ $(intermediates)/bindings/V8OESStandardDerivatives.h \
+ $(intermediates)/bindings/V8WebGLContextEvent.h \
+ $(intermediates)/bindings/V8WebKitLoseContext.h
+endif
+
$(GEN): PRIVATE_PATH := $(LOCAL_PATH)
$(GEN): PRIVATE_CUSTOM_TOOL = SOURCE_ROOT=$(PRIVATE_PATH) perl -I$(PRIVATE_PATH)/bindings/scripts $(PRIVATE_PATH)/bindings/scripts/generate-bindings.pl --defines "$(FEATURE_DEFINES) LANGUAGE_JAVASCRIPT" --generator V8 --include dom --include html --include html/canvas --outputdir $(dir $@) $<
$(GEN): $(intermediates)/bindings/V8%.h : $(LOCAL_PATH)/html/canvas/%.idl $(js_binding_scripts)
diff --git a/Source/WebCore/Android.mk b/Source/WebCore/Android.mk
index bc0e8ea..a731deb 100644
--- a/Source/WebCore/Android.mk
+++ b/Source/WebCore/Android.mk
@@ -1,5 +1,6 @@
##
## Copyright 2009, The Android Open Source Project
+## Copyright (C) 2011, 2012, Sony Ericsson Mobile Communications AB
##
## Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions
@@ -389,8 +390,27 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \
html/canvas/Uint8Array.cpp \
html/canvas/WebGLExtension.cpp \
html/canvas/WebGLObject.cpp \
- html/canvas/WebGLVertexArrayObjectOES.cpp \
- \
+ html/canvas/WebGLVertexArrayObjectOES.cpp
+
+ifeq ($(ENABLE_WEBGL), true)
+LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \
+ html/canvas/CanvasContextAttributes.cpp \
+ html/canvas/OESStandardDerivatives.cpp \
+ html/canvas/WebGLBuffer.cpp \
+ html/canvas/WebGLContextAttributes.cpp \
+ html/canvas/WebGLContextEvent.cpp \
+ html/canvas/WebGLFramebuffer.cpp \
+ html/canvas/WebGLGetInfo.cpp \
+ html/canvas/WebGLProgram.cpp \
+ html/canvas/WebGLRenderbuffer.cpp \
+ html/canvas/WebGLRenderingContext.cpp \
+ html/canvas/WebGLShader.cpp \
+ html/canvas/WebGLTexture.cpp \
+ html/canvas/WebGLUniformLocation.cpp \
+ html/canvas/WebKitLoseContext.cpp
+endif
+
+LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \
html/parser/HTMLConstructionSite.cpp \
html/parser/HTMLDocumentParser.cpp \
html/parser/HTMLElementStack.cpp \
@@ -692,6 +712,18 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \
platform/graphics/android/ZoomManager.cpp \
platform/graphics/android/android_graphics.cpp
+ifeq ($(ENABLE_WEBGL), true)
+LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \
+ platform/graphics/ANGLEWebKitBridge.cpp \
+ platform/graphics/GraphicsContext3D.cpp \
+ platform/graphics/android/Extensions3DAndroid.cpp \
+ platform/graphics/android/GraphicsContext3DAndroid.cpp \
+ platform/graphics/android/GraphicsContext3DInternal.cpp \
+ platform/graphics/android/GraphicsContext3DProxy.cpp \
+ platform/graphics/android/WebGLLayer.cpp \
+ platform/image-decoders/png/PNGImageDecoder.cpp
+endif
+
ifeq ($(ENABLE_SVG), true)
LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \
platform/graphics/filters/DistantLightSource.cpp \
diff --git a/Source/WebCore/Android.v8bindings.mk b/Source/WebCore/Android.v8bindings.mk
index a24a4a3..e536446 100644
--- a/Source/WebCore/Android.v8bindings.mk
+++ b/Source/WebCore/Android.v8bindings.mk
@@ -1,5 +1,6 @@
##
## Copyright 2009, The Android Open Source Project
+## Copyright (C) 2011, Sony Ericsson Mobile Communications AB
##
## Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions
@@ -180,6 +181,11 @@ LOCAL_SRC_FILES += \
bindings/v8/custom/V8WebKitAnimationCustom.cpp \
bindings/v8/custom/V8WebSocketCustom.cpp
+ifeq ($(ENABLE_WEBGL), true)
+LOCAL_SRC_FILES += \
+ bindings/v8/custom/V8WebGLRenderingContextCustom.cpp
+endif
+
ifeq ($(ENABLE_SVG), true)
LOCAL_SRC_FILES += \
bindings/v8/custom/V8SVGDocumentCustom.cpp \
diff --git a/Source/WebCore/bindings/v8/custom/V8ArrayBufferViewCustom.h b/Source/WebCore/bindings/v8/custom/V8ArrayBufferViewCustom.h
index f842b6d..4a107d5 100644
--- a/Source/WebCore/bindings/v8/custom/V8ArrayBufferViewCustom.h
+++ b/Source/WebCore/bindings/v8/custom/V8ArrayBufferViewCustom.h
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2009 Google Inc. All rights reserved.
+ * Copyright (C) 2012 Sony Mobile Communications AB
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -54,15 +55,16 @@ v8::Handle<v8::Value> constructWebGLArrayWithArrayBufferArgument(const v8::Argum
if (!ok)
return throwError("Could not convert argument 1 to a number");
}
- if ((buf->byteLength() - offset) % sizeof(ElementType))
- return throwError("ArrayBuffer length minus the byteOffset is not a multiple of the element size.", V8Proxy::RangeError);
- uint32_t length = (buf->byteLength() - offset) / sizeof(ElementType);
+ uint32_t length = 0;
if (argLen > 2) {
length = toUInt32(args[2], ok);
if (!ok)
return throwError("Could not convert argument 2 to a number");
+ } else {
+ if ((buf->byteLength() - offset) % sizeof(ElementType))
+ return throwError("ArrayBuffer length minus the byteOffset is not a multiple of the element size.", V8Proxy::RangeError);
+ length = (buf->byteLength() - offset) / sizeof(ElementType);
}
-
RefPtr<ArrayClass> array = ArrayClass::create(buf, offset, length);
if (!array) {
V8Proxy::setDOMException(INDEX_SIZE_ERR);
diff --git a/Source/WebCore/dom/Document.cpp b/Source/WebCore/dom/Document.cpp
index 6869c9a..1e79771 100644
--- a/Source/WebCore/dom/Document.cpp
+++ b/Source/WebCore/dom/Document.cpp
@@ -8,6 +8,8 @@
* Copyright (C) 2008, 2009 Google Inc. All rights reserved.
* Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
* Copyright (c) 2011, Code Aurora Forum. All rights reserved
+ * Copyright (C) 2011, 2012 Sony Ericsson Mobile Communications AB
+ * Copyright (C) 2012 Sony Mobile Communcations AB
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -442,6 +444,9 @@ Document::Document(Frame* frame, const KURL& url, bool isXHTML, bool isHTML)
#if ENABLE(WML)
, m_containsWMLContent(false)
#endif
+#if ENABLE(WEBGL) && PLATFORM(ANDROID)
+ , m_containsWebGLContent(false)
+#endif
, m_weakReference(DocumentWeakReference::create(this))
, m_idAttributeName(idAttr)
#if ENABLE(FULLSCREEN_API)
@@ -5109,4 +5114,29 @@ DocumentLoader* Document::loader() const
return loader;
}
+#if ENABLE(WEBGL) && PLATFORM(ANDROID)
+void Document::suspendDocument()
+{
+ HashSet<Element*>::iterator end = m_documentSuspendCallbackElements.end();
+ for (HashSet<Element*>::iterator i = m_documentSuspendCallbackElements.begin(); i != end; ++i)
+ (*i)->documentWasSuspended();
+}
+
+void Document::resumeDocument()
+{
+ HashSet<Element*>::iterator end = m_documentSuspendCallbackElements.end();
+ for (HashSet<Element*>::iterator i = m_documentSuspendCallbackElements.begin(); i != end; ++i)
+ (*i)->documentWillResume();
+}
+
+void Document::registerForDocumentSuspendCallbacks(Element* e)
+{
+ m_documentSuspendCallbackElements.add(e);
+}
+
+void Document::unregisterForDocumentSuspendCallbacks(Element* e)
+{
+ m_documentSuspendCallbackElements.remove(e);
+}
+#endif
} // namespace WebCore
diff --git a/Source/WebCore/dom/Document.h b/Source/WebCore/dom/Document.h
index 7478e6c..10ac00a 100644
--- a/Source/WebCore/dom/Document.h
+++ b/Source/WebCore/dom/Document.h
@@ -6,6 +6,8 @@
* Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
* Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
* Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2011, 2012 Sony Ericsson Mobile Communications AB
+ * Copyright (C) 2012 Sony Mobile Communcations AB
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -1037,6 +1039,15 @@ public:
void initializeWMLPageState();
#endif
+#if ENABLE(WEBGL) && PLATFORM(ANDROID)
+ void setContainsWebGLContent(bool value) { m_containsWebGLContent = value; }
+ bool containsWebGLContent() const { return m_containsWebGLContent; }
+ void suspendDocument();
+ void resumeDocument();
+ void registerForDocumentSuspendCallbacks(Element*);
+ void unregisterForDocumentSuspendCallbacks(Element*);
+#endif
+
bool containsValidityStyleRules() const { return m_containsValidityStyleRules; }
void setContainsValidityStyleRules() { m_containsValidityStyleRules = true; }
@@ -1371,6 +1382,11 @@ private:
bool m_containsWMLContent;
#endif
+#if ENABLE(WEBGL) && PLATFORM(ANDROID)
+ bool m_containsWebGLContent;
+ HashSet<Element*> m_documentSuspendCallbackElements;
+#endif
+
RefPtr<DocumentWeakReference> m_weakReference;
HashSet<MediaCanStartListener*> m_mediaCanStartListeners;
diff --git a/Source/WebCore/dom/Element.h b/Source/WebCore/dom/Element.h
index d269dbe..97265e9 100644
--- a/Source/WebCore/dom/Element.h
+++ b/Source/WebCore/dom/Element.h
@@ -4,6 +4,8 @@
* (C) 2001 Peter Kelly (pmk@post.com)
* (C) 2001 Dirk Mueller (mueller@kde.org)
* Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2012 Sony Ericsson Mobile Communications AB
+ * Copyright (C) 2012 Sony Mobile Communications AB
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -351,6 +353,11 @@ public:
PassRefPtr<WebKitAnimationList> webkitGetAnimations() const;
+#if ENABLE(WEBGL) && PLATFORM(ANDROID)
+ virtual void documentWasSuspended() {}
+ virtual void documentWillResume() {}
+#endif
+
protected:
Element(const QualifiedName& tagName, Document* document, ConstructionType type)
: ContainerNode(document, type)
diff --git a/Source/WebCore/history/PageCache.cpp b/Source/WebCore/history/PageCache.cpp
index 204ab36..818aa38 100644
--- a/Source/WebCore/history/PageCache.cpp
+++ b/Source/WebCore/history/PageCache.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2011, Sony Ericsson Mobile Communications AB
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -283,6 +284,9 @@ bool PageCache::canCachePageContainingThisFrame(Frame* frame)
&& !frame->document()->containsWMLContent()
&& !frame->document()->isWMLDocument()
#endif
+#if ENABLE(WEBGL) && PLATFORM(ANDROID)
+ && !frame->document()->containsWebGLContent()
+#endif
&& frame->loader()->client()->canCachePage();
}
diff --git a/Source/WebCore/html/HTMLCanvasElement.cpp b/Source/WebCore/html/HTMLCanvasElement.cpp
index ece22c2..fbd9c03 100644
--- a/Source/WebCore/html/HTMLCanvasElement.cpp
+++ b/Source/WebCore/html/HTMLCanvasElement.cpp
@@ -2,6 +2,8 @@
* Copyright (C) 2004, 2006, 2007 Apple Inc. All rights reserved.
* Copyright (C) 2007 Alp Toker <alp@atoker.com>
* Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved.
+ * Copyright (C) 2011, 2012 Sony Ericsson Mobile Communications AB
+ * Copyright (C) 2012 Sony Mobile Communications AB
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -157,6 +159,11 @@ HTMLCanvasElement::~HTMLCanvasElement()
CanvasLayerAndroid::markGLAssetsForRemoval(id);
delete m_canvasLayer;
SLOGD("++++++++++++++++ Deleting the canvas with id %d", id);
+
+#if ENABLE(WEBGL)
+ document()->unregisterForDocumentActivationCallbacks(this);
+ document()->unregisterForDocumentSuspendCallbacks(this);
+#endif
#endif
}
@@ -247,6 +254,11 @@ CanvasRenderingContext* HTMLCanvasElement::getContext(const String& type, Canvas
if (m_context) {
// Need to make sure a RenderLayer and compositing layer get created for the Canvas
setNeedsStyleRecalc(SyntheticStyleChange);
+#if PLATFORM(ANDROID)
+ document()->registerForDocumentActivationCallbacks(this);
+ document()->registerForDocumentSuspendCallbacks(this);
+ document()->setContainsWebGLContent(true);
+#endif
}
}
return m_context.get();
@@ -335,7 +347,8 @@ void HTMLCanvasElement::paint(GraphicsContext* context, const IntRect& r)
ImageBuffer* imageBuffer = buffer();
if (imageBuffer) {
#if PLATFORM(ANDROID)
- if (imageBuffer->drawsUsingRecording()) {
+ bool is3D = m_context && m_context->is3d();
+ if (!is3D && imageBuffer->drawsUsingRecording()) {
// The canvas will draw onto a recording canvas. We want to pass the
// recorded canvas content onto the GraphicsLayerAndroid recording
// canvas.
@@ -360,7 +373,6 @@ void HTMLCanvasElement::paint(GraphicsContext* context, const IntRect& r)
m_canUseGpuRendering = false;
}
#endif
-
if (m_presentedImage)
context->drawImage(m_presentedImage.get(), ColorSpaceDeviceRGB, r);
else if (imageBuffer->drawsUsingCopy())
@@ -408,6 +420,40 @@ bool HTMLCanvasElement::is3D() const
{
return m_context && m_context->is3d();
}
+
+#if PLATFORM(ANDROID)
+void HTMLCanvasElement::documentDidBecomeActive()
+{
+ if (m_context && m_context->is3d()) {
+ WebGLRenderingContext* context3D = static_cast<WebGLRenderingContext*>(m_context.get());
+ context3D->recreateSurface();
+ }
+}
+
+void HTMLCanvasElement::documentWillBecomeInactive()
+{
+ if (m_context && m_context->is3d()) {
+ WebGLRenderingContext* context3D = static_cast<WebGLRenderingContext*>(m_context.get());
+ context3D->releaseSurface();
+ }
+}
+
+void HTMLCanvasElement::documentWasSuspended()
+{
+ if (m_context && m_context->is3d()) {
+ WebGLRenderingContext* context3D = static_cast<WebGLRenderingContext*>(m_context.get());
+ context3D->releaseSurface();
+ }
+}
+
+void HTMLCanvasElement::documentWillResume()
+{
+ if (m_context && m_context->is3d()) {
+ WebGLRenderingContext* context3D = static_cast<WebGLRenderingContext*>(m_context.get());
+ context3D->recreateSurface();
+ }
+}
+#endif
#endif
void HTMLCanvasElement::makeRenderingResultsAvailable()
diff --git a/Source/WebCore/html/HTMLCanvasElement.h b/Source/WebCore/html/HTMLCanvasElement.h
index 2502585..eafea67 100644
--- a/Source/WebCore/html/HTMLCanvasElement.h
+++ b/Source/WebCore/html/HTMLCanvasElement.h
@@ -2,6 +2,8 @@
* Copyright (C) 2004, 2006, 2009, 2010 Apple Inc. All rights reserved.
* Copyright (C) 2007 Alp Toker <alp@atoker.com>
* Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved.
+ * Copyright (C) 2011, 2012 Sony Ericsson Mobile Communications AB
+ * Copyright (C) 2012 Sony Mobile Communications AB
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -135,6 +137,12 @@ public:
#if ENABLE(WEBGL)
bool is3D() const;
+#if PLATFORM(ANDROID)
+ void documentDidBecomeActive();
+ void documentWillBecomeInactive();
+ void documentWasSuspended();
+ void documentWillResume();
+#endif
#endif
void makeRenderingResultsAvailable();
diff --git a/Source/WebCore/html/canvas/ArrayBuffer.cpp b/Source/WebCore/html/canvas/ArrayBuffer.cpp
index 4f75cc3..9c072ed 100644
--- a/Source/WebCore/html/canvas/ArrayBuffer.cpp
+++ b/Source/WebCore/html/canvas/ArrayBuffer.cpp
@@ -1,5 +1,7 @@
/*
* Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2012 Sony Ericsson Mobile Communications AB
+ * Copyright (C) 2012 Sony Mobile Communications AB
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -30,6 +32,16 @@
namespace WebCore {
+static int clampValue(int x, int left, int right)
+{
+ ASSERT(left <= right);
+ if (x < left)
+ x = left;
+ if (right < x)
+ x = right;
+ return x;
+}
+
PassRefPtr<ArrayBuffer> ArrayBuffer::create(unsigned numElements, unsigned elementByteSize)
{
void* data = tryAllocate(numElements, elementByteSize);
@@ -43,7 +55,7 @@ PassRefPtr<ArrayBuffer> ArrayBuffer::create(ArrayBuffer* other)
return ArrayBuffer::create(other->data(), other->byteLength());
}
-PassRefPtr<ArrayBuffer> ArrayBuffer::create(void* source, unsigned byteLength)
+PassRefPtr<ArrayBuffer> ArrayBuffer::create(const void* source, unsigned byteLength)
{
void* data = tryAllocate(byteLength, 1);
if (!data)
@@ -74,6 +86,30 @@ unsigned ArrayBuffer::byteLength() const
return m_sizeInBytes;
}
+PassRefPtr<ArrayBuffer> ArrayBuffer::slice(int begin, int end) const
+{
+ return sliceImpl(clampIndex(begin), clampIndex(end));
+}
+
+PassRefPtr<ArrayBuffer> ArrayBuffer::slice(int begin) const
+{
+ return sliceImpl(clampIndex(begin), byteLength());
+}
+
+PassRefPtr<ArrayBuffer> ArrayBuffer::sliceImpl(unsigned begin, unsigned end) const
+{
+ unsigned size = begin <= end ? end - begin : 0;
+ return ArrayBuffer::create(static_cast<const char*>(data()) + begin, size);
+}
+
+unsigned ArrayBuffer::clampIndex(int index) const
+{
+ unsigned currentLength = byteLength();
+ if (index < 0)
+ index = currentLength + index;
+ return clampValue(index, 0, currentLength);
+}
+
ArrayBuffer::~ArrayBuffer()
{
WTF::fastFree(m_data);
diff --git a/Source/WebCore/html/canvas/ArrayBuffer.h b/Source/WebCore/html/canvas/ArrayBuffer.h
index ff5e599..bd18306 100644
--- a/Source/WebCore/html/canvas/ArrayBuffer.h
+++ b/Source/WebCore/html/canvas/ArrayBuffer.h
@@ -1,5 +1,7 @@
/*
* Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2012 Sony Ericsson Mobile Communications AB
+ * Copyright (C) 2012 Sony Mobile Communications AB
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -35,18 +37,24 @@ class ArrayBuffer : public RefCounted<ArrayBuffer> {
public:
static PassRefPtr<ArrayBuffer> create(unsigned numElements, unsigned elementByteSize);
static PassRefPtr<ArrayBuffer> create(ArrayBuffer*);
- static PassRefPtr<ArrayBuffer> create(void* source, unsigned byteLength);
+ static PassRefPtr<ArrayBuffer> create(const void* source, unsigned byteLength);
void* data();
const void* data() const;
unsigned byteLength() const;
+ PassRefPtr<ArrayBuffer> slice(int begin, int end) const;
+ PassRefPtr<ArrayBuffer> slice(int begin) const;
+
~ArrayBuffer();
private:
ArrayBuffer(void* data, unsigned sizeInBytes);
ArrayBuffer(unsigned numElements, unsigned elementByteSize);
static void* tryAllocate(unsigned numElements, unsigned elementByteSize);
+ PassRefPtr<ArrayBuffer> sliceImpl(unsigned begin, unsigned end) const;
+ unsigned clampIndex(int index) const;
+
unsigned m_sizeInBytes;
void* m_data;
};
diff --git a/Source/WebCore/html/canvas/ArrayBuffer.idl b/Source/WebCore/html/canvas/ArrayBuffer.idl
index 6f63e65..bd4e77f 100644
--- a/Source/WebCore/html/canvas/ArrayBuffer.idl
+++ b/Source/WebCore/html/canvas/ArrayBuffer.idl
@@ -1,5 +1,7 @@
/*
* Copyright (C) 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2012 Sony Ericsson Mobile Communications AB
+ * Copyright (C) 2012 Sony Mobile Communications AB
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -32,6 +34,7 @@ module html {
V8CustomConstructor,
] ArrayBuffer {
readonly attribute int byteLength;
+ ArrayBuffer slice(in long begin, in [Optional] long end);
};
}
diff --git a/Source/WebCore/html/canvas/WebGLRenderingContext.cpp b/Source/WebCore/html/canvas/WebGLRenderingContext.cpp
index b0b7e69a..58d4b59 100644
--- a/Source/WebCore/html/canvas/WebGLRenderingContext.cpp
+++ b/Source/WebCore/html/canvas/WebGLRenderingContext.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2011, 2012 Sony Ericsson Mobile Communications AB
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -328,29 +329,14 @@ private:
void WebGLRenderingContext::WebGLRenderingContextRestoreTimer::fired()
{
- // Timer is started when m_contextLost is false. It will first call
- // onLostContext, which will set m_contextLost to true. Then it will keep
- // calling restoreContext and reschedule itself until m_contextLost is back
- // to false.
- if (!m_context->m_contextLost) {
- m_context->onLostContext();
- startOneShot(secondsBetweenRestoreAttempts);
- } else {
- // The rendering context is not restored if there is no handler for
- // the context restored event.
- if (!m_context->canvas()->hasEventListeners(eventNames().webglcontextrestoredEvent))
- return;
-
- m_context->restoreContext();
- if (m_context->m_contextLost)
- startOneShot(secondsBetweenRestoreAttempts);
- }
+ m_context->maybeRestoreContext(RealLostContext);
}
class WebGLRenderingContextLostCallback : public GraphicsContext3D::ContextLostCallback {
public:
WebGLRenderingContextLostCallback(WebGLRenderingContext* cb) : m_contextLostCallback(cb) {}
- virtual void onContextLost() { m_contextLostCallback->forceLostContext(); }
+ virtual void onContextLost() {
+ m_contextLostCallback->forceLostContext(WebGLRenderingContext::RealLostContext); }
virtual ~WebGLRenderingContextLostCallback() {}
private:
WebGLRenderingContext* m_contextLostCallback;
@@ -367,7 +353,11 @@ PassOwnPtr<WebGLRenderingContext> WebGLRenderingContext::create(HTMLCanvasElemen
attributes.antialias = false;
}
+#if PLATFORM(ANDROID)
+ RefPtr<GraphicsContext3D> context(GraphicsContext3D::create(canvas, attributes, 0));
+#else
RefPtr<GraphicsContext3D> context(GraphicsContext3D::create(attributes, hostWindow));
+#endif
if (!context) {
canvas->dispatchEvent(WebGLContextEvent::create(eventNames().webglcontextcreationerrorEvent, false, true, "Could not create a WebGL context."));
@@ -381,6 +371,7 @@ WebGLRenderingContext::WebGLRenderingContext(HTMLCanvasElement* passedCanvas, Pa
GraphicsContext3D::Attributes attributes)
: CanvasRenderingContext(passedCanvas)
, m_context(context)
+ , m_restoreAllowed(false)
, m_restoreTimer(this)
, m_videoCache(4)
, m_contextLost(false)
@@ -554,9 +545,10 @@ void WebGLRenderingContext::paintRenderingResultsToCanvas()
{
// Until the canvas is written to by the application, the clear that
// happened after it was composited should be ignored by the compositor.
- if (m_context->layerComposited() && !m_attributes.preserveDrawingBuffer)
+ if (m_context->layerComposited() && !m_attributes.preserveDrawingBuffer) {
+ m_context->paintCompositedResultsToCanvas(this);
canvas()->makePresentationCopy();
- else
+ } else
canvas()->clearPresentationCopy();
clearIfComposited();
if (!m_markedCanvasDirty && !m_layerCleared)
@@ -577,6 +569,18 @@ bool WebGLRenderingContext::paintsIntoCanvasBuffer() const
return m_context->paintsIntoCanvasBuffer();
}
+#if PLATFORM(ANDROID)
+void WebGLRenderingContext::recreateSurface()
+{
+ m_context->recreateSurface();
+}
+
+void WebGLRenderingContext::releaseSurface()
+{
+ m_context->releaseSurface();
+}
+#endif
+
void WebGLRenderingContext::reshape(int width, int height)
{
if (m_needsUpdate) {
@@ -593,6 +597,20 @@ void WebGLRenderingContext::reshape(int width, int height)
m_context->reshape(width, height);
}
+GC3Dsizei WebGLRenderingContext::drawingBufferWidth()
+{
+ if (isContextLost())
+ return 0;
+ return m_context->getInternalFramebufferSize().width();
+}
+
+GC3Dsizei WebGLRenderingContext::drawingBufferHeight()
+{
+ if (isContextLost())
+ return 0;
+ return m_context->getInternalFramebufferSize().height();
+}
+
unsigned int WebGLRenderingContext::sizeInBytes(GC3Denum type)
{
switch (type) {
@@ -856,7 +874,9 @@ void WebGLRenderingContext::bufferData(GC3Denum target, ArrayBuffer* data, GC3De
}
}
- m_context->bufferData(target, data->byteLength(), data->data(), usage);
+ // Some platforms incorrectly signal GL_OUT_OF_MEMORY if size == 0
+ if (data->byteLength() > 0)
+ m_context->bufferData(target, data->byteLength(), data->data(), usage);
cleanupAfterGraphicsCall(false);
}
@@ -879,7 +899,9 @@ void WebGLRenderingContext::bufferData(GC3Denum target, ArrayBufferView* data, G
}
}
- m_context->bufferData(target, data->byteLength(), data->baseAddress(), usage);
+ // Some platforms incorrectly signal GL_OUT_OF_MEMORY if size == 0
+ if (data->byteLength() > 0)
+ m_context->bufferData(target, data->byteLength(), data->baseAddress(), usage);
cleanupAfterGraphicsCall(false);
}
@@ -1048,8 +1070,10 @@ void WebGLRenderingContext::copyTexImage2D(GC3Denum target, GC3Dint level, GC3De
return;
}
clearIfComposited();
- if (isResourceSafe())
- m_context->copyTexImage2D(target, level, internalformat, x, y, width, height, border);
+ if (isResourceSafe()) {
+ if (width > 0 && height > 0)
+ m_context->copyTexImage2D(target, level, internalformat, x, y, width, height, border);
+ }
else {
GC3Dint clippedX, clippedY;
GC3Dsizei clippedWidth, clippedHeight;
@@ -1060,8 +1084,11 @@ void WebGLRenderingContext::copyTexImage2D(GC3Denum target, GC3Dint level, GC3De
m_context->copyTexSubImage2D(target, level, clippedX - x, clippedY - y,
clippedX, clippedY, clippedWidth, clippedHeight);
}
- } else
- m_context->copyTexImage2D(target, level, internalformat, x, y, width, height, border);
+ } else {
+ if (width > 0 && height > 0)
+ m_context->copyTexImage2D(target, level, internalformat,
+ x, y, width, height, border);
+ }
}
// FIXME: if the framebuffer is not complete, none of the below should be executed.
tex->setLevelInfo(target, level, internalformat, width, height, GraphicsContext3D::UNSIGNED_BYTE);
@@ -1914,6 +1941,12 @@ WebGLGetInfo WebGLRenderingContext::getBufferParameter(GC3Denum target, GC3Denum
return WebGLGetInfo();
}
+ // Some platforms fail to raise INVALID_OPERATION if no array buffer is bound
+ if (target == GraphicsContext3D::ARRAY_BUFFER && !m_boundArrayBuffer) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
+ return WebGLGetInfo();
+ }
+
WebGLStateRestorer(this, false);
GC3Dint value = 0;
m_context->getBufferParameteriv(target, pname, &value);
@@ -2647,14 +2680,6 @@ GC3Dboolean WebGLRenderingContext::isBuffer(WebGLBuffer* buffer)
bool WebGLRenderingContext::isContextLost()
{
- if (m_restoreTimer.isActive())
- return true;
-
- bool newContextLost = m_context->getExtensions()->getGraphicsResetStatusARB() != GraphicsContext3D::NO_ERROR;
-
- if (newContextLost != m_contextLost)
- m_restoreTimer.startOneShot(secondsBetweenRestoreAttempts);
-
return m_contextLost;
}
@@ -2850,7 +2875,51 @@ void WebGLRenderingContext::readPixels(GC3Dint x, GC3Dint y, GC3Dsizei width, GC
}
clearIfComposited();
void* data = pixels->baseAddress();
- m_context->readPixels(x, y, width, height, format, type, data);
+
+ // WebGL requires that areas lying outside the frame buffer should be filled with 0.
+ // Most OpenGL platforms do not support this directly.
+ GC3Dint clippedX, clippedY;
+ GC3Dsizei clippedWidth, clippedHeight;
+ if (clip2D(x, y, width, height, getBoundFramebufferWidth(), getBoundFramebufferHeight(),
+ &clippedX, &clippedY, &clippedWidth, &clippedHeight)) {
+ unsigned int padding = 0;
+ m_context->computeImageSizeInBytes(format, type, clippedWidth, clippedHeight,
+ m_packAlignment, &totalBytesRequired, &padding);
+ char *tmp = (char *)fastMalloc(totalBytesRequired);
+ // Some platforms incorrectly signal GL_INVALID_VALUE if width == 0 || height == 0
+ if (clippedWidth > 0 && clippedHeight > 0)
+ m_context->readPixels(clippedX, clippedY, clippedWidth,
+ clippedHeight, format, type, tmp);
+
+ unsigned int bytesPerComponent, componentsPerPixel;
+ m_context->computeFormatAndTypeParameters(format, type, &componentsPerPixel,
+ &bytesPerComponent);
+ int clippedRowBytes = bytesPerComponent * componentsPerPixel * clippedWidth;
+ int clippedStride = clippedRowBytes + padding;
+ int rowBytes = bytesPerComponent * componentsPerPixel * width;
+ int stride = rowBytes + padding;
+ char *src = tmp;
+ char *dst = (char *)data;
+ int xdelta = (clippedX - x) * bytesPerComponent * componentsPerPixel;
+ for (int r = y; r < y + height; r++) {
+ if (r < y + height - 1)
+ memset(dst, 0, stride);
+ else
+ memset(dst, 0, rowBytes);
+ if (r >= clippedY && r < clippedY + clippedHeight) {
+ memcpy(dst + xdelta, src, clippedRowBytes);
+ src += clippedStride;
+ }
+ dst += stride;
+ }
+ fastFree(tmp);
+ }
+ else {
+ // Some platforms incorrectly signal GL_INVALID_VALUE if width == 0 || height == 0
+ if (width > 0 && height > 0)
+ m_context->readPixels(x, y, width, height, format, type, data);
+ }
+
#if OS(DARWIN)
// FIXME: remove this section when GL driver bug on Mac is fixed, i.e.,
// when alpha is off, readPixels should set alpha to 255 instead of 0.
@@ -3145,7 +3214,6 @@ void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum
ec = SECURITY_ERR;
return;
}
-
texImage2DImpl(target, level, internalformat, format, type, image->cachedImage()->image(),
m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
}
@@ -3173,7 +3241,8 @@ void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum
}
#if ENABLE(VIDEO)
-PassRefPtr<Image> WebGLRenderingContext::videoFrameToImage(HTMLVideoElement* video, ExceptionCode& ec)
+PassRefPtr<Image> WebGLRenderingContext::videoFrameToImage(HTMLVideoElement* video,
+ ExceptionCode& ec)
{
if (!video || !video->videoWidth() || !video->videoHeight()) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
@@ -3887,17 +3956,30 @@ void WebGLRenderingContext::viewport(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3D
cleanupAfterGraphicsCall(false);
}
-void WebGLRenderingContext::forceLostContext()
+void WebGLRenderingContext::forceLostContext(WebGLRenderingContext::LostContextMode mode)
{
if (isContextLost()) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
return;
}
- m_restoreTimer.startOneShot(0);
+ loseContext();
+
+ if (mode == RealLostContext)
+ m_restoreTimer.startOneShot(0);
}
-void WebGLRenderingContext::onLostContext()
+void WebGLRenderingContext::forceRestoreContext()
+{
+ if (!isContextLost()) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
+ return;
+ }
+
+ maybeRestoreContext(SyntheticLostContext);
+}
+
+void WebGLRenderingContext::loseContext()
{
m_contextLost = true;
@@ -3905,7 +3987,7 @@ void WebGLRenderingContext::onLostContext()
// There is no direct way to clear errors from a GL implementation and
// looping until getError() becomes NO_ERROR might cause an infinite loop if
- // the driver or context implementation had a bug. So, loop a reasonably
+ // the driver or context implementation had a bug. So, loop a reasonably
// large number of times to clear any existing errors.
for (int i = 0; i < 100; ++i) {
if (m_context->getError() == GraphicsContext3D::NO_ERROR)
@@ -3913,14 +3995,67 @@ void WebGLRenderingContext::onLostContext()
}
m_context->synthesizeGLError(GraphicsContext3D::CONTEXT_LOST_WEBGL);
- canvas()->dispatchEvent(WebGLContextEvent::create(eventNames().webglcontextlostEvent, false, true, ""));
+ RefPtr<WebGLContextEvent> event = WebGLContextEvent::create(eventNames().webglcontextlostEvent, false, true, "");
+ canvas()->dispatchEvent(event);
+ m_restoreAllowed = event->defaultPrevented();
}
-void WebGLRenderingContext::restoreContext()
+void WebGLRenderingContext::maybeRestoreContext(WebGLRenderingContext::LostContextMode mode)
{
+ if (!m_contextLost) {
+ ASSERT(mode == SyntheticLostContext);
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
+ return;
+ }
+
+ // The rendering context is not restored unless the default
+ // behavior of the webglcontextlost event was prevented earlier.
+ if (!m_restoreAllowed) {
+ if (mode == SyntheticLostContext)
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
+ return;
+ }
+
+ int contextLostReason = m_context->getExtensions()->getGraphicsResetStatusARB();
+
+ switch (contextLostReason) {
+ case GraphicsContext3D::NO_ERROR:
+ // The GraphicsContext3D implementation might not fully
+ // support GL_ARB_robustness semantics yet. Alternatively, the
+ // WebGL WEBKIT_lose_context extension might have been used to
+ // force a lost context.
+ break;
+ case Extensions3D::GUILTY_CONTEXT_RESET_ARB:
+ // The rendering context is not restored if this context was
+ // guilty of causing the graphics reset.
+ printWarningToConsole("WARNING: WebGL content on the page caused the graphics card to reset; not restoring the context");
+ return;
+ case Extensions3D::INNOCENT_CONTEXT_RESET_ARB:
+ // Always allow the context to be restored.
+ break;
+ case Extensions3D::UNKNOWN_CONTEXT_RESET_ARB:
+ // Warn. Ideally, prompt the user telling them that WebGL
+ // content on the page might have caused the graphics card to
+ // reset and ask them whether they want to continue running
+ // the content. Only if they say "yes" should we start
+ // attempting to restore the context.
+ printWarningToConsole("WARNING: WebGL content on the page might have caused the graphics card to reset");
+ break;
+ }
+
+#if PLATFORM(ANDROID)
+ RefPtr<GraphicsContext3D> context(GraphicsContext3D::create(canvas(), m_attributes, 0));
+#else
RefPtr<GraphicsContext3D> context(GraphicsContext3D::create(m_attributes, canvas()->document()->view()->root()->hostWindow()));
- if (!context)
+#endif
+ if (!context) {
+ if (mode == RealLostContext)
+ m_restoreTimer.startOneShot(secondsBetweenRestoreAttempts);
+ else
+ // This likely shouldn't happen but is the best way to report it to the WebGL app.
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
return;
+ }
m_context = context;
m_contextLost = false;
diff --git a/Source/WebCore/html/canvas/WebGLRenderingContext.h b/Source/WebCore/html/canvas/WebGLRenderingContext.h
index 9eb170b..5a2d406 100644
--- a/Source/WebCore/html/canvas/WebGLRenderingContext.h
+++ b/Source/WebCore/html/canvas/WebGLRenderingContext.h
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2011 Sony Ericsson Mobile Communications AB
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -71,6 +72,9 @@ public:
virtual bool isAccelerated() const { return true; }
virtual bool paintsIntoCanvasBuffer() const;
+ GC3Dsizei drawingBufferWidth();
+ GC3Dsizei drawingBufferHeight();
+
void activeTexture(GC3Denum texture, ExceptionCode&);
void attachShader(WebGLProgram*, WebGLShader*, ExceptionCode&);
void bindAttribLocation(WebGLProgram*, GC3Duint index, const String& name, ExceptionCode&);
@@ -274,9 +278,16 @@ public:
void viewport(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height);
- void forceLostContext();
- void onLostContext();
- void restoreContext();
+ // WEBKIT_lose_context support
+ enum LostContextMode {
+ // Lost context occurred at the graphics system level.
+ RealLostContext,
+
+ // Lost context provoked by WEBKIT_lose_context.
+ SyntheticLostContext
+ };
+ void forceLostContext(LostContextMode);
+ void forceRestoreContext();
GraphicsContext3D* graphicsContext3D() const { return m_context.get(); }
#if USE(ACCELERATED_COMPOSITING)
@@ -297,6 +308,11 @@ public:
int getNumberOfExtensions();
WebGLExtension* getExtensionNumber(int i);
+#if PLATFORM(ANDROID)
+ void recreateSurface();
+ void releaseSurface();
+#endif
+
private:
friend class WebGLObject;
friend class OESVertexArrayObject;
@@ -361,6 +377,7 @@ public:
WebGLRenderingContext* m_context;
};
+ bool m_restoreAllowed;
WebGLRenderingContextRestoreTimer m_restoreTimer;
bool m_needsUpdate;
@@ -612,6 +629,10 @@ public:
bool simulateVertexAttrib0(GC3Dsizei numVertex);
void restoreStatesAfterVertexAttrib0Simulation();
+ void loseContext();
+ // Helper for restoration after context lost.
+ void maybeRestoreContext(LostContextMode);
+
friend class WebGLStateRestorer;
};
diff --git a/Source/WebCore/html/canvas/WebGLRenderingContext.idl b/Source/WebCore/html/canvas/WebGLRenderingContext.idl
index 7a19814..305ea7c 100644
--- a/Source/WebCore/html/canvas/WebGLRenderingContext.idl
+++ b/Source/WebCore/html/canvas/WebGLRenderingContext.idl
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2011 Sony Ericsson Mobile Communications AB
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -450,6 +451,9 @@ module html {
const unsigned int UNPACK_COLORSPACE_CONVERSION_WEBGL = 0x9243;
const unsigned int BROWSER_DEFAULT_WEBGL = 0x9244;
+ readonly attribute unsigned int drawingBufferWidth;
+ readonly attribute unsigned int drawingBufferHeight;
+
[StrictTypeChecking] void activeTexture(in unsigned long texture) raises(DOMException);
[StrictTypeChecking] void attachShader(in WebGLProgram program, in WebGLShader shader) raises(DOMException);
[StrictTypeChecking] void bindAttribLocation(in WebGLProgram program, in unsigned long index, in DOMString name) raises(DOMException);
diff --git a/Source/WebCore/html/canvas/WebKitLoseContext.cpp b/Source/WebCore/html/canvas/WebKitLoseContext.cpp
index c594e32..3c0a5f3 100644
--- a/Source/WebCore/html/canvas/WebKitLoseContext.cpp
+++ b/Source/WebCore/html/canvas/WebKitLoseContext.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2010 Google Inc. All rights reserved.
+ * Copyright (C) 2012 Sony Ericsson Mobile Communications AB
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -56,7 +57,13 @@ PassRefPtr<WebKitLoseContext> WebKitLoseContext::create(WebGLRenderingContext* c
void WebKitLoseContext::loseContext()
{
if (m_context)
- m_context->forceLostContext();
+ m_context->forceLostContext(WebGLRenderingContext::SyntheticLostContext);
+}
+
+void WebKitLoseContext::restoreContext()
+{
+ if (m_context)
+ m_context->forceRestoreContext();
}
} // namespace WebCore
diff --git a/Source/WebCore/html/canvas/WebKitLoseContext.h b/Source/WebCore/html/canvas/WebKitLoseContext.h
index b713bef..5822e54 100644
--- a/Source/WebCore/html/canvas/WebKitLoseContext.h
+++ b/Source/WebCore/html/canvas/WebKitLoseContext.h
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2010 Google Inc. All rights reserved.
+ * Copyright (C) 2012 Sony Ericsson Mobile Communications AB
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -42,6 +43,7 @@ public:
virtual ExtensionName getName() const;
void loseContext();
+ void restoreContext();
void contextDestroyed() { m_context = 0; }
private:
diff --git a/Source/WebCore/html/canvas/WebKitLoseContext.idl b/Source/WebCore/html/canvas/WebKitLoseContext.idl
index 83fc909..8b249bd 100644
--- a/Source/WebCore/html/canvas/WebKitLoseContext.idl
+++ b/Source/WebCore/html/canvas/WebKitLoseContext.idl
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2010 Google Inc. All rights reserved.
+ * Copyright (C) 2012 Sony Ericsson Mobile Communications AB
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -26,5 +27,6 @@
module html {
interface [Conditional=WEBGL, OmitConstructor] WebKitLoseContext {
[StrictTypeChecking] void loseContext();
+ [StrictTypeChecking] void restoreContext();
};
}
diff --git a/Source/WebCore/platform/graphics/ANGLEWebKitBridge.h b/Source/WebCore/platform/graphics/ANGLEWebKitBridge.h
index a9d2238..e8008a7 100644
--- a/Source/WebCore/platform/graphics/ANGLEWebKitBridge.h
+++ b/Source/WebCore/platform/graphics/ANGLEWebKitBridge.h
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2011, Sony Ericsson Mobile Communications AB
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -29,7 +30,7 @@
#include "PlatformString.h"
#include <wtf/text/CString.h>
-#if !PLATFORM(GTK)
+#if !PLATFORM(GTK) && !PLATFORM(ANDROID)
#include "ANGLE/ShaderLang.h"
#else
#include "ShaderLang.h"
diff --git a/Source/WebCore/platform/graphics/GraphicsContext3D.cpp b/Source/WebCore/platform/graphics/GraphicsContext3D.cpp
index 324fed8..4aa5bcf 100644
--- a/Source/WebCore/platform/graphics/GraphicsContext3D.cpp
+++ b/Source/WebCore/platform/graphics/GraphicsContext3D.cpp
@@ -56,10 +56,13 @@ namespace {
} // anonymous namespace
-
PassRefPtr<DrawingBuffer> GraphicsContext3D::createDrawingBuffer(const IntSize& size)
{
- return DrawingBuffer::create(this, size);
+#if ENABLE(ACCELERATED_2D_CANVAS)
+ return DrawingBuffer::create(this, size);
+#else
+ return 0;
+#endif
}
bool GraphicsContext3D::texImage2DResourceSafe(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, GC3Dint unpackAlignment)
diff --git a/Source/WebCore/platform/graphics/GraphicsContext3D.h b/Source/WebCore/platform/graphics/GraphicsContext3D.h
index 80226cf..b2a4d3a 100644
--- a/Source/WebCore/platform/graphics/GraphicsContext3D.h
+++ b/Source/WebCore/platform/graphics/GraphicsContext3D.h
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2011, Sony Ericsson Mobile Communications AB
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -88,6 +89,9 @@ class Extensions3D;
class Extensions3DOpenGL;
#endif
class HostWindow;
+#if PLATFORM(ANDROID)
+class HTMLCanvasElement;
+#endif
class Image;
class ImageData;
#if USE(CAIRO)
@@ -101,7 +105,7 @@ struct ActiveInfo {
};
// FIXME: ideally this would be used on all platforms.
-#if PLATFORM(CHROMIUM) || PLATFORM(QT) || PLATFORM(GTK)
+#if PLATFORM(ANDROID) || PLATFORM(CHROMIUM) || PLATFORM(QT) || PLATFORM(GTK)
class GraphicsContext3DInternal;
#endif
@@ -452,7 +456,12 @@ public:
void setContextLostCallback(PassOwnPtr<ContextLostCallback>);
+#if PLATFORM(ANDROID)
+ static PassRefPtr<GraphicsContext3D> create(HTMLCanvasElement*, Attributes,
+ HostWindow*, RenderStyle = RenderOffscreen);
+#else
static PassRefPtr<GraphicsContext3D> create(Attributes, HostWindow*, RenderStyle = RenderOffscreen);
+#endif
~GraphicsContext3D();
#if PLATFORM(MAC)
@@ -474,6 +483,12 @@ public:
#elif PLATFORM(GTK)
PlatformGraphicsContext3D platformGraphicsContext3D();
Platform3DObject platformTexture() const { return m_texture; }
+#elif PLATFORM(ANDROID)
+ PlatformGraphicsContext3D platformGraphicsContext3D();
+ Platform3DObject platformTexture() const;
+#if USE(ACCELERATED_COMPOSITING)
+ PlatformLayer* platformLayer() const;
+#endif
#else
PlatformGraphicsContext3D platformGraphicsContext3D() const { return NullPlatformGraphicsContext3D; }
Platform3DObject platformTexture() const { return NullPlatform3DObject; }
@@ -770,12 +785,18 @@ public:
int canvasWidth, int canvasHeight, PlatformContextCairo* context);
#endif
+#if PLATFORM(ANDROID)
+ void recreateSurface();
+ void releaseSurface();
+#endif
+
void markContextChanged();
void markLayerComposited();
bool layerComposited() const;
void paintRenderingResultsToCanvas(CanvasRenderingContext* context);
PassRefPtr<ImageData> paintRenderingResultsToImageData();
+ bool paintCompositedResultsToCanvas(CanvasRenderingContext* context);
#if PLATFORM(QT)
bool paintsIntoCanvasBuffer() const { return true; }
@@ -821,7 +842,12 @@ public:
IntSize getInternalFramebufferSize();
private:
+#if PLATFORM(ANDROID)
+ GraphicsContext3D(HTMLCanvasElement* canvas, Attributes attrs,
+ HostWindow* hostWindow, bool renderDirectlyToHostWindow);
+#else
GraphicsContext3D(Attributes attrs, HostWindow* hostWindow, bool renderDirectlyToHostWindow);
+#endif
// Each platform must provide an implementation of this method.
//
@@ -929,7 +955,7 @@ public:
#endif
// FIXME: ideally this would be used on all platforms.
-#if PLATFORM(CHROMIUM) || PLATFORM(QT) || PLATFORM(GTK)
+#if PLATFORM(ANDROID) || PLATFORM(CHROMIUM) || PLATFORM(QT) || PLATFORM(GTK)
friend class GraphicsContext3DInternal;
OwnPtr<GraphicsContext3DInternal> m_internal;
#endif
diff --git a/Source/WebCore/platform/graphics/android/Extensions3DAndroid.cpp b/Source/WebCore/platform/graphics/android/Extensions3DAndroid.cpp
new file mode 100644
index 0000000..a2c63d2
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/Extensions3DAndroid.cpp
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2011, Sony Ericsson Mobile Communications AB
+ * All rights reserved.
+ *
+ * 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.
+ * * Neither the name of the Sony Ericsson Mobile Communications AB nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 SONY ERICSSON MOBILE COMMUNICATIONS AB 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"
+
+#if ENABLE(WEBGL)
+
+#include "Extensions3DAndroid.h"
+#include "GraphicsContext3D.h"
+
+#include <GLES2/gl2.h>
+
+namespace WebCore {
+
+Extensions3DAndroid::Extensions3DAndroid(const char* extensions)
+ : m_extensions(extensions)
+{
+}
+
+Extensions3DAndroid::~Extensions3DAndroid()
+{
+}
+
+bool Extensions3DAndroid::supports(const String& ext)
+{
+ return m_extensions.contains(ext);
+}
+
+void Extensions3DAndroid::ensureEnabled(const String& name)
+{
+}
+
+bool Extensions3DAndroid::isEnabled(const String& name)
+{
+ return supports(name);
+}
+
+int Extensions3DAndroid::getGraphicsResetStatusARB()
+{
+ return GraphicsContext3D::NO_ERROR;
+}
+
+void Extensions3DAndroid::blitFramebuffer(long srcX0, long srcY0, long srcX1, long srcY1,
+ long dstX0, long dstY0, long dstX1, long dstY1,
+ unsigned long mask, unsigned long filter)
+{
+}
+
+void Extensions3DAndroid::renderbufferStorageMultisample(unsigned long target,
+ unsigned long samples,
+ unsigned long internalformat,
+ unsigned long width,
+ unsigned long height)
+{
+}
+
+Platform3DObject Extensions3DAndroid::createVertexArrayOES()
+{
+ return 0;
+}
+
+void Extensions3DAndroid::deleteVertexArrayOES(Platform3DObject)
+{
+}
+
+GC3Dboolean Extensions3DAndroid::isVertexArrayOES(Platform3DObject)
+{
+ return GL_FALSE;
+}
+
+void Extensions3DAndroid::bindVertexArrayOES(Platform3DObject)
+{
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(WEBGL)
diff --git a/Source/WebCore/platform/graphics/android/Extensions3DAndroid.h b/Source/WebCore/platform/graphics/android/Extensions3DAndroid.h
new file mode 100644
index 0000000..3f72ab0
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/Extensions3DAndroid.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2011, Sony Ericsson Mobile Communications AB
+ * All rights reserved.
+ *
+ * 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.
+ * * Neither the name of the Sony Ericsson Mobile Communications AB nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 SONY ERICSSON MOBILE COMMUNICATIONS AB 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 Extensions3DAndroid_h
+#define Extensions3DAndroid_h
+
+#include "Extensions3D.h"
+#include "PlatformString.h"
+
+namespace WebCore {
+
+class Extensions3DAndroid : public Extensions3D {
+public:
+ Extensions3DAndroid(const char* extensions);
+ virtual ~Extensions3DAndroid();
+
+ // Extensions3D methods.
+ virtual bool supports(const String&);
+ virtual void ensureEnabled(const String&);
+ virtual bool isEnabled(const String&);
+ virtual int getGraphicsResetStatusARB();
+ virtual void blitFramebuffer(long srcX0, long srcY0, long srcX1, long srcY1,
+ long dstX0, long dstY0, long dstX1, long dstY1,
+ unsigned long mask, unsigned long filter);
+ virtual void renderbufferStorageMultisample(unsigned long target, unsigned long samples,
+ unsigned long internalformat, unsigned long width,
+ unsigned long height);
+ virtual Platform3DObject createVertexArrayOES();
+ virtual void deleteVertexArrayOES(Platform3DObject);
+ virtual GC3Dboolean isVertexArrayOES(Platform3DObject);
+ virtual void bindVertexArrayOES(Platform3DObject);
+
+private:
+ String m_extensions;
+};
+
+} // namespace WebCore
+
+#endif // Extensions3DAndroid_h
diff --git a/Source/WebCore/platform/graphics/android/GraphicsContext3DAndroid.cpp b/Source/WebCore/platform/graphics/android/GraphicsContext3DAndroid.cpp
new file mode 100644
index 0000000..df706a2
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/GraphicsContext3DAndroid.cpp
@@ -0,0 +1,1368 @@
+/*
+ * Copyright (C) 2011, 2012, Sony Ericsson Mobile Communications AB
+ * Copyright (C) 2012 Sony Mobile Communications AB
+ * All rights reserved.
+ *
+ * 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.
+ * * Neither the name of the Sony Ericsson Mobile Communications AB nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 SONY ERICSSON MOBILE COMMUNICATIONS AB 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"
+
+#if ENABLE(WEBGL)
+#include "BitmapImage.h"
+#include "text/CString.h"
+#include "GraphicsContext3D.h"
+#include "GraphicsContext3DInternal.h"
+#include "Image.h"
+#include "ImageData.h"
+#include "ImageDecoder.h"
+#include "SkBitmap.h"
+#include "SkBitmapRef.h"
+
+namespace WebCore {
+
+
+PassRefPtr<GraphicsContext3D> GraphicsContext3D::create(HTMLCanvasElement* canvas, Attributes attrs,
+ HostWindow *win, RenderStyle style)
+{
+ GraphicsContext3D *context = new GraphicsContext3D(canvas, attrs, win, false);
+ if (!context->m_internal->isValid()) {
+ // Something failed during initialization
+ delete context;
+ return 0;
+ }
+ return adoptRef(context);
+}
+
+GraphicsContext3D::GraphicsContext3D(HTMLCanvasElement* canvas, Attributes attrs,
+ HostWindow* hostWindow, bool renderDirectlyToHostWindow)
+ : m_internal(new GraphicsContext3DInternal(canvas, attrs, hostWindow))
+{
+ LOGWEBGL("GraphicsContext3D() = %p", this);
+ m_currentWidth = m_internal->width();
+ m_currentHeight = m_internal->height();
+}
+
+GraphicsContext3D::~GraphicsContext3D()
+{
+ LOGWEBGL("~GraphicsContext3D()");
+}
+
+PlatformLayer* GraphicsContext3D::platformLayer() const
+{
+ return m_internal->platformLayer();
+}
+
+void GraphicsContext3D::makeContextCurrent() {
+ m_internal->makeContextCurrent();
+}
+
+bool GraphicsContext3D::isGLES2Compliant() const
+{
+ return true;
+}
+
+void GraphicsContext3D::synthesizeGLError(GC3Denum error)
+{
+ m_internal->synthesizeGLError(error);
+}
+
+Extensions3D* GraphicsContext3D::getExtensions()
+{
+ return m_internal->getExtensions();
+}
+
+void GraphicsContext3D::paintRenderingResultsToCanvas(CanvasRenderingContext* context)
+{
+ makeContextCurrent();
+ m_internal->paintRenderingResultsToCanvas(context);
+}
+
+PassRefPtr<ImageData> GraphicsContext3D::paintRenderingResultsToImageData()
+{
+ makeContextCurrent();
+ return m_internal->paintRenderingResultsToImageData();
+}
+
+bool GraphicsContext3D::paintCompositedResultsToCanvas(CanvasRenderingContext* context)
+{
+ makeContextCurrent();
+ return m_internal->paintCompositedResultsToCanvas(context);
+}
+
+bool GraphicsContext3D::getImageData(Image* image,
+ unsigned int format,
+ unsigned int type,
+ bool premultiplyAlpha,
+ bool ignoreGammaAndColorProfile,
+ Vector<uint8_t>& outputVector)
+{
+ LOGWEBGL("getImageData(%p, %u, %u, %s, %s)", image, format, type,
+ premultiplyAlpha ? "true" : "false", ignoreGammaAndColorProfile ? "true" : "false");
+ if (!image)
+ return false;
+
+ AlphaOp neededAlphaOp = AlphaDoNothing;
+ bool hasAlpha = (image->data() && image->isBitmapImage()) ?
+ static_cast<BitmapImage*>(image)->frameHasAlphaAtIndex(0) : true;
+ ImageDecoder* decoder = 0;
+ ImageFrame* buf = 0;
+
+ if ((ignoreGammaAndColorProfile || (hasAlpha && !premultiplyAlpha)) && image->data()) {
+ // Attempt to get raw unpremultiplied image data
+ decoder = ImageDecoder::create(*(image->data()),
+ premultiplyAlpha ?
+ ImageSource::AlphaPremultiplied :
+ ImageSource::AlphaNotPremultiplied,
+ ignoreGammaAndColorProfile ?
+ ImageSource::GammaAndColorProfileIgnored :
+ ImageSource::GammaAndColorProfileApplied);
+ if (decoder) {
+ decoder->setData(image->data(), true);
+ buf = decoder->frameBufferAtIndex(0);
+ if (buf && buf->hasAlpha() && premultiplyAlpha)
+ neededAlphaOp = AlphaDoPremultiply;
+ }
+ }
+
+ SkBitmapRef* bitmapRef = 0;
+ if (!buf) {
+ bitmapRef = image->nativeImageForCurrentFrame();
+ if (!bitmapRef)
+ return false;
+ if (!premultiplyAlpha && hasAlpha)
+ neededAlphaOp = AlphaDoUnmultiply;
+ }
+
+ SkBitmap& bitmap = buf ? buf->bitmap() : bitmapRef->bitmap();
+ unsigned char* pixels = 0;
+ int rowBytes = 0;
+ uint32_t* tmpPixels = 0;
+
+ int width = bitmap.width();
+ int height = bitmap.height();
+ int iwidth = image->width();
+ int iheight = image->height();
+ LOGWEBGL(" bitmap.width() = %d, image->width() = %d, bitmap.height = %d, image->height() = %d",
+ width, iwidth, height, iheight);
+ if (width != iwidth || height != iheight) {
+ // This image has probably been subsampled because it was too big.
+ // Currently, we cannot handle this in WebGL: give up.
+ return false;
+ }
+ SkBitmap::Config skiaConfig = bitmap.getConfig();
+
+ bitmap.lockPixels();
+ if (skiaConfig == SkBitmap::kARGB_8888_Config) {
+ LOGWEBGL(" skiaConfig = kARGB_8888_Config");
+ pixels = reinterpret_cast<unsigned char*>(bitmap.getPixels());
+ rowBytes = bitmap.rowBytes();
+ if (!pixels) {
+ bitmap.unlockPixels();
+ return false;
+ }
+ }
+ else if (skiaConfig == SkBitmap::kIndex8_Config) {
+ LOGWEBGL(" skiaConfig = kIndex8_Config");
+ rowBytes = width * 4;
+ tmpPixels = (uint32_t*)fastMalloc(width * height * 4);
+ if (!tmpPixels) {
+ bitmap.unlockPixels();
+ return false;
+ }
+ for (int i = 0; i < height; i++) {
+ for (int j = 0; j < width; j++) {
+ SkPMColor c = bitmap.getIndex8Color(j, i);
+ tmpPixels[i * width + j] = c;//SkExpand_8888(c);
+ }
+ }
+ pixels = (unsigned char*)tmpPixels;
+ }
+
+ outputVector.resize(rowBytes * height);
+ LOGWEBGL("rowBytes() = %d, width() = %d, height() = %d", rowBytes, width, height);
+
+ bool res = packPixels(pixels,
+ SourceFormatRGBA8, width, height, 0,
+ format, type, neededAlphaOp, outputVector.data());
+ bitmap.unlockPixels();
+
+ if (decoder)
+ delete decoder;
+
+ if (tmpPixels)
+ fastFree(tmpPixels);
+
+ return res;
+}
+
+unsigned GraphicsContext3D::createBuffer()
+{
+ LOGWEBGL("glCreateBuffer()");
+ makeContextCurrent();
+ GLuint b = 0;
+ glGenBuffers(1, &b);
+ return b;
+}
+
+unsigned GraphicsContext3D::createFramebuffer()
+{
+ LOGWEBGL("glCreateFramebuffer()");
+ makeContextCurrent();
+ GLuint fb = 0;
+ glGenFramebuffers(1, &fb);
+ return fb;
+}
+
+unsigned GraphicsContext3D::createProgram()
+{
+ LOGWEBGL("glCreateProgram()");
+ makeContextCurrent();
+ return glCreateProgram();
+}
+
+unsigned GraphicsContext3D::createRenderbuffer()
+{
+ LOGWEBGL("glCreateRenderbuffer()");
+ makeContextCurrent();
+ GLuint rb = 0;
+ glGenRenderbuffers(1, &rb);
+ return rb;
+}
+
+unsigned GraphicsContext3D::createShader(GC3Denum type)
+{
+ LOGWEBGL("glCreateShader()");
+ makeContextCurrent();
+ return glCreateShader((type == FRAGMENT_SHADER) ? GL_FRAGMENT_SHADER : GL_VERTEX_SHADER);
+}
+
+unsigned GraphicsContext3D::createTexture()
+{
+ LOGWEBGL("glCreateTexture()");
+ makeContextCurrent();
+ GLuint t = 0;
+ glGenTextures(1, &t);
+ return t;
+}
+
+void GraphicsContext3D::deleteBuffer(unsigned buffer)
+{
+ LOGWEBGL("glDeleteBuffers()");
+ makeContextCurrent();
+ glDeleteBuffers(1, &buffer);
+}
+
+void GraphicsContext3D::deleteFramebuffer(unsigned framebuffer)
+{
+ LOGWEBGL("glDeleteFramebuffers()");
+ makeContextCurrent();
+ glDeleteFramebuffers(1, &framebuffer);
+}
+
+void GraphicsContext3D::deleteProgram(unsigned program)
+{
+ LOGWEBGL("glDeleteProgram()");
+ makeContextCurrent();
+ glDeleteProgram(program);
+}
+
+void GraphicsContext3D::deleteRenderbuffer(unsigned renderbuffer)
+{
+ LOGWEBGL("glDeleteRenderbuffers()");
+ makeContextCurrent();
+ glDeleteRenderbuffers(1, &renderbuffer);
+}
+
+void GraphicsContext3D::deleteShader(unsigned shader)
+{
+ LOGWEBGL("glDeleteShader()");
+ makeContextCurrent();
+ glDeleteShader(shader);
+}
+
+void GraphicsContext3D::deleteTexture(unsigned texture)
+{
+ LOGWEBGL("glDeleteTextures()");
+ makeContextCurrent();
+ glDeleteTextures(1, &texture);
+}
+
+
+void GraphicsContext3D::activeTexture(GC3Denum texture)
+{
+ LOGWEBGL("glActiveTexture(%ld)", texture);
+ makeContextCurrent();
+ glActiveTexture(texture);
+}
+
+void GraphicsContext3D::attachShader(Platform3DObject program, Platform3DObject shader)
+{
+ LOGWEBGL("glAttachShader(%d, %d)", program, shader);
+ makeContextCurrent();
+ glAttachShader(program, shader);
+}
+
+void GraphicsContext3D::bindAttribLocation(Platform3DObject program, GC3Duint index,
+ const String& name)
+{
+ CString cs = name.utf8();
+ LOGWEBGL("glBindAttribLocation(%d, %d, %s)", program, index, cs.data());
+ if (!program)
+ return;
+ makeContextCurrent();
+ glBindAttribLocation(program, index, cs.data());
+}
+
+void GraphicsContext3D::bindBuffer(GC3Denum target, Platform3DObject buffer)
+{
+ LOGWEBGL("glBindBuffer(%d, %d)", target, buffer);
+ makeContextCurrent();
+ glBindBuffer(target, buffer);
+}
+
+void GraphicsContext3D::bindFramebuffer(GC3Denum target, Platform3DObject framebuffer)
+{
+ LOGWEBGL("bindFrameBuffer(%d, %d)", target, framebuffer);
+ m_internal->bindFramebuffer(target, framebuffer);
+}
+
+void GraphicsContext3D::bindRenderbuffer(GC3Denum target, Platform3DObject renderbuffer)
+{
+ LOGWEBGL("glBindRenderBuffer(%d, %d)", target, renderbuffer);
+ makeContextCurrent();
+ glBindRenderbuffer(target, renderbuffer);
+}
+
+void GraphicsContext3D::bindTexture(GC3Denum target, Platform3DObject texture)
+{
+ LOGWEBGL("glBindTexture(%d, %d)", target, texture);
+ makeContextCurrent();
+ glBindTexture(target, texture);
+}
+
+void GraphicsContext3D::blendColor(GC3Dclampf red, GC3Dclampf green,
+ GC3Dclampf blue, GC3Dclampf alpha)
+{
+ LOGWEBGL("glBlendColor(%lf, %lf, %lf, %lf)", red, green, blue, alpha);
+ makeContextCurrent();
+ glBlendColor(CLAMP(red), CLAMP(green), CLAMP(blue), CLAMP(alpha));
+}
+
+void GraphicsContext3D::blendEquation(GC3Denum mode)
+{
+ LOGWEBGL("glBlendEquation(%d)", mode);
+ makeContextCurrent();
+ glBlendEquation(mode);
+}
+
+void GraphicsContext3D::blendEquationSeparate(GC3Denum modeRGB, GC3Denum modeAlpha)
+{
+ LOGWEBGL("glBlendEquationSeparate(%d, %d)", modeRGB, modeAlpha);
+ makeContextCurrent();
+ glBlendEquationSeparate(modeRGB, modeAlpha);
+}
+
+void GraphicsContext3D::blendFunc(GC3Denum sfactor, GC3Denum dfactor)
+{
+ LOGWEBGL("glBlendFunc(%d, %d)", sfactor, dfactor);
+ makeContextCurrent();
+ glBlendFunc(sfactor, dfactor);
+}
+
+void GraphicsContext3D::blendFuncSeparate(GC3Denum srcRGB, GC3Denum dstRGB,
+ GC3Denum srcAlpha, GC3Denum dstAlpha)
+{
+ LOGWEBGL("glBlendFuncSeparate(%lu, %lu, %lu, %lu)", srcRGB, dstRGB, srcAlpha, dstAlpha);
+ makeContextCurrent();
+ glBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
+}
+
+void GraphicsContext3D::bufferData(GC3Denum target, GC3Dsizeiptr size, GC3Denum usage)
+{
+ LOGWEBGL("glBufferData(%lu, %d, %lu)", target, size, usage);
+ makeContextCurrent();
+ glBufferData(target, size, 0, usage);
+}
+
+void GraphicsContext3D::bufferData(GC3Denum target, GC3Dsizeiptr size,
+ const void* data, GC3Denum usage)
+{
+ LOGWEBGL("glBufferData(%lu, %d, %p, %lu)", target, size, data, usage);
+ makeContextCurrent();
+ glBufferData(target, size, data, usage);
+}
+
+void GraphicsContext3D::bufferSubData(GC3Denum target, GC3Dintptr offset,
+ GC3Dsizeiptr size, const void* data)
+{
+ LOGWEBGL("glBufferSubData(%lu, %ld, %d, %p)", target, offset, size, data);
+ makeContextCurrent();
+ glBufferSubData(target, offset, size, data);
+}
+
+GC3Denum GraphicsContext3D::checkFramebufferStatus(GC3Denum target)
+{
+ LOGWEBGL("glCheckFramebufferStatus(%lu)", target);
+ makeContextCurrent();
+ return glCheckFramebufferStatus(target);
+}
+
+void GraphicsContext3D::clear(GC3Dbitfield mask)
+{
+ LOGWEBGL("glClear(%lu)", mask);
+ makeContextCurrent();
+ glClear(mask);
+}
+
+void GraphicsContext3D::clearColor(GC3Dclampf red, GC3Dclampf green,
+ GC3Dclampf blue, GC3Dclampf alpha)
+{
+ LOGWEBGL("glClearColor(%.2lf, %.2lf, %.2lf, %.2lf)", red, green, blue, alpha);
+ makeContextCurrent();
+ glClearColor(CLAMP(red), CLAMP(green), CLAMP(blue), CLAMP(alpha));
+}
+
+void GraphicsContext3D::clearDepth(GC3Dclampf depth)
+{
+ LOGWEBGL("glClearDepthf(%.2lf)", depth);
+ makeContextCurrent();
+ glClearDepthf(CLAMP(depth));
+}
+
+void GraphicsContext3D::clearStencil(GC3Dint s)
+{
+ LOGWEBGL("glClearStencil(%ld)", s);
+ makeContextCurrent();
+ glClearStencil(s);
+}
+
+void GraphicsContext3D::colorMask(GC3Dboolean red, GC3Dboolean green,
+ GC3Dboolean blue, GC3Dboolean alpha)
+{
+ LOGWEBGL("glColorMask(%s, %s, %s, %s)", red ? "true" : "false", green ? "true" : "false",
+ blue ? "true" : "false", alpha ? "true" : "false");
+ makeContextCurrent();
+ glColorMask(red, green, blue, alpha);
+}
+
+void GraphicsContext3D::compileShader(Platform3DObject shader)
+{
+ LOGWEBGL("compileShader(%lu)", shader);
+ makeContextCurrent();
+ m_internal->compileShader(shader);
+}
+
+void GraphicsContext3D::copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
+ GC3Dint x, GC3Dint y, GC3Dsizei width,
+ GC3Dsizei height, GC3Dint border)
+{
+ LOGWEBGL("glCopyTexImage2D(%lu, %ld, %lu, %ld, %ld, %lu, %lu, %ld",
+ target, level, internalformat, x, y, width, height, border);
+ makeContextCurrent();
+ glCopyTexImage2D(target, level, internalformat, x, y, width, height, border);
+}
+
+void GraphicsContext3D::copyTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset,
+ GC3Dint yoffset, GC3Dint x, GC3Dint y, GC3Dsizei width,
+ GC3Dsizei height)
+{
+ LOGWEBGL("glCopyTexSubImage2D(%lu, %ld, %ld, %ld, %ld, %ld, %lu, %lu)",
+ target, level, xoffset, yoffset, x, y, width, height);
+ makeContextCurrent();
+ glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
+}
+
+void GraphicsContext3D::cullFace(GC3Denum mode)
+{
+ LOGWEBGL("glCullFace(%lu)", mode);
+ makeContextCurrent();
+ glCullFace(mode);
+}
+
+void GraphicsContext3D::depthFunc(GC3Denum func)
+{
+ LOGWEBGL("glDepthFunc(%lu)", func);
+ makeContextCurrent();
+ glDepthFunc(func);
+}
+
+void GraphicsContext3D::depthMask(GC3Dboolean flag)
+{
+ LOGWEBGL("glDepthMask(%s)", flag ? "true" : "false");
+ makeContextCurrent();
+ glDepthMask(flag);
+}
+
+void GraphicsContext3D::depthRange(GC3Dclampf zNear, GC3Dclampf zFar)
+{
+ LOGWEBGL("glDepthRangef(%.2lf, %.2lf)", zNear, zFar);
+ makeContextCurrent();
+ glDepthRangef(CLAMP(zNear), CLAMP(zFar));
+}
+
+void GraphicsContext3D::detachShader(Platform3DObject program, Platform3DObject shader)
+{
+ LOGWEBGL("glDetachShader(%lu, %lu)", program, shader);
+ makeContextCurrent();
+ glDetachShader(program, shader);
+}
+
+void GraphicsContext3D::disable(GC3Denum cap)
+{
+ LOGWEBGL("glDisable(%lu)", cap);
+ makeContextCurrent();
+ glDisable(cap);
+}
+
+void GraphicsContext3D::disableVertexAttribArray(GC3Duint index)
+{
+ LOGWEBGL("glDisableVertexAttribArray(%lu)", index);
+ makeContextCurrent();
+ glDisableVertexAttribArray(index);
+}
+
+void GraphicsContext3D::drawArrays(GC3Denum mode, GC3Dint first, GC3Dsizei count)
+{
+ LOGWEBGL("glDrawArrays(%lu, %ld, %ld)", mode, first, count);
+ makeContextCurrent();
+ glDrawArrays(mode, first, count);
+}
+
+void GraphicsContext3D::drawElements(GC3Denum mode, GC3Dsizei count,
+ GC3Denum type, GC3Dintptr offset)
+{
+ LOGWEBGL("glDrawElements(%lu, %lu, %lu, %ld)", mode, count, type, offset);
+ makeContextCurrent();
+ glDrawElements(mode, count, type, reinterpret_cast<void*>(static_cast<intptr_t>(offset)));
+}
+
+void GraphicsContext3D::enable(GC3Denum cap)
+{
+ LOGWEBGL("glEnable(0x%04x)", cap);
+ makeContextCurrent();
+ glEnable(cap);
+}
+
+void GraphicsContext3D::enableVertexAttribArray(GC3Duint index)
+{
+ LOGWEBGL("glEnableVertexAttribArray(%lu)", index);
+ makeContextCurrent();
+ glEnableVertexAttribArray(index);
+}
+
+void GraphicsContext3D::finish()
+{
+ LOGWEBGL("glFinish()");
+ makeContextCurrent();
+ glFinish();
+}
+
+void GraphicsContext3D::flush()
+{
+ LOGWEBGL("glFlush()");
+ makeContextCurrent();
+ glFlush();
+}
+
+void GraphicsContext3D::framebufferRenderbuffer(GC3Denum target, GC3Denum attachment,
+ GC3Denum renderbuffertarget,
+ Platform3DObject renderbuffer)
+{
+ LOGWEBGL("glFramebufferRenderbuffer(%lu, %lu, %lu, %lu)", target, attachment,
+ renderbuffertarget, renderbuffer);
+ makeContextCurrent();
+ glFramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer);
+}
+
+void GraphicsContext3D::framebufferTexture2D(GC3Denum target, GC3Denum attachment,
+ GC3Denum textarget, Platform3DObject texture,
+ GC3Dint level)
+{
+ LOGWEBGL("glFramebufferTexture2D(%lu, %lu, %lu, %lu, %ld)",
+ target, attachment, textarget, texture, level);
+ makeContextCurrent();
+ glFramebufferTexture2D(target, attachment, textarget, texture, level);
+}
+
+void GraphicsContext3D::frontFace(GC3Denum mode)
+{
+ LOGWEBGL("glFrontFace(%lu)", mode);
+ makeContextCurrent();
+ glFrontFace(mode);
+}
+
+void GraphicsContext3D::generateMipmap(GC3Denum target)
+{
+ LOGWEBGL("glGenerateMipmap(%lu)", target);
+ makeContextCurrent();
+ glGenerateMipmap(target);
+}
+
+bool GraphicsContext3D::getActiveAttrib(Platform3DObject program, GC3Duint index, ActiveInfo& info)
+{
+ LOGWEBGL("glGetActiveAttrib(%lu, %lu)", program, index);
+ if (!program) {
+ synthesizeGLError(INVALID_VALUE);
+ return false;
+ }
+ makeContextCurrent();
+ GLint maxAttributeSize = 0;
+ glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxAttributeSize);
+ GLchar name[maxAttributeSize];
+ GLsizei nameLength = 0;
+ GLint size = 0;
+ GLenum type = 0;
+ glGetActiveAttrib(program, index, maxAttributeSize, &nameLength, &size, &type, name);
+ if (!nameLength)
+ return false;
+ info.name = String(name, nameLength);
+ info.type = type;
+ info.size = size;
+ return true;
+}
+
+bool GraphicsContext3D::getActiveUniform(Platform3DObject program, GC3Duint index, ActiveInfo& info)
+{
+ LOGWEBGL("glGetActiveUniform(%lu, %lu)", program, index);
+ if (!program) {
+ synthesizeGLError(INVALID_VALUE);
+ return false;
+ }
+ makeContextCurrent();
+ GLint maxUniformSize = 0;
+ glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxUniformSize);
+ GLchar name[maxUniformSize];
+ GLsizei nameLength = 0;
+ GLint size = 0;
+ GLenum type = 0;
+ glGetActiveUniform(program, index, maxUniformSize, &nameLength, &size, &type, name);
+ if (!nameLength)
+ return false;
+ info.name = String(name, nameLength);
+ info.type = type;
+ info.size = size;
+ return true;
+}
+
+void GraphicsContext3D::getAttachedShaders(Platform3DObject program, GC3Dsizei maxCount,
+ GC3Dsizei* count, Platform3DObject* shaders)
+{
+ LOGWEBGL("glGetAttachedShaders(%lu, %d, %p, %p)", program, maxCount, count, shaders);
+ if (!program) {
+ synthesizeGLError(INVALID_VALUE);
+ return;
+ }
+ makeContextCurrent();
+ glGetAttachedShaders(program, maxCount, count, shaders);
+}
+
+GC3Dint GraphicsContext3D::getAttribLocation(Platform3DObject program, const String& name)
+{
+ CString cs = name.utf8();
+ LOGWEBGL("glGetAttribLocation(%lu, %s)", program, cs.data());
+ if (!program) {
+ return -1;
+ }
+ makeContextCurrent();
+
+ return glGetAttribLocation(program, cs.data());
+}
+
+void GraphicsContext3D::getBooleanv(GC3Denum pname, GC3Dboolean* value)
+{
+ LOGWEBGL("glGetBooleanv(%lu, %p)", pname, value);
+ makeContextCurrent();
+ glGetBooleanv(pname, value);
+}
+
+void GraphicsContext3D::getBufferParameteriv(GC3Denum target, GC3Denum pname, GC3Dint* value)
+{
+ LOGWEBGL("glGetBufferParameteriv(%lu, %lu, %p)", target, pname, value);
+ makeContextCurrent();
+ glGetBufferParameteriv(target, pname, value);
+}
+
+GraphicsContext3D::Attributes GraphicsContext3D::getContextAttributes()
+{
+ LOGWEBGL("getContextAttributes()");
+ return m_internal->getContextAttributes();
+}
+
+GC3Denum GraphicsContext3D::getError()
+{
+ LOGWEBGL("getError()");
+ return m_internal->getError();
+}
+
+void GraphicsContext3D::getFloatv(GC3Denum pname, GC3Dfloat* value)
+{
+ LOGWEBGL("glGetFloatv(%lu, %p)", pname, value);
+ makeContextCurrent();
+ glGetFloatv(pname, value);
+}
+
+void GraphicsContext3D::getFramebufferAttachmentParameteriv(GC3Denum target, GC3Denum attachment,
+ GC3Denum pname, GC3Dint* value)
+{
+ LOGWEBGL("glGetFramebufferAttachmentParameteriv(%lu, %lu, %lu, %p)",
+ target, attachment, pname, value);
+ makeContextCurrent();
+ if (attachment == DEPTH_STENCIL_ATTACHMENT)
+ attachment = DEPTH_ATTACHMENT;
+ glGetFramebufferAttachmentParameteriv(target, attachment, pname, value);
+}
+
+void GraphicsContext3D::getIntegerv(GC3Denum pname, GC3Dint* value)
+{
+ LOGWEBGL("glGetIntegerv(%lu, %p)", pname, value);
+ makeContextCurrent();
+ glGetIntegerv(pname, value);
+}
+
+void GraphicsContext3D::getProgramiv(Platform3DObject program, GC3Denum pname, GC3Dint* value)
+{
+ LOGWEBGL("glGetProgramiv(%lu, %lu, %p)", program, pname, value);
+ makeContextCurrent();
+ glGetProgramiv(program, pname, value);
+}
+
+String GraphicsContext3D::getProgramInfoLog(Platform3DObject program)
+{
+ LOGWEBGL("glGetProgramInfoLog(%lu)", program);
+ makeContextCurrent();
+ GLint length;
+ glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length);
+ if (!length)
+ return "";
+
+ GLsizei size;
+ GLchar* info = (GLchar*)fastMalloc(length);
+ glGetProgramInfoLog(program, length, &size, info);
+ String s(info);
+ fastFree(info);
+
+ return s;
+}
+
+void GraphicsContext3D::getRenderbufferParameteriv(GC3Denum target, GC3Denum pname, GC3Dint* value)
+{
+ LOGWEBGL("glGetRenderbufferParameteriv(%lu, %lu, %p)", target, pname, value);
+ makeContextCurrent();
+ glGetRenderbufferParameteriv(target, pname, value);
+}
+
+void GraphicsContext3D::getShaderiv(Platform3DObject shader, GC3Denum pname, GC3Dint* value)
+{
+ LOGWEBGL("glGetShaderiv(%lu, %lu, %p)", shader, pname, value);
+ makeContextCurrent();
+ glGetShaderiv(shader, pname, value);
+}
+
+String GraphicsContext3D::getShaderInfoLog(Platform3DObject shader)
+{
+ LOGWEBGL("getShaderInfoLog(%lu)", shader);
+ makeContextCurrent();
+ return m_internal->getShaderInfoLog(shader);
+}
+
+String GraphicsContext3D::getShaderSource(Platform3DObject shader)
+{
+ LOGWEBGL("getShaderSource(%lu)", shader);
+ makeContextCurrent();
+ return m_internal->getShaderSource(shader);
+}
+
+String GraphicsContext3D::getString(GC3Denum name)
+{
+ LOGWEBGL("glGetString(%lu)", name);
+ makeContextCurrent();
+ return String(reinterpret_cast<const char*>(glGetString(name)));
+}
+
+void GraphicsContext3D::getTexParameterfv(GC3Denum target, GC3Denum pname, GC3Dfloat* value)
+{
+ LOGWEBGL("glGetTexParameterfv(%lu, %lu, %p)", target, pname, value);
+ makeContextCurrent();
+ glGetTexParameterfv(target, pname, value);
+}
+
+void GraphicsContext3D::getTexParameteriv(GC3Denum target, GC3Denum pname, GC3Dint* value)
+{
+ LOGWEBGL("glGetTexParameteriv(%lu, %lu, %p)", target, pname, value);
+ makeContextCurrent();
+ glGetTexParameteriv(target, pname, value);
+}
+
+void GraphicsContext3D::getUniformfv(Platform3DObject program, GC3Dint location, GC3Dfloat* value)
+{
+ LOGWEBGL("glGetUniformfv(%lu, %ld, %p)", program, location, value);
+ makeContextCurrent();
+ glGetUniformfv(program, location, value);
+}
+
+void GraphicsContext3D::getUniformiv(Platform3DObject program, GC3Dint location, GC3Dint* value)
+{
+ LOGWEBGL("glGetUniformiv(%lu, %ld, %p)", program, location, value);
+ makeContextCurrent();
+ glGetUniformiv(program, location, value);
+}
+
+GC3Dint GraphicsContext3D::getUniformLocation(Platform3DObject program, const String& name)
+{
+ CString cs = name.utf8();
+ LOGWEBGL("glGetUniformLocation(%lu, %s)", program, cs.data());
+ makeContextCurrent();
+ return glGetUniformLocation(program, cs.data());
+}
+
+void GraphicsContext3D::getVertexAttribfv(GC3Duint index, GC3Denum pname, GC3Dfloat* value)
+{
+ LOGWEBGL("glGetVertexAttribfv(%lu, %lu, %p)", index, pname, value);
+ makeContextCurrent();
+ glGetVertexAttribfv(index, pname, value);
+}
+
+void GraphicsContext3D::getVertexAttribiv(GC3Duint index, GC3Denum pname, GC3Dint* value)
+{
+ LOGWEBGL("glGetVertexAttribiv(%lu, %lu, %p)", index, pname, value);
+ makeContextCurrent();
+ glGetVertexAttribiv(index, pname, value);
+}
+
+GC3Dsizeiptr GraphicsContext3D::getVertexAttribOffset(GC3Duint index, GC3Denum pname)
+{
+ LOGWEBGL("glGetVertexAttribOffset(%lu, %lu)", index, pname);
+ GLvoid* pointer = 0;
+ glGetVertexAttribPointerv(index, pname, &pointer);
+ return static_cast<GC3Dsizeiptr>(reinterpret_cast<intptr_t>(pointer));
+}
+
+void GraphicsContext3D::hint(GC3Denum target, GC3Denum mode)
+{
+ LOGWEBGL("glHint(%lu, %lu)", target, mode);
+ makeContextCurrent();
+ glHint(target, mode);
+}
+
+GC3Dboolean GraphicsContext3D::isBuffer(Platform3DObject buffer)
+{
+ LOGWEBGL("glIsBuffer(%lu)", buffer);
+ if (!buffer)
+ return GL_FALSE;
+ makeContextCurrent();
+ return glIsBuffer(buffer);
+}
+
+GC3Dboolean GraphicsContext3D::isEnabled(GC3Denum cap)
+{
+ LOGWEBGL("glIsEnabled(%lu)", cap);
+ makeContextCurrent();
+ return glIsEnabled(cap);
+}
+
+GC3Dboolean GraphicsContext3D::isFramebuffer(Platform3DObject framebuffer)
+{
+ LOGWEBGL("glIsFramebuffer(%lu)", framebuffer);
+ if (!framebuffer)
+ return GL_FALSE;
+ makeContextCurrent();
+ return glIsFramebuffer(framebuffer);
+}
+
+GC3Dboolean GraphicsContext3D::isProgram(Platform3DObject program)
+{
+ LOGWEBGL("glIsProgram(%lu)", program);
+ if (!program)
+ return GL_FALSE;
+ makeContextCurrent();
+ return glIsProgram(program);
+}
+
+GC3Dboolean GraphicsContext3D::isRenderbuffer(Platform3DObject renderbuffer)
+{
+ LOGWEBGL("glIsRenderbuffer(%lu)", renderbuffer);
+ if (!renderbuffer)
+ return GL_FALSE;
+ makeContextCurrent();
+ return glIsRenderbuffer(renderbuffer);
+}
+
+GC3Dboolean GraphicsContext3D::isShader(Platform3DObject shader)
+{
+ LOGWEBGL("glIsShader(%lu)", shader);
+ if (!shader)
+ return GL_FALSE;
+ makeContextCurrent();
+ return glIsShader(shader);
+}
+
+GC3Dboolean GraphicsContext3D::isTexture(Platform3DObject texture)
+{
+ LOGWEBGL("glIsTexture(%lu)", texture);
+ if (!texture)
+ return GL_FALSE;
+ makeContextCurrent();
+ return glIsTexture(texture);
+}
+
+void GraphicsContext3D::lineWidth(GC3Dfloat width)
+{
+ LOGWEBGL("glLineWidth(%.2lf)", width);
+ makeContextCurrent();
+ glLineWidth((GLfloat)width);
+}
+
+void GraphicsContext3D::linkProgram(Platform3DObject program)
+{
+ LOGWEBGL("glLinkProgram(%lu)", program);
+ makeContextCurrent();
+ glLinkProgram(program);
+}
+
+void GraphicsContext3D::pixelStorei(GC3Denum pname, GC3Dint param)
+{
+ LOGWEBGL("glPixelStorei(%lu, %ld)", pname, param);
+ makeContextCurrent();
+ glPixelStorei(pname, param);
+}
+
+void GraphicsContext3D::polygonOffset(GC3Dfloat factor, GC3Dfloat units)
+{
+ LOGWEBGL("glPolygonOffset(%.2lf, %.2lf)", factor, units);
+ makeContextCurrent();
+ glPolygonOffset((GLfloat)factor, (GLfloat)units);
+}
+
+void GraphicsContext3D::readPixels(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height,
+ GC3Denum format, GC3Denum type, void* data)
+{
+ LOGWEBGL("glReadPixels(%ld, %ld, %lu, %lu, %lu, %lu, %p)",
+ x, y, width, height, format, type, data);
+ makeContextCurrent();
+ glReadPixels(x, y, width, height, format, type, data);
+}
+
+void GraphicsContext3D::releaseShaderCompiler()
+{
+ LOGWEBGL("glReleaseShaderCompiler()");
+ makeContextCurrent();
+ glReleaseShaderCompiler();
+}
+
+void GraphicsContext3D::renderbufferStorage(GC3Denum target, GC3Denum internalformat,
+ GC3Dsizei width, GC3Dsizei height)
+{
+ LOGWEBGL("glRenderbufferStorage(%lu, %lu, %lu, %lu)",
+ target, internalformat, width, height);
+ makeContextCurrent();
+ glRenderbufferStorage(target, internalformat, width, height);
+}
+
+void GraphicsContext3D::sampleCoverage(GC3Dclampf value, GC3Dboolean invert)
+{
+ LOGWEBGL("glSampleCoverage(%.2lf, %s)", value, invert ? "true" : "false");
+ makeContextCurrent();
+ glSampleCoverage(CLAMP(value), invert);
+}
+
+void GraphicsContext3D::scissor(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height)
+{
+ LOGWEBGL("glScissor(%ld, %ld, %lu, %lu)", x, y, width, height);
+ makeContextCurrent();
+ glScissor(x, y, width, height);
+}
+
+void GraphicsContext3D::shaderSource(Platform3DObject shader, const String& source)
+{
+ LOGWEBGL("shaderSource(%lu, %s)", shader, source.utf8().data());
+ makeContextCurrent();
+ m_internal->shaderSource(shader, source);
+}
+
+void GraphicsContext3D::stencilFunc(GC3Denum func, GC3Dint ref, GC3Duint mask)
+{
+ LOGWEBGL("glStencilFunc(%lu, %ld, %lu)", func, ref, mask);
+ makeContextCurrent();
+ glStencilFunc(func, ref, mask);
+}
+
+void GraphicsContext3D::stencilFuncSeparate(GC3Denum face, GC3Denum func, GC3Dint ref, GC3Duint mask)
+{
+ LOGWEBGL("glStencilFuncSeparate(%lu, %lu, %ld, %lu)", face, func, ref, mask);
+ makeContextCurrent();
+ glStencilFuncSeparate(face, func, ref, mask);
+}
+
+void GraphicsContext3D::stencilMask(GC3Duint mask)
+{
+ LOGWEBGL("glStencilMask(%lu)", mask);
+ makeContextCurrent();
+ glStencilMask(mask);
+}
+
+void GraphicsContext3D::stencilMaskSeparate(GC3Denum face, GC3Duint mask)
+{
+ LOGWEBGL("glStencilMaskSeparate(%lu, %lu)", face, mask);
+ makeContextCurrent();
+ glStencilMaskSeparate(face, mask);
+}
+
+void GraphicsContext3D::stencilOp(GC3Denum fail, GC3Denum zfail, GC3Denum zpass)
+{
+ LOGWEBGL("glStencilOp(%lu, %lu, %lu)", fail, zfail, zpass);
+ makeContextCurrent();
+ glStencilOp(fail, zfail, zpass);
+}
+
+void GraphicsContext3D::stencilOpSeparate(GC3Denum face, GC3Denum fail,
+ GC3Denum zfail, GC3Denum zpass)
+{
+ LOGWEBGL("glStencilOpSeparate(%lu, %lu, %lu, %lu)", face, fail, zfail, zpass);
+ makeContextCurrent();
+ glStencilOpSeparate(face, fail, zfail, zpass);
+}
+
+bool GraphicsContext3D::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
+ GC3Dsizei width, GC3Dsizei height, GC3Dint border,
+ GC3Denum format, GC3Denum type, const void* pixels)
+{
+ LOGWEBGL("glTexImage2D(%u, %u, %u, %u, %u, %u, %u, %u, %p)",
+ target, level, internalformat, width, height, border, format, type, pixels);
+ if (width && height && !pixels) {
+ synthesizeGLError(INVALID_VALUE);
+ return false;
+ }
+ makeContextCurrent();
+ glTexImage2D(target, level, internalformat, width, height, border, format, type, pixels);
+ return true;
+}
+
+void GraphicsContext3D::texParameterf(GC3Denum target, GC3Denum pname, GC3Dfloat param)
+{
+ LOGWEBGL("glTexParameterf(%u, %u, %f)", target, pname, param);
+ makeContextCurrent();
+ glTexParameterf(target, pname, param);
+}
+
+void GraphicsContext3D::texParameteri(GC3Denum target, GC3Denum pname, GC3Dint param)
+{
+ LOGWEBGL("glTexParameteri(%u, %u, %d)", target, pname, param);
+ makeContextCurrent();
+ glTexParameteri(target, pname, param);
+}
+
+void GraphicsContext3D::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset,
+ GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height,
+ GC3Denum format, GC3Denum type, const void* pixels)
+{
+ LOGWEBGL("glTexSubImage2D(%u, %u, %u, %u, %u, %u, %u, %u, %p)", target, level, xoffset,
+ yoffset, width, height, format, type, pixels);
+ if (width && height && !pixels) {
+ synthesizeGLError(INVALID_VALUE);
+ return;
+ }
+ makeContextCurrent();
+ glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
+}
+
+void GraphicsContext3D::uniform1f(GC3Dint location, GC3Dfloat x)
+{
+ LOGWEBGL("glUniform1f(%ld, %f)", location, x);
+ makeContextCurrent();
+ glUniform1f(location, x);
+}
+
+void GraphicsContext3D::uniform1fv(GC3Dint location, GC3Dfloat* v, GC3Dsizei size)
+{
+ LOGWEBGL("glUniform1fv(%ld, %p, %d)", location, v, size);
+ makeContextCurrent();
+ glUniform1fv(location, size, v);
+}
+
+void GraphicsContext3D::uniform1i(GC3Dint location, GC3Dint x)
+{
+ LOGWEBGL("glUniform1i(%ld, %d)", location, x);
+ makeContextCurrent();
+ glUniform1i(location, x);
+}
+
+void GraphicsContext3D::uniform1iv(GC3Dint location, GC3Dint* v, GC3Dsizei size)
+{
+ LOGWEBGL("glUniform1iv(%ld, %p, %d)", location, v, size);
+ makeContextCurrent();
+ glUniform1iv(location, size, v);
+}
+
+void GraphicsContext3D::uniform2f(GC3Dint location, GC3Dfloat x, float y)
+{
+ LOGWEBGL("glUniform2f(%ld, %f, %f)", location, x, y);
+ makeContextCurrent();
+ glUniform2f(location, x, y);
+}
+
+void GraphicsContext3D::uniform2fv(GC3Dint location, GC3Dfloat* v, GC3Dsizei size)
+{
+ LOGWEBGL("glUniform2fv(%ld, %p, %d)", location, v, size);
+ makeContextCurrent();
+ glUniform2fv(location, size, v);
+}
+
+void GraphicsContext3D::uniform2i(GC3Dint location, GC3Dint x, GC3Dint y)
+{
+ LOGWEBGL("glUniform2i(%ld, %d, %d)", location, x, y);
+ makeContextCurrent();
+ glUniform2i(location, x, y);
+}
+
+void GraphicsContext3D::uniform2iv(GC3Dint location, GC3Dint* v, GC3Dsizei size)
+{
+ LOGWEBGL("glUniform2iv(%ld, %p, %d)", location, v, size);
+ makeContextCurrent();
+ glUniform2iv(location, size, v);
+}
+
+void GraphicsContext3D::uniform3f(GC3Dint location, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z)
+{
+ LOGWEBGL("glUniform3f(%ld, %f, %f, %f)", location, x, y, z);
+ makeContextCurrent();
+ glUniform3f(location, x, y, z);
+}
+
+void GraphicsContext3D::uniform3fv(GC3Dint location, GC3Dfloat* v, GC3Dsizei size)
+{
+ LOGWEBGL("glUniform3fv(%ld, %p, %d)", location, v, size);
+ makeContextCurrent();
+ glUniform3fv(location, size, v);
+}
+
+void GraphicsContext3D::uniform3i(GC3Dint location, GC3Dint x, GC3Dint y, GC3Dint z)
+{
+ LOGWEBGL("glUniform3i(%ld, %d, %d, %d)", location, x, y, z);
+ makeContextCurrent();
+ glUniform3i(location, x, y, z);
+}
+
+void GraphicsContext3D::uniform3iv(GC3Dint location, GC3Dint* v, GC3Dsizei size)
+{
+ LOGWEBGL("glUniform3iv(%ld, %p, %d)", location, v, size);
+ makeContextCurrent();
+ glUniform3iv(location, size, v);
+}
+
+void GraphicsContext3D::uniform4f(GC3Dint location, GC3Dfloat x, GC3Dfloat y,
+ GC3Dfloat z, GC3Dfloat w)
+{
+ LOGWEBGL("glUniform4f(%ld, %f, %f, %f, %f)", location, x, y, z, w);
+ makeContextCurrent();
+ glUniform4f(location, x, y, z, w);
+}
+
+void GraphicsContext3D::uniform4fv(GC3Dint location, GC3Dfloat* v, GC3Dsizei size)
+{
+ LOGWEBGL("glUniform4fv(%ld, %p, %d)", location, v, size);
+ makeContextCurrent();
+ glUniform4fv(location, size, v);
+}
+
+void GraphicsContext3D::uniform4i(GC3Dint location, GC3Dint x, GC3Dint y, GC3Dint z, GC3Dint w)
+{
+ LOGWEBGL("glUniform4i(%ld, %d, %d, %d, %d)", location, x, y, z, w);
+ makeContextCurrent();
+ glUniform4i(location, x, y, z, w);
+}
+
+void GraphicsContext3D::uniform4iv(GC3Dint location, GC3Dint* v, GC3Dsizei size)
+{
+ LOGWEBGL("glUniform4iv(%ld, %p, %d)", location, v, size);
+ makeContextCurrent();
+ glUniform4iv(location, size, v);
+}
+
+void GraphicsContext3D::uniformMatrix2fv(GC3Dint location, GC3Dboolean transpose,
+ GC3Dfloat* value, GC3Dsizei size)
+{
+ LOGWEBGL("glUniformMatrix2fv(%ld, %s, %p, %d)",
+ location, transpose ? "true" : "false", value, size);
+ makeContextCurrent();
+ glUniformMatrix2fv(location, size, transpose, value);
+}
+
+void GraphicsContext3D::uniformMatrix3fv(GC3Dint location, GC3Dboolean transpose,
+ GC3Dfloat* value, GC3Dsizei size)
+{
+ LOGWEBGL("glUniformMatrix3fv(%ld, %s, %p, %d)",
+ location, transpose ? "true" : "false", value, size);
+ makeContextCurrent();
+ glUniformMatrix3fv(location, size, transpose, value);
+}
+
+void GraphicsContext3D::uniformMatrix4fv(GC3Dint location, GC3Dboolean transpose,
+ GC3Dfloat* value, GC3Dsizei size)
+{
+ LOGWEBGL("glUniformMatrix4fv(%ld, %s, %p, %d)",
+ location, transpose ? "true" : "false", value, size);
+ makeContextCurrent();
+ glUniformMatrix4fv(location, size, transpose, value);
+}
+
+void GraphicsContext3D::useProgram(Platform3DObject program)
+{
+ LOGWEBGL("glUseProgram(%lu)", program);
+ makeContextCurrent();
+ glUseProgram(program);
+}
+
+void GraphicsContext3D::validateProgram(Platform3DObject program)
+{
+ LOGWEBGL("glValidateProgram(%lu)", program);
+ makeContextCurrent();
+ glValidateProgram(program);
+}
+
+void GraphicsContext3D::vertexAttrib1f(GC3Duint index, GC3Dfloat x)
+{
+ LOGWEBGL("glVertexAttrib1f(%lu, %f)", index, x);
+ makeContextCurrent();
+ glVertexAttrib1f(index, x);
+}
+
+void GraphicsContext3D::vertexAttrib1fv(GC3Duint index, GC3Dfloat* values)
+{
+ LOGWEBGL("glVertexAttrib1fv(%lu, %p)", index, values);
+ makeContextCurrent();
+ glVertexAttrib1fv(index, values);
+}
+
+void GraphicsContext3D::vertexAttrib2f(GC3Duint index, GC3Dfloat x, GC3Dfloat y)
+{
+ LOGWEBGL("glVertexAttrib2f(%lu, %f, %f)", index, x, y);
+ makeContextCurrent();
+ glVertexAttrib2f(index, x, y);
+}
+
+void GraphicsContext3D::vertexAttrib2fv(GC3Duint index, GC3Dfloat* values)
+{
+ LOGWEBGL("glVertexAttrib2fv(%lu, %p)", index, values);
+ makeContextCurrent();
+ glVertexAttrib2fv(index, values);
+}
+
+void GraphicsContext3D::vertexAttrib3f(GC3Duint index, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z)
+{
+ LOGWEBGL("glVertexAttrib3f(%lu, %f, %f, %f)", index, x, y, z);
+ makeContextCurrent();
+ glVertexAttrib3f(index, x, y, z);
+}
+
+void GraphicsContext3D::vertexAttrib3fv(GC3Duint index, GC3Dfloat* values)
+{
+ LOGWEBGL("glVertexAttrib3fv(%lu, %p)", index, values);
+ makeContextCurrent();
+ glVertexAttrib3fv(index, values);
+}
+
+void GraphicsContext3D::vertexAttrib4f(GC3Duint index, GC3Dfloat x, GC3Dfloat y,
+ GC3Dfloat z, GC3Dfloat w)
+{
+ LOGWEBGL("glVertexAttrib4f(%lu, %f, %f, %f, %f)", index, x, y, z, w);
+ makeContextCurrent();
+ glVertexAttrib4f(index, x, y, z, w);
+}
+
+void GraphicsContext3D::vertexAttrib4fv(GC3Duint index, GC3Dfloat* values)
+{
+ LOGWEBGL("glVertexAttrib4fv(%lu, %p)", index, values);
+ makeContextCurrent();
+ glVertexAttrib4fv(index, values);
+}
+
+void GraphicsContext3D::vertexAttribPointer(GC3Duint index, GC3Dint size, GC3Denum type,
+ GC3Dboolean normalized, GC3Dsizei stride,
+ GC3Dintptr offset)
+{
+ LOGWEBGL("glVertexAttribPointer(%lu, %d, %d, %s, %lu, %lu)", index, size, type,
+ normalized ? "true" : "false", stride, offset);
+ makeContextCurrent();
+ glVertexAttribPointer(index, size, type, normalized, stride,
+ reinterpret_cast<GLvoid*>(static_cast<intptr_t>(offset)));
+}
+
+void GraphicsContext3D::viewport(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height)
+{
+ LOGWEBGL("viewport(%ld, %ld, %lu, %lu)", x, y, width, height);
+ makeContextCurrent();
+ m_internal->viewport(x, y, width, height);
+}
+
+void GraphicsContext3D::reshape(int width, int height)
+{
+ LOGWEBGL("reshape(%d, %d)", width, height);
+ if ((width == m_currentWidth) && (height == m_currentHeight)) {
+ return;
+ }
+ m_internal->reshape(width, height);
+ m_currentWidth = m_internal->width();
+ m_currentHeight = m_internal->height();
+}
+
+void GraphicsContext3D::recreateSurface()
+{
+ LOGWEBGL("recreateSurface()");
+ m_internal->recreateSurface();
+}
+
+void GraphicsContext3D::releaseSurface()
+{
+ LOGWEBGL("releaseSurface()");
+ m_internal->releaseSurface();
+}
+
+IntSize GraphicsContext3D::getInternalFramebufferSize()
+{
+ return IntSize(m_currentWidth, m_currentHeight);
+}
+
+void GraphicsContext3D::markContextChanged()
+{
+ LOGWEBGL("markContextChanged()");
+ m_internal->markContextChanged();
+}
+
+void GraphicsContext3D::markLayerComposited()
+{
+ LOGWEBGL("markLayerComposited()");
+ m_internal->markLayerComposited();
+}
+
+bool GraphicsContext3D::layerComposited() const
+{
+ LOGWEBGL("layerComposited()");
+ return m_internal->layerComposited();
+}
+
+void GraphicsContext3D::setContextLostCallback(PassOwnPtr<ContextLostCallback>)
+{
+}
+}
+#endif
diff --git a/Source/WebCore/platform/graphics/android/GraphicsContext3DInternal.cpp b/Source/WebCore/platform/graphics/android/GraphicsContext3DInternal.cpp
new file mode 100644
index 0000000..928702f
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/GraphicsContext3DInternal.cpp
@@ -0,0 +1,1013 @@
+/*
+ * Copyright (C) 2011, 2012, Sony Ericsson Mobile Communications AB
+ * Copyright (C) 2012 Sony Mobile Communications AB
+ * All rights reserved.
+ *
+ * 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.
+ * * Neither the name of the Sony Ericsson Mobile Communications AB nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 SONY ERICSSON MOBILE COMMUNICATIONS AB 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 "GraphicsContext3DInternal.h"
+
+#include "Frame.h"
+#include "HostWindow.h"
+#include "HTMLCanvasElement.h"
+#include "ImageBuffer.h"
+#include "ImageData.h"
+#include "PlatformGraphicsContext.h"
+#include "RenderLayer.h"
+#include "RenderLayerBacking.h"
+#include "RenderObject.h"
+#include "TilesManager.h"
+#include "TransformationMatrix.h"
+#include "WebViewCore.h"
+
+#include "SkBitmap.h"
+#include "SkDevice.h"
+#include <hardware/hardware.h>
+#include <surfaceflinger/ISurfaceComposer.h>
+#include <surfaceflinger/SurfaceComposerClient.h>
+#include <surfaceflinger/IGraphicBufferAlloc.h>
+#include <JNIUtility.h>
+
+#if ENABLE(WEBGL)
+namespace WebCore {
+
+class FBO {
+public:
+ static FBO* createFBO(EGLDisplay dpy, int width, int height);
+ ~FBO();
+
+ EGLSyncKHR sync() { return m_sync; }
+ void setSync(EGLSyncKHR sync) { m_sync = sync; }
+
+ GLuint fbo() { return m_fbo; }
+ EGLImageKHR image() { return m_image; }
+
+ bool isLocked() { return m_locked; }
+ void setLocked(bool locked) { m_locked = locked; }
+
+ bool lockGraphicBuffer(void** ptr) {
+ return (m_grBuffer.get() &&
+ (m_grBuffer->lock(GraphicBuffer::USAGE_SW_READ_RARELY, ptr) == NO_ERROR));
+ }
+ void unlockGraphicBuffer() {
+ if (m_grBuffer.get())
+ m_grBuffer->unlock();
+ }
+
+ int bytesPerRow() { return m_grBuffer.get() ? m_grBuffer->getStride() * 4 : 0; }
+
+private:
+ FBO(EGLDisplay dpy);
+ bool init(int width, int height);
+ GLuint createTexture(EGLImageKHR image, int width, int height);
+
+ EGLDisplay m_dpy;
+ GLuint m_texture;
+ GLuint m_fbo;
+ GLuint m_depthBuffer;
+ EGLImageKHR m_image;
+ EGLSyncKHR m_sync;
+ sp<IGraphicBufferAlloc> m_graphicBufferAlloc;
+ sp<GraphicBuffer> m_grBuffer;
+ bool m_locked;
+};
+
+
+#define CANVAS_MAX_WIDTH 1280
+#define CANVAS_MAX_HEIGHT 1280
+
+EGLint GraphicsContext3DInternal::checkEGLError(const char* s)
+{
+ EGLint error = eglGetError();
+ if (error == EGL_SUCCESS) {
+ LOGWEBGL("%s() OK", s);
+ }
+ else {
+ LOGWEBGL("after %s() eglError = 0x%x", s, error);
+ }
+
+ return error;
+}
+
+GLint GraphicsContext3DInternal::checkGLError(const char* s)
+{
+ GLint error = glGetError();
+ if (error == GL_NO_ERROR) {
+ LOGWEBGL("%s() OK", s);
+ }
+ else {
+ LOGWEBGL("after %s() glError (0x%x)", s, error);
+ }
+
+ return error;
+}
+
+GraphicsContext3DInternal::GraphicsContext3DInternal(HTMLCanvasElement* canvas,
+ GraphicsContext3D::Attributes attrs,
+ HostWindow* hostWindow)
+ : m_proxy(new GraphicsContext3DProxy())
+ , m_compositingLayer(new WebGLLayer(m_proxy.get()))
+ , m_canvas(canvas)
+ , m_attrs(attrs)
+ , m_layerComposited(false)
+ , m_canvasDirty(false)
+ , m_width(1)
+ , m_height(1)
+ , m_maxwidth(CANVAS_MAX_WIDTH)
+ , m_maxheight(CANVAS_MAX_HEIGHT)
+ , m_dpy(EGL_NO_DISPLAY)
+ , m_config(0)
+ , m_surface(EGL_NO_SURFACE)
+ , m_context(EGL_NO_CONTEXT)
+ , m_syncThread(0)
+ , m_threadState(THREAD_STATE_STOPPED)
+ , m_syncTimer(this, &GraphicsContext3DInternal::syncTimerFired)
+ , m_syncRequested(false)
+ , m_extensions(0)
+ , m_contextId(0)
+{
+ LOGWEBGL("GraphicsContext3DInternal() = %p, m_compositingLayer = %p", this, m_compositingLayer);
+ m_compositingLayer->ref();
+ m_proxy->setGraphicsContext(this);
+
+ if (!m_canvas || !m_canvas->document() || !m_canvas->document()->view())
+ return;
+ JNIEnv* env = JSC::Bindings::getJNIEnv();
+ WebViewCore* core = WebViewCore::getWebViewCore(m_canvas->document()->view());
+ if (!core)
+ return;
+ jobject tmp = core->getWebViewJavaObject();
+ m_webView = env->NewGlobalRef(tmp);
+ if (!m_webView)
+ return;
+ jclass webViewClass = env->GetObjectClass(m_webView);
+ m_postInvalidate = env->GetMethodID(webViewClass, "postInvalidate", "()V");
+ env->DeleteLocalRef(webViewClass);
+ if (!m_postInvalidate)
+ return;
+
+ if (!initEGL())
+ return;
+
+ if (!createContext(true)) {
+ LOGWEBGL("Create context failed. Perform JS garbage collection and try again.");
+ // Probably too many contexts. Force a JS garbage collection, and then try again.
+ // This typically only happens in Khronos Conformance tests.
+ m_canvas->document()->frame()->script()->lowMemoryNotification();
+ if (!createContext(true)) {
+ LOGWEBGL("Create context still failed: aborting.");
+ return;
+ }
+ }
+
+ const char *ext = (const char *)glGetString(GL_EXTENSIONS);
+ // Only willing to support GL_OES_texture_npot at this time
+ m_extensions.set(new Extensions3DAndroid(strstr(ext, "GL_OES_texture_npot") ?
+ "GL_OES_texture_npot" : ""));
+ LOGWEBGL("GL_EXTENSIONS = %s", ext);
+
+ // ANGLE initialization.
+ ShBuiltInResources resources;
+ ShInitBuiltInResources(&resources);
+
+ glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &resources.MaxVertexAttribs);
+ glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &resources.MaxVertexUniformVectors);
+ glGetIntegerv(GL_MAX_VARYING_VECTORS, &resources.MaxVaryingVectors);
+ glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &resources.MaxVertexTextureImageUnits);
+ glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &resources.MaxCombinedTextureImageUnits);
+ glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &resources.MaxTextureImageUnits);
+ glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &resources.MaxFragmentUniformVectors);
+
+ resources.MaxDrawBuffers = 1;
+ m_compiler.setResources(resources);
+
+ m_savedViewport.x = 0;
+ m_savedViewport.y = 0;
+ m_savedViewport.width = m_width;
+ m_savedViewport.height = m_height;
+
+ glClearColor(0, 0, 0, 0);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ startSyncThread();
+
+ static int contextCounter = 1;
+ m_contextId = contextCounter++;
+}
+
+GraphicsContext3DInternal::~GraphicsContext3DInternal()
+{
+ LOGWEBGL("~GraphicsContext3DInternal(), this = %p", this);
+
+ stopSyncThread();
+
+ m_proxy->setGraphicsContext(0);
+ MutexLocker lock(m_fboMutex);
+ m_compositingLayer->unref();
+ m_compositingLayer = 0;
+ deleteContext(true);
+
+ JNIEnv* env = JSC::Bindings::getJNIEnv();
+ env->DeleteGlobalRef(m_webView);
+}
+
+bool GraphicsContext3DInternal::initEGL()
+{
+ m_dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ if (m_dpy == EGL_NO_DISPLAY)
+ return false;
+
+ EGLint majorVersion;
+ EGLint minorVersion;
+ EGLBoolean returnValue = eglInitialize(m_dpy, &majorVersion, &minorVersion);
+ if (returnValue != EGL_TRUE)
+ return false;
+
+ LOGWEBGL("EGL version %d.%d", majorVersion, minorVersion);
+ const char *s = eglQueryString(m_dpy, EGL_VENDOR);
+ LOGWEBGL("EGL_VENDOR = %s", s);
+ s = eglQueryString(m_dpy, EGL_VERSION);
+ LOGWEBGL("EGL_VERSION = %s", s);
+ s = eglQueryString(m_dpy, EGL_EXTENSIONS);
+ LOGWEBGL("EGL_EXTENSIONS = %s", s);
+ s = eglQueryString(m_dpy, EGL_CLIENT_APIS);
+ LOGWEBGL("EGL_CLIENT_APIS = %s", s);
+
+ EGLint* config_attribs = new EGLint[21];
+ int p = 0;
+ config_attribs[p++] = EGL_BLUE_SIZE;
+ config_attribs[p++] = 8;
+ config_attribs[p++] = EGL_GREEN_SIZE;
+ config_attribs[p++] = 8;
+ config_attribs[p++] = EGL_RED_SIZE;
+ config_attribs[p++] = 8;
+ config_attribs[p++] = EGL_SURFACE_TYPE;
+ config_attribs[p++] = EGL_PBUFFER_BIT;
+ config_attribs[p++] = EGL_RENDERABLE_TYPE;
+ config_attribs[p++] = EGL_OPENGL_ES2_BIT;
+ config_attribs[p++] = EGL_ALPHA_SIZE;
+ config_attribs[p++] = m_attrs.alpha ? 8 : 0;
+ if (m_attrs.depth) {
+ config_attribs[p++] = EGL_DEPTH_SIZE;
+ config_attribs[p++] = 16;
+ }
+ if (m_attrs.stencil) {
+ config_attribs[p++] = EGL_STENCIL_SIZE;
+ config_attribs[p++] = 8;
+ }
+ if (m_attrs.antialias) {
+ config_attribs[p++] = EGL_SAMPLE_BUFFERS;
+ config_attribs[p++] = 1;
+ config_attribs[p++] = EGL_SAMPLES;
+ config_attribs[p++] = 4;
+ }
+ config_attribs[p] = EGL_NONE;
+
+ EGLint num_configs = 0;
+ return (eglChooseConfig(m_dpy, config_attribs, &m_config, 1, &num_configs) == EGL_TRUE);
+}
+
+bool GraphicsContext3DInternal::createContext(bool createEGLContext)
+{
+ LOGWEBGL("createContext()");
+ EGLint context_attribs[] = {
+ EGL_CONTEXT_CLIENT_VERSION, 2,
+ EGL_NONE};
+
+ if (createEGLContext) {
+ EGLint surface_attribs[] = {
+ EGL_WIDTH, 1,
+ EGL_HEIGHT, 1,
+ EGL_NONE};
+ m_surface = eglCreatePbufferSurface(m_dpy, m_config, surface_attribs);
+ m_context = eglCreateContext(m_dpy, m_config, EGL_NO_CONTEXT, context_attribs);
+ }
+ if (m_context == EGL_NO_CONTEXT) {
+ deleteContext(createEGLContext);
+ return false;
+ }
+
+ makeContextCurrent();
+ for (int i = 0; i < NUM_BUFFERS; i++) {
+ FBO* tmp = FBO::createFBO(m_dpy, m_width > 0 ? m_width : 1, m_height > 0 ? m_height : 1);
+ if (tmp == 0) {
+ LOGWEBGL("Failed to create FBO");
+ deleteContext(createEGLContext);
+ return false;
+ }
+ m_fbo[i] = tmp;
+ m_freeBuffers.append(tmp);
+ }
+
+ m_currentFBO = dequeueBuffer();
+ m_boundFBO = m_currentFBO->fbo();
+ m_frontFBO = 0;
+ glBindFramebuffer(GL_FRAMEBUFFER, m_boundFBO);
+
+ return true;
+}
+
+void GraphicsContext3DInternal::deleteContext(bool deleteEGLContext)
+{
+ LOGWEBGL("deleteContext(%s)", deleteEGLContext ? "true" : "false");
+
+ makeContextCurrent();
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+ m_freeBuffers.clear();
+ m_queuedBuffers.clear();
+ m_preparedBuffers.clear();
+ for (int i = 0; i < NUM_BUFFERS; i++) {
+ if (m_fbo[i]) {
+ delete m_fbo[i];
+ m_fbo[i] = 0;
+ }
+ }
+ m_currentFBO = 0;
+ m_frontFBO = 0;
+
+ eglMakeCurrent(m_dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ if (deleteEGLContext) {
+ if (m_surface != EGL_NO_SURFACE) {
+ eglDestroySurface(m_dpy, m_surface);
+ m_surface = EGL_NO_SURFACE;
+ }
+ if (m_context != EGL_NO_CONTEXT) {
+ eglDestroyContext(m_dpy, m_context);
+ m_context = EGL_NO_CONTEXT;
+ }
+ }
+}
+
+void GraphicsContext3DInternal::makeContextCurrent()
+{
+ if (eglGetCurrentContext() != m_context && m_context != EGL_NO_CONTEXT) {
+ eglMakeCurrent(m_dpy, m_surface, m_surface, m_context);
+ }
+}
+
+GraphicsContext3D::Attributes GraphicsContext3DInternal::getContextAttributes()
+{
+ return m_attrs;
+}
+
+unsigned long GraphicsContext3DInternal::getError()
+{
+ if (m_syntheticErrors.size() > 0) {
+ ListHashSet<unsigned long>::iterator iter = m_syntheticErrors.begin();
+ unsigned long err = *iter;
+ m_syntheticErrors.remove(iter);
+ return err;
+ }
+ LOGWEBGL("glGetError()");
+ makeContextCurrent();
+ return glGetError();
+}
+
+void GraphicsContext3DInternal::synthesizeGLError(unsigned long error)
+{
+ m_syntheticErrors.add(error);
+}
+
+FBO* FBO::createFBO(EGLDisplay dpy, int width, int height)
+{
+ LOGWEBGL("createFBO()");
+ FBO* fbo = new FBO(dpy);
+
+ if (!fbo->init(width, height)) {
+ delete fbo;
+ return 0;
+ }
+ return fbo;
+}
+
+FBO::FBO(EGLDisplay dpy)
+ : m_dpy(dpy)
+ , m_texture(0)
+ , m_fbo(0)
+ , m_depthBuffer(0)
+ , m_image(0)
+ , m_sync(0)
+ , m_grBuffer(0)
+ , m_locked(false)
+{
+}
+
+bool FBO::init(int width, int height)
+{
+ // 1. Allocate a graphic buffer
+ sp<ISurfaceComposer> composer(ComposerService::getComposerService());
+ m_graphicBufferAlloc = composer->createGraphicBufferAlloc();
+
+ status_t error;
+ m_grBuffer = m_graphicBufferAlloc->createGraphicBuffer(width, height,
+ HAL_PIXEL_FORMAT_RGBA_8888,
+ GRALLOC_USAGE_HW_TEXTURE, &error);
+ if (error != NO_ERROR) {
+ LOGWEBGL(" failed to allocate GraphicBuffer, error = %d", error);
+ return false;
+ }
+
+ void *addr = 0;
+ if (m_grBuffer->lock(GRALLOC_USAGE_SW_WRITE_RARELY, &addr) != NO_ERROR) {
+ LOGWEBGL(" failed to lock the GraphicBuffer");
+ return false;
+ }
+ // WebGL requires all buffers to be initialized to 0.
+ memset(addr, 0, width * height * 4);
+ m_grBuffer->unlock();
+
+ ANativeWindowBuffer* clientBuf = m_grBuffer->getNativeBuffer();
+ if (clientBuf->handle == 0) {
+ LOGWEBGL(" empty handle in GraphicBuffer");
+ return false;
+ }
+
+ // 2. Create an EGLImage from the graphic buffer
+ const EGLint attrs[] = {
+ EGL_IMAGE_PRESERVED_KHR, EGL_TRUE,
+ EGL_NONE, EGL_NONE
+ };
+ m_image = eglCreateImageKHR(m_dpy,
+ EGL_NO_CONTEXT,
+ EGL_NATIVE_BUFFER_ANDROID,
+ (EGLClientBuffer)clientBuf,
+ attrs);
+ if (GraphicsContext3DInternal::checkEGLError("eglCreateImageKHR") != EGL_SUCCESS) {
+ LOGWEBGL("eglCreateImageKHR() failed");
+ return false;
+ }
+
+ // 3. Create a texture from the EGLImage
+ m_texture = createTexture(m_image, width, height);
+ if (m_texture == 0) {
+ LOGWEBGL("createTexture() failed");
+ return false;
+ }
+
+ // 4. Create the Framebuffer Object from the texture
+ glGenFramebuffers(1, &m_fbo);
+ glGenRenderbuffers(1, &m_depthBuffer);
+
+ glBindRenderbuffer(GL_RENDERBUFFER, m_depthBuffer);
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height);
+ if (GraphicsContext3DInternal::checkGLError("glRenderbufferStorage") != GL_NO_ERROR) {
+ return false;
+ }
+ glBindRenderbuffer(GL_RENDERBUFFER, 0);
+
+ glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture, 0);
+ if (GraphicsContext3DInternal::checkGLError("glFramebufferTexture2D") != GL_NO_ERROR) {
+ return false;
+ }
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthBuffer);
+ if (GraphicsContext3DInternal::checkGLError("glFramebufferRenderbuffer") != GL_NO_ERROR) {
+ return false;
+ }
+
+ GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ if (status != GL_FRAMEBUFFER_COMPLETE) {
+ LOGWEBGL("Framebuffer incomplete: %d", status);
+ return false;
+ }
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+ return true;
+}
+
+FBO::~FBO()
+{
+ LOGWEBGL("FBO::~FBO()");
+ if (m_image) {
+ eglDestroyImageKHR(m_dpy, m_image);
+ GraphicsContext3DInternal::checkEGLError("eglDestroyImageKHR");
+ }
+ if (m_texture)
+ glDeleteTextures(1, &m_texture);
+ if (m_depthBuffer)
+ glDeleteRenderbuffers(1, &m_depthBuffer);
+ if (m_fbo)
+ glDeleteFramebuffers(1, &m_fbo);
+}
+
+GLuint FBO::createTexture(EGLImageKHR image, int width, int height)
+{
+ LOGWEBGL("createTexture(image = %p)", image);
+ GLuint texture;
+
+ glGenTextures(1, &texture);
+ glBindTexture(GL_TEXTURE_2D, texture);
+
+ //glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ //glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+ bool error = false;
+ if (image) {
+ glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)image);
+ error = (GraphicsContext3DInternal::checkGLError("glEGLImageTargetTexture2DOES")
+ != GL_NO_ERROR);
+ }
+ else {
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+ error = (GraphicsContext3DInternal::checkGLError("glTexImage2D()") != GL_NO_ERROR);
+ }
+ glBindTexture(GL_TEXTURE_2D, 0);
+ if (error) {
+ glDeleteTextures(1, &texture);
+ texture = 0;
+ }
+
+ return texture;
+}
+
+void GraphicsContext3DInternal::startSyncThread()
+{
+ LOGWEBGL("+startSyncThread()");
+ MutexLocker lock(m_threadMutex);
+ m_threadState = THREAD_STATE_STOPPED;
+ m_syncThread = createThread(syncThreadStart, this, "GraphicsContext3DInternal");
+ // Wait for thread to start
+ while (m_threadState != THREAD_STATE_RUN) {
+ m_threadCondition.wait(m_threadMutex);
+ }
+ LOGWEBGL("-startSyncThread()");
+}
+
+void GraphicsContext3DInternal::stopSyncThread()
+{
+ LOGWEBGL("+stopSyncThread()");
+ MutexLocker lock(m_threadMutex);
+ if (m_syncThread) {
+ m_threadState = THREAD_STATE_STOP;
+ // Signal thread to wake up
+ m_threadCondition.broadcast();
+ // Wait for thread to stop
+ while (m_threadState != THREAD_STATE_STOPPED) {
+ m_threadCondition.wait(m_threadMutex);
+ }
+ m_syncThread = 0;
+ }
+ LOGWEBGL("-stopSyncThread()");
+}
+
+void* GraphicsContext3DInternal::syncThreadStart(void* ctx)
+{
+ GraphicsContext3DInternal* context = static_cast<GraphicsContext3DInternal*>(ctx);
+ context->runSyncThread();
+
+ return 0;
+}
+
+void GraphicsContext3DInternal::runSyncThread()
+{
+ LOGWEBGL("SyncThread: starting");
+ FBO* fbo = 0;
+
+ MutexLocker lock(m_threadMutex);
+ m_threadState = THREAD_STATE_RUN;
+ // Signal to creator that we are up and running
+ m_threadCondition.broadcast();
+
+ while (m_threadState == THREAD_STATE_RUN) {
+ while (m_threadState == THREAD_STATE_RUN) {
+ {
+ MutexLocker lock(m_fboMutex);
+ if (!m_queuedBuffers.isEmpty()) {
+ fbo = m_queuedBuffers.takeFirst();
+ break;
+ }
+ }
+ m_threadCondition.wait(m_threadMutex);
+ }
+ LOGWEBGL("SyncThread: woke after waiting for FBO, fbo = %p", fbo);
+ if (m_threadState != THREAD_STATE_RUN)
+ break;
+
+ if (fbo->sync() != EGL_NO_SYNC_KHR) {
+ eglClientWaitSyncKHR(m_dpy, fbo->sync(), 0, 0);
+ eglDestroySyncKHR(m_dpy, fbo->sync());
+ fbo->setSync(EGL_NO_SYNC_KHR);
+ LOGWEBGL("SyncThread: returned after waiting for Sync");
+ }
+
+ {
+ MutexLocker lock(m_fboMutex);
+ m_preparedBuffers.append(fbo);
+ LOGWEBGL("SyncThread: prepared buffer = %p", fbo);
+ updateFrontBuffer();
+ }
+
+ // Invalidate the canvas region
+ // TODO: Don't invalidate when offscreen.
+ if (m_postInvalidate) {
+ JNIEnv* env = JSC::Bindings::getJNIEnv();
+ env->CallVoidMethod(m_webView, m_postInvalidate);
+ }
+ }
+
+ // Signal to calling thread that we have stopped
+ m_threadState = THREAD_STATE_STOPPED;
+ m_threadCondition.broadcast();
+ LOGWEBGL("SyncThread: terminating");
+}
+
+PlatformLayer* GraphicsContext3DInternal::platformLayer() const
+{
+ LOGWEBGL("platformLayer()");
+ return m_compositingLayer;
+}
+
+void GraphicsContext3DInternal::reshape(int width, int height)
+{
+ LOGWEBGL("reshape(%d, %d)", width, height);
+ bool mustRestoreFBO = (m_boundFBO != (m_currentFBO ? m_currentFBO->fbo() : 0));
+
+ m_width = width > m_maxwidth ? m_maxwidth : width;
+ m_height = height > m_maxheight ? m_maxheight : height;
+
+ stopSyncThread();
+ makeContextCurrent();
+ m_proxy->setGraphicsContext(0);
+ {
+ MutexLocker lock(m_fboMutex);
+ deleteContext(false);
+
+ if (createContext(false)) {
+ if (!mustRestoreFBO) {
+ m_boundFBO = m_currentFBO->fbo();
+ }
+ glBindFramebuffer(GL_FRAMEBUFFER, m_boundFBO);
+ }
+ }
+ m_proxy->setGraphicsContext(this);
+ startSyncThread();
+}
+
+void GraphicsContext3DInternal::recreateSurface()
+{
+ LOGWEBGL("recreateSurface()");
+ if (m_currentFBO != 0)
+ // We already have a current surface
+ return;
+ reshape(m_width, m_height);
+ glViewport(m_savedViewport.x, m_savedViewport.y, m_savedViewport.width, m_savedViewport.height);
+}
+
+void GraphicsContext3DInternal::releaseSurface()
+{
+ LOGWEBGL("releaseSurface(%d)", m_contextId);
+ if (m_currentFBO == 0)
+ // We don't have any current surface
+ return;
+ stopSyncThread();
+ m_proxy->setGraphicsContext(0);
+ {
+ MutexLocker lock(m_fboMutex);
+ deleteContext(false);
+ }
+ makeContextCurrent();
+ m_proxy->setGraphicsContext(this);
+}
+
+void GraphicsContext3DInternal::syncTimerFired(Timer<GraphicsContext3DInternal>*)
+{
+ m_syncRequested = false;
+
+ // Do not perform the composition step if it is an offscreen canvas
+ if (m_canvas->renderer())
+ swapBuffers();
+}
+
+void GraphicsContext3DInternal::markContextChanged()
+{
+ if (!m_syncRequested) {
+ m_syncTimer.startOneShot(0);
+ m_syncRequested = true;
+ }
+ m_canvasDirty = true;
+ m_layerComposited = false;
+}
+
+/*
+ * Must hold m_fboMutex when calling this function.
+ */
+FBO* GraphicsContext3DInternal::dequeueBuffer()
+{
+ LOGWEBGL("GraphicsContext3DInternal::dequeueBuffer()");
+ while (m_freeBuffers.isEmpty()) {
+ m_fboCondition.wait(m_fboMutex);
+ }
+ FBO* fbo = m_freeBuffers.takeFirst();
+
+ if (fbo->sync() != EGL_NO_SYNC_KHR) {
+ eglClientWaitSyncKHR(m_dpy, fbo->sync(), 0, 0);
+ eglDestroySyncKHR(m_dpy, fbo->sync());
+ fbo->setSync(EGL_NO_SYNC_KHR);
+ }
+
+ return fbo;
+}
+
+void GraphicsContext3DInternal::swapBuffers()
+{
+ LOGWEBGL("+swapBuffers()");
+
+ MutexLocker lock(m_fboMutex);
+ FBO* fbo = m_currentFBO;
+ if (fbo == 0)
+ return;
+
+ makeContextCurrent();
+
+ bool mustRestoreFBO = (m_boundFBO != fbo->fbo());
+ if (mustRestoreFBO) {
+ glBindFramebuffer(GL_FRAMEBUFFER, fbo->fbo());
+ }
+
+ // Create the fence sync and notify the sync thread
+ fbo->setSync(eglCreateSyncKHR(m_dpy, EGL_SYNC_FENCE_KHR, 0));
+ glFlush();
+ m_queuedBuffers.append(fbo);
+ m_threadCondition.broadcast();
+
+ // Dequeue a new buffer
+ fbo = dequeueBuffer();
+ m_currentFBO = fbo;
+
+ if (!mustRestoreFBO) {
+ m_boundFBO = m_currentFBO->fbo();
+ }
+ glBindFramebuffer(GL_FRAMEBUFFER, m_boundFBO);
+ m_canvasDirty = false;
+ m_layerComposited = true;
+ LOGWEBGL("-swapBuffers()");
+}
+
+void GraphicsContext3DInternal::updateFrontBuffer()
+{
+ if (!m_preparedBuffers.isEmpty()) {
+ if (m_frontFBO == 0) {
+ m_frontFBO = m_preparedBuffers.takeFirst();
+ }
+ else if (!m_frontFBO->isLocked()) {
+ m_freeBuffers.append(m_frontFBO);
+ m_frontFBO = m_preparedBuffers.takeFirst();
+ m_fboCondition.broadcast();
+ }
+ }
+}
+
+bool GraphicsContext3DInternal::lockFrontBuffer(EGLImageKHR& image, SkRect& rect)
+{
+ LOGWEBGL("GraphicsContext3DInternal::lockFrontBuffer()");
+ MutexLocker lock(m_fboMutex);
+ FBO* fbo = m_frontFBO;
+
+ if (!fbo || !fbo->image()) {
+ LOGWEBGL("-GraphicsContext3DInternal::lockFrontBuffer(), fbo = %p", fbo);
+ return false;
+ }
+
+ fbo->setLocked(true);
+ image = fbo->image();
+
+ RenderObject* renderer = m_canvas->renderer();
+ if (renderer && renderer->isBox()) {
+ RenderBox* box = (RenderBox*)renderer;
+ rect.set(box->borderLeft() + box->paddingLeft(),
+ box->borderTop() + box->paddingTop(),
+ box->borderLeft() + box->paddingLeft() + box->contentWidth(),
+ box->borderTop() + box->paddingTop() + box->contentHeight());
+ }
+
+ return true;
+}
+
+void GraphicsContext3DInternal::releaseFrontBuffer()
+{
+ LOGWEBGL("GraphicsContext3DInternal::releaseFrontBuffer()");
+ MutexLocker lock(m_fboMutex);
+ FBO* fbo = m_frontFBO;
+
+ if (fbo) {
+ fbo->setLocked(false);
+ if (fbo->sync() != EGL_NO_SYNC_KHR) {
+ eglDestroySyncKHR(m_dpy, fbo->sync());
+ }
+ fbo->setSync(eglCreateSyncKHR(m_dpy, EGL_SYNC_FENCE_KHR, 0));
+ }
+ updateFrontBuffer();
+}
+
+void GraphicsContext3DInternal::paintRenderingResultsToCanvas(CanvasRenderingContext* context)
+{
+ LOGWEBGL("+paintRenderingResultsToCanvas()");
+ ImageBuffer* imageBuffer = context->canvas()->buffer();
+ const SkBitmap& canvasBitmap =
+ imageBuffer->context()->platformContext()->mCanvas->getDevice()->accessBitmap(false);
+ SkCanvas canvas(canvasBitmap);
+
+ SkBitmap bitmap;
+ bitmap.setConfig(SkBitmap::kARGB_8888_Config, m_width, m_height);
+ bitmap.allocPixels();
+ unsigned char *pixels = static_cast<unsigned char*>(bitmap.getPixels());
+ glReadPixels(0, 0, m_width, m_height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
+
+ SkRect dstRect;
+ dstRect.iset(0, 0, imageBuffer->size().width(), imageBuffer->size().height());
+ canvas.drawBitmapRect(bitmap, 0, dstRect);
+ LOGWEBGL("-paintRenderingResultsToCanvas()");
+}
+
+PassRefPtr<ImageData> GraphicsContext3DInternal::paintRenderingResultsToImageData()
+{
+ LOGWEBGL("+paintRenderingResultsToImageData()");
+ RefPtr<ImageData> imageData = ImageData::create(IntSize(m_width, m_height));
+ unsigned char* pixels = imageData->data()->data()->data();
+
+ glReadPixels(0, 0, m_width, m_height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
+ LOGWEBGL("-paintRenderingResultsToImageData()");
+
+ return imageData;
+}
+
+bool GraphicsContext3DInternal::paintCompositedResultsToCanvas(CanvasRenderingContext* context)
+{
+ LOGWEBGL("paintCompositedResultsToCanvas()");
+ ImageBuffer* imageBuffer = context->canvas()->buffer();
+ const SkBitmap& canvasBitmap =
+ imageBuffer->context()->platformContext()->mCanvas->getDevice()->accessBitmap(false);
+ SkCanvas canvas(canvasBitmap);
+
+ MutexLocker lock(m_fboMutex);
+
+ FBO* fbo = m_frontFBO;
+ if (!fbo)
+ return false;
+
+ SkBitmap bitmap;
+ bitmap.setConfig(SkBitmap::kARGB_8888_Config, m_width, m_height, fbo->bytesPerRow());
+
+ unsigned char* bits = NULL;
+ if (fbo->lockGraphicBuffer((void**)&bits)) {
+ bitmap.setPixels(bits);
+
+ SkRect dstRect;
+ dstRect.iset(0, 0, imageBuffer->size().width(), imageBuffer->size().height());
+ canvas.save();
+ canvas.translate(0, SkIntToScalar(imageBuffer->size().height()));
+ canvas.scale(SK_Scalar1, -SK_Scalar1);
+ canvas.drawBitmapRect(bitmap, 0, dstRect);
+ canvas.restore();
+ bitmap.setPixels(0);
+ fbo->unlockGraphicBuffer();
+ }
+
+ return true;
+}
+
+void GraphicsContext3DInternal::bindFramebuffer(GC3Denum target, Platform3DObject buffer)
+{
+ LOGWEBGL("bindFrameBuffer()");
+ makeContextCurrent();
+ MutexLocker lock(m_fboMutex);
+ if (!buffer && m_currentFBO) {
+ buffer = m_currentFBO->fbo();
+ }
+ glBindFramebuffer(target, buffer);
+ m_boundFBO = buffer;
+}
+
+void GraphicsContext3DInternal::compileShader(Platform3DObject shader)
+{
+ LOGWEBGL("compileShader()");
+ HashMap<Platform3DObject, ShaderSourceEntry>::iterator result = m_shaderSourceMap.find(shader);
+ if (result == m_shaderSourceMap.end()) {
+ LOGWEBGL(" shader not found");
+ return;
+ }
+ ShaderSourceEntry& entry = result->second;
+
+ int shaderType;
+ glGetShaderiv(shader, GL_SHADER_TYPE, &shaderType);
+
+ ANGLEShaderType ast = shaderType == GL_VERTEX_SHADER ?
+ SHADER_TYPE_VERTEX : SHADER_TYPE_FRAGMENT;
+
+ String src;
+ String log;
+ bool isValid = m_compiler.validateShaderSource(entry.source.utf8().data(), ast, src, log);
+
+ entry.log = log;
+ entry.isValid = isValid;
+
+ if (!isValid) {
+ LOGWEBGL(" shader validation failed");
+ return;
+ }
+ int len = entry.source.length();
+ CString cstr = entry.source.utf8();
+ const char* s = cstr.data();
+
+ LOGWEBGL("glShaderSource(%s)", cstr.data());
+ glShaderSource(shader, 1, &s, &len);
+
+ LOGWEBGL("glCompileShader()");
+ glCompileShader(shader);
+}
+
+String GraphicsContext3DInternal::getShaderInfoLog(Platform3DObject shader)
+{
+ LOGWEBGL("getShaderInfoLog()");
+ HashMap<Platform3DObject, ShaderSourceEntry>::iterator result = m_shaderSourceMap.find(shader);
+
+ if (result == m_shaderSourceMap.end()) {
+ LOGWEBGL(" shader not found");
+ return "";
+ }
+
+ ShaderSourceEntry entry = result->second;
+
+ if (entry.isValid) {
+ LOGWEBGL(" validated shader, retrieve OpenGL log");
+ GLuint shaderID = shader;
+ GLint logLength;
+ glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &logLength);
+ if (!logLength)
+ return "";
+
+ char* log = 0;
+ if ((log = (char *)fastMalloc(logLength * sizeof(char))) == 0)
+ return "";
+ GLsizei returnedLogLength;
+ glGetShaderInfoLog(shaderID, logLength, &returnedLogLength, log);
+ String res = String(log, returnedLogLength);
+ fastFree(log);
+
+ return res;
+ }
+ else {
+ LOGWEBGL(" non-validated shader, use ANGLE log");
+ return entry.log;
+ }
+}
+
+String GraphicsContext3DInternal::getShaderSource(Platform3DObject shader)
+{
+ LOGWEBGL("getShaderSource()");
+ HashMap<Platform3DObject, ShaderSourceEntry>::iterator result = m_shaderSourceMap.find(shader);
+
+ if (result == m_shaderSourceMap.end())
+ return "";
+
+ return result->second.source;
+}
+
+void GraphicsContext3DInternal::shaderSource(Platform3DObject shader, const String& string)
+{
+ LOGWEBGL("shaderSource()");
+ ShaderSourceEntry entry;
+
+ entry.source = string;
+
+ m_shaderSourceMap.set(shader, entry);
+}
+
+void GraphicsContext3DInternal::viewport(long x, long y, unsigned long width, unsigned long height)
+{
+ LOGWEBGL("glViewport(%d, %d, %d, %d)", x, y, width, height);
+ glViewport(x, y, width, height);
+ m_savedViewport.x = x;
+ m_savedViewport.y = y;
+ m_savedViewport.width = width;
+ m_savedViewport.height = height;
+}
+}
+#endif // ENABLE(WEBGL)
diff --git a/Source/WebCore/platform/graphics/android/GraphicsContext3DInternal.h b/Source/WebCore/platform/graphics/android/GraphicsContext3DInternal.h
new file mode 100644
index 0000000..98fca6c
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/GraphicsContext3DInternal.h
@@ -0,0 +1,221 @@
+/*
+ * Copyright (C) 2011, 2012, Sony Ericsson Mobile Communications AB
+ * Copyright (C) 2012, Sony Mobile Communications AB
+ * All rights reserved.
+ *
+ * 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.
+ * * Neither the name of the Sony Ericsson Mobile Communications AB nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 SONY ERICSSON MOBILE COMMUNICATIONS AB 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 GraphicsContext3DInternal_h
+#define GraphicsContext3D3DInternal_h
+
+#include "ANGLEWebKitBridge.h"
+#include "CanvasRenderingContext.h"
+#include "Extensions3DAndroid.h"
+#include "GraphicsContext3D.h"
+#include "HTMLCanvasElement.h"
+#include "SkRect.h"
+#include "Threading.h"
+#include "Timer.h"
+#include "TransformationMatrix.h"
+#include "WebGLLayer.h"
+
+#include <wtf/Deque.h>
+#include <wtf/RefPtr.h>
+
+#include <EGL/egl.h>
+#include <GLES2/gl2.h>
+#include <ui/android_native_buffer.h>
+#include <ui/GraphicBuffer.h>
+
+#include <utils/Log.h>
+
+#undef WEBGL_LOGGING
+//#define WEBGL_LOGGING 1
+#ifdef WEBGL_LOGGING
+#define LOGWEBGL(...) ((void)android_printLog(ANDROID_LOG_DEBUG, "WebGL", __VA_ARGS__))
+#else
+#define LOGWEBGL(...)
+#endif
+
+// This can be increased to 3, for example, if that has a positive impact on performance.
+#define NUM_BUFFERS 2
+
+using namespace android;
+
+namespace WebCore {
+
+#define CLAMP(x) GraphicsContext3DInternal::clampValue(x)
+
+typedef enum {
+ THREAD_STATE_STOPPED,
+ THREAD_STATE_RUN,
+ THREAD_STATE_RESTART,
+ THREAD_STATE_STOP
+} thread_state_t;
+
+class GraphicsContext3DProxy;
+class FBO;
+
+class GraphicsContext3DInternal : public RefCounted<GraphicsContext3DInternal> {
+public:
+ GraphicsContext3DInternal(HTMLCanvasElement* canvas, GraphicsContext3D::Attributes attrs,
+ HostWindow* hostWindow);
+ ~GraphicsContext3DInternal();
+
+ bool isValid() { return m_contextId > 0; }
+
+ PlatformLayer* platformLayer() const;
+
+ void makeContextCurrent();
+ GraphicsContext3D::Attributes getContextAttributes();
+ void reshape(int width, int height);
+
+ unsigned long getError();
+ void synthesizeGLError(unsigned long error);
+
+ void recreateSurface();
+ void releaseSurface();
+
+ void markContextChanged();
+ void markLayerComposited() { m_layerComposited = true; }
+ bool layerComposited() const { return m_layerComposited; }
+
+ void updateFrontBuffer();
+ bool lockFrontBuffer(EGLImageKHR& image, SkRect& rect);
+ void releaseFrontBuffer();
+
+ void paintRenderingResultsToCanvas(CanvasRenderingContext* context);
+ PassRefPtr<ImageData> paintRenderingResultsToImageData();
+ bool paintCompositedResultsToCanvas(CanvasRenderingContext* context);
+
+ // Shader handling, required since we validate shader source with ANGLE
+ void compileShader(Platform3DObject shader);
+ String getShaderInfoLog(Platform3DObject shader);
+ String getShaderSource(Platform3DObject shader);
+ void shaderSource(Platform3DObject shader, const String& string);
+
+ void viewport(long x, long y, unsigned long width, unsigned long height);
+
+ int width() { return m_width; }
+ int height() { return m_height; }
+
+ Extensions3D* getExtensions() { return m_extensions.get(); }
+
+ void bindFramebuffer(GC3Denum target, Platform3DObject buffer);
+
+ static GLclampf clampValue(GLclampf x) {
+ GLclampf tmp = x;
+ if (tmp < 0.0f)
+ tmp = 0.0f;
+ else if (tmp > 1.0f)
+ tmp = 1.0f;
+ return tmp;
+ }
+
+ static GLclampf clampValue(double d) {
+ GLclampf tmp = (GLclampf)d;
+ if (tmp < 0.0f)
+ tmp = 0.0f;
+ else if (tmp > 1.0f)
+ tmp = 1.0f;
+ return tmp;
+ }
+
+ static EGLint checkEGLError(const char* s);
+ static GLint checkGLError(const char* s);
+
+private:
+ bool initEGL();
+ bool createContext(bool createEGLContext);
+ void deleteContext(bool deleteEGLContext);
+
+ RefPtr<GraphicsContext3DProxy> m_proxy;
+ WebGLLayer *m_compositingLayer;
+ HTMLCanvasElement* m_canvas;
+ GraphicsContext3D::Attributes m_attrs;
+ bool m_layerComposited;
+ bool m_canvasDirty;
+
+ int m_width;
+ int m_height;
+ int m_maxwidth;
+ int m_maxheight;
+
+ EGLDisplay m_dpy;
+ EGLConfig m_config;
+ EGLSurface m_surface;
+ EGLContext m_context;
+
+ // Routines for FBOs
+ FBO* m_fbo[NUM_BUFFERS];
+ GLuint m_boundFBO;
+ FBO* m_currentFBO;
+ FBO* m_frontFBO;
+ Deque<FBO*> m_freeBuffers;
+ Deque<FBO*> m_queuedBuffers;
+ Deque<FBO*> m_preparedBuffers;
+ WTF::Mutex m_fboMutex;
+ WTF::ThreadCondition m_fboCondition;
+
+ void startSyncThread();
+ void stopSyncThread();
+ static void* syncThreadStart(void* ctx);
+ void runSyncThread();
+ ThreadIdentifier m_syncThread;
+ thread_state_t m_threadState;
+ WTF::Mutex m_threadMutex;
+ WTF::ThreadCondition m_threadCondition;
+
+ void syncTimerFired(Timer<GraphicsContext3DInternal>*);
+ FBO* dequeueBuffer();
+ void swapBuffers();
+ Timer<GraphicsContext3DInternal> m_syncTimer;
+ bool m_syncRequested;
+
+ typedef struct {
+ String source;
+ String log;
+ bool isValid;
+ } ShaderSourceEntry;
+ HashMap<Platform3DObject, ShaderSourceEntry> m_shaderSourceMap;
+ ANGLEWebKitBridge m_compiler;
+
+ // Errors raised by synthesizeGLError().
+ ListHashSet<unsigned long> m_syntheticErrors;
+
+ struct {
+ GLint x, y;
+ GLsizei width, height;
+ } m_savedViewport;
+ OwnPtr<Extensions3DAndroid> m_extensions;
+ int m_contextId;
+
+ // Java method used for invalidating the canvas area
+ jobject m_webView;
+ jmethodID m_postInvalidate;
+};
+
+} // namespace WebCore
+
+#endif // GraphicsContext3DInternal_h
diff --git a/Source/WebCore/platform/graphics/android/GraphicsContext3DProxy.cpp b/Source/WebCore/platform/graphics/android/GraphicsContext3DProxy.cpp
new file mode 100644
index 0000000..0d273bb
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/GraphicsContext3DProxy.cpp
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2012 Sony Ericsson Mobile Communications AB
+ * Copyright (C) 2012 Sony Mobile Communications AB
+ *
+ * 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"
+
+#if ENABLE(WEBGL)
+
+#include "GraphicsContext3DProxy.h"
+#include "GraphicsContext3DInternal.h"
+
+namespace WebCore {
+
+GraphicsContext3DProxy::GraphicsContext3DProxy()
+{
+ LOGWEBGL("GraphicsContext3DProxy::GraphicsContext3DProxy(), this = %p", this);
+}
+
+GraphicsContext3DProxy::~GraphicsContext3DProxy()
+{
+ LOGWEBGL("GraphicsContext3DProxy::~GraphicsContext3DProxy(), this = %p", this);
+}
+
+void GraphicsContext3DProxy::setGraphicsContext(GraphicsContext3DInternal* context)
+{
+ MutexLocker lock(m_mutex);
+ m_context = context;
+}
+
+void GraphicsContext3DProxy::incr()
+{
+ MutexLocker lock(m_mutex);
+ m_refcount++;
+}
+
+void GraphicsContext3DProxy::decr()
+{
+ MutexLocker lock(m_mutex);
+ m_refcount--;
+ if (m_refcount == 0) {
+ glDeleteTextures(1, &m_texture);
+ m_texture = 0;
+ }
+}
+
+bool GraphicsContext3DProxy::lockFrontBuffer(GLuint& texture, SkRect& rect)
+{
+ MutexLocker lock(m_mutex);
+ if (!m_context) {
+ return false;
+ }
+ EGLImageKHR image;
+ bool locked = m_context->lockFrontBuffer(image, rect);
+ if (locked) {
+ if (m_texture == 0)
+ glGenTextures(1, &m_texture);
+
+ glBindTexture(GL_TEXTURE_EXTERNAL_OES, m_texture);
+ glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, image);
+ texture = m_texture;
+ }
+
+ return locked;
+}
+
+void GraphicsContext3DProxy::releaseFrontBuffer()
+{
+ MutexLocker lock(m_mutex);
+ if (!m_context) {
+ return;
+ }
+ glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
+ m_context->releaseFrontBuffer();
+}
+}
+#endif // ENABLE(WEBGL)
diff --git a/Source/WebCore/platform/graphics/android/GraphicsContext3DProxy.h b/Source/WebCore/platform/graphics/android/GraphicsContext3DProxy.h
new file mode 100644
index 0000000..060acdf
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/GraphicsContext3DProxy.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2012 Sony Ericsson Mobile Communications AB
+ * Copyright (C) 2012 Sony Mobile Communications AB
+ *
+ * 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 GraphicsContext3DProxy_h
+#define GraphicsContext3DProxy_h
+
+#include "config.h"
+
+#include "SkRect.h"
+#include "Threading.h"
+#include <wtf/RefCounted.h>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <GLES2/gl2.h>
+
+namespace WebCore {
+
+class GraphicsContext3DInternal;
+
+class GraphicsContext3DProxy: public RefCounted<GraphicsContext3DProxy> {
+public:
+ GraphicsContext3DProxy();
+ ~GraphicsContext3DProxy();
+
+ void setGraphicsContext(GraphicsContext3DInternal* context);
+ void incr();
+ void decr();
+
+ bool lockFrontBuffer(GLuint& texture, SkRect& rect);
+ void releaseFrontBuffer();
+
+private:
+ WTF::Mutex m_mutex;
+ GraphicsContext3DInternal* m_context;
+ GLuint m_texture;
+ int m_refcount;
+};
+
+}
+#endif
diff --git a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp
index 7a692c4..c5583d0 100644
--- a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp
+++ b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2009 The Android Open Source Project
+ * Copyright (C) 2011, Sony Ericsson Mobile Communications AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -121,6 +122,9 @@ GraphicsLayerAndroid::GraphicsLayerAndroid(GraphicsLayerClient* client) :
m_haveContents(false),
m_newImage(false),
m_image(0),
+#if ENABLE(WEBGL)
+ m_is3DCanvas(false),
+#endif
m_foregroundLayer(0),
m_foregroundClipLayer(0)
{
@@ -455,6 +459,14 @@ void GraphicsLayerAndroid::setNeedsDisplay()
setNeedsDisplayInRect(rect);
}
+#if ENABLE(WEBGL)
+void GraphicsLayerAndroid::setContentsNeedsDisplay()
+{
+ if (m_is3DCanvas)
+ setNeedsDisplay();
+}
+#endif
+
// Helper to set and clear the painting phase as well as auto restore the
// original phase.
class PaintingPhase {
@@ -897,12 +909,11 @@ void GraphicsLayerAndroid::setContentsToMedia(PlatformLayer* mediaLayer)
}
}
+#if ENABLE(WEBGL)
void GraphicsLayerAndroid::setContentsToCanvas(PlatformLayer* canvasLayer)
{
if (m_contentLayer != canvasLayer && canvasLayer) {
-
- // TODO add a copy method to LayerAndroid to sync everything
- // copy data from the original content layer to the new one
+ // Copy data from the original content layer to the new one
canvasLayer->setPosition(m_contentLayer->getPosition().fX,
m_contentLayer->getPosition().fY);
canvasLayer->setSize(m_contentLayer->getWidth(), m_contentLayer->getHeight());
@@ -912,17 +923,40 @@ void GraphicsLayerAndroid::setContentsToCanvas(PlatformLayer* canvasLayer)
m_contentLayer->unref();
m_contentLayer = canvasLayer;
- // If the parent exists then notify it to re-sync it's children
- if (m_parent) {
- GraphicsLayerAndroid* parent = static_cast<GraphicsLayerAndroid*>(m_parent);
- parent->m_needsSyncChildren = true;
- }
m_needsSyncChildren = true;
+ m_is3DCanvas = true;
- setNeedsDisplay();
- askForSync();
+ setDrawsContent(true);
}
}
+#endif
+
+// TODO: Remove when canvas acceleration starts using the WebGLRenderingContext.
+void GraphicsLayerAndroid::setContentsToGPUCanvas(PlatformLayer* canvasLayer)
+{
+ if (m_contentLayer == canvasLayer || !canvasLayer)
+ return;
+
+ // Copy data from the original content layer to the new one
+ canvasLayer->setPosition(m_contentLayer->getPosition().fX,
+ m_contentLayer->getPosition().fY);
+ canvasLayer->setSize(m_contentLayer->getWidth(), m_contentLayer->getHeight());
+ canvasLayer->setDrawTransform(*m_contentLayer->drawTransform());
+
+ canvasLayer->ref();
+ m_contentLayer->unref();
+ m_contentLayer = canvasLayer;
+
+ // If the parent exists then notify it to re-sync it's children
+ if (m_parent) {
+ GraphicsLayerAndroid* parent = static_cast<GraphicsLayerAndroid*>(m_parent);
+ parent->m_needsSyncChildren = true;
+ }
+ m_needsSyncChildren = true;
+
+ setNeedsDisplay();
+ askForSync();
+}
PlatformLayer* GraphicsLayerAndroid::platformLayer() const
{
diff --git a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.h b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.h
index 51f7063..3f8404e 100644
--- a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.h
+++ b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.h
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2009 The Android Open Source Project
+ * Copyright (C) 2011, Sony Ericsson Mobile Communications AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -81,6 +82,10 @@ public:
virtual void setNeedsDisplay();
virtual void setNeedsDisplayInRect(const FloatRect&);
+#if ENABLE(WEBGL)
+ virtual void setContentsNeedsDisplay();
+#endif
+
virtual bool addAnimation(const KeyframeValueList& valueList,
const IntSize& boxSize,
const Animation* anim,
@@ -105,7 +110,10 @@ public:
virtual void setContentsToImage(Image*);
virtual void setContentsToMedia(PlatformLayer*);
+#if ENABLE(WEBGL)
virtual void setContentsToCanvas(PlatformLayer*);
+#endif
+ virtual void setContentsToGPUCanvas(PlatformLayer*);
virtual PlatformLayer* platformLayer() const;
void pauseDisplay(bool state);
@@ -151,6 +159,10 @@ private:
bool m_newImage;
Image* m_image;
+#if ENABLE(WEBGL)
+ bool m_is3DCanvas;
+#endif
+
SkRegion m_dirtyRegion;
LayerAndroid* m_contentLayer;
diff --git a/Source/WebCore/platform/graphics/android/WebGLLayer.cpp b/Source/WebCore/platform/graphics/android/WebGLLayer.cpp
new file mode 100644
index 0000000..a0056b7
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/WebGLLayer.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2011, 2012 Sony Ericsson Mobile Communications AB
+ * Copyright (C) 2012 Sony Mobile Communications AB
+ *
+ * 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"
+
+#if ENABLE(WEBGL) && USE(ACCELERATED_COMPOSITING)
+
+#include "WebGLLayer.h"
+
+#include "GraphicsContext3DInternal.h"
+#include "SkRect.h"
+#include "TilesManager.h"
+#include "TransformationMatrix.h"
+
+namespace WebCore {
+
+WebGLLayer::WebGLLayer(GraphicsContext3DProxy* proxy)
+ : LayerAndroid((RenderLayer*)0)
+ , m_proxy(proxy)
+{
+ m_proxy->incr();
+}
+
+WebGLLayer::WebGLLayer(const WebGLLayer& layer)
+ : LayerAndroid(layer)
+ , m_proxy(layer.m_proxy)
+{
+ m_proxy->incr();
+}
+
+WebGLLayer::~WebGLLayer()
+{
+ m_proxy->decr();
+}
+
+bool WebGLLayer::drawGL()
+{
+ bool askScreenUpdate = false;
+
+ askScreenUpdate |= LayerAndroid::drawGL();
+
+ if (m_proxy.get()) {
+ GLuint texture;
+ SkRect localBounds;
+ bool locked = m_proxy->lockFrontBuffer(texture, localBounds);
+ if (locked) {
+ // Flip the y-coordinate
+ TransformationMatrix transform = m_drawTransform;
+ transform = transform.translate(0, 2 * localBounds.top() + localBounds.height());
+ transform = transform.scale3d(1.0, -1.0, 1.0);
+ TilesManager::instance()->shader()->drawLayerQuad(transform, localBounds,
+ texture, 1.0f, true, GL_TEXTURE_EXTERNAL_OES);
+ m_proxy->releaseFrontBuffer();
+ }
+ }
+
+ return askScreenUpdate;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(WEBGL) && USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/android/WebGLLayer.h b/Source/WebCore/platform/graphics/android/WebGLLayer.h
new file mode 100644
index 0000000..c47cdbf
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/WebGLLayer.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2011, 2012 Sony Ericsson Mobile Communications AB
+ * Copyright (C) 2012 Sony Mobile Communications AB
+ *
+ * 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 WebGLLayer_h
+#define WebGLLayer_h
+
+#include "config.h"
+
+#if ENABLE(WEBGL) && USE(ACCELERATED_COMPOSITING)
+
+#include "GLUtils.h"
+#include "GraphicsContext3DProxy.h"
+#include "LayerAndroid.h"
+#include "RefPtr.h"
+#include <jni.h>
+
+namespace WebCore {
+
+class GraphicsContext3DInternal;
+
+class WebGLLayer : public LayerAndroid {
+public:
+ WebGLLayer(GraphicsContext3DProxy* proxy);
+ WebGLLayer(const WebGLLayer& layer);
+ virtual ~WebGLLayer();
+
+ virtual LayerAndroid* copy() const { return new WebGLLayer(*this); }
+ virtual bool drawGL();
+
+private:
+ RefPtr<GraphicsContext3DProxy> m_proxy;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(WEBGL) && USE(ACCELERATED_COMPOSITING)
+#endif // WebGLLayer_h
diff --git a/Source/WebCore/platform/image-decoders/ImageDecoder.cpp b/Source/WebCore/platform/image-decoders/ImageDecoder.cpp
index 24a9f90..504eb08 100644
--- a/Source/WebCore/platform/image-decoders/ImageDecoder.cpp
+++ b/Source/WebCore/platform/image-decoders/ImageDecoder.cpp
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2008-2009 Torch Mobile, Inc.
* Copyright (C) Research In Motion Limited 2009-2010. All rights reserved.
+ * Copyright (C) 2012, Sony Ericsson Mobile Communications AB
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -94,10 +95,10 @@ bool matchesCURSignature(char* contents)
}
-#if !OS(ANDROID)
// This method requires BMPImageDecoder, PNGImageDecoder, ICOImageDecoder and
// JPEGDecoder, which aren't used on Android, and which don't all compile.
// TODO: Find a better fix.
+// WebGL: Activated the GIF and PNG image decoders for Android.
ImageDecoder* ImageDecoder::create(const SharedBuffer& data, ImageSource::AlphaOption alphaOption, ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption)
{
static const unsigned lengthOfLongestSignature = 14; // To wit: "RIFF????WEBPVP"
@@ -109,9 +110,12 @@ ImageDecoder* ImageDecoder::create(const SharedBuffer& data, ImageSource::AlphaO
if (matchesGIFSignature(contents))
return new GIFImageDecoder(alphaOption, gammaAndColorProfileOption);
+#if !OS(ANDROID) || ENABLE(WEBGL)
if (matchesPNGSignature(contents))
return new PNGImageDecoder(alphaOption, gammaAndColorProfileOption);
+#endif
+#if !OS(ANDROID)
if (matchesJPEGSignature(contents))
return new JPEGImageDecoder(alphaOption, gammaAndColorProfileOption);
@@ -125,10 +129,10 @@ ImageDecoder* ImageDecoder::create(const SharedBuffer& data, ImageSource::AlphaO
if (matchesICOSignature(contents) || matchesCURSignature(contents))
return new ICOImageDecoder(alphaOption, gammaAndColorProfileOption);
+#endif // !OS(ANDROID)
return 0;
}
-#endif // !OS(ANDROID)
#if !USE(SKIA)
diff --git a/Source/WebCore/rendering/RenderLayerBacking.cpp b/Source/WebCore/rendering/RenderLayerBacking.cpp
index f1f5502..bfb2219 100644
--- a/Source/WebCore/rendering/RenderLayerBacking.cpp
+++ b/Source/WebCore/rendering/RenderLayerBacking.cpp
@@ -63,6 +63,10 @@
#include "RenderVNode.h"
#endif
+#if PLATFORM(ANDROID)
+#include "GraphicsLayerAndroid.h"
+#endif
+
using namespace std;
namespace WebCore {
@@ -318,12 +322,14 @@ bool RenderLayerBacking::updateGraphicsLayerConfiguration()
layerConfigChanged = true;
}
#endif
- else if (renderer->isCanvas()){
+ else if (renderer->isCanvas()) {
HTMLCanvasElement *canvas = static_cast<HTMLCanvasElement*>(renderer->node());
if (canvas->isUsingGpuRendering())
- {
+#if PLATFORM(ANDROID)
+ static_cast<GraphicsLayerAndroid*>(graphicsLayer())->setContentsToGPUCanvas(canvas->platformLayer());
+#else
m_graphicsLayer->setContentsToCanvas(canvas->platformLayer());
- }
+#endif
layerConfigChanged = true;
}
diff --git a/Source/WebCore/rendering/RenderLayerCompositor.cpp b/Source/WebCore/rendering/RenderLayerCompositor.cpp
index d528c90..4908489 100644
--- a/Source/WebCore/rendering/RenderLayerCompositor.cpp
+++ b/Source/WebCore/rendering/RenderLayerCompositor.cpp
@@ -1532,16 +1532,11 @@ bool RenderLayerCompositor::requiresCompositingForCanvas(RenderObject* renderer)
if (!(m_compositingTriggers & ChromeClient::CanvasTrigger))
return false;
- if (renderer->isCanvas()) {
- HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(renderer->node());
- return canvas->isUsingGpuRendering();
- }
+ if (!renderer->isCanvas())
+ return false;
- if (renderer->isCanvas()) {
- HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(renderer->node());
- return canvas->renderingContext() && canvas->renderingContext()->isAccelerated();
- }
- return false;
+ HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(renderer->node());
+ return (canvas->renderingContext() && canvas->renderingContext()->isAccelerated()) || canvas->isUsingGpuRendering();
}
bool RenderLayerCompositor::requiresCompositingForPlugin(RenderObject* renderer) const
diff --git a/Source/WebKit/android/jni/WebSettings.cpp b/Source/WebKit/android/jni/WebSettings.cpp
index 09c0290..f732716 100644
--- a/Source/WebKit/android/jni/WebSettings.cpp
+++ b/Source/WebKit/android/jni/WebSettings.cpp
@@ -1,6 +1,7 @@
/*
* Copyright 2007, The Android Open Source Project
* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (C) 2011, Sony Ericsson Mobile Communications AB
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -602,6 +603,10 @@ public:
str = (jstring)env->GetObjectField(obj, gFieldIds->mDataPath);
WebCore::INodeProxy::setAppDataPath(jstringToWtfString(env, str));
#endif
+
+#if ENABLE(WEBGL)
+ s->setWebGLEnabled(false);
+#endif
}
};
diff --git a/Source/WebKit/android/jni/WebViewCore.cpp b/Source/WebKit/android/jni/WebViewCore.cpp
index 14610d5..7f9ba86 100755
--- a/Source/WebKit/android/jni/WebViewCore.cpp
+++ b/Source/WebKit/android/jni/WebViewCore.cpp
@@ -1,6 +1,8 @@
/*
* Copyright 2006, The Android Open Source Project
* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (C) 2012 Sony Ericsson Mobile Communications AB.
+ * Copyright (C) 2012 Sony Mobile Communications AB
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -4649,6 +4651,11 @@ static void Pause(JNIEnv* env, jobject obj)
proxy->pause();
}
#endif
+#if ENABLE(WEBGL)
+ Document* document = frame->document();
+ if (document)
+ document->suspendDocument();
+#endif
}
GET_NATIVE_VIEW(env, obj)->deviceMotionAndOrientationManager()->maybeSuspendClients();
@@ -4676,6 +4683,11 @@ static void Resume(JNIEnv* env, jobject obj)
proxy->resume();
}
#endif
+#if ENABLE(WEBGL)
+ Document* document = frame->document();
+ if (document)
+ document->resumeDocument();
+#endif
}
GET_NATIVE_VIEW(env, obj)->deviceMotionAndOrientationManager()->maybeResumeClients();