summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/platform/graphics/android
diff options
context:
space:
mode:
authorPierre-Antoine LaFayette <plafayet@codeaurora.org>2011-12-29 15:13:33 +0100
committerSteve Kondik <shade@chemlab.org>2013-01-20 18:38:26 -0800
commit70f026a42cf1bee061389fa6ce790ea1186f0703 (patch)
treeb0de5b5676433d2382e7cf1307b54edc19fc42a5 /Source/WebCore/platform/graphics/android
parenta815c626d7df7e24ba9e0df27c27735d4e069ffd (diff)
downloadexternal_webkit-70f026a42cf1bee061389fa6ce790ea1186f0703.zip
external_webkit-70f026a42cf1bee061389fa6ce790ea1186f0703.tar.gz
external_webkit-70f026a42cf1bee061389fa6ce790ea1186f0703.tar.bz2
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. Includes runtime enablement through Browser Settings -> Labs menu. Enable WebGL debug logs and FPS timing with: adb shell setprop debug.webgl 1 Includes Cross-origin resource sharing support. Includes fixes for the following Khronos WebGL 1.0.1. tests: - premultiplyalpha-test.html - struct-nesting-exceeds-maximum.html - index-validation.html - context-attributes-alpha-depth-stencil-antialias.html - program-test.html - object-deletion-behaviour.html Squashed patches: ----------------------------------------------------------- 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 https://www.codeaurora.org/gitweb/quic/la/?p=platform/external/webkit.git;a=commit;h=c72ff2aa562941d94ceb51ba685d60809ca882a6 Updates to fix some test failures in Khronos Conformance Test Suite: - Increase max identifier length in shaders to 256 - Add length check on uniforms and attributes - Add minimal support for compressed textures (that is, just return the correct error codes) - Add support for Uint8ClampedByteArray - Modify how error checking is done on framebuffer operations - Activate the GL_OES_packed_depth_stencil extension - Activate the GL_OES_texture_float extension https://www.codeaurora.org/gitweb/quic/la/?p=platform/external/webkit.git;a=commit;h=5bfe05848c12a2894697fbb503cfa79981eb96bd Fix WebGL 1.0.1 premultiplyalpha-test conformance test Fixing bug with toDataURL when called against a Canvas in which WebGL content is being rendered and make sure paintRenderingResultsToImageData isn't used for the premultiplied case. ihttps://www.codeaurora.org/gitweb/quic/la/?p=platform/external/webkit.git;a=commit;h=5834a1e00f89d898a7a0039d47916b196e40a2c8 Update ANGLE to r1009 to fix WebGL 1.0.1 conformance test Fixes struct-nesting-exceeds-maximum Khronos WebGL conformance test. https://www.codeaurora.org/gitweb/quic/la/?p=platform/external/webkit.git;a=commit;h=ae2392db6360b41a5717f3770a9e63b1bcea45d6 vertexAttribPointer needs to reject large negative offsets https://bugs.webkit.org/show_bug.cgi?id=85117 Reviewed by Kenneth Russell. Source/WebCore: * html/canvas/WebGLRenderingContext.cpp: Use long long for GLsizeiptr and GLintptr (WebCore): (WebCore::WebGLRenderingContext::bufferData): (WebCore::WebGLRenderingContext::bufferSubData): (WebCore::WebGLRenderingContext::drawElements): (WebCore::WebGLRenderingContext::getVertexAttribOffset): (WebCore::WebGLRenderingContext::vertexAttribPointer): * html/canvas/WebGLRenderingContext.h: Ditto (WebGLRenderingContext): * html/canvas/WebGLRenderingContext.idl: Ditto LayoutTests: * fast/canvas/webgl/index-validation-expected.txt: * fast/canvas/webgl/index-validation.html: Add a test case for large negative offset. git-svn-id: http://svn.webkit.org/repository/webkit/trunk@116374 268f45cc-cd09-0410-ab3c-d52691b4dbfc https://www.codeaurora.org/gitweb/quic/la/?p=platform/external/webkit.git;a=commit;h=b3a02a0942a0e2c44d23961382145fad6016b2ef Fix for context-attributes-alpha-depth-stencil-antialias Support for alpha, depth and stencil to fix WebGL Khronos 1.0.1 conformance test. Report back that antialiasing is not supported on our platform. https://www.codeaurora.org/gitweb/quic/la/?p=platform/external/webkit.git;a=commit;h=22e98195ac73e7e12a59d5b9a42dfc4e2252b475 WebGLRenderingContext should defer caching program info https://bugs.webkit.org/show_bug.cgi?id=83513 Reviewed by Kenneth Russell. * html/canvas/WebGLProgram.cpp: (WebCore::WebGLProgram::WebGLProgram): (WebCore::WebGLProgram::numActiveAttribLocations): call cacheInfoIfNeeded(); (WebCore::WebGLProgram::getActiveAttribLocation): Ditto. (WebCore::WebGLProgram::isUsingVertexAttrib0): Ditto. (WebCore::WebGLProgram::getLinkStatus): Ditto. (WebCore): (WebCore::WebGLProgram::cacheActiveAttribLocations): (WebCore::WebGLProgram::cacheInfoIfNeeded): Cache link status, active attire locations, etc if needed. (WebCore::WebGLProgram::increaseLinkCount): also invalidate cached info. * html/canvas/WebGLProgram.h: (WebGLProgram): * html/canvas/WebGLRenderingContext.cpp: (WebCore): (WebCore::WebGLRenderingContext::linkProgram): Do not cache program info immediately. git-svn-id: http://svn.webkit.org/repository/webkit/trunk@113915 268f45cc-cd09-0410-ab3c-d52691b4dbfc https://www.codeaurora.org/gitweb/quic/la/?p=platform/external/webkit.git;a=commit;h=66bc9c1b9eb5151b1b236199d0eeb17df0557b47 Runtime enablement of WebGL Hooks up with the Java side to enable/disable WebGL through the debug menu. https://www.codeaurora.org/gitweb/quic/la/?p=platform/external/webkit.git;a=commit;h=75aab57859de45a0aaec5a7cad41a12111e9a82e Support the usage of CORS for WebGL and the 2D canvas Factor CORS request preparation out of DocumentThreadableLoader https://bugs.webkit.org/show_bug.cgi?id=61209 2011-05-20 Adam Barth <abarth@webkit.org> Reviewed by Alexey Proskuryakov. Factor CORS request preparation out of DocumentThreadableLoader https://bugs.webkit.org/show_bug.cgi?id=61209 DocumentThreadableLoader has two jobs: 1) Proxy loads between threads. 2) Run the CORS state machine. This patch begins the work of separating those concerns, allowing CORS to be used elsewhere in the loading pipeline. In particular, this patch moves knowledge of how to prepare CORS requests out of DocumentThreadableLoder. * loader/CrossOriginAccessControl.cpp: (WebCore::isOnAccessControlSimpleRequestHeaderWhitelist): (WebCore::updateRequestForAccessControl): (WebCore::createAccessControlPreflightRequest): * loader/CrossOriginAccessControl.h: * loader/DocumentThreadableLoader.cpp: (WebCore::DocumentThreadableLoader::DocumentThreadableLoader): (WebCore::DocumentThreadableLoader::makeSimpleCrossOriginAccessRequest): (WebCore::DocumentThreadableLoader::makeCrossOriginAccessRequestWithPreflight): git-svn-id: http://svn.webkit.org/repository/webkit/trunk@86980 268f45cc-cd09-0410-ab3c-d52691b4dbfc Add rel type prerender to distinguish prerender from prefetch https://bugs.webkit.org/show_bug.cgi?id=61079 2011-05-21 Gavin Peters <gavinp@chromium.org> Reviewed by Adam Barth. Add rel type prerender to distinguish prerender from prefetch https://bugs.webkit.org/show_bug.cgi?id=61079 Chrome right now uses <link rel=prefetch ...> for one of two things, to warm the cache in the same way as firefox, or to launch a speculative rendering of a web page, for faster "loading" when the user navigates to it. This new rel type will let us distinguish the two cases; the rel type prerender isn't used on the web today, but the Google Web Search example prerendering application is ready to experiment with it. * fast/dom/HTMLLinkElement/prerender-expected.txt: Added. * fast/dom/HTMLLinkElement/prerender.html: Added. * platform/gtk/Skipped: * platform/mac/Skipped: * platform/qt/Skipped: * platform/win/Skipped: 2011-05-21 Gavin Peters <gavinp@chromium.org> Reviewed by Adam Barth. Add rel type prerender to distinguish prerender from prefetch https://bugs.webkit.org/show_bug.cgi?id=61079 Chrome right now uses <link rel=prefetch ...> for one of two things, to warm the cache in the same way as firefox, or to launch a speculative rendering of a web page, for faster "loading" when the user navigates to it. This new rel type will let us distinguish the two cases; the rel type prerender isn't used on the web today, but the Google Web Search example prerendering application is ready to experiment with it. Test: fast/dom/HTMLLinkElement/prerender.html * html/HTMLLinkElement.cpp: (WebCore::HTMLLinkElement::tokenizeRelAttribute): (WebCore::HTMLLinkElement::process): * html/HTMLLinkElement.h: (WebCore::HTMLLinkElement::RelAttribute::RelAttribute): * loader/cache/CachedResource.cpp: (WebCore::defaultPriorityForResourceType): * loader/cache/CachedResource.h: (WebCore::CachedResource::isLinkResource): * loader/cache/CachedResourceLoader.cpp: (WebCore::createResource): (WebCore::CachedResourceLoader::requestLinkResource): (WebCore::CachedResourceLoader::canRequest): * loader/cache/CachedResourceLoader.h: * loader/cache/CachedResourceRequest.cpp: (WebCore::cachedResourceTypeToTargetType): (WebCore::CachedResourceRequest::load): * platform/network/ResourceRequestBase.h: git-svn-id: http://svn.webkit.org/repository/webkit/trunk@87020 268f45cc-cd09-0410-ab3c-d52691b4dbfc Make CachedResource take a ResourceRequest instead of just a url string. 2011-05-24 Nate Chapin <japhet@chromium.org> Reviewed by Adam Barth. Change CachedResources to take a ResourceRequest instead of a url in their constructors and provide a very minimal set of cases for avoiding reusing a CachedResource. The ResourceRequest part of this change requires pushing responsibility for calling Document::completeURL() to the caller, instead of CachedResourceLoader, since ResourceRequest ASSERTs if it is constructed with an invalid url. https://bugs.webkit.org/show_bug.cgi?id=61318 Refactor, no new tests. * css/CSSFontSelector.cpp: (WebCore::CSSFontSelector::addFontFaceRule): * css/CSSImageValue.cpp: (WebCore::CSSImageValue::cachedImage): * css/CSSImportRule.cpp: (WebCore::CSSImportRule::insertedIntoParent): * dom/ProcessingInstruction.cpp: (WebCore::ProcessingInstruction::checkStyleSheet): * dom/ScriptElement.cpp: (WebCore::ScriptElement::requestScript): * html/HTMLLinkElement.cpp: (WebCore::HTMLLinkElement::process): * loader/ImageLoader.cpp: (WebCore::ImageLoader::updateFromElement): * loader/cache/CachedCSSStyleSheet.cpp: (WebCore::CachedCSSStyleSheet::CachedCSSStyleSheet): (WebCore::CachedCSSStyleSheet::didAddClient): (WebCore::CachedCSSStyleSheet::checkNotify): * loader/cache/CachedCSSStyleSheet.h: * loader/cache/CachedFont.cpp: (WebCore::CachedFont::CachedFont): * loader/cache/CachedFont.h: * loader/cache/CachedImage.cpp: (WebCore::CachedImage::CachedImage): (WebCore::CachedImage::checkShouldPaintBrokenImage): * loader/cache/CachedImage.h: * loader/cache/CachedResource.cpp: (WebCore::CachedResource::CachedResource): (WebCore::reuseRequest): (WebCore::CachedResource::allowReuseOfRequest): (WebCore::CachedResource::removeClient): (WebCore::CachedResource::canUseCacheValidator): * loader/cache/CachedResource.h: (WebCore::CachedResource::resourceRequest): (WebCore::CachedResource::url): * loader/cache/CachedResourceLoader.cpp: * loader/cache/CachedResourceLoader.h: * loader/cache/CachedResourceRequest.cpp: (WebCore::CachedResourceRequest::load): * loader/cache/CachedScript.cpp: (WebCore::CachedScript::CachedScript): * loader/cache/CachedScript.h: * loader/cache/CachedXSLStyleSheet.cpp: (WebCore::CachedXSLStyleSheet::CachedXSLStyleSheet): (WebCore::CachedXSLStyleSheet::didAddClient): (WebCore::CachedXSLStyleSheet::checkNotify): * loader/cache/CachedXSLStyleSheet.h: * svg/SVGFEImageElement.cpp: (WebCore::SVGFEImageElement::requestImageResource): * svg/SVGFontFaceUriElement.cpp: (WebCore::SVGFontFaceUriElement::loadFont): * xml/XSLImportRule.cpp: (WebCore::XSLImportRule::loadSheet): git-svn-id: http://svn.webkit.org/repository/webkit/trunk@87239 268f45cc-cd09-0410-ab3c-d52691b4dbfc Support cross-origin property for images 2011-05-26 Adam Barth <abarth@webkit.org> Reviewed by Eric Seidel. Support cross-origin property for images https://bugs.webkit.org/show_bug.cgi?id=61015 Test various cases involving CORS requests and canvas tainting. * http/tests/security/canvas-remote-read-remote-image-allowed-expected.txt: Added. * http/tests/security/canvas-remote-read-remote-image-allowed-with-credentials-expected.txt: Added. * http/tests/security/canvas-remote-read-remote-image-allowed-with-credentials.html: Added. * http/tests/security/canvas-remote-read-remote-image-allowed.html: Added. * http/tests/security/canvas-remote-read-remote-image-blocked-no-crossorigin-expected.txt: Added. * http/tests/security/canvas-remote-read-remote-image-blocked-no-crossorigin.html: Added. * http/tests/security/resources/abe-allow-credentials.php: Added. * http/tests/security/resources/abe-allow-star.php: Added. 2011-05-26 Adam Barth <abarth@webkit.org> Reviewed by Eric Seidel. Support cross-origin property for images https://bugs.webkit.org/show_bug.cgi?id=61015 This patch add support for the crossorigin attribute of images and teaches 2D canvas to respect that flag and not taint a canvas if the image drawn on the canvas is allowed by CORS. While I was editing this code, I couldn't resist a couple touch-up changes. Tests: http/tests/security/canvas-remote-read-remote-image-allowed-with-credentials.html http/tests/security/canvas-remote-read-remote-image-allowed.html http/tests/security/canvas-remote-read-remote-image-blocked-no-crossorigin.html * html/HTMLAttributeNames.in: * html/HTMLCanvasElement.cpp: (WebCore::HTMLCanvasElement::securityOrigin): * html/HTMLCanvasElement.h: * html/HTMLImageElement.idl: * html/canvas/CanvasRenderingContext.cpp: (WebCore::CanvasRenderingContext::checkOrigin): * html/canvas/CanvasRenderingContext2D.cpp: (WebCore::CanvasRenderingContext2D::createPattern): * loader/ImageLoader.cpp: (WebCore::ImageLoader::updateFromElement): * loader/cache/CachedResource.cpp: (WebCore::CachedResource::passesAccessControlCheck): * loader/cache/CachedResource.h: git-svn-id: http://svn.webkit.org/repository/webkit/trunk@87473 268f45cc-cd09-0410-ab3c-d52691b4dbfc HTMLVideoElement::currentSrc() should return a KURL 2011-05-27 Adam Barth <abarth@webkit.org> Reviewed by Eric Seidel. HTMLVideoElement::currentSrc() should return a KURL https://bugs.webkit.org/show_bug.cgi?id=61578 I suspect we got into this mess because the author of this code didn't know about the URL attribute in WebKit IDL, which is super useful! Bad news: The line of code in question seems to have another bug, which I've documented in a FIXME. Let the yak shaving continue! * html/HTMLMediaElement.cpp: (WebCore::urlForLogging): (WebCore::HTMLMediaElement::loadResource): (WebCore::HTMLMediaElement::isSafeToLoadURL): (WebCore::HTMLMediaElement::selectNextSourceChild): (WebCore::HTMLMediaElement::getPluginProxyParams): * html/HTMLMediaElement.h: (WebCore::HTMLMediaElement::currentSrc): (WebCore::HTMLMediaElement::currentURL): * html/canvas/CanvasRenderingContext.cpp: (WebCore::CanvasRenderingContext::checkOrigin): * rendering/HitTestResult.cpp: (WebCore::HitTestResult::absoluteMediaURL): - This complete URL call was unnecessary because currentSrc is already absolute. git-svn-id: http://svn.webkit.org/repository/webkit/trunk@87539 268f45cc-cd09-0410-ab3c-d52691b4dbfc Disallow use of cross-domain media (images, video) in WebGL 2011-06-09 Kenneth Russell <kbr@google.com> Reviewed by Adam Barth. Disallow use of cross-domain media (images, video) in WebGL https://bugs.webkit.org/show_bug.cgi?id=62257 Updated WebGL implementation to track recent spec updates in this area. Tests: http/tests/security/webgl-remote-read-remote-image-allowed-with-credentials.html http/tests/security/webgl-remote-read-remote-image-allowed.html http/tests/security/webgl-remote-read-remote-image-blocked-no-crossorigin.html * html/canvas/CanvasRenderingContext.cpp: (WebCore::CanvasRenderingContext::wouldTaintOrigin): (WebCore::CanvasRenderingContext::checkOrigin): * html/canvas/CanvasRenderingContext.h: (WebCore::CanvasRenderingContext::checkOrigin): * html/canvas/WebGLRenderingContext.cpp: (WebCore::WebGLRenderingContext::readPixels): (WebCore::WebGLRenderingContext::texImage2D): (WebCore::WebGLRenderingContext::videoFrameToImage): (WebCore::WebGLRenderingContext::texSubImage2D): * html/canvas/WebGLRenderingContext.h: 2011-06-09 Kenneth Russell <kbr@google.com> Reviewed by Adam Barth. Disallow use of cross-domain media (images, video) in WebGL https://bugs.webkit.org/show_bug.cgi?id=62257 Updated origin-clean-conformance.html to track upstream version in Khronos repository. Added new layout tests mirroring those added in bug 61015 which verify that new CORS support for images is working in the context of WebGL. Verified new tests in WebKit and Chromium. Skipped tests on platforms where WebGL is disabled. * http/tests/canvas/webgl/origin-clean-conformance-expected.txt: * http/tests/canvas/webgl/origin-clean-conformance.html: * http/tests/security/webgl-remote-read-remote-image-allowed-expected.txt: Added. * http/tests/security/webgl-remote-read-remote-image-allowed-with-credentials-expected.txt: Added. * http/tests/security/webgl-remote-read-remote-image-allowed-with-credentials.html: Added. * http/tests/security/webgl-remote-read-remote-image-allowed.html: Added. * http/tests/security/webgl-remote-read-remote-image-blocked-no-crossorigin-expected.txt: Added. * http/tests/security/webgl-remote-read-remote-image-blocked-no-crossorigin.html: Added. * platform/gtk/Skipped: * platform/mac-leopard/Skipped: * platform/mac-wk2/Skipped: * platform/qt/Skipped: git-svn-id: http://svn.webkit.org/repository/webkit/trunk@88489 268f45cc-cd09-0410-ab3c-d52691b4dbfc https://www.codeaurora.org/gitweb/quic/la/?p=platform/external/webkit.git;a=commit;h=0ddd7c1d91c08fbee6c99b79fa9971a7ac914384 Runtime enablement of WebGL logs Allows enabling WebGL method level logging using: adb shell setprop debug.webgl 1 https://www.codeaurora.org/gitweb/quic/la/?p=platform/external/webkit.git;a=commit;h=307d4a2b5b20f2609497ceaea1eca2e29a8a781f Adding WebGL FPS timing to logs Samples WebGL average FPS every 15 frames and outputs to WebGL debug log. TODO: Add setting to browser debug settings that overlays FPS on web pages. Postpone deleteRenderbuffer/deleteTexture until all framebuffer attachment points are removed. https://bugs.webkit.org/show_bug.cgi?id=74741 Reviewed by Kenneth Russell. Source/WebCore: Use WebGLObject's attachment count mechanism to track if a renderbuffer/texture is still attached to framebuffers, and if its deletion should be delated or not. * html/canvas/WebGLFramebuffer.cpp: (WebCore::WebGLFramebuffer::setAttachmentForBoundFramebuffer): (WebCore::WebGLFramebuffer::getAttachment): (WebCore::WebGLFramebuffer::removeAttachmentFromBoundFramebuffer): (WebCore::WebGLFramebuffer::deleteObjectImpl): (WebCore::WebGLFramebuffer::isBound): * html/canvas/WebGLFramebuffer.h: LayoutTests: * fast/canvas/webgl/object-deletion-behaviour-expected.txt: * fast/canvas/webgl/object-deletion-behaviour.html: synced with khronos side. git-svn-id: http://svn.webkit.org/repository/webkit/trunk@103272 268f45cc-cd09-0410-ab3c-d52691b4dbfc https://www.codeaurora.org/gitweb/quic/la/?p=platform/external/webkit.git;a=commit;h=9def386340c74f2a745fb041b1cb11daa30d1a82 ----------------------------------------------------------- (cherry-picked from commit 6d9d732ff06a6b265d02b18d7034068a68ef0fde) Conflicts: Android.mk Source/WebCore/ChangeLog Change-Id: I3bbf993fe5a3d6cea53e019c8fa3912ecd2bd429
Diffstat (limited to 'Source/WebCore/platform/graphics/android')
-rw-r--r--Source/WebCore/platform/graphics/android/Extensions3DAndroid.cpp102
-rw-r--r--Source/WebCore/platform/graphics/android/Extensions3DAndroid.h64
-rw-r--r--Source/WebCore/platform/graphics/android/GraphicsContext3DAndroid.cpp1368
-rw-r--r--Source/WebCore/platform/graphics/android/GraphicsContext3DInternal.cpp1104
-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.cpp34
-rw-r--r--Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.h14
-rw-r--r--Source/WebCore/platform/graphics/android/ImageBufferAndroid.cpp35
-rw-r--r--Source/WebCore/platform/graphics/android/WebGLLayer.cpp85
-rw-r--r--Source/WebCore/platform/graphics/android/WebGLLayer.h61
-rw-r--r--Source/WebCore/platform/graphics/android/layers/LayerAndroid.cpp14
-rw-r--r--Source/WebCore/platform/graphics/android/layers/LayerAndroid.h1
-rw-r--r--Source/WebCore/platform/graphics/android/layers/VideoLayerManager.h2
15 files changed, 3258 insertions, 9 deletions
diff --git a/Source/WebCore/platform/graphics/android/Extensions3DAndroid.cpp b/Source/WebCore/platform/graphics/android/Extensions3DAndroid.cpp
new file mode 100644
index 0000000..36fbe15
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/Extensions3DAndroid.cpp
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2011, 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 "Extensions3DAndroid.h"
+#include "GraphicsContext3D.h"
+
+#include <GLES2/gl2.h>
+
+namespace WebCore {
+
+Extensions3DAndroid::Extensions3DAndroid(const String& 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..ff50fa8
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/Extensions3DAndroid.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2011, 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 Extensions3DAndroid_h
+#define Extensions3DAndroid_h
+
+#include "Extensions3D.h"
+#include "PlatformString.h"
+
+namespace WebCore {
+
+class Extensions3DAndroid : public Extensions3D {
+public:
+ Extensions3DAndroid(const String& 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..85c9719
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/GraphicsContext3DInternal.cpp
@@ -0,0 +1,1104 @@
+/*
+ * 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 "CurrentTime.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 <binder/IBinder.h>
+#include <hardware/hardware.h>
+#include <private/gui/ComposerService.h>
+#include <gui/IGraphicBufferAlloc.h>
+#include <gui/ISurfaceComposer.h>
+#include <gui/SurfaceComposerClient.h>
+#include <JNIUtility.h>
+
+#if ENABLE(WEBGL)
+namespace WebCore {
+
+class WebGLFPSTimer {
+public:
+ WebGLFPSTimer()
+ : m_ticks(0)
+ {
+ m_startTime = currentTime();
+ }
+
+ void tick()
+ {
+ if (++m_ticks == s_sampleRate)
+ reset();
+ }
+
+ void reset()
+ {
+ double totalTime = currentTime() - m_startTime;
+ if (totalTime > 0) {
+ double averageFPS = m_ticks / totalTime;
+ LOGWEBGL("Average FPS: %0.3f", averageFPS);
+ }
+
+ m_ticks = 0;
+ m_startTime = currentTime();
+ }
+
+private:
+ long m_ticks;
+ double m_startTime;
+
+ static const int s_sampleRate;
+};
+
+const int WebGLFPSTimer::s_sampleRate = 15;
+
+#define OLD_GRAPHICBUFFER_ALLOC
+class FBO {
+public:
+ static FBO* createFBO(EGLDisplay dpy, int width, int height, GraphicsContext3D::Attributes attrs);
+ ~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, GraphicsContext3D::Attributes attrs);
+
+ GLuint createTexture(EGLImageKHR image, int width, int height);
+
+ EGLDisplay m_dpy;
+ GLuint m_texture;
+ GLuint m_fbo;
+ GLuint m_depthBuffer;
+ GLuint m_stencilBuffer;
+ 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
+
+bool GraphicsContext3DInternal::s_loggingEnabled = false;
+
+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_webGLFPSTimer(0)
+ , m_extensions(0)
+ , m_contextId(0)
+{
+ enableLogging();
+
+ //Need to initialize to a NULL state so that if you FBO creation fails later on, its in a valid state during destruction
+ for (int i = 0; i < NUM_BUFFERS; i++) {
+ m_fbo[i] = NULL;
+ }
+
+ 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;
+ }
+ }
+
+ m_webGLFPSTimer.set(new WebGLFPSTimer());
+
+ const char *ext = (const char *)glGetString(GL_EXTENSIONS);
+ LOGWEBGL("GL_EXTENSIONS = %s", ext);
+ // Want to keep control of which extensions are used
+ String extensions = "";
+ if (strstr(ext, "GL_OES_texture_npot"))
+ extensions.append("GL_OES_texture_npot");
+ if (strstr(ext, "GL_OES_packed_depth_stencil"))
+ extensions.append(" GL_OES_packed_depth_stencil");
+ if (strstr(ext, "GL_OES_texture_float"))
+ extensions.append(" GL_OES_texture_float");
+ m_extensions.set(new Extensions3DAndroid(extensions));
+
+ // 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[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;
+ }
+ // Antialiasing currently is not supported.
+ m_attrs.antialias = false;
+ 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, m_attrs);
+ 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, GraphicsContext3D::Attributes attributes)
+{
+ LOGWEBGL("createFBO()");
+ FBO* fbo = new FBO(dpy);
+
+ if (!fbo->init(width, height, attributes)) {
+ 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, GraphicsContext3D::Attributes attributes)
+{
+ // 1. Allocate a graphic buffer
+ sp<ISurfaceComposer> composer(ComposerService::getComposerService());
+ m_graphicBufferAlloc = composer->createGraphicBufferAlloc();
+
+ status_t error;
+
+ PixelFormat format = attributes.alpha ? HAL_PIXEL_FORMAT_RGBA_8888 : HAL_PIXEL_FORMAT_RGBX_8888;
+
+ m_grBuffer = m_graphicBufferAlloc->createGraphicBuffer(width, height, format,
+ 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);
+
+ if (attributes.depth) {
+ 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;
+ }
+
+ if (attributes.stencil) {
+ glGenRenderbuffers(1, &m_stencilBuffer);
+ glBindRenderbuffer(GL_RENDERBUFFER, m_stencilBuffer);
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, 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;
+
+ if (attributes.depth) {
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthBuffer);
+ if (GraphicsContext3DInternal::checkGLError("glFramebufferRenderbuffer") != GL_NO_ERROR)
+ return false;
+ }
+
+ if (attributes.stencil) {
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_stencilBuffer);
+ 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_stencilBuffer)
+ glDeleteRenderbuffers(1, &m_stencilBuffer);
+ 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
+ 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()
+{
+ if (s_loggingEnabled)
+ m_webGLFPSTimer->tick();
+
+ 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.setXYWH(box->borderLeft() + box->paddingLeft(),
+ box->borderTop() + box->paddingTop(),
+ box->contentWidth(),
+ 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()->recordingCanvas()->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);
+}
+
+PassRefPtr<ImageData> GraphicsContext3DInternal::paintRenderingResultsToImageData()
+{
+ LOGWEBGL("paintRenderingResultsToImageData()");
+
+ // Reading premultiplied alpha would involve unpremultiplying, which is lossy.
+ if (m_attrs.premultipliedAlpha)
+ return 0;
+
+ 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);
+
+ return imageData;
+}
+
+bool GraphicsContext3DInternal::paintCompositedResultsToCanvas(CanvasRenderingContext* context)
+{
+ LOGWEBGL("paintCompositedResultsToCanvas()");
+ ImageBuffer* imageBuffer = context->canvas()->buffer();
+ const SkBitmap& canvasBitmap =
+ imageBuffer->context()->platformContext()->recordingCanvas()->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("glBindFrameBuffer(%d, %d)", target, buffer);
+ 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;
+}
+
+void GraphicsContext3DInternal::enableLogging()
+{
+ char value[PROPERTY_VALUE_MAX];
+ property_get("debug.webgl", value, "0");
+ s_loggingEnabled = atoi(value) ? true : false;
+}
+
+}
+#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..513de49
--- /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/GraphicBuffer.h>
+
+// This can be increased to 3, for example, if that has a positive impact on performance.
+#define NUM_BUFFERS 2
+
+#include <cutils/properties.h>
+#include <cutils/log.h>
+
+#define LOGWEBGL(...) (GraphicsContext3DInternal::s_loggingEnabled ? \
+ (void)android_printLog(ANDROID_LOG_DEBUG, "WebGL", __VA_ARGS__) : (void)0)
+
+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 WebGLFPSTimer;
+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);
+ static void enableLogging();
+ static bool s_loggingEnabled;
+
+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;
+
+ OwnPtr<WebGLFPSTimer> m_webGLFPSTimer;
+
+ 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 6edbe6a..3196895 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.
@@ -106,6 +107,9 @@ GraphicsLayerAndroid::GraphicsLayerAndroid(GraphicsLayerClient* client) :
m_haveContents(false),
m_newImage(false),
m_image(0),
+#if ENABLE(WEBGL)
+ m_is3DCanvas(false),
+#endif
m_fixedBackgroundLayer(0),
m_foregroundLayer(0),
m_foregroundClipLayer(0)
@@ -478,6 +482,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 {
@@ -1074,6 +1086,28 @@ void GraphicsLayerAndroid::setContentsToMedia(PlatformLayer* mediaLayer)
}
}
+#if ENABLE(WEBGL)
+void GraphicsLayerAndroid::setContentsToCanvas(PlatformLayer* canvasLayer)
+{
+ if (m_contentLayer != canvasLayer && canvasLayer) {
+ // 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;
+
+ m_needsSyncChildren = true;
+ m_is3DCanvas = true;
+
+ setDrawsContent(true);
+ }
+}
+#endif
+
PlatformLayer* GraphicsLayerAndroid::platformLayer() const
{
ALOGV("platformLayer");
diff --git a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.h b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.h
index 28d4b09..5418745 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.
@@ -92,6 +93,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,
@@ -116,6 +121,9 @@ public:
virtual void setContentsToImage(Image*);
virtual void setContentsToMedia(PlatformLayer*);
+#if ENABLE(WEBGL)
+ virtual void setContentsToCanvas(PlatformLayer*);
+#endif
virtual PlatformLayer* platformLayer() const;
void pauseDisplay(bool state);
@@ -165,6 +173,12 @@ private:
bool m_newImage;
Image* m_image;
+#if ENABLE(WEBGL)
+ bool m_is3DCanvas;
+#endif
+
+ SkRegion m_dirtyRegion;
+
LayerAndroid* m_contentLayer;
FixedBackgroundImageLayerAndroid* m_fixedBackgroundLayer;
LayerAndroid* m_foregroundLayer;
diff --git a/Source/WebCore/platform/graphics/android/ImageBufferAndroid.cpp b/Source/WebCore/platform/graphics/android/ImageBufferAndroid.cpp
index f36200d..9571ec2 100644
--- a/Source/WebCore/platform/graphics/android/ImageBufferAndroid.cpp
+++ b/Source/WebCore/platform/graphics/android/ImageBufferAndroid.cpp
@@ -30,6 +30,7 @@
#include "BitmapImage.h"
#include "ColorSpace.h"
#include "GraphicsContext.h"
+#include "MIMETypeRegistry.h"
#include "NotImplemented.h"
#include "PlatformBridge.h"
#include "PlatformGraphicsContext.h"
@@ -43,6 +44,10 @@
#include "SkStream.h"
#include "SkUnPreMultiply.h"
+#include "image-encoders/skia/JPEGImageEncoder.h"
+#include "image-encoders/skia/PNGImageEncoder.h"
+#include <wtf/text/StringConcatenate.h>
+
using namespace std;
namespace WebCore {
@@ -245,8 +250,36 @@ void ImageBuffer::putUnmultipliedImageData(ByteArray* source, const IntSize& sou
}
}
+template <typename T>
+static String ImageToDataURL(T& source, const String& mimeType, const double* quality)
+{
+ ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType));
+
+ Vector<unsigned char> encodedImage;
+ if (mimeType == "image/jpeg") {
+ int compressionQuality = JPEGImageEncoder::DefaultCompressionQuality;
+ if (quality && *quality >= 0.0 && *quality <= 1.0)
+ compressionQuality = static_cast<int>(*quality * 100 + 0.5);
+ if (!JPEGImageEncoder::encode(source, compressionQuality, &encodedImage))
+ return "data:,";
+ } else {
+ if (!PNGImageEncoder::encode(source, &encodedImage))
+ return "data:,";
+ ASSERT(mimeType == "image/png");
+ }
+
+ Vector<char> base64Data;
+ base64Encode(*reinterpret_cast<Vector<char>*>(&encodedImage), base64Data);
+
+ return makeString("data:", mimeType, ";base64,", base64Data);
+}
+
+String ImageDataToDataURL(const ImageData& source, const String& mimeType, const double* quality)
+{
+ return ImageToDataURL(source, mimeType, quality);
+}
-String ImageBuffer::toDataURL(const String&, const double*) const
+String ImageBuffer::toDataURL(const String& mimeType, const double* quality) const
{
// Encode the image into a vector.
SkDynamicMemoryWStream pngStream;
diff --git a/Source/WebCore/platform/graphics/android/WebGLLayer.cpp b/Source/WebCore/platform/graphics/android/WebGLLayer.cpp
new file mode 100644
index 0000000..af1f31d
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/WebGLLayer.cpp
@@ -0,0 +1,85 @@
+/*
+ * 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 "DrawQuadData.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 layerTilesDisabled)
+{
+ bool askScreenUpdate = false;
+
+ askScreenUpdate |= LayerAndroid::drawGL(layerTilesDisabled);
+
+ 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);
+ TextureQuadData data(texture, GL_TEXTURE_EXTERNAL_OES, GL_LINEAR, LayerQuad, &transform, &localBounds);
+ TilesManager::instance()->shader()->drawQuad(&data);
+ 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..e7371f7
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/WebGLLayer.h
@@ -0,0 +1,61 @@
+/*
+ * 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(bool layerTilesDisabled);
+ virtual bool isWebGL() const { return true; }
+
+private:
+ RefPtr<GraphicsContext3DProxy> m_proxy;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(WEBGL) && USE(ACCELERATED_COMPOSITING)
+#endif // WebGLLayer_h
diff --git a/Source/WebCore/platform/graphics/android/layers/LayerAndroid.cpp b/Source/WebCore/platform/graphics/android/layers/LayerAndroid.cpp
index 1064388..d58c4ee 100644
--- a/Source/WebCore/platform/graphics/android/layers/LayerAndroid.cpp
+++ b/Source/WebCore/platform/graphics/android/layers/LayerAndroid.cpp
@@ -27,7 +27,7 @@
#include "SkPaint.h"
#include "SkPicture.h"
#include "SkTypeface.h"
-#include "Surface.h"
+#include "rendering/Surface.h"
#include "TilesManager.h"
#include <wtf/CurrentTime.h>
@@ -148,8 +148,8 @@ LayerAndroid::LayerAndroid(const LayerAndroid& layer) : Layer(layer),
}
if (hasAbsoluteChildren && !hasOnlyAbsoluteFollowers) {
- Vector<LayerAndroid*> normalLayers;
- Vector<LayerAndroid*> absoluteLayers;
+ WTF::Vector<LayerAndroid*> normalLayers;
+ WTF::Vector<LayerAndroid*> absoluteLayers;
for (int i = 0; i < layer.countChildren(); i++) {
LayerAndroid* child = layer.getChild(i);
if (child->isPositionAbsolute()
@@ -307,7 +307,7 @@ void LayerAndroid::addAnimation(PassRefPtr<AndroidAnimation> prpAnim)
void LayerAndroid::removeAnimationsForProperty(AnimatedPropertyID property)
{
KeyframesMap::const_iterator end = m_animations.end();
- Vector<pair<String, int> > toDelete;
+ WTF::Vector<pair<String, int> > toDelete;
for (KeyframesMap::const_iterator it = m_animations.begin(); it != end; ++it) {
if ((it->second)->type() == property)
toDelete.append(it->first);
@@ -320,7 +320,7 @@ void LayerAndroid::removeAnimationsForProperty(AnimatedPropertyID property)
void LayerAndroid::removeAnimationsForKeyframes(const String& name)
{
KeyframesMap::const_iterator end = m_animations.end();
- Vector<pair<String, int> > toDelete;
+ WTF::Vector<pair<String, int> > toDelete;
for (KeyframesMap::const_iterator it = m_animations.begin(); it != end; ++it) {
if ((it->second)->isNamed(name))
toDelete.append(it->first);
@@ -704,7 +704,7 @@ void LayerAndroid::assignSurfaces(LayerMergeState* mergeState)
int count = this->countChildren();
if (count > 0) {
mergeState->depth++;
- Vector <LayerAndroid*> sublayers;
+ WTF::Vector <LayerAndroid*> sublayers;
for (int i = 0; i < count; i++)
sublayers.append(getChild(i));
@@ -895,7 +895,7 @@ bool LayerAndroid::drawChildrenCanvas(SkCanvas* canvas, PaintStyle style)
bool askScreenUpdate = false;
int count = this->countChildren();
if (count > 0) {
- Vector <LayerAndroid*> sublayers;
+ WTF::Vector <LayerAndroid*> sublayers;
for (int i = 0; i < count; i++)
sublayers.append(this->getChild(i));
diff --git a/Source/WebCore/platform/graphics/android/layers/LayerAndroid.h b/Source/WebCore/platform/graphics/android/layers/LayerAndroid.h
index 6c2e43d..b3518e9 100644
--- a/Source/WebCore/platform/graphics/android/layers/LayerAndroid.h
+++ b/Source/WebCore/platform/graphics/android/layers/LayerAndroid.h
@@ -243,6 +243,7 @@ public:
virtual bool isIFrame() const { return false; }
virtual bool isIFrameContent() const { return false; }
virtual bool isFixedBackground() const { return false; }
+ virtual bool isWebGL() const { return false; }
bool isPositionFixed() const { return m_fixedPosition; }
void setAbsolutePosition(bool isAbsolute) { m_isPositionAbsolute = isAbsolute; }
diff --git a/Source/WebCore/platform/graphics/android/layers/VideoLayerManager.h b/Source/WebCore/platform/graphics/android/layers/VideoLayerManager.h
index 346afe4..e0975ee 100644
--- a/Source/WebCore/platform/graphics/android/layers/VideoLayerManager.h
+++ b/Source/WebCore/platform/graphics/android/layers/VideoLayerManager.h
@@ -120,7 +120,7 @@ private:
// The retiredTextures is used to communicate between UI thread and webcore
// thread. Basically, GL textures are determined to retire in the webcore
// thread, and really get deleted in the UI thread.
- Vector<GLuint> m_retiredTextures;
+ WTF::Vector<GLuint> m_retiredTextures;
android::Mutex m_retiredTexturesLock;
GLuint createTextureFromImage(RenderSkinMediaButton::MediaButton buttonType);