summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/html/canvas
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/html/canvas')
-rw-r--r--Source/WebCore/html/canvas/ArrayBuffer.cpp38
-rw-r--r--Source/WebCore/html/canvas/ArrayBuffer.h10
-rw-r--r--Source/WebCore/html/canvas/ArrayBuffer.idl3
-rw-r--r--Source/WebCore/html/canvas/ArrayBufferView.h2
-rw-r--r--Source/WebCore/html/canvas/CanvasRenderingContext.cpp63
-rw-r--r--Source/WebCore/html/canvas/CanvasRenderingContext.h21
-rw-r--r--Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp10
-rw-r--r--Source/WebCore/html/canvas/Uint8Array.h3
-rw-r--r--Source/WebCore/html/canvas/Uint8ClampedArray.cpp73
-rw-r--r--Source/WebCore/html/canvas/Uint8ClampedArray.h64
-rw-r--r--Source/WebCore/html/canvas/Uint8ClampedArray.idl49
-rw-r--r--Source/WebCore/html/canvas/WebGLFramebuffer.cpp210
-rw-r--r--Source/WebCore/html/canvas/WebGLFramebuffer.h21
-rw-r--r--Source/WebCore/html/canvas/WebGLGetInfo.cpp17
-rw-r--r--Source/WebCore/html/canvas/WebGLGetInfo.h6
-rw-r--r--Source/WebCore/html/canvas/WebGLObject.cpp10
-rw-r--r--Source/WebCore/html/canvas/WebGLObject.h7
-rw-r--r--Source/WebCore/html/canvas/WebGLProgram.cpp84
-rw-r--r--Source/WebCore/html/canvas/WebGLProgram.h21
-rw-r--r--Source/WebCore/html/canvas/WebGLRenderingContext.cpp523
-rw-r--r--Source/WebCore/html/canvas/WebGLRenderingContext.h60
-rw-r--r--Source/WebCore/html/canvas/WebGLRenderingContext.idl31
-rw-r--r--Source/WebCore/html/canvas/WebKitLoseContext.cpp9
-rw-r--r--Source/WebCore/html/canvas/WebKitLoseContext.h2
-rw-r--r--Source/WebCore/html/canvas/WebKitLoseContext.idl2
25 files changed, 1010 insertions, 329 deletions
diff --git a/Source/WebCore/html/canvas/ArrayBuffer.cpp b/Source/WebCore/html/canvas/ArrayBuffer.cpp
index 4f75cc3..9c072ed 100644
--- a/Source/WebCore/html/canvas/ArrayBuffer.cpp
+++ b/Source/WebCore/html/canvas/ArrayBuffer.cpp
@@ -1,5 +1,7 @@
/*
* Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2012 Sony Ericsson Mobile Communications AB
+ * Copyright (C) 2012 Sony Mobile Communications AB
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -30,6 +32,16 @@
namespace WebCore {
+static int clampValue(int x, int left, int right)
+{
+ ASSERT(left <= right);
+ if (x < left)
+ x = left;
+ if (right < x)
+ x = right;
+ return x;
+}
+
PassRefPtr<ArrayBuffer> ArrayBuffer::create(unsigned numElements, unsigned elementByteSize)
{
void* data = tryAllocate(numElements, elementByteSize);
@@ -43,7 +55,7 @@ PassRefPtr<ArrayBuffer> ArrayBuffer::create(ArrayBuffer* other)
return ArrayBuffer::create(other->data(), other->byteLength());
}
-PassRefPtr<ArrayBuffer> ArrayBuffer::create(void* source, unsigned byteLength)
+PassRefPtr<ArrayBuffer> ArrayBuffer::create(const void* source, unsigned byteLength)
{
void* data = tryAllocate(byteLength, 1);
if (!data)
@@ -74,6 +86,30 @@ unsigned ArrayBuffer::byteLength() const
return m_sizeInBytes;
}
+PassRefPtr<ArrayBuffer> ArrayBuffer::slice(int begin, int end) const
+{
+ return sliceImpl(clampIndex(begin), clampIndex(end));
+}
+
+PassRefPtr<ArrayBuffer> ArrayBuffer::slice(int begin) const
+{
+ return sliceImpl(clampIndex(begin), byteLength());
+}
+
+PassRefPtr<ArrayBuffer> ArrayBuffer::sliceImpl(unsigned begin, unsigned end) const
+{
+ unsigned size = begin <= end ? end - begin : 0;
+ return ArrayBuffer::create(static_cast<const char*>(data()) + begin, size);
+}
+
+unsigned ArrayBuffer::clampIndex(int index) const
+{
+ unsigned currentLength = byteLength();
+ if (index < 0)
+ index = currentLength + index;
+ return clampValue(index, 0, currentLength);
+}
+
ArrayBuffer::~ArrayBuffer()
{
WTF::fastFree(m_data);
diff --git a/Source/WebCore/html/canvas/ArrayBuffer.h b/Source/WebCore/html/canvas/ArrayBuffer.h
index ff5e599..bd18306 100644
--- a/Source/WebCore/html/canvas/ArrayBuffer.h
+++ b/Source/WebCore/html/canvas/ArrayBuffer.h
@@ -1,5 +1,7 @@
/*
* Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2012 Sony Ericsson Mobile Communications AB
+ * Copyright (C) 2012 Sony Mobile Communications AB
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -35,18 +37,24 @@ class ArrayBuffer : public RefCounted<ArrayBuffer> {
public:
static PassRefPtr<ArrayBuffer> create(unsigned numElements, unsigned elementByteSize);
static PassRefPtr<ArrayBuffer> create(ArrayBuffer*);
- static PassRefPtr<ArrayBuffer> create(void* source, unsigned byteLength);
+ static PassRefPtr<ArrayBuffer> create(const void* source, unsigned byteLength);
void* data();
const void* data() const;
unsigned byteLength() const;
+ PassRefPtr<ArrayBuffer> slice(int begin, int end) const;
+ PassRefPtr<ArrayBuffer> slice(int begin) const;
+
~ArrayBuffer();
private:
ArrayBuffer(void* data, unsigned sizeInBytes);
ArrayBuffer(unsigned numElements, unsigned elementByteSize);
static void* tryAllocate(unsigned numElements, unsigned elementByteSize);
+ PassRefPtr<ArrayBuffer> sliceImpl(unsigned begin, unsigned end) const;
+ unsigned clampIndex(int index) const;
+
unsigned m_sizeInBytes;
void* m_data;
};
diff --git a/Source/WebCore/html/canvas/ArrayBuffer.idl b/Source/WebCore/html/canvas/ArrayBuffer.idl
index 6f63e65..bd4e77f 100644
--- a/Source/WebCore/html/canvas/ArrayBuffer.idl
+++ b/Source/WebCore/html/canvas/ArrayBuffer.idl
@@ -1,5 +1,7 @@
/*
* Copyright (C) 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2012 Sony Ericsson Mobile Communications AB
+ * Copyright (C) 2012 Sony Mobile Communications AB
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -32,6 +34,7 @@ module html {
V8CustomConstructor,
] ArrayBuffer {
readonly attribute int byteLength;
+ ArrayBuffer slice(in long begin, in [Optional] long end);
};
}
diff --git a/Source/WebCore/html/canvas/ArrayBufferView.h b/Source/WebCore/html/canvas/ArrayBufferView.h
index d06fc8d..39a4583 100644
--- a/Source/WebCore/html/canvas/ArrayBufferView.h
+++ b/Source/WebCore/html/canvas/ArrayBufferView.h
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2012 Sony Mobile Communications AB
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -41,6 +42,7 @@ class ArrayBufferView : public RefCounted<ArrayBufferView> {
public:
virtual bool isByteArray() const { return false; }
virtual bool isUnsignedByteArray() const { return false; }
+ virtual bool isUnsignedByteClampedArray() const { return false; }
virtual bool isShortArray() const { return false; }
virtual bool isUnsignedShortArray() const { return false; }
virtual bool isIntArray() const { return false; }
diff --git a/Source/WebCore/html/canvas/CanvasRenderingContext.cpp b/Source/WebCore/html/canvas/CanvasRenderingContext.cpp
index c814c66..3622b06 100644
--- a/Source/WebCore/html/canvas/CanvasRenderingContext.cpp
+++ b/Source/WebCore/html/canvas/CanvasRenderingContext.cpp
@@ -51,48 +51,73 @@ void CanvasRenderingContext::deref()
m_canvas->deref();
}
-void CanvasRenderingContext::checkOrigin(const CanvasPattern* pattern)
+bool CanvasRenderingContext::wouldTaintOrigin(const CanvasPattern* pattern)
{
if (canvas()->originClean() && pattern && !pattern->originClean())
- canvas()->setOriginTainted();
+ return true;
+ return false;
}
-void CanvasRenderingContext::checkOrigin(const HTMLCanvasElement* sourceCanvas)
+bool CanvasRenderingContext::wouldTaintOrigin(const HTMLCanvasElement* sourceCanvas)
{
if (canvas()->originClean() && sourceCanvas && !sourceCanvas->originClean())
- canvas()->setOriginTainted();
+ return true;
+ return false;
}
-void CanvasRenderingContext::checkOrigin(const HTMLImageElement* image)
+bool CanvasRenderingContext::wouldTaintOrigin(const HTMLImageElement* image)
{
if (!image || !canvas()->originClean())
- return;
+ return false;
CachedImage* cachedImage = image->cachedImage();
- checkOrigin(cachedImage->response().url());
+ if (!cachedImage->passesAccessControlCheck(canvas()->securityOrigin())) {
+ if (wouldTaintOrigin(cachedImage->response().url()))
+ return true;
+ }
- if (canvas()->originClean() && !cachedImage->image()->hasSingleSecurityOrigin())
- canvas()->setOriginTainted();
+ if (!cachedImage->image()->hasSingleSecurityOrigin())
+ return true;
+
+ return false;
}
-void CanvasRenderingContext::checkOrigin(const HTMLVideoElement* video)
+bool CanvasRenderingContext::wouldTaintOrigin(const HTMLVideoElement* video)
{
#if ENABLE(VIDEO)
- checkOrigin(KURL(KURL(), video->currentSrc()));
- if (canvas()->originClean() && video && !video->hasSingleSecurityOrigin())
- canvas()->setOriginTainted();
+ // FIXME: This check is likely wrong when a redirect is involved. We need
+ // to test the finalURL. Please be careful when fixing this issue not to
+ // make currentSrc be the final URL because then the
+ // HTMLMediaElement.currentSrc DOM API would leak redirect destinations!
+ if (!video || !canvas()->originClean())
+ return false;
+
+ if (wouldTaintOrigin(video->currentSrc()))
+ return true;
+
+ if (!video->hasSingleSecurityOrigin())
+ return true;
#endif
+
+ return false;
}
-void CanvasRenderingContext::checkOrigin(const KURL& url)
+bool CanvasRenderingContext::wouldTaintOrigin(const KURL& url)
{
- if (!canvas()->originClean() || m_cleanOrigins.contains(url.string()))
- return;
+ if (!canvas()->originClean() || m_cleanURLs.contains(url.string()))
+ return false;
- if (canvas()->securityOrigin().taintsCanvas(url))
+ if (canvas()->securityOrigin()->taintsCanvas(url))
+ return true;
+
+ m_cleanURLs.add(url.string());
+ return false;
+}
+
+void CanvasRenderingContext::checkOrigin(const KURL& url)
+{
+ if (wouldTaintOrigin(url))
canvas()->setOriginTainted();
- else
- m_cleanOrigins.add(url.string());
}
} // namespace WebCore
diff --git a/Source/WebCore/html/canvas/CanvasRenderingContext.h b/Source/WebCore/html/canvas/CanvasRenderingContext.h
index a143596..8426752 100644
--- a/Source/WebCore/html/canvas/CanvasRenderingContext.h
+++ b/Source/WebCore/html/canvas/CanvasRenderingContext.h
@@ -27,6 +27,7 @@
#define CanvasRenderingContext_h
#include "GraphicsLayer.h"
+#include "HTMLCanvasElement.h"
#include <wtf/HashSet.h>
#include <wtf/Noncopyable.h>
@@ -35,7 +36,6 @@
namespace WebCore {
class CanvasPattern;
-class HTMLCanvasElement;
class HTMLImageElement;
class HTMLVideoElement;
class KURL;
@@ -44,7 +44,6 @@ class WebGLObject;
class CanvasRenderingContext {
WTF_MAKE_NONCOPYABLE(CanvasRenderingContext); WTF_MAKE_FAST_ALLOCATED;
public:
- CanvasRenderingContext(HTMLCanvasElement*);
virtual ~CanvasRenderingContext() { }
// Ref and deref the m_canvas
@@ -65,15 +64,23 @@ public:
#endif
protected:
- void checkOrigin(const CanvasPattern*);
- void checkOrigin(const HTMLCanvasElement*);
- void checkOrigin(const HTMLImageElement*);
- void checkOrigin(const HTMLVideoElement*);
+ CanvasRenderingContext(HTMLCanvasElement*);
+ bool wouldTaintOrigin(const CanvasPattern*);
+ bool wouldTaintOrigin(const HTMLCanvasElement*);
+ bool wouldTaintOrigin(const HTMLImageElement*);
+ bool wouldTaintOrigin(const HTMLVideoElement*);
+ bool wouldTaintOrigin(const KURL&);
+
+ template<class T> void checkOrigin(const T* arg)
+ {
+ if (wouldTaintOrigin(arg))
+ canvas()->setOriginTainted();
+ }
void checkOrigin(const KURL&);
private:
HTMLCanvasElement* m_canvas;
- HashSet<String> m_cleanOrigins;
+ HashSet<String> m_cleanURLs;
};
} // namespace WebCore
diff --git a/Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp b/Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp
index 2051750..6261c2c 100644
--- a/Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp
+++ b/Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp
@@ -84,6 +84,14 @@ using namespace HTMLNames;
static const char* const defaultFont = "10px sans-serif";
+static bool isOriginClean(CachedImage* cachedImage, SecurityOrigin* securityOrigin)
+{
+ if (!cachedImage->image()->hasSingleSecurityOrigin())
+ return false;
+ if (cachedImage->passesAccessControlCheck(securityOrigin))
+ return true;
+ return !securityOrigin->taintsCanvas(cachedImage->response().url());
+}
class CanvasStrokeStyleApplier : public StrokeStyleApplier {
public:
@@ -1525,7 +1533,7 @@ PassRefPtr<CanvasPattern> CanvasRenderingContext2D::createPattern(HTMLImageEleme
if (!cachedImage || !image->cachedImage()->image())
return CanvasPattern::create(Image::nullImage(), repeatX, repeatY, true);
- bool originClean = !canvas()->securityOrigin().taintsCanvas(KURL(KURL(), cachedImage->response().url())) && cachedImage->image()->hasSingleSecurityOrigin();
+ bool originClean = isOriginClean(cachedImage, canvas()->securityOrigin());
return CanvasPattern::create(cachedImage->image(), repeatX, repeatY, originClean);
}
diff --git a/Source/WebCore/html/canvas/Uint8Array.h b/Source/WebCore/html/canvas/Uint8Array.h
index 3da1eaa..1cbd5b4 100644
--- a/Source/WebCore/html/canvas/Uint8Array.h
+++ b/Source/WebCore/html/canvas/Uint8Array.h
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2009 Apple Inc. All rights reserved.
* Copyright (C) 2009 Google Inc. All rights reserved.
+ * Copyright (C) 2012 Sony Mobile Communications AB
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -46,7 +47,7 @@ public:
PassRefPtr<Uint8Array> subarray(int start) const;
PassRefPtr<Uint8Array> subarray(int start, int end) const;
-private:
+protected:
Uint8Array(PassRefPtr<ArrayBuffer> buffer,
unsigned byteOffset,
unsigned length);
diff --git a/Source/WebCore/html/canvas/Uint8ClampedArray.cpp b/Source/WebCore/html/canvas/Uint8ClampedArray.cpp
new file mode 100644
index 0000000..32828d1
--- /dev/null
+++ b/Source/WebCore/html/canvas/Uint8ClampedArray.cpp
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ * Copyright (C) 2012 Sony Mobile Communications AB.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "Uint8ClampedArray.h"
+
+namespace WebCore {
+
+PassRefPtr<Uint8ClampedArray> Uint8ClampedArray::create(unsigned length)
+{
+ return TypedArrayBase<unsigned char>::create<Uint8ClampedArray>(length);
+}
+
+PassRefPtr<Uint8ClampedArray> Uint8ClampedArray::create(unsigned char* array, unsigned length)
+{
+ return TypedArrayBase<unsigned char>::create<Uint8ClampedArray>(array, length);
+}
+
+PassRefPtr<Uint8ClampedArray> Uint8ClampedArray::create(PassRefPtr<ArrayBuffer> buffer, unsigned byteOffset, unsigned length)
+{
+ return TypedArrayBase<unsigned char>::create<Uint8ClampedArray>(buffer, byteOffset, length);
+}
+
+void Uint8ClampedArray::set(unsigned index, double value)
+{
+ if (index >= m_length)
+ return;
+ if (isnan(value) || value < 0)
+ value = 0;
+ else if (value > 255)
+ value = 255;
+ data()[index] = static_cast<unsigned char>(value + 0.5);
+}
+
+Uint8ClampedArray::Uint8ClampedArray(PassRefPtr<ArrayBuffer> buffer, unsigned byteOffset, unsigned length)
+ : Uint8Array(buffer, byteOffset, length)
+{
+}
+
+PassRefPtr<Uint8ClampedArray> Uint8ClampedArray::subarray(int start) const
+{
+ return subarray(start, length());
+}
+
+PassRefPtr<Uint8ClampedArray> Uint8ClampedArray::subarray(int start, int end) const
+{
+ return subarrayImpl<Uint8ClampedArray>(start, end);
+}
+}
diff --git a/Source/WebCore/html/canvas/Uint8ClampedArray.h b/Source/WebCore/html/canvas/Uint8ClampedArray.h
new file mode 100644
index 0000000..79757d8
--- /dev/null
+++ b/Source/WebCore/html/canvas/Uint8ClampedArray.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ * Copyright (C) 2012 Sony Mobile Communications AB.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef Uint8ClampedArray_h
+#define Uint8ClampedArray_h
+
+#include "IntegralTypedArrayBase.h"
+#include "Uint8Array.h"
+
+namespace WebCore {
+
+class ArrayBuffer;
+
+class Uint8ClampedArray : public Uint8Array {
+public:
+ static PassRefPtr<Uint8ClampedArray> create(unsigned length);
+ static PassRefPtr<Uint8ClampedArray> create(unsigned char* array, unsigned length);
+ static PassRefPtr<Uint8ClampedArray> create(PassRefPtr<ArrayBuffer> buffer, unsigned byteOffset, unsigned length);
+
+ // Can't use "using" here due to a bug in the RVCT compiler.
+ void set(TypedArrayBase<unsigned char>* array, unsigned offset, ExceptionCode& ec) { TypedArrayBase<unsigned char>::set(array, offset, ec); }
+ void set(unsigned index, double value);
+
+ PassRefPtr<Uint8ClampedArray> subarray(int start) const;
+ PassRefPtr<Uint8ClampedArray> subarray(int start, int end) const;
+
+private:
+ Uint8ClampedArray(PassRefPtr<ArrayBuffer> buffer,
+ unsigned byteOffset,
+ unsigned length);
+ // Make constructor visible to superclass.
+ friend class TypedArrayBase<unsigned char>;
+
+ // Overridden from ArrayBufferView.
+ virtual bool isUnsignedByteClampedArray() const { return true; }
+};
+
+} // namespace WebCore
+
+#endif // Uint8Array_h
diff --git a/Source/WebCore/html/canvas/Uint8ClampedArray.idl b/Source/WebCore/html/canvas/Uint8ClampedArray.idl
new file mode 100644
index 0000000..5c5513a
--- /dev/null
+++ b/Source/WebCore/html/canvas/Uint8ClampedArray.idl
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ * Copyright (C) 2012 Sony Mobile Communications AB.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+module html {
+ interface [
+ CanBeConstructed,
+ CustomConstructFunction,
+ V8CustomConstructor,
+ HasNumericIndexGetter,
+ HasCustomIndexSetter,
+ GenerateNativeConverter,
+ NoStaticTables,
+ CustomToJS,
+ DontCheckEnums
+ ] Uint8ClampedArray : Uint8Array {
+ const unsigned int BYTES_PER_ELEMENT = 1;
+
+ readonly attribute unsigned long length;
+ Uint8ClampedArray subarray(in long start, in [Optional] long end);
+
+ // void set(in Uint8ClampedArray array, [Optional] in unsigned long offset);
+ // void set(in sequence<long> array, [Optional] in unsigned long offset);
+ [Custom] void set();
+ };
+}
diff --git a/Source/WebCore/html/canvas/WebGLFramebuffer.cpp b/Source/WebCore/html/canvas/WebGLFramebuffer.cpp
index 4b721eb..3c1c718 100644
--- a/Source/WebCore/html/canvas/WebGLFramebuffer.cpp
+++ b/Source/WebCore/html/canvas/WebGLFramebuffer.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2012 Sony Mobile Communications AB
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -35,12 +36,47 @@ namespace WebCore {
namespace {
- // This function is only for depth/stencil/depth_stencil attachment.
- // Currently we assume these attachments are all renderbuffers.
- GC3Denum getInternalFormat(WebGLObject* buffer)
+ bool isAttachmentComplete(WebGLObject* attachedObject, GC3Denum attachment)
{
- ASSERT(buffer && buffer->isRenderbuffer());
- return (reinterpret_cast<WebGLRenderbuffer*>(buffer))->getInternalFormat();
+ ASSERT(attachedObject && attachedObject->object());
+ ASSERT(attachedObject->isRenderbuffer());
+ WebGLRenderbuffer* buffer = reinterpret_cast<WebGLRenderbuffer*>(attachedObject);
+ switch (attachment) {
+ case GraphicsContext3D::DEPTH_ATTACHMENT:
+ if (buffer->getInternalFormat() != GraphicsContext3D::DEPTH_COMPONENT16)
+ return false;
+ break;
+ case GraphicsContext3D::STENCIL_ATTACHMENT:
+ if (buffer->getInternalFormat() != GraphicsContext3D::STENCIL_INDEX8)
+ return false;
+ break;
+ case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT:
+ if (buffer->getInternalFormat() != GraphicsContext3D::DEPTH_STENCIL)
+ return false;
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ return false;
+ }
+ if (!buffer->getWidth() || !buffer->getHeight())
+ return false;
+ return true;
+ }
+
+ GC3Dsizei getImageWidth(WebGLObject* attachedObject)
+ {
+ ASSERT(attachedObject && attachedObject->object());
+ ASSERT(attachedObject->isRenderbuffer());
+ WebGLRenderbuffer* buffer = reinterpret_cast<WebGLRenderbuffer*>(attachedObject);
+ return buffer->getWidth();
+ }
+
+ GC3Dsizei getImageHeight(WebGLObject* attachedObject)
+ {
+ ASSERT(attachedObject && attachedObject->object());
+ ASSERT(attachedObject->isRenderbuffer());
+ WebGLRenderbuffer* buffer = reinterpret_cast<WebGLRenderbuffer*>(attachedObject);
+ return buffer->getHeight();
}
bool isUninitialized(WebGLObject* attachedObject)
@@ -82,10 +118,12 @@ WebGLFramebuffer::WebGLFramebuffer(WebGLRenderingContext* ctx)
setObject(context()->graphicsContext3D()->createFramebuffer());
}
-void WebGLFramebuffer::setAttachment(GC3Denum attachment, GC3Denum texTarget, WebGLTexture* texture, GC3Dint level)
+void WebGLFramebuffer::setAttachmentForBoundFramebuffer(GC3Denum attachment, GC3Denum texTarget, WebGLTexture* texture, GC3Dint level)
{
+ ASSERT(isBound());
if (!object())
return;
+ removeAttachmentFromBoundFramebuffer(attachment);
if (texture && !texture->object())
texture = 0;
switch (attachment) {
@@ -106,14 +144,19 @@ void WebGLFramebuffer::setAttachment(GC3Denum attachment, GC3Denum texTarget, We
m_depthStencilAttachment = texture;
break;
default:
- return;
+ ASSERT_NOT_REACHED();
+ break;
}
+ if (texture)
+ texture->onAttached();
}
-void WebGLFramebuffer::setAttachment(GC3Denum attachment, WebGLRenderbuffer* renderbuffer)
+void WebGLFramebuffer::setAttachmentForBoundFramebuffer(GC3Denum attachment, WebGLRenderbuffer* renderbuffer)
{
+ ASSERT(isBound());
if (!object())
return;
+ removeAttachmentFromBoundFramebuffer(attachment);
if (renderbuffer && !renderbuffer->object())
renderbuffer = 0;
switch (attachment) {
@@ -130,8 +173,11 @@ void WebGLFramebuffer::setAttachment(GC3Denum attachment, WebGLRenderbuffer* ren
m_depthStencilAttachment = renderbuffer;
break;
default:
- return;
+ ASSERT_NOT_REACHED();
+ break;
}
+ if (renderbuffer)
+ renderbuffer->onAttached();
}
WebGLObject* WebGLFramebuffer::getAttachment(GC3Denum attachment) const
@@ -148,24 +194,78 @@ WebGLObject* WebGLFramebuffer::getAttachment(GC3Denum attachment) const
case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT:
return m_depthStencilAttachment.get();
default:
+ ASSERT_NOT_REACHED();
return 0;
}
}
-void WebGLFramebuffer::removeAttachment(WebGLObject* attachment)
+void WebGLFramebuffer::removeAttachmentFromBoundFramebuffer(GC3Denum attachment)
{
+ ASSERT(isBound());
if (!object())
return;
- if (attachment == m_colorAttachment.get())
- m_colorAttachment = 0;
- else if (attachment == m_depthAttachment.get())
- m_depthAttachment = 0;
- else if (attachment == m_stencilAttachment.get())
- m_stencilAttachment = 0;
- else if (attachment == m_depthStencilAttachment.get())
- m_depthStencilAttachment = 0;
- else
+
+ switch (attachment) {
+ case GraphicsContext3D::COLOR_ATTACHMENT0:
+ if (m_colorAttachment) {
+ m_colorAttachment->onDetached();
+ m_colorAttachment = 0;
+ m_texTarget = 0;
+ m_texLevel = -1;
+ }
+ break;
+ case GraphicsContext3D::DEPTH_ATTACHMENT:
+ if (m_depthAttachment) {
+ m_depthAttachment->onDetached();
+ m_depthAttachment = 0;
+ }
+ break;
+ case GraphicsContext3D::STENCIL_ATTACHMENT:
+ if (m_stencilAttachment) {
+ m_stencilAttachment->onDetached();
+ m_stencilAttachment = 0;
+ }
+ break;
+ case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT:
+ if (m_depthStencilAttachment) {
+ m_depthStencilAttachment->onDetached();
+ m_depthStencilAttachment = 0;
+ }
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ break;
+ }
+}
+
+void WebGLFramebuffer::removeAttachmentFromBoundFramebuffer(WebGLObject* attachment)
+{
+ ASSERT(isBound());
+ if (!object())
+ return;
+ if (!attachment)
return;
+ GraphicsContext3D* gc3d = context()->graphicsContext3D();
+ if (attachment == m_colorAttachment.get()) {
+ if (attachment->isRenderbuffer())
+ gc3d->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::RENDERBUFFER, 0);
+ else
+ gc3d->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, m_texTarget, 0, m_texLevel);
+ removeAttachmentFromBoundFramebuffer(GraphicsContext3D::COLOR_ATTACHMENT0);
+ }
+ if (attachment == m_depthAttachment.get()) {
+ gc3d->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::DEPTH_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, 0);
+ removeAttachmentFromBoundFramebuffer(GraphicsContext3D::DEPTH_ATTACHMENT);
+ }
+ if (attachment == m_stencilAttachment.get()) {
+ gc3d->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::STENCIL_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, 0);
+ removeAttachmentFromBoundFramebuffer(GraphicsContext3D::STENCIL_ATTACHMENT);
+ }
+ if (attachment == m_depthStencilAttachment.get()) {
+ gc3d->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::DEPTH_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, 0);
+ gc3d->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::STENCIL_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, 0);
+ removeAttachmentFromBoundFramebuffer(GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT);
+ }
}
GC3Dsizei WebGLFramebuffer::getWidth() const
@@ -213,34 +313,67 @@ GC3Denum WebGLFramebuffer::getColorBufferFormat() const
return 0;
}
-bool WebGLFramebuffer::isIncomplete(bool checkInternalFormat) const
+GC3Denum WebGLFramebuffer::checkStatus() const
{
unsigned int count = 0;
+ GC3Dsizei width = 0, height = 0;
if (isDepthAttached()) {
- if (checkInternalFormat && getInternalFormat(m_depthAttachment.get()) != GraphicsContext3D::DEPTH_COMPONENT16)
- return true;
+ if (!isAttachmentComplete(m_depthAttachment.get(), GraphicsContext3D::DEPTH_ATTACHMENT))
+ return GraphicsContext3D::FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+ width = getImageWidth(m_depthAttachment.get());
+ height = getImageHeight(m_depthAttachment.get());
count++;
}
if (isStencilAttached()) {
- if (checkInternalFormat && getInternalFormat(m_stencilAttachment.get()) != GraphicsContext3D::STENCIL_INDEX8)
- return true;
+ if (!isAttachmentComplete(m_stencilAttachment.get(), GraphicsContext3D::STENCIL_ATTACHMENT))
+ return GraphicsContext3D::FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+ if (!count) {
+ width = getImageWidth(m_stencilAttachment.get());
+ height = getImageHeight(m_stencilAttachment.get());
+ } else {
+ if (width != getImageWidth(m_stencilAttachment.get()) || height != getImageHeight(m_stencilAttachment.get()))
+ return GraphicsContext3D::FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
+ }
count++;
}
if (isDepthStencilAttached()) {
- if (checkInternalFormat && getInternalFormat(m_depthStencilAttachment.get()) != GraphicsContext3D::DEPTH_STENCIL)
- return true;
+ if (!isAttachmentComplete(m_depthStencilAttachment.get(), GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT))
+ return GraphicsContext3D::FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
if (!isValid(m_depthStencilAttachment.get()))
- return true;
+ return GraphicsContext3D::FRAMEBUFFER_UNSUPPORTED;
+ if (!count) {
+ width = getImageWidth(m_depthStencilAttachment.get());
+ height = getImageHeight(m_depthStencilAttachment.get());
+ } else {
+ if (width != getImageWidth(m_depthStencilAttachment.get()) || height != getImageHeight(m_depthStencilAttachment.get()))
+ return GraphicsContext3D::FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
+ }
count++;
}
+ // WebGL specific: no conflicting DEPTH/STENCIL/DEPTH_STENCIL attachments.
if (count > 1)
- return true;
- return false;
+ return GraphicsContext3D::FRAMEBUFFER_UNSUPPORTED;
+ if (isColorAttached()) {
+ // FIXME: if color buffer is texture, is ALPHA, LUMINANCE or LUMINANCE_ALPHA valid?
+ if (!getColorBufferFormat())
+ return GraphicsContext3D::FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+ if (!count) {
+ if (!getWidth() || !getHeight())
+ return GraphicsContext3D::FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+ } else {
+ if (width != getWidth() || height != getHeight())
+ return GraphicsContext3D::FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
+ }
+ } else {
+ if (!count)
+ return GraphicsContext3D::FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
+ }
+ return GraphicsContext3D::FRAMEBUFFER_COMPLETE;
}
bool WebGLFramebuffer::onAccess(bool needToInitializeRenderbuffers)
{
- if (isIncomplete(true))
+ if (checkStatus() != GraphicsContext3D::FRAMEBUFFER_COMPLETE)
return false;
if (needToInitializeRenderbuffers)
return initializeRenderbuffers();
@@ -249,11 +382,15 @@ bool WebGLFramebuffer::onAccess(bool needToInitializeRenderbuffers)
void WebGLFramebuffer::deleteObjectImpl(Platform3DObject object)
{
+ if (m_colorAttachment)
+ m_colorAttachment->onDetached();
+ if (m_depthAttachment)
+ m_depthAttachment->onDetached();
+ if (m_stencilAttachment)
+ m_stencilAttachment->onDetached();
+ if (m_depthStencilAttachment)
+ m_depthStencilAttachment->onDetached();
context()->graphicsContext3D()->deleteFramebuffer(object);
- m_colorAttachment = 0;
- m_depthAttachment = 0;
- m_stencilAttachment = 0;
- m_depthStencilAttachment = 0;
}
bool WebGLFramebuffer::initializeRenderbuffers()
@@ -352,6 +489,11 @@ bool WebGLFramebuffer::initializeRenderbuffers()
return true;
}
+bool WebGLFramebuffer::isBound() const
+{
+ return (context()->m_framebufferBinding.get() == this);
+}
+
}
#endif // ENABLE(WEBGL)
diff --git a/Source/WebCore/html/canvas/WebGLFramebuffer.h b/Source/WebCore/html/canvas/WebGLFramebuffer.h
index a1cb86f..b03ec58 100644
--- a/Source/WebCore/html/canvas/WebGLFramebuffer.h
+++ b/Source/WebCore/html/canvas/WebGLFramebuffer.h
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2012 Sony Mobile Communications AB
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -42,10 +43,12 @@ public:
static PassRefPtr<WebGLFramebuffer> create(WebGLRenderingContext*);
- void setAttachment(GC3Denum attachment, GC3Denum texTarget, WebGLTexture*, GC3Dint level);
- void setAttachment(GC3Denum attachment, WebGLRenderbuffer*);
- // If an object is attached to the framebuffer, remove it.
- void removeAttachment(WebGLObject*);
+ void setAttachmentForBoundFramebuffer(GC3Denum attachment, GC3Denum texTarget, WebGLTexture*, GC3Dint level);
+ void setAttachmentForBoundFramebuffer(GC3Denum attachment, WebGLRenderbuffer*);
+ // If an object is attached to the currently bound framebuffer, remove it.
+ void removeAttachmentFromBoundFramebuffer(WebGLObject*);
+ // If a given attachment point for the currently bound framebuffer is not null, remove the attached object.
+ void removeAttachmentFromBoundFramebuffer(GC3Denum);
WebGLObject* getAttachment(GC3Denum) const;
GC3Denum getColorBufferFormat() const;
@@ -60,8 +63,11 @@ public:
// needToInitializeRenderbuffers is true.
bool onAccess(bool needToInitializeRenderbuffers);
- // Return false does not mean COMPLETE, might still be INCOMPLETE.
- bool isIncomplete(bool checkInternalFormat) const;
+ // Software version of glCheckFramebufferStatus(), except that when
+ // FRAMEBUFFER_COMPLETE is returned, it is still possible for
+ // glCheckFramebufferStatus() to return FRAMEBUFFER_UNSUPPORTED,
+ // depending on hardware implementation.
+ GC3Denum checkStatus() const;
bool hasEverBeenBound() const { return object() && m_hasEverBeenBound; }
@@ -78,6 +84,9 @@ private:
// Return false if framebuffer is incomplete.
bool initializeRenderbuffers();
+ // Check if the framebuffer is currently bound.
+ bool isBound() const;
+
bool isColorAttached() const { return (m_colorAttachment && m_colorAttachment->object()); }
bool isDepthAttached() const { return (m_depthAttachment && m_depthAttachment->object()); }
bool isStencilAttached() const { return (m_stencilAttachment && m_stencilAttachment->object()); }
diff --git a/Source/WebCore/html/canvas/WebGLGetInfo.cpp b/Source/WebCore/html/canvas/WebGLGetInfo.cpp
index 17be974..5faec15 100644
--- a/Source/WebCore/html/canvas/WebGLGetInfo.cpp
+++ b/Source/WebCore/html/canvas/WebGLGetInfo.cpp
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2009 Apple Inc. All Rights Reserved.
* Copyright (C) 2009 Google Inc. All Rights Reserved.
+ * Copyright (C) 2012 Sony Mobile Communications AB
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -135,6 +136,16 @@ WebGLGetInfo::WebGLGetInfo(PassRefPtr<Uint8Array> value)
{
}
+WebGLGetInfo::WebGLGetInfo(PassRefPtr<Uint32Array> value)
+ : m_type(kTypeWebGLUnsignedIntArray)
+ , m_bool(false)
+ , m_float(0)
+ , m_int(0)
+ , m_unsignedInt(0)
+ , m_webglUnsignedIntArray(value)
+{
+}
+
WebGLGetInfo::WebGLGetInfo(PassRefPtr<WebGLVertexArrayObjectOES> value)
: m_type(kTypeWebGLVertexArrayObjectOES)
, m_webglVertexArrayObject(value)
@@ -234,6 +245,12 @@ PassRefPtr<Uint8Array> WebGLGetInfo::getWebGLUnsignedByteArray() const
return m_webglUnsignedByteArray;
}
+PassRefPtr<Uint32Array> WebGLGetInfo::getWebGLUnsignedIntArray() const
+{
+ ASSERT(getType() == kTypeWebGLUnsignedIntArray);
+ return m_webglUnsignedIntArray;
+}
+
PassRefPtr<WebGLVertexArrayObjectOES> WebGLGetInfo::getWebGLVertexArrayObjectOES() const
{
ASSERT(getType() == kTypeWebGLVertexArrayObjectOES);
diff --git a/Source/WebCore/html/canvas/WebGLGetInfo.h b/Source/WebCore/html/canvas/WebGLGetInfo.h
index bc2aacc..0303399 100644
--- a/Source/WebCore/html/canvas/WebGLGetInfo.h
+++ b/Source/WebCore/html/canvas/WebGLGetInfo.h
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2009 Apple Inc. All Rights Reserved.
* Copyright (C) 2009 Google Inc. All Rights Reserved.
+ * Copyright (C) 2012 Sony Mobile Communications AB
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -31,6 +32,7 @@
#include "Int32Array.h"
#include "PlatformString.h"
#include "Uint8Array.h"
+#include "Uint32Array.h"
#include "WebGLBuffer.h"
#include "WebGLFramebuffer.h"
#include "WebGLProgram.h"
@@ -67,6 +69,7 @@ public:
kTypeWebGLRenderbuffer,
kTypeWebGLTexture,
kTypeWebGLUnsignedByteArray,
+ kTypeWebGLUnsignedIntArray,
kTypeWebGLVertexArrayObjectOES,
};
@@ -88,6 +91,7 @@ public:
WebGLGetInfo(PassRefPtr<WebGLRenderbuffer> value);
WebGLGetInfo(PassRefPtr<WebGLTexture> value);
WebGLGetInfo(PassRefPtr<Uint8Array> value);
+ WebGLGetInfo(PassRefPtr<Uint32Array> value);
WebGLGetInfo(PassRefPtr<WebGLVertexArrayObjectOES> value);
virtual ~WebGLGetInfo();
@@ -110,6 +114,7 @@ public:
PassRefPtr<WebGLRenderbuffer> getWebGLRenderbuffer() const;
PassRefPtr<WebGLTexture> getWebGLTexture() const;
PassRefPtr<Uint8Array> getWebGLUnsignedByteArray() const;
+ PassRefPtr<Uint32Array> getWebGLUnsignedIntArray() const;
PassRefPtr<WebGLVertexArrayObjectOES> getWebGLVertexArrayObjectOES() const;
private:
@@ -130,6 +135,7 @@ private:
RefPtr<WebGLRenderbuffer> m_webglRenderbuffer;
RefPtr<WebGLTexture> m_webglTexture;
RefPtr<Uint8Array> m_webglUnsignedByteArray;
+ RefPtr<Uint32Array> m_webglUnsignedIntArray;
RefPtr<WebGLVertexArrayObjectOES> m_webglVertexArrayObject;
};
diff --git a/Source/WebCore/html/canvas/WebGLObject.cpp b/Source/WebCore/html/canvas/WebGLObject.cpp
index d47013e..7b629a6 100644
--- a/Source/WebCore/html/canvas/WebGLObject.cpp
+++ b/Source/WebCore/html/canvas/WebGLObject.cpp
@@ -66,6 +66,16 @@ void WebGLObject::deleteObject()
}
}
+void WebGLObject::detachContext()
+{
+ m_attachmentCount = 0; // Make sure OpenGL resource is deleted.
+ if (m_context) {
+ deleteObject();
+ m_context->removeObject(this);
+ m_context = 0;
+ }
+}
+
}
#endif // ENABLE(WEBGL)
diff --git a/Source/WebCore/html/canvas/WebGLObject.h b/Source/WebCore/html/canvas/WebGLObject.h
index 3bb9f29..44cc36f 100644
--- a/Source/WebCore/html/canvas/WebGLObject.h
+++ b/Source/WebCore/html/canvas/WebGLObject.h
@@ -46,12 +46,7 @@ public:
// FIXME: revisit this when resource sharing between contexts are implemented.
void deleteObject();
- void detachContext()
- {
- m_attachmentCount = 0; // Make sure OpenGL resource is deleted.
- deleteObject();
- m_context = 0;
- }
+ void detachContext();
WebGLRenderingContext* context() const { return m_context; }
diff --git a/Source/WebCore/html/canvas/WebGLProgram.cpp b/Source/WebCore/html/canvas/WebGLProgram.cpp
index d3efda4..ec99dc4 100644
--- a/Source/WebCore/html/canvas/WebGLProgram.cpp
+++ b/Source/WebCore/html/canvas/WebGLProgram.cpp
@@ -42,6 +42,7 @@ WebGLProgram::WebGLProgram(WebGLRenderingContext* ctx)
: WebGLObject(ctx)
, m_linkStatus(false)
, m_linkCount(0)
+ , m_infoValid(true)
{
setObject(context()->graphicsContext3D()->createProgram());
}
@@ -59,43 +60,23 @@ void WebGLProgram::deleteObjectImpl(Platform3DObject obj)
}
}
-bool WebGLProgram::cacheActiveAttribLocations()
-{
- m_activeAttribLocations.clear();
- if (!object())
- return false;
- GraphicsContext3D* context3d = context()->graphicsContext3D();
-
- // Assume link status has already been cached.
- if (!m_linkStatus)
- return false;
-
- GC3Dint numAttribs = 0;
- context3d->getProgramiv(object(), GraphicsContext3D::ACTIVE_ATTRIBUTES, &numAttribs);
- m_activeAttribLocations.resize(static_cast<size_t>(numAttribs));
- for (int i = 0; i < numAttribs; ++i) {
- ActiveInfo info;
- context3d->getActiveAttrib(object(), i, info);
- m_activeAttribLocations[i] = context3d->getAttribLocation(object(), info.name.charactersWithNullTermination());
- }
-
- return true;
-}
-
-unsigned WebGLProgram::numActiveAttribLocations() const
+unsigned WebGLProgram::numActiveAttribLocations()
{
+ cacheInfoIfNeeded();
return m_activeAttribLocations.size();
}
-GC3Dint WebGLProgram::getActiveAttribLocation(GC3Duint index) const
+GC3Dint WebGLProgram::getActiveAttribLocation(GC3Duint index)
{
+ cacheInfoIfNeeded();
if (index >= numActiveAttribLocations())
return -1;
return m_activeAttribLocations[index];
}
-bool WebGLProgram::isUsingVertexAttrib0() const
+bool WebGLProgram::isUsingVertexAttrib0()
{
+ cacheInfoIfNeeded();
for (unsigned ii = 0; ii < numActiveAttribLocations(); ++ii) {
if (!getActiveAttribLocation(ii))
return true;
@@ -103,6 +84,24 @@ bool WebGLProgram::isUsingVertexAttrib0() const
return false;
}
+bool WebGLProgram::getLinkStatus()
+{
+ cacheInfoIfNeeded();
+ return m_linkStatus;
+}
+
+void WebGLProgram::setLinkStatus(bool status)
+{
+ cacheInfoIfNeeded();
+ m_linkStatus = status;
+}
+
+void WebGLProgram::increaseLinkCount()
+{
+ ++m_linkCount;
+ m_infoValid = false;
+}
+
WebGLShader* WebGLProgram::getAttachedShader(GC3Denum type)
{
switch (type) {
@@ -155,6 +154,39 @@ bool WebGLProgram::detachShader(WebGLShader* shader)
}
}
+void WebGLProgram::cacheActiveAttribLocations(GraphicsContext3D* context3d)
+{
+ m_activeAttribLocations.clear();
+
+ GC3Dint numAttribs = 0;
+ context3d->getProgramiv(object(), GraphicsContext3D::ACTIVE_ATTRIBUTES, &numAttribs);
+ m_activeAttribLocations.resize(static_cast<size_t>(numAttribs));
+ for (int i = 0; i < numAttribs; ++i) {
+ ActiveInfo info;
+ context3d->getActiveAttrib(object(), i, info);
+ m_activeAttribLocations[i] = context3d->getAttribLocation(object(), info.name.charactersWithNullTermination());
+ }
+}
+
+void WebGLProgram::cacheInfoIfNeeded()
+{
+ if (m_infoValid)
+ return;
+
+ if (!object())
+ return;
+
+ GraphicsContext3D* ctx = context()->graphicsContext3D();
+ if (!ctx)
+ return;
+ GC3Dint linkStatus = 0;
+ ctx->getProgramiv(object(), GraphicsContext3D::LINK_STATUS, &linkStatus);
+ m_linkStatus = linkStatus;
+ if (m_linkStatus)
+ cacheActiveAttribLocations(ctx);
+ m_infoValid = true;
+}
+
}
#endif // ENABLE(WEBGL)
diff --git a/Source/WebCore/html/canvas/WebGLProgram.h b/Source/WebCore/html/canvas/WebGLProgram.h
index 0dd3ba0..13a5bdd 100644
--- a/Source/WebCore/html/canvas/WebGLProgram.h
+++ b/Source/WebCore/html/canvas/WebGLProgram.h
@@ -42,23 +42,21 @@ public:
static PassRefPtr<WebGLProgram> create(WebGLRenderingContext*);
- // cacheActiveAttribLocation() is only called once after linkProgram()
- // succeeds.
- bool cacheActiveAttribLocations();
- unsigned numActiveAttribLocations() const;
- GC3Dint getActiveAttribLocation(GC3Duint index) const;
+ unsigned numActiveAttribLocations();
+ GC3Dint getActiveAttribLocation(GC3Duint index);
- bool isUsingVertexAttrib0() const;
+ bool isUsingVertexAttrib0();
- bool getLinkStatus() const { return m_linkStatus; }
- void setLinkStatus(bool status) { m_linkStatus = status; }
+ bool getLinkStatus();
+ void setLinkStatus(bool);
unsigned getLinkCount() const { return m_linkCount; }
// This is to be called everytime after the program is successfully linked.
// We don't deal with integer overflow here, assuming in reality a program
// will never be linked so many times.
- void increaseLinkCount() { ++m_linkCount; }
+ // Also, we invalidate the cached program info.
+ void increaseLinkCount();
WebGLShader* getAttachedShader(GC3Denum);
bool attachShader(WebGLShader*);
@@ -72,6 +70,9 @@ protected:
private:
virtual bool isProgram() const { return true; }
+ void cacheActiveAttribLocations(GraphicsContext3D*);
+ void cacheInfoIfNeeded();
+
Vector<GC3Dint> m_activeAttribLocations;
GC3Dint m_linkStatus;
@@ -82,6 +83,8 @@ private:
RefPtr<WebGLShader> m_vertexShader;
RefPtr<WebGLShader> m_fragmentShader;
+
+ bool m_infoValid;
};
} // namespace WebCore
diff --git a/Source/WebCore/html/canvas/WebGLRenderingContext.cpp b/Source/WebCore/html/canvas/WebGLRenderingContext.cpp
index 933d37f..7e7bfe3 100644
--- a/Source/WebCore/html/canvas/WebGLRenderingContext.cpp
+++ b/Source/WebCore/html/canvas/WebGLRenderingContext.cpp
@@ -1,5 +1,7 @@
/*
* Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2011, 2012 Sony Ericsson Mobile Communications AB
+ * Copyright (C) 2012 Sony Mobile Communications AB
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -51,6 +53,7 @@
#include "RenderLayer.h"
#include "Settings.h"
#include "Uint16Array.h"
+#include "Uint32Array.h"
#include "WebGLActiveInfo.h"
#include "WebGLBuffer.h"
#include "WebGLContextAttributes.h"
@@ -328,29 +331,14 @@ private:
void WebGLRenderingContext::WebGLRenderingContextRestoreTimer::fired()
{
- // Timer is started when m_contextLost is false. It will first call
- // onLostContext, which will set m_contextLost to true. Then it will keep
- // calling restoreContext and reschedule itself until m_contextLost is back
- // to false.
- if (!m_context->m_contextLost) {
- m_context->onLostContext();
- startOneShot(secondsBetweenRestoreAttempts);
- } else {
- // The rendering context is not restored if there is no handler for
- // the context restored event.
- if (!m_context->canvas()->hasEventListeners(eventNames().webglcontextrestoredEvent))
- return;
-
- m_context->restoreContext();
- if (m_context->m_contextLost)
- startOneShot(secondsBetweenRestoreAttempts);
- }
+ m_context->maybeRestoreContext(RealLostContext);
}
class WebGLRenderingContextLostCallback : public GraphicsContext3D::ContextLostCallback {
public:
WebGLRenderingContextLostCallback(WebGLRenderingContext* cb) : m_contextLostCallback(cb) {}
- virtual void onContextLost() { m_contextLostCallback->forceLostContext(); }
+ virtual void onContextLost() {
+ m_contextLostCallback->forceLostContext(WebGLRenderingContext::RealLostContext); }
virtual ~WebGLRenderingContextLostCallback() {}
private:
WebGLRenderingContext* m_contextLostCallback;
@@ -367,7 +355,11 @@ PassOwnPtr<WebGLRenderingContext> WebGLRenderingContext::create(HTMLCanvasElemen
attributes.antialias = false;
}
+#if PLATFORM(ANDROID)
+ RefPtr<GraphicsContext3D> context(GraphicsContext3D::create(canvas, attributes, 0));
+#else
RefPtr<GraphicsContext3D> context(GraphicsContext3D::create(attributes, hostWindow));
+#endif
if (!context) {
canvas->dispatchEvent(WebGLContextEvent::create(eventNames().webglcontextcreationerrorEvent, false, true, "Could not create a WebGL context."));
@@ -381,6 +373,7 @@ WebGLRenderingContext::WebGLRenderingContext(HTMLCanvasElement* passedCanvas, Pa
GraphicsContext3D::Attributes attributes)
: CanvasRenderingContext(passedCanvas)
, m_context(context)
+ , m_restoreAllowed(false)
, m_restoreTimer(this)
, m_videoCache(4)
, m_contextLost(false)
@@ -554,9 +547,10 @@ void WebGLRenderingContext::paintRenderingResultsToCanvas()
{
// Until the canvas is written to by the application, the clear that
// happened after it was composited should be ignored by the compositor.
- if (m_context->layerComposited() && !m_attributes.preserveDrawingBuffer)
+ if (m_context->layerComposited() && !m_attributes.preserveDrawingBuffer) {
+ m_context->paintCompositedResultsToCanvas(this);
canvas()->makePresentationCopy();
- else
+ } else
canvas()->clearPresentationCopy();
clearIfComposited();
if (!m_markedCanvasDirty && !m_layerCleared)
@@ -577,6 +571,18 @@ bool WebGLRenderingContext::paintsIntoCanvasBuffer() const
return m_context->paintsIntoCanvasBuffer();
}
+#if PLATFORM(ANDROID)
+void WebGLRenderingContext::recreateSurface()
+{
+ m_context->recreateSurface();
+}
+
+void WebGLRenderingContext::releaseSurface()
+{
+ m_context->releaseSurface();
+}
+#endif
+
void WebGLRenderingContext::reshape(int width, int height)
{
if (m_needsUpdate) {
@@ -593,6 +599,20 @@ void WebGLRenderingContext::reshape(int width, int height)
m_context->reshape(width, height);
}
+GC3Dsizei WebGLRenderingContext::drawingBufferWidth()
+{
+ if (isContextLost())
+ return 0;
+ return m_context->getInternalFramebufferSize().width();
+}
+
+GC3Dsizei WebGLRenderingContext::drawingBufferHeight()
+{
+ if (isContextLost())
+ return 0;
+ return m_context->getInternalFramebufferSize().height();
+}
+
unsigned int WebGLRenderingContext::sizeInBytes(GC3Denum type)
{
switch (type) {
@@ -648,6 +668,8 @@ void WebGLRenderingContext::bindAttribLocation(WebGLProgram* program, GC3Duint i
UNUSED_PARAM(ec);
if (isContextLost() || !validateWebGLObject(program))
return;
+ if (!validateLocationLength(name))
+ return;
if (!validateString(name))
return;
m_context->bindAttribLocation(objectOrZero(program), index, name);
@@ -814,7 +836,7 @@ void WebGLRenderingContext::blendFuncSeparate(GC3Denum srcRGB, GC3Denum dstRGB,
cleanupAfterGraphicsCall(false);
}
-void WebGLRenderingContext::bufferData(GC3Denum target, GC3Dsizeiptr size, GC3Denum usage, ExceptionCode& ec)
+void WebGLRenderingContext::bufferData(GC3Denum target, long long size, GC3Denum usage, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
if (isContextLost())
@@ -827,13 +849,13 @@ void WebGLRenderingContext::bufferData(GC3Denum target, GC3Dsizeiptr size, GC3De
return;
}
if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
- if (!buffer->associateBufferData(size)) {
+ if (!buffer->associateBufferData(static_cast<GC3Dsizeiptr>(size))) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
return;
}
}
- m_context->bufferData(target, size, usage);
+ m_context->bufferData(target, static_cast<GC3Dsizeiptr>(size), usage);
cleanupAfterGraphicsCall(false);
}
@@ -856,7 +878,9 @@ void WebGLRenderingContext::bufferData(GC3Denum target, ArrayBuffer* data, GC3De
}
}
- m_context->bufferData(target, data->byteLength(), data->data(), usage);
+ // Some platforms incorrectly signal GL_OUT_OF_MEMORY if size == 0
+ if (data->byteLength() > 0)
+ m_context->bufferData(target, data->byteLength(), data->data(), usage);
cleanupAfterGraphicsCall(false);
}
@@ -879,11 +903,13 @@ void WebGLRenderingContext::bufferData(GC3Denum target, ArrayBufferView* data, G
}
}
- m_context->bufferData(target, data->byteLength(), data->baseAddress(), usage);
+ // Some platforms incorrectly signal GL_OUT_OF_MEMORY if size == 0
+ if (data->byteLength() > 0)
+ m_context->bufferData(target, data->byteLength(), data->baseAddress(), usage);
cleanupAfterGraphicsCall(false);
}
-void WebGLRenderingContext::bufferSubData(GC3Denum target, GC3Dintptr offset, ArrayBuffer* data, ExceptionCode& ec)
+void WebGLRenderingContext::bufferSubData(GC3Denum target, long long offset, ArrayBuffer* data, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
if (isContextLost())
@@ -898,17 +924,17 @@ void WebGLRenderingContext::bufferSubData(GC3Denum target, GC3Dintptr offset, Ar
if (!data)
return;
if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
- if (!buffer->associateBufferSubData(offset, data)) {
+ if (!buffer->associateBufferSubData(static_cast<GC3Dintptr>(offset), data)) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
return;
}
}
- m_context->bufferSubData(target, offset, data->byteLength(), data->data());
+ m_context->bufferSubData(target, static_cast<GC3Dintptr>(offset), data->byteLength(), data->data());
cleanupAfterGraphicsCall(false);
}
-void WebGLRenderingContext::bufferSubData(GC3Denum target, GC3Dintptr offset, ArrayBufferView* data, ExceptionCode& ec)
+void WebGLRenderingContext::bufferSubData(GC3Denum target, long long offset, ArrayBufferView* data, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
if (isContextLost())
@@ -923,13 +949,13 @@ void WebGLRenderingContext::bufferSubData(GC3Denum target, GC3Dintptr offset, Ar
if (!data)
return;
if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
- if (!buffer->associateBufferSubData(offset, data)) {
+ if (!buffer->associateBufferSubData(static_cast<GC3Dintptr>(offset), data)) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
return;
}
}
- m_context->bufferSubData(target, offset, data->byteLength(), data->baseAddress());
+ m_context->bufferSubData(target, static_cast<GC3Dintptr>(offset), data->byteLength(), data->baseAddress());
cleanupAfterGraphicsCall(false);
}
@@ -943,9 +969,10 @@ GC3Denum WebGLRenderingContext::checkFramebufferStatus(GC3Denum target)
}
if (!m_framebufferBinding || !m_framebufferBinding->object())
return GraphicsContext3D::FRAMEBUFFER_COMPLETE;
- if (m_framebufferBinding->isIncomplete(true))
- return GraphicsContext3D::FRAMEBUFFER_UNSUPPORTED;
- unsigned long result = m_context->checkFramebufferStatus(target);
+ GC3Denum result = m_framebufferBinding->checkStatus();
+ if (result != GraphicsContext3D::FRAMEBUFFER_COMPLETE)
+ return result;
+ result = m_context->checkFramebufferStatus(target);
cleanupAfterGraphicsCall(false);
return result;
}
@@ -1026,6 +1053,34 @@ void WebGLRenderingContext::compileShader(WebGLShader* shader, ExceptionCode& ec
cleanupAfterGraphicsCall(false);
}
+void WebGLRenderingContext::compressedTexImage2D(GC3Denum target, GC3Dint level,
+ GC3Denum internalformat, GC3Dsizei width,
+ GC3Dsizei height, GC3Dint border,
+ ArrayBufferView* data)
+{
+ if (isContextLost())
+ return;
+ if (!validateTexFuncLevel(target, level))
+ return;
+
+ // Currently, we have no support for compressed textures:
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
+}
+
+void WebGLRenderingContext::compressedTexSubImage2D(GC3Denum target, GC3Dint level,
+ GC3Dint xoffset, GC3Dint yoffset,
+ GC3Dsizei width, GC3Dsizei height,
+ GC3Denum format, ArrayBufferView* data)
+{
+ if (isContextLost())
+ return;
+ if (!validateTexFuncLevel(target, level))
+ return;
+
+ // Currently, we have no support for compressed textures:
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
+}
+
void WebGLRenderingContext::copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border)
{
if (isContextLost())
@@ -1048,8 +1103,10 @@ void WebGLRenderingContext::copyTexImage2D(GC3Denum target, GC3Dint level, GC3De
return;
}
clearIfComposited();
- if (isResourceSafe())
- m_context->copyTexImage2D(target, level, internalformat, x, y, width, height, border);
+ if (isResourceSafe()) {
+ if (width > 0 && height > 0)
+ m_context->copyTexImage2D(target, level, internalformat, x, y, width, height, border);
+ }
else {
GC3Dint clippedX, clippedY;
GC3Dsizei clippedWidth, clippedHeight;
@@ -1060,8 +1117,11 @@ void WebGLRenderingContext::copyTexImage2D(GC3Denum target, GC3Dint level, GC3De
m_context->copyTexSubImage2D(target, level, clippedX - x, clippedY - y,
clippedX, clippedY, clippedWidth, clippedHeight);
}
- } else
- m_context->copyTexImage2D(target, level, internalformat, x, y, width, height, border);
+ } else {
+ if (width > 0 && height > 0)
+ m_context->copyTexImage2D(target, level, internalformat,
+ x, y, width, height, border);
+ }
}
// FIXME: if the framebuffer is not complete, none of the below should be executed.
tex->setLevelInfo(target, level, internalformat, width, height, GraphicsContext3D::UNSIGNED_BYTE);
@@ -1256,7 +1316,7 @@ void WebGLRenderingContext::deleteRenderbuffer(WebGLRenderbuffer* renderbuffer)
if (renderbuffer == m_renderbufferBinding)
m_renderbufferBinding = 0;
if (m_framebufferBinding)
- m_framebufferBinding->removeAttachment(renderbuffer);
+ m_framebufferBinding->removeAttachmentFromBoundFramebuffer(renderbuffer);
}
void WebGLRenderingContext::deleteShader(WebGLShader* shader)
@@ -1275,7 +1335,7 @@ void WebGLRenderingContext::deleteTexture(WebGLTexture* texture)
m_textureUnits[i].m_textureCubeMapBinding = 0;
}
if (m_framebufferBinding)
- m_framebufferBinding->removeAttachment(texture);
+ m_framebufferBinding->removeAttachmentFromBoundFramebuffer(texture);
}
void WebGLRenderingContext::depthFunc(GC3Denum func)
@@ -1586,7 +1646,7 @@ void WebGLRenderingContext::drawArrays(GC3Denum mode, GC3Dint first, GC3Dsizei c
cleanupAfterGraphicsCall(true);
}
-void WebGLRenderingContext::drawElements(GC3Denum mode, GC3Dsizei count, GC3Denum type, GC3Dintptr offset, ExceptionCode& ec)
+void WebGLRenderingContext::drawElements(GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
@@ -1621,14 +1681,14 @@ void WebGLRenderingContext::drawElements(GC3Denum mode, GC3Dsizei count, GC3Denu
int numElements = 0;
if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
// Ensure we have a valid rendering state
- if (!validateElementArraySize(count, type, offset)) {
+ if (!validateElementArraySize(count, type, static_cast<GC3Dintptr>(offset))) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
return;
}
if (!count)
return;
if (!validateIndexArrayConservative(type, numElements) || !validateRenderingState(numElements)) {
- if (!validateIndexArrayPrecise(count, type, offset, numElements) || !validateRenderingState(numElements)) {
+ if (!validateIndexArrayPrecise(count, type, static_cast<GC3Dintptr>(offset), numElements) || !validateRenderingState(numElements)) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
return;
}
@@ -1649,12 +1709,12 @@ void WebGLRenderingContext::drawElements(GC3Denum mode, GC3Dsizei count, GC3Denu
bool vertexAttrib0Simulated = false;
if (!isGLES2Compliant()) {
if (!numElements)
- validateIndexArrayPrecise(count, type, offset, numElements);
+ validateIndexArrayPrecise(count, type, static_cast<GC3Dintptr>(offset), numElements);
vertexAttrib0Simulated = simulateVertexAttrib0(numElements);
}
if (!isGLES2NPOTStrict())
handleNPOTTextures(true);
- m_context->drawElements(mode, count, type, offset);
+ m_context->drawElements(mode, count, type, static_cast<GC3Dintptr>(offset));
if (!isGLES2Compliant() && vertexAttrib0Simulated)
restoreStatesAfterVertexAttrib0Simulation();
if (!isGLES2NPOTStrict())
@@ -1752,7 +1812,7 @@ void WebGLRenderingContext::framebufferRenderbuffer(GC3Denum target, GC3Denum at
default:
m_context->framebufferRenderbuffer(target, attachment, renderbuffertarget, objectOrZero(buffer));
}
- m_framebufferBinding->setAttachment(attachment, buffer);
+ m_framebufferBinding->setAttachmentForBoundFramebuffer(attachment, buffer);
if (reattachDepth) {
Platform3DObject object = objectOrZero(m_framebufferBinding->getAttachment(GraphicsContext3D::DEPTH_ATTACHMENT));
if (object)
@@ -1797,7 +1857,7 @@ void WebGLRenderingContext::framebufferTexture2D(GC3Denum target, GC3Denum attac
return;
}
m_context->framebufferTexture2D(target, attachment, textarget, objectOrZero(texture), level);
- m_framebufferBinding->setAttachment(attachment, textarget, texture, level);
+ m_framebufferBinding->setAttachmentForBoundFramebuffer(attachment, textarget, texture, level);
cleanupAfterGraphicsCall(false);
}
@@ -1869,23 +1929,15 @@ bool WebGLRenderingContext::getAttachedShaders(WebGLProgram* program, Vector<Web
shaderObjects.clear();
if (isContextLost() || !validateWebGLObject(program))
return false;
- GC3Dint numShaders = 0;
- m_context->getProgramiv(objectOrZero(program), GraphicsContext3D::ATTACHED_SHADERS, &numShaders);
- if (numShaders) {
- OwnArrayPtr<Platform3DObject> shaders = adoptArrayPtr(new Platform3DObject[numShaders]);
- GC3Dsizei count = 0;
- m_context->getAttachedShaders(objectOrZero(program), numShaders, &count, shaders.get());
- if (count != numShaders)
- return false;
- shaderObjects.resize(numShaders);
- for (GC3Dint ii = 0; ii < numShaders; ++ii) {
- WebGLShader* shader = findShader(shaders[ii]);
- if (!shader) {
- shaderObjects.clear();
- return false;
- }
- shaderObjects[ii] = shader;
- }
+
+ const GC3Denum shaderType[] = {
+ GraphicsContext3D::VERTEX_SHADER,
+ GraphicsContext3D::FRAGMENT_SHADER
+ };
+ for (unsigned i = 0; i < sizeof(shaderType) / sizeof(GC3Denum); ++i) {
+ WebGLShader* shader = program->getAttachedShader(shaderType[i]);
+ if (shader)
+ shaderObjects.append(shader);
}
return true;
}
@@ -1894,6 +1946,8 @@ GC3Dint WebGLRenderingContext::getAttribLocation(WebGLProgram* program, const St
{
if (isContextLost())
return -1;
+ if (!validateLocationLength(name))
+ return -1;
if (!validateString(name))
return -1;
return m_context->getAttribLocation(objectOrZero(program), name);
@@ -1914,6 +1968,12 @@ WebGLGetInfo WebGLRenderingContext::getBufferParameter(GC3Denum target, GC3Denum
return WebGLGetInfo();
}
+ // Some platforms fail to raise INVALID_OPERATION if no array buffer is bound
+ if (target == GraphicsContext3D::ARRAY_BUFFER && !m_boundArrayBuffer) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
+ return WebGLGetInfo();
+ }
+
WebGLStateRestorer(this, false);
GC3Dint value = 0;
m_context->getBufferParameteriv(target, pname, &value);
@@ -1979,46 +2039,51 @@ WebGLGetInfo WebGLRenderingContext::getFramebufferAttachmentParameter(GC3Denum t
UNUSED_PARAM(ec);
if (isContextLost() || !validateFramebufferFuncParameters(target, attachment))
return WebGLGetInfo();
- switch (pname) {
- case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
- case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
- case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
- case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
- break;
- default:
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
- return WebGLGetInfo();
- }
- if (!m_framebufferBinding || !m_framebufferBinding->object() || m_framebufferBinding->isIncomplete(false)) {
+ if (!m_framebufferBinding || !m_framebufferBinding->object()) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
return WebGLGetInfo();
}
- if (pname != GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
- WebGLStateRestorer(this, false);
- GC3Dint value = 0;
- m_context->getFramebufferAttachmentParameteriv(target, attachment, pname, &value);
+ WebGLObject* object = m_framebufferBinding->getAttachment(attachment);
+ if (!object) {
if (pname == GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)
- return WebGLGetInfo(static_cast<unsigned int>(value));
- return WebGLGetInfo(value);
+ return WebGLGetInfo(static_cast<unsigned int>(GraphicsContext3D::NONE));
+ // OpenGL ES 2.0 specifies INVALID_ENUM in this case, while desktop GL
+ // specifies INVALID_OPERATION.
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
+ return WebGLGetInfo();
}
- WebGLStateRestorer(this, false);
- GC3Dint type = 0;
- m_context->getFramebufferAttachmentParameteriv(target, attachment, GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &type);
- if (!type)
- return WebGLGetInfo();
- GC3Dint value = 0;
- m_context->getFramebufferAttachmentParameteriv(target, attachment, GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &value);
- switch (type) {
- case GraphicsContext3D::RENDERBUFFER:
- return WebGLGetInfo(PassRefPtr<WebGLRenderbuffer>(findRenderbuffer(static_cast<Platform3DObject>(value))));
- case GraphicsContext3D::TEXTURE:
- return WebGLGetInfo(PassRefPtr<WebGLTexture>(findTexture(static_cast<Platform3DObject>(value))));
- default:
- // FIXME: raise exception?
- return WebGLGetInfo();
+ ASSERT(object->isTexture() || object->isRenderbuffer());
+ if (object->isTexture()) {
+ switch (pname) {
+ case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
+ return WebGLGetInfo(static_cast<unsigned int>(GraphicsContext3D::TEXTURE));
+ case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
+ return WebGLGetInfo(PassRefPtr<WebGLTexture>(reinterpret_cast<WebGLTexture*>(object)));
+ case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
+ case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
+ {
+ WebGLStateRestorer(this, false);
+ GC3Dint value = 0;
+ m_context->getFramebufferAttachmentParameteriv(target, attachment, pname, &value);
+ return WebGLGetInfo(value);
+ }
+ default:
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
+ return WebGLGetInfo();
+ }
+ } else {
+ switch (pname) {
+ case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
+ return WebGLGetInfo(static_cast<unsigned int>(GraphicsContext3D::RENDERBUFFER));
+ case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
+ return WebGLGetInfo(PassRefPtr<WebGLRenderbuffer>(reinterpret_cast<WebGLRenderbuffer*>(object)));
+ default:
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
+ return WebGLGetInfo();
+ }
}
}
@@ -2062,8 +2127,8 @@ WebGLGetInfo WebGLRenderingContext::getParameter(GC3Denum pname, ExceptionCode&
case GraphicsContext3D::COLOR_WRITEMASK:
return getBooleanArrayParameter(pname);
case GraphicsContext3D::COMPRESSED_TEXTURE_FORMATS:
- // Defined as null in the spec
- return WebGLGetInfo();
+ // Currently, we have no support for compressed textures:
+ return WebGLGetInfo(Uint32Array::create(0, 0));
case GraphicsContext3D::CULL_FACE:
return getBooleanParameter(pname);
case GraphicsContext3D::CULL_FACE_MODE:
@@ -2558,6 +2623,8 @@ PassRefPtr<WebGLUniformLocation> WebGLRenderingContext::getUniformLocation(WebGL
UNUSED_PARAM(ec);
if (isContextLost() || !validateWebGLObject(program))
return 0;
+ if (!validateLocationLength(name))
+ return 0;
if (!validateString(name))
return 0;
WebGLStateRestorer(this, false);
@@ -2603,13 +2670,13 @@ WebGLGetInfo WebGLRenderingContext::getVertexAttrib(GC3Duint index, GC3Denum pna
}
}
-GC3Dsizeiptr WebGLRenderingContext::getVertexAttribOffset(GC3Duint index, GC3Denum pname)
+long long WebGLRenderingContext::getVertexAttribOffset(GC3Duint index, GC3Denum pname)
{
if (isContextLost())
return 0;
GC3Dsizeiptr result = m_context->getVertexAttribOffset(index, pname);
cleanupAfterGraphicsCall(false);
- return result;
+ return static_cast<long long>(result);
}
void WebGLRenderingContext::hint(GC3Denum target, GC3Denum mode)
@@ -2647,14 +2714,6 @@ GC3Dboolean WebGLRenderingContext::isBuffer(WebGLBuffer* buffer)
bool WebGLRenderingContext::isContextLost()
{
- if (m_restoreTimer.isActive())
- return true;
-
- bool newContextLost = m_context->getExtensions()->getGraphicsResetStatusARB() != GraphicsContext3D::NO_ERROR;
-
- if (newContextLost != m_contextLost)
- m_restoreTimer.startOneShot(secondsBetweenRestoreAttempts);
-
return m_contextLost;
}
@@ -2736,12 +2795,6 @@ void WebGLRenderingContext::linkProgram(WebGLProgram* program, ExceptionCode& ec
m_context->linkProgram(objectOrZero(program));
program->increaseLinkCount();
- // cache link status
- GC3Dint value = 0;
- m_context->getProgramiv(objectOrZero(program), GraphicsContext3D::LINK_STATUS, &value);
- program->setLinkStatus(static_cast<bool>(value));
- // Need to cache link status before caching active attribute locations.
- program->cacheActiveAttribLocations();
cleanupAfterGraphicsCall(false);
}
@@ -2792,14 +2845,13 @@ void WebGLRenderingContext::polygonOffset(GC3Dfloat factor, GC3Dfloat units)
cleanupAfterGraphicsCall(false);
}
-void WebGLRenderingContext::readPixels(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, ArrayBufferView* pixels, ExceptionCode& ec)
+void WebGLRenderingContext::readPixels(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, ArrayBufferView* pixels, ExceptionCode&)
{
if (isContextLost())
return;
- if (!canvas()->originClean()) {
- ec = SECURITY_ERR;
- return;
- }
+ // Due to WebGL's same-origin restrictions, it is not possible to
+ // taint the origin using the WebGL API.
+ ASSERT(canvas()->originClean());
// Validate input parameters.
if (!pixels) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
@@ -2851,7 +2903,51 @@ void WebGLRenderingContext::readPixels(GC3Dint x, GC3Dint y, GC3Dsizei width, GC
}
clearIfComposited();
void* data = pixels->baseAddress();
- m_context->readPixels(x, y, width, height, format, type, data);
+
+ // WebGL requires that areas lying outside the frame buffer should be filled with 0.
+ // Most OpenGL platforms do not support this directly.
+ GC3Dint clippedX, clippedY;
+ GC3Dsizei clippedWidth, clippedHeight;
+ if (clip2D(x, y, width, height, getBoundFramebufferWidth(), getBoundFramebufferHeight(),
+ &clippedX, &clippedY, &clippedWidth, &clippedHeight)) {
+ unsigned int padding = 0;
+ m_context->computeImageSizeInBytes(format, type, clippedWidth, clippedHeight,
+ m_packAlignment, &totalBytesRequired, &padding);
+ char *tmp = (char *)fastMalloc(totalBytesRequired);
+ // Some platforms incorrectly signal GL_INVALID_VALUE if width == 0 || height == 0
+ if (clippedWidth > 0 && clippedHeight > 0)
+ m_context->readPixels(clippedX, clippedY, clippedWidth,
+ clippedHeight, format, type, tmp);
+
+ unsigned int bytesPerComponent, componentsPerPixel;
+ m_context->computeFormatAndTypeParameters(format, type, &componentsPerPixel,
+ &bytesPerComponent);
+ int clippedRowBytes = bytesPerComponent * componentsPerPixel * clippedWidth;
+ int clippedStride = clippedRowBytes + padding;
+ int rowBytes = bytesPerComponent * componentsPerPixel * width;
+ int stride = rowBytes + padding;
+ char *src = tmp;
+ char *dst = (char *)data;
+ int xdelta = (clippedX - x) * bytesPerComponent * componentsPerPixel;
+ for (int r = y; r < y + height; r++) {
+ if (r < y + height - 1)
+ memset(dst, 0, stride);
+ else
+ memset(dst, 0, rowBytes);
+ if (r >= clippedY && r < clippedY + clippedHeight) {
+ memcpy(dst + xdelta, src, clippedRowBytes);
+ src += clippedStride;
+ }
+ dst += stride;
+ }
+ fastFree(tmp);
+ }
+ else {
+ // Some platforms incorrectly signal GL_INVALID_VALUE if width == 0 || height == 0
+ if (width > 0 && height > 0)
+ m_context->readPixels(x, y, width, height, format, type, data);
+ }
+
#if OS(DARWIN)
// FIXME: remove this section when GL driver bug on Mac is fixed, i.e.,
// when alpha is off, readPixels should set alpha to 255 instead of 0.
@@ -3142,7 +3238,11 @@ void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum
return;
if (!validateHTMLImageElement(image))
return;
- checkOrigin(image);
+ if (wouldTaintOrigin(image)) {
+ ec = SECURITY_ERR;
+ return;
+ }
+
texImage2DImpl(target, level, internalformat, format, type, image->cachedImage()->image(),
m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
}
@@ -3157,7 +3257,10 @@ void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum
m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
return;
}
- checkOrigin(canvas);
+ if (wouldTaintOrigin(canvas)) {
+ ec = SECURITY_ERR;
+ return;
+ }
RefPtr<ImageData> imageData = canvas->getImageData();
if (imageData)
texImage2D(target, level, internalformat, format, type, imageData.get(), ec);
@@ -3167,7 +3270,7 @@ void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum
}
#if ENABLE(VIDEO)
-PassRefPtr<Image> WebGLRenderingContext::videoFrameToImage(HTMLVideoElement* video)
+PassRefPtr<Image> WebGLRenderingContext::videoFrameToImage(HTMLVideoElement* video, ExceptionCode& ec)
{
if (!video || !video->videoWidth() || !video->videoHeight()) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
@@ -3179,7 +3282,10 @@ PassRefPtr<Image> WebGLRenderingContext::videoFrameToImage(HTMLVideoElement* vid
m_context->synthesizeGLError(GraphicsContext3D::OUT_OF_MEMORY);
return 0;
}
- checkOrigin(video);
+ if (wouldTaintOrigin(video)) {
+ ec = SECURITY_ERR;
+ return 0;
+ }
IntRect destRect(0, 0, size.width(), size.height());
// FIXME: Turn this into a GPU-GPU texture copy instead of CPU readback.
video->paintCurrentFrameInContext(buf->context(), destRect);
@@ -3192,8 +3298,8 @@ void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum
ec = 0;
if (isContextLost())
return;
- RefPtr<Image> image = videoFrameToImage(video);
- if (!video)
+ RefPtr<Image> image = videoFrameToImage(video, ec);
+ if (!image)
return;
texImage2DImpl(target, level, internalformat, format, type, image.get(), m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
}
@@ -3334,7 +3440,10 @@ void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Din
return;
if (!validateHTMLImageElement(image))
return;
- checkOrigin(image);
+ if (wouldTaintOrigin(image)) {
+ ec = SECURITY_ERR;
+ return;
+ }
texSubImage2DImpl(target, level, xoffset, yoffset, format, type, image->cachedImage()->image(),
m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
}
@@ -3349,7 +3458,10 @@ void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Din
m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
return;
}
- checkOrigin(canvas);
+ if (wouldTaintOrigin(canvas)) {
+ ec = SECURITY_ERR;
+ return;
+ }
RefPtr<ImageData> imageData = canvas->getImageData();
if (imageData)
texSubImage2D(target, level, xoffset, yoffset, format, type, imageData.get(), ec);
@@ -3365,8 +3477,8 @@ void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Din
ec = 0;
if (isContextLost())
return;
- RefPtr<Image> image = videoFrameToImage(video);
- if (!video)
+ RefPtr<Image> image = videoFrameToImage(video, ec);
+ if (!image)
return;
texSubImage2DImpl(target, level, xoffset, yoffset, format, type, image.get(), m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
}
@@ -3799,7 +3911,7 @@ void WebGLRenderingContext::vertexAttrib4fv(GC3Duint index, GC3Dfloat* v, GC3Dsi
vertexAttribfvImpl(index, v, size, 4);
}
-void WebGLRenderingContext::vertexAttribPointer(GC3Duint index, GC3Dint size, GC3Denum type, GC3Dboolean normalized, GC3Dsizei stride, GC3Dintptr offset, ExceptionCode& ec)
+void WebGLRenderingContext::vertexAttribPointer(GC3Duint index, GC3Dint size, GC3Denum type, GC3Dboolean normalized, GC3Dsizei stride, long long offset, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
if (isContextLost())
@@ -3833,7 +3945,7 @@ void WebGLRenderingContext::vertexAttribPointer(GC3Duint index, GC3Dint size, GC
m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
return;
}
- if ((stride % typeSize) || (offset % typeSize)) {
+ if ((stride % typeSize) || (static_cast<GC3Dintptr>(offset) % typeSize)) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
return;
}
@@ -3849,8 +3961,8 @@ void WebGLRenderingContext::vertexAttribPointer(GC3Duint index, GC3Dint size, GC
state.normalized = normalized;
state.stride = validatedStride;
state.originalStride = stride;
- state.offset = offset;
- m_context->vertexAttribPointer(index, size, type, normalized, stride, offset);
+ state.offset = static_cast<GC3Dintptr>(offset);
+ m_context->vertexAttribPointer(index, size, type, normalized, stride, static_cast<GC3Dintptr>(offset));
cleanupAfterGraphicsCall(false);
}
@@ -3872,17 +3984,30 @@ void WebGLRenderingContext::viewport(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3D
cleanupAfterGraphicsCall(false);
}
-void WebGLRenderingContext::forceLostContext()
+void WebGLRenderingContext::forceLostContext(WebGLRenderingContext::LostContextMode mode)
{
if (isContextLost()) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
return;
}
- m_restoreTimer.startOneShot(0);
+ loseContext();
+
+ if (mode == RealLostContext)
+ m_restoreTimer.startOneShot(0);
}
-void WebGLRenderingContext::onLostContext()
+void WebGLRenderingContext::forceRestoreContext()
+{
+ if (!isContextLost()) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
+ return;
+ }
+
+ maybeRestoreContext(SyntheticLostContext);
+}
+
+void WebGLRenderingContext::loseContext()
{
m_contextLost = true;
@@ -3890,7 +4015,7 @@ void WebGLRenderingContext::onLostContext()
// There is no direct way to clear errors from a GL implementation and
// looping until getError() becomes NO_ERROR might cause an infinite loop if
- // the driver or context implementation had a bug. So, loop a reasonably
+ // the driver or context implementation had a bug. So, loop a reasonably
// large number of times to clear any existing errors.
for (int i = 0; i < 100; ++i) {
if (m_context->getError() == GraphicsContext3D::NO_ERROR)
@@ -3898,14 +4023,67 @@ void WebGLRenderingContext::onLostContext()
}
m_context->synthesizeGLError(GraphicsContext3D::CONTEXT_LOST_WEBGL);
- canvas()->dispatchEvent(WebGLContextEvent::create(eventNames().webglcontextlostEvent, false, true, ""));
+ RefPtr<WebGLContextEvent> event = WebGLContextEvent::create(eventNames().webglcontextlostEvent, false, true, "");
+ canvas()->dispatchEvent(event);
+ m_restoreAllowed = event->defaultPrevented();
}
-void WebGLRenderingContext::restoreContext()
+void WebGLRenderingContext::maybeRestoreContext(WebGLRenderingContext::LostContextMode mode)
{
+ if (!m_contextLost) {
+ ASSERT(mode == SyntheticLostContext);
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
+ return;
+ }
+
+ // The rendering context is not restored unless the default
+ // behavior of the webglcontextlost event was prevented earlier.
+ if (!m_restoreAllowed) {
+ if (mode == SyntheticLostContext)
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
+ return;
+ }
+
+ int contextLostReason = m_context->getExtensions()->getGraphicsResetStatusARB();
+
+ switch (contextLostReason) {
+ case GraphicsContext3D::NO_ERROR:
+ // The GraphicsContext3D implementation might not fully
+ // support GL_ARB_robustness semantics yet. Alternatively, the
+ // WebGL WEBKIT_lose_context extension might have been used to
+ // force a lost context.
+ break;
+ case Extensions3D::GUILTY_CONTEXT_RESET_ARB:
+ // The rendering context is not restored if this context was
+ // guilty of causing the graphics reset.
+ printWarningToConsole("WARNING: WebGL content on the page caused the graphics card to reset; not restoring the context");
+ return;
+ case Extensions3D::INNOCENT_CONTEXT_RESET_ARB:
+ // Always allow the context to be restored.
+ break;
+ case Extensions3D::UNKNOWN_CONTEXT_RESET_ARB:
+ // Warn. Ideally, prompt the user telling them that WebGL
+ // content on the page might have caused the graphics card to
+ // reset and ask them whether they want to continue running
+ // the content. Only if they say "yes" should we start
+ // attempting to restore the context.
+ printWarningToConsole("WARNING: WebGL content on the page might have caused the graphics card to reset");
+ break;
+ }
+
+#if PLATFORM(ANDROID)
+ RefPtr<GraphicsContext3D> context(GraphicsContext3D::create(canvas(), m_attributes, 0));
+#else
RefPtr<GraphicsContext3D> context(GraphicsContext3D::create(m_attributes, canvas()->document()->view()->root()->hostWindow()));
- if (!context)
+#endif
+ if (!context) {
+ if (mode == RealLostContext)
+ m_restoreTimer.startOneShot(secondsBetweenRestoreAttempts);
+ else
+ // This likely shouldn't happen but is the best way to report it to the WebGL app.
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
return;
+ }
m_context = context;
m_contextLost = false;
@@ -3927,59 +4105,10 @@ void WebGLRenderingContext::addObject(WebGLObject* object)
void WebGLRenderingContext::detachAndRemoveAllObjects()
{
- HashSet<RefPtr<WebGLObject> >::iterator pend = m_canvasObjects.end();
- for (HashSet<RefPtr<WebGLObject> >::iterator it = m_canvasObjects.begin(); it != pend; ++it)
+ while (m_canvasObjects.size() > 0) {
+ HashSet<WebGLObject*>::iterator it = m_canvasObjects.begin();
(*it)->detachContext();
-
- m_canvasObjects.clear();
-}
-
-WebGLTexture* WebGLRenderingContext::findTexture(Platform3DObject obj)
-{
- if (!obj)
- return 0;
- HashSet<RefPtr<WebGLObject> >::iterator pend = m_canvasObjects.end();
- for (HashSet<RefPtr<WebGLObject> >::iterator it = m_canvasObjects.begin(); it != pend; ++it) {
- if ((*it)->isTexture() && (*it)->object() == obj)
- return reinterpret_cast<WebGLTexture*>((*it).get());
}
- return 0;
-}
-
-WebGLRenderbuffer* WebGLRenderingContext::findRenderbuffer(Platform3DObject obj)
-{
- if (!obj)
- return 0;
- HashSet<RefPtr<WebGLObject> >::iterator pend = m_canvasObjects.end();
- for (HashSet<RefPtr<WebGLObject> >::iterator it = m_canvasObjects.begin(); it != pend; ++it) {
- if ((*it)->isRenderbuffer() && (*it)->object() == obj)
- return reinterpret_cast<WebGLRenderbuffer*>((*it).get());
- }
- return 0;
-}
-
-WebGLBuffer* WebGLRenderingContext::findBuffer(Platform3DObject obj)
-{
- if (!obj)
- return 0;
- HashSet<RefPtr<WebGLObject> >::iterator pend = m_canvasObjects.end();
- for (HashSet<RefPtr<WebGLObject> >::iterator it = m_canvasObjects.begin(); it != pend; ++it) {
- if ((*it)->isBuffer() && (*it)->object() == obj)
- return reinterpret_cast<WebGLBuffer*>((*it).get());
- }
- return 0;
-}
-
-WebGLShader* WebGLRenderingContext::findShader(Platform3DObject obj)
-{
- if (!obj)
- return 0;
- HashSet<RefPtr<WebGLObject> >::iterator pend = m_canvasObjects.end();
- for (HashSet<RefPtr<WebGLObject> >::iterator it = m_canvasObjects.begin(); it != pend; ++it) {
- if ((*it)->isShader() && (*it)->object() == obj)
- return reinterpret_cast<WebGLShader*>((*it).get());
- }
- return 0;
}
WebGLGetInfo WebGLRenderingContext::getBooleanParameter(GC3Denum pname)
@@ -4198,6 +4327,16 @@ WebGLTexture* WebGLRenderingContext::validateTextureBinding(GC3Denum target, boo
return tex;
}
+bool WebGLRenderingContext::validateLocationLength(const String& string)
+{
+ const unsigned maxWebGLLocationLength = 256;
+ if (string.length() > maxWebGLLocationLength) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ return false;
+ }
+ return true;
+}
+
bool WebGLRenderingContext::validateSize(GC3Dint x, GC3Dint y)
{
if (x < 0 || y < 0) {
diff --git a/Source/WebCore/html/canvas/WebGLRenderingContext.h b/Source/WebCore/html/canvas/WebGLRenderingContext.h
index 23c147d..2a0a90d 100644
--- a/Source/WebCore/html/canvas/WebGLRenderingContext.h
+++ b/Source/WebCore/html/canvas/WebGLRenderingContext.h
@@ -1,5 +1,7 @@
/*
* Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2011 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
@@ -71,6 +73,9 @@ public:
virtual bool isAccelerated() const { return true; }
virtual bool paintsIntoCanvasBuffer() const;
+ GC3Dsizei drawingBufferWidth();
+ GC3Dsizei drawingBufferHeight();
+
void activeTexture(GC3Denum texture, ExceptionCode&);
void attachShader(WebGLProgram*, WebGLShader*, ExceptionCode&);
void bindAttribLocation(WebGLProgram*, GC3Duint index, const String& name, ExceptionCode&);
@@ -84,11 +89,11 @@ public:
void blendFunc(GC3Denum sfactor, GC3Denum dfactor);
void blendFuncSeparate(GC3Denum srcRGB, GC3Denum dstRGB, GC3Denum srcAlpha, GC3Denum dstAlpha);
- void bufferData(GC3Denum target, GC3Dsizeiptr size, GC3Denum usage, ExceptionCode&);
+ void bufferData(GC3Denum target, long long size, GC3Denum usage, ExceptionCode&);
void bufferData(GC3Denum target, ArrayBuffer* data, GC3Denum usage, ExceptionCode&);
void bufferData(GC3Denum target, ArrayBufferView* data, GC3Denum usage, ExceptionCode&);
- void bufferSubData(GC3Denum target, GC3Dintptr offset, ArrayBuffer* data, ExceptionCode&);
- void bufferSubData(GC3Denum target, GC3Dintptr offset, ArrayBufferView* data, ExceptionCode&);
+ void bufferSubData(GC3Denum target, long long offset, ArrayBuffer* data, ExceptionCode&);
+ void bufferSubData(GC3Denum target, long long offset, ArrayBufferView* data, ExceptionCode&);
GC3Denum checkFramebufferStatus(GC3Denum target);
void clear(GC3Dbitfield mask);
@@ -98,8 +103,12 @@ public:
void colorMask(GC3Dboolean red, GC3Dboolean green, GC3Dboolean blue, GC3Dboolean alpha);
void compileShader(WebGLShader*, ExceptionCode&);
- // void compressedTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Dsizei imageSize, const void* data);
- // void compressedTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei GC3Dsizei height, GC3Denum format, GC3Dsizei imageSize, const void* data);
+ void compressedTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
+ GC3Dsizei width, GC3Dsizei height, GC3Dint border,
+ ArrayBufferView* data);
+ void compressedTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset,
+ GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height,
+ GC3Denum format, ArrayBufferView* data);
void copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border);
void copyTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height);
@@ -127,7 +136,7 @@ public:
void disable(GC3Denum cap);
void disableVertexAttribArray(GC3Duint index, ExceptionCode&);
void drawArrays(GC3Denum mode, GC3Dint first, GC3Dsizei count, ExceptionCode&);
- void drawElements(GC3Denum mode, GC3Dsizei count, GC3Denum type, GC3Dintptr offset, ExceptionCode&);
+ void drawElements(GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset, ExceptionCode&);
void enable(GC3Denum cap);
void enableVertexAttribArray(GC3Duint index, ExceptionCode&);
@@ -163,7 +172,7 @@ public:
WebGLGetInfo getUniform(WebGLProgram*, const WebGLUniformLocation*, ExceptionCode&);
PassRefPtr<WebGLUniformLocation> getUniformLocation(WebGLProgram*, const String&, ExceptionCode&);
WebGLGetInfo getVertexAttrib(GC3Duint index, GC3Denum pname, ExceptionCode&);
- GC3Dsizeiptr getVertexAttribOffset(GC3Duint index, GC3Denum pname);
+ long long getVertexAttribOffset(GC3Duint index, GC3Denum pname);
void hint(GC3Denum target, GC3Denum mode);
GC3Dboolean isBuffer(WebGLBuffer*);
@@ -270,13 +279,20 @@ public:
void vertexAttrib4fv(GC3Duint index, Float32Array* values);
void vertexAttrib4fv(GC3Duint index, GC3Dfloat* values, GC3Dsizei size);
void vertexAttribPointer(GC3Duint index, GC3Dint size, GC3Denum type, GC3Dboolean normalized,
- GC3Dsizei stride, GC3Dintptr offset, ExceptionCode&);
+ GC3Dsizei stride, long long offset, ExceptionCode&);
void viewport(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height);
- void forceLostContext();
- void onLostContext();
- void restoreContext();
+ // WEBKIT_lose_context support
+ enum LostContextMode {
+ // Lost context occurred at the graphics system level.
+ RealLostContext,
+
+ // Lost context provoked by WEBKIT_lose_context.
+ SyntheticLostContext
+ };
+ void forceLostContext(LostContextMode);
+ void forceRestoreContext();
GraphicsContext3D* graphicsContext3D() const { return m_context.get(); }
#if USE(ACCELERATED_COMPOSITING)
@@ -297,7 +313,13 @@ public:
int getNumberOfExtensions();
WebGLExtension* getExtensionNumber(int i);
+#if PLATFORM(ANDROID)
+ void recreateSurface();
+ void releaseSurface();
+#endif
+
private:
+ friend class WebGLFramebuffer;
friend class WebGLObject;
friend class OESVertexArrayObject;
@@ -307,10 +329,6 @@ public:
void addObject(WebGLObject*);
void detachAndRemoveAllObjects();
- WebGLTexture* findTexture(Platform3DObject);
- WebGLRenderbuffer* findRenderbuffer(Platform3DObject);
- WebGLBuffer* findBuffer(Platform3DObject);
- WebGLShader* findShader(Platform3DObject);
void markContextChanged();
void cleanupAfterGraphicsCall(bool changed)
@@ -348,7 +366,7 @@ public:
bool validateWebGLObject(WebGLObject*);
#if ENABLE(VIDEO)
- PassRefPtr<Image> videoFrameToImage(HTMLVideoElement*);
+ PassRefPtr<Image> videoFrameToImage(HTMLVideoElement*, ExceptionCode&);
#endif
RefPtr<GraphicsContext3D> m_context;
@@ -361,11 +379,12 @@ public:
WebGLRenderingContext* m_context;
};
+ bool m_restoreAllowed;
WebGLRenderingContextRestoreTimer m_restoreTimer;
bool m_needsUpdate;
bool m_markedCanvasDirty;
- HashSet<RefPtr<WebGLObject> > m_canvasObjects;
+ HashSet<WebGLObject*> m_canvasObjects;
// List of bound VBO's. Used to maintain info about sizes for ARRAY_BUFFER and stored values for ELEMENT_ARRAY_BUFFER
RefPtr<WebGLBuffer> m_boundArrayBuffer;
@@ -515,6 +534,9 @@ public:
// Helper function to get the bound framebuffer's height.
int getBoundFramebufferHeight();
+ // Helper function to verify limits on the length of uniform and attribute locations.
+ bool validateLocationLength(const String&);
+
// Helper function to check if size is non-negative.
// Generate GL error and return false for negative inputs; otherwise, return true.
bool validateSize(GC3Dint x, GC3Dint y);
@@ -612,6 +634,10 @@ public:
bool simulateVertexAttrib0(GC3Dsizei numVertex);
void restoreStatesAfterVertexAttrib0Simulation();
+ void loseContext();
+ // Helper for restoration after context lost.
+ void maybeRestoreContext(LostContextMode);
+
friend class WebGLStateRestorer;
};
diff --git a/Source/WebCore/html/canvas/WebGLRenderingContext.idl b/Source/WebCore/html/canvas/WebGLRenderingContext.idl
index 7a19814..0a22c6d 100644
--- a/Source/WebCore/html/canvas/WebGLRenderingContext.idl
+++ b/Source/WebCore/html/canvas/WebGLRenderingContext.idl
@@ -1,5 +1,7 @@
/*
* Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2011 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
@@ -450,6 +452,9 @@ module html {
const unsigned int UNPACK_COLORSPACE_CONVERSION_WEBGL = 0x9243;
const unsigned int BROWSER_DEFAULT_WEBGL = 0x9244;
+ readonly attribute unsigned int drawingBufferWidth;
+ readonly attribute unsigned int drawingBufferHeight;
+
[StrictTypeChecking] void activeTexture(in unsigned long texture) raises(DOMException);
[StrictTypeChecking] void attachShader(in WebGLProgram program, in WebGLShader shader) raises(DOMException);
[StrictTypeChecking] void bindAttribLocation(in WebGLProgram program, in unsigned long index, in DOMString name) raises(DOMException);
@@ -464,9 +469,9 @@ module html {
[StrictTypeChecking] void blendFuncSeparate(in unsigned long srcRGB, in unsigned long dstRGB, in unsigned long srcAlpha, in unsigned long dstAlpha);
[StrictTypeChecking] void bufferData(in unsigned long target, in ArrayBuffer data, in unsigned long usage) raises (DOMException);
[StrictTypeChecking] void bufferData(in unsigned long target, in ArrayBufferView data, in unsigned long usage) raises (DOMException);
- [StrictTypeChecking] void bufferData(in unsigned long target, in long size, in unsigned long usage) raises (DOMException);
- [StrictTypeChecking] void bufferSubData(in unsigned long target, in long offset, in ArrayBuffer data) raises (DOMException);
- [StrictTypeChecking] void bufferSubData(in unsigned long target, in long offset, in ArrayBufferView data) raises (DOMException);
+ [StrictTypeChecking] void bufferData(in unsigned long target, in long long size, in unsigned long usage) raises (DOMException);
+ [StrictTypeChecking] void bufferSubData(in unsigned long target, in long long offset, in ArrayBuffer data) raises (DOMException);
+ [StrictTypeChecking] void bufferSubData(in unsigned long target, in long long offset, in ArrayBufferView data) raises (DOMException);
[StrictTypeChecking] unsigned long checkFramebufferStatus(in unsigned long target);
[StrictTypeChecking] void clear(in unsigned long mask);
@@ -476,8 +481,18 @@ module html {
[StrictTypeChecking] void colorMask(in boolean red, in boolean green, in boolean blue, in boolean alpha);
[StrictTypeChecking] void compileShader(in WebGLShader shader) raises(DOMException);
- //void compressedTexImage2D(in unsigned long target, in long level, in unsigned long internalformat, in unsigned long width, in unsigned long height, in long border, in unsigned long imageSize, const void* data);
- //void compressedTexSubImage2D(in unsigned long target, in long level, in long xoffset, in long yoffset, in unsigned long width, in unsigned long height, in unsigned long format, in unsigned long imageSize, const void* data);
+ [StrictTypeChecking] void compressedTexImage2D(in unsigned long target,
+ in long level,
+ in unsigned long internalformat,
+ in long width, in long height,
+ in long border,
+ in ArrayBufferView data);
+ [StrictTypeChecking] void compressedTexSubImage2D(in unsigned long target,
+ in long level,
+ in long xoffset, in long yoffset,
+ in long width, in long height,
+ in unsigned long format,
+ in ArrayBufferView data);
[StrictTypeChecking] void copyTexImage2D(in unsigned long target, in long level, in unsigned long internalformat, in long x, in long y, in long width, in long height, in long border);
[StrictTypeChecking] void copyTexSubImage2D(in unsigned long target, in long level, in long xoffset, in long yoffset, in long x, in long y, in long width, in long height);
@@ -506,7 +521,7 @@ module html {
[StrictTypeChecking] void disable(in unsigned long cap);
[StrictTypeChecking] void disableVertexAttribArray(in unsigned long index) raises(DOMException);
[StrictTypeChecking] void drawArrays(in unsigned long mode, in long first, in long count) raises(DOMException);
- [StrictTypeChecking] void drawElements(in unsigned long mode, in long count, in unsigned long type, in long offset) raises(DOMException);
+ [StrictTypeChecking] void drawElements(in unsigned long mode, in long count, in unsigned long type, in long long offset) raises(DOMException);
[StrictTypeChecking] void enable(in unsigned long cap);
[StrictTypeChecking] void enableVertexAttribArray(in unsigned long index) raises(DOMException);
@@ -567,7 +582,7 @@ module html {
// any getVertexAttrib(in unsigned long index, in unsigned long pname) raises(DOMException);
[StrictTypeChecking, Custom] void getVertexAttrib();
- [StrictTypeChecking] long getVertexAttribOffset(in unsigned long index, in unsigned long pname);
+ [StrictTypeChecking] long long getVertexAttribOffset(in unsigned long index, in unsigned long pname);
[StrictTypeChecking] void hint(in unsigned long target, in unsigned long mode);
[StrictTypeChecking] boolean isBuffer(in WebGLBuffer buffer);
@@ -661,7 +676,7 @@ module html {
[StrictTypeChecking] void vertexAttrib4f(in unsigned long indx, in float x, in float y, in float z, in float w);
[StrictTypeChecking, Custom] void vertexAttrib4fv(in unsigned long indx, in Float32Array values);
[StrictTypeChecking] void vertexAttribPointer(in unsigned long indx, in long size, in unsigned long type, in boolean normalized,
- in long stride, in long offset) raises(DOMException);
+ in long stride, in long long offset) raises(DOMException);
[StrictTypeChecking] void viewport(in long x, in long y, in long width, in long height);
};
diff --git a/Source/WebCore/html/canvas/WebKitLoseContext.cpp b/Source/WebCore/html/canvas/WebKitLoseContext.cpp
index c594e32..3c0a5f3 100644
--- a/Source/WebCore/html/canvas/WebKitLoseContext.cpp
+++ b/Source/WebCore/html/canvas/WebKitLoseContext.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2010 Google Inc. All rights reserved.
+ * Copyright (C) 2012 Sony Ericsson Mobile Communications AB
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -56,7 +57,13 @@ PassRefPtr<WebKitLoseContext> WebKitLoseContext::create(WebGLRenderingContext* c
void WebKitLoseContext::loseContext()
{
if (m_context)
- m_context->forceLostContext();
+ m_context->forceLostContext(WebGLRenderingContext::SyntheticLostContext);
+}
+
+void WebKitLoseContext::restoreContext()
+{
+ if (m_context)
+ m_context->forceRestoreContext();
}
} // namespace WebCore
diff --git a/Source/WebCore/html/canvas/WebKitLoseContext.h b/Source/WebCore/html/canvas/WebKitLoseContext.h
index b713bef..5822e54 100644
--- a/Source/WebCore/html/canvas/WebKitLoseContext.h
+++ b/Source/WebCore/html/canvas/WebKitLoseContext.h
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2010 Google Inc. All rights reserved.
+ * Copyright (C) 2012 Sony Ericsson Mobile Communications AB
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -42,6 +43,7 @@ public:
virtual ExtensionName getName() const;
void loseContext();
+ void restoreContext();
void contextDestroyed() { m_context = 0; }
private:
diff --git a/Source/WebCore/html/canvas/WebKitLoseContext.idl b/Source/WebCore/html/canvas/WebKitLoseContext.idl
index 83fc909..8b249bd 100644
--- a/Source/WebCore/html/canvas/WebKitLoseContext.idl
+++ b/Source/WebCore/html/canvas/WebKitLoseContext.idl
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2010 Google Inc. All rights reserved.
+ * Copyright (C) 2012 Sony Ericsson Mobile Communications AB
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -26,5 +27,6 @@
module html {
interface [Conditional=WEBGL, OmitConstructor] WebKitLoseContext {
[StrictTypeChecking] void loseContext();
+ [StrictTypeChecking] void restoreContext();
};
}