diff options
author | Steve Block <steveblock@google.com> | 2010-04-27 16:31:00 +0100 |
---|---|---|
committer | Steve Block <steveblock@google.com> | 2010-05-11 14:42:12 +0100 |
commit | dcc8cf2e65d1aa555cce12431a16547e66b469ee (patch) | |
tree | 92a8d65cd5383bca9749f5327fb5e440563926e6 /WebCore/html/canvas | |
parent | ccac38a6b48843126402088a309597e682f40fe6 (diff) | |
download | external_webkit-dcc8cf2e65d1aa555cce12431a16547e66b469ee.zip external_webkit-dcc8cf2e65d1aa555cce12431a16547e66b469ee.tar.gz external_webkit-dcc8cf2e65d1aa555cce12431a16547e66b469ee.tar.bz2 |
Merge webkit.org at r58033 : Initial merge by git
Change-Id: If006c38561af287c50cd578d251629b51e4d8cd1
Diffstat (limited to 'WebCore/html/canvas')
32 files changed, 866 insertions, 343 deletions
diff --git a/WebCore/html/canvas/CanvasRenderingContext2D.cpp b/WebCore/html/canvas/CanvasRenderingContext2D.cpp index 6fe74f9..0baa0e6 100644 --- a/WebCore/html/canvas/CanvasRenderingContext2D.cpp +++ b/WebCore/html/canvas/CanvasRenderingContext2D.cpp @@ -39,7 +39,6 @@ #include "CSSMutableStyleDeclaration.h" #include "CSSPropertyNames.h" #include "CSSStyleSelector.h" -#include "Document.h" #include "ExceptionCode.h" #include "FloatConversion.h" #include "GraphicsContext.h" @@ -90,12 +89,18 @@ private: CanvasRenderingContext2D* m_canvasContext; }; - - -CanvasRenderingContext2D::CanvasRenderingContext2D(HTMLCanvasElement* canvas) +CanvasRenderingContext2D::CanvasRenderingContext2D(HTMLCanvasElement* canvas, bool usesCSSCompatibilityParseMode, bool usesDashboardCompatibilityMode) : CanvasRenderingContext(canvas) , m_stateStack(1) + , m_usesCSSCompatibilityParseMode(usesCSSCompatibilityParseMode) +#if ENABLE(DASHBOARD_SUPPORT) + , m_usesDashboardCompatibilityMode(usesDashboardCompatibilityMode) +#endif { +#if !ENABLE(DASHBOARD_SUPPORT) + ASSERT_UNUSED(usesDashboardCompatibilityMode, !usesDashboardCompatibilityMode); +#endif + // Make sure that even if the drawingContext() has a different default // thickness, it is in sync with the canvas thickness. setLineWidth(lineWidth()); @@ -636,9 +641,8 @@ void CanvasRenderingContext2D::rect(float x, float y, float width, float height) #if ENABLE(DASHBOARD_SUPPORT) void CanvasRenderingContext2D::clearPathForDashboardBackwardCompatibilityMode() { - if (Settings* settings = canvas()->document()->settings()) - if (settings->usesDashboardBackwardCompatibilityMode()) - m_path.clear(); + if (m_usesDashboardCompatibilityMode) + m_path.clear(); } #endif @@ -941,7 +945,7 @@ static inline FloatRect normalizeRect(const FloatRect& rect) void CanvasRenderingContext2D::checkOrigin(const KURL& url) { - if (canvas()->document()->securityOrigin()->taintsCanvas(url)) + if (canvas()->securityOrigin().taintsCanvas(url)) canvas()->setOriginTainted(); } @@ -950,26 +954,45 @@ void CanvasRenderingContext2D::checkOrigin(const String& url) checkOrigin(KURL(KURL(), url)); } -void CanvasRenderingContext2D::drawImage(HTMLImageElement* image, float x, float y) +void CanvasRenderingContext2D::drawImage(HTMLImageElement* image, float x, float y, ExceptionCode& ec) { - ASSERT(image); + if (!image) { + ec = TYPE_MISMATCH_ERR; + return; + } IntSize s = size(image); - ExceptionCode ec; drawImage(image, x, y, s.width(), s.height(), ec); } void CanvasRenderingContext2D::drawImage(HTMLImageElement* image, float x, float y, float width, float height, ExceptionCode& ec) { - ASSERT(image); + if (!image) { + ec = TYPE_MISMATCH_ERR; + return; + } IntSize s = size(image); drawImage(image, FloatRect(0, 0, s.width(), s.height()), FloatRect(x, y, width, height), ec); } +void CanvasRenderingContext2D::drawImage(HTMLImageElement* image, + float sx, float sy, float sw, float sh, + float dx, float dy, float dw, float dh, ExceptionCode& ec) +{ + if (!image) { + ec = TYPE_MISMATCH_ERR; + return; + } + drawImage(image, FloatRect(sx, sy, sw, sh), FloatRect(dx, dy, dw, dh), ec); +} + void CanvasRenderingContext2D::drawImage(HTMLImageElement* image, const FloatRect& srcRect, const FloatRect& dstRect, ExceptionCode& ec) { - ASSERT(image); + if (!image) { + ec = TYPE_MISMATCH_ERR; + return; + } ec = 0; @@ -1004,24 +1027,39 @@ void CanvasRenderingContext2D::drawImage(HTMLImageElement* image, const FloatRec c->drawImage(cachedImage->image(), DeviceColorSpace, destRect, sourceRect, state().m_globalComposite); } -void CanvasRenderingContext2D::drawImage(HTMLCanvasElement* canvas, float x, float y) +void CanvasRenderingContext2D::drawImage(HTMLCanvasElement* canvas, float x, float y, ExceptionCode& ec) { - ASSERT(canvas); - ExceptionCode ec; + if (!canvas) { + ec = TYPE_MISMATCH_ERR; + return; + } drawImage(canvas, x, y, canvas->width(), canvas->height(), ec); } void CanvasRenderingContext2D::drawImage(HTMLCanvasElement* canvas, float x, float y, float width, float height, ExceptionCode& ec) { - ASSERT(canvas); + if (!canvas) { + ec = TYPE_MISMATCH_ERR; + return; + } drawImage(canvas, FloatRect(0, 0, canvas->width(), canvas->height()), FloatRect(x, y, width, height), ec); } +void CanvasRenderingContext2D::drawImage(HTMLCanvasElement* canvas, + float sx, float sy, float sw, float sh, + float dx, float dy, float dw, float dh, ExceptionCode& ec) +{ + drawImage(canvas, FloatRect(sx, sy, sw, sh), FloatRect(dx, dy, dw, dh), ec); +} + void CanvasRenderingContext2D::drawImage(HTMLCanvasElement* sourceCanvas, const FloatRect& srcRect, const FloatRect& dstRect, ExceptionCode& ec) { - ASSERT(sourceCanvas); + if (!sourceCanvas) { + ec = TYPE_MISMATCH_ERR; + return; + } ec = 0; @@ -1057,26 +1095,41 @@ void CanvasRenderingContext2D::drawImage(HTMLCanvasElement* sourceCanvas, const } #if ENABLE(VIDEO) -void CanvasRenderingContext2D::drawImage(HTMLVideoElement* video, float x, float y) +void CanvasRenderingContext2D::drawImage(HTMLVideoElement* video, float x, float y, ExceptionCode& ec) { - ASSERT(video); + if (!video) { + ec = TYPE_MISMATCH_ERR; + return; + } IntSize s = size(video); - ExceptionCode ec; drawImage(video, x, y, s.width(), s.height(), ec); } void CanvasRenderingContext2D::drawImage(HTMLVideoElement* video, float x, float y, float width, float height, ExceptionCode& ec) { - ASSERT(video); + if (!video) { + ec = TYPE_MISMATCH_ERR; + return; + } IntSize s = size(video); drawImage(video, FloatRect(0, 0, s.width(), s.height()), FloatRect(x, y, width, height), ec); } +void CanvasRenderingContext2D::drawImage(HTMLVideoElement* video, + float sx, float sy, float sw, float sh, + float dx, float dy, float dw, float dh, ExceptionCode& ec) +{ + drawImage(video, FloatRect(sx, sy, sw, sh), FloatRect(dx, dy, dw, dh), ec); +} + void CanvasRenderingContext2D::drawImage(HTMLVideoElement* video, const FloatRect& srcRect, const FloatRect& dstRect, ExceptionCode& ec) { - ASSERT(video); + if (!video) { + ec = TYPE_MISMATCH_ERR; + return; + } ec = 0; FloatRect videoRect = FloatRect(FloatPoint(), size(video)); @@ -1161,9 +1214,8 @@ void CanvasRenderingContext2D::setCompositeOperation(const String& operation) void CanvasRenderingContext2D::prepareGradientForDashboard(CanvasGradient* gradient) const { #if ENABLE(DASHBOARD_SUPPORT) - if (Settings* settings = canvas()->document()->settings()) - if (settings->usesDashboardBackwardCompatibilityMode()) - gradient->setDashboardCompatibilityMode(); + if (m_usesDashboardCompatibilityMode) + gradient->setDashboardCompatibilityMode(); #else UNUSED_PARAM(gradient); #endif @@ -1196,6 +1248,10 @@ PassRefPtr<CanvasGradient> CanvasRenderingContext2D::createRadialGradient(float PassRefPtr<CanvasPattern> CanvasRenderingContext2D::createPattern(HTMLImageElement* image, const String& repetitionType, ExceptionCode& ec) { + if (!image) { + ec = TYPE_MISMATCH_ERR; + return 0; + } bool repeatX, repeatY; ec = 0; CanvasPattern::parseRepetitionType(repetitionType, repeatX, repeatY, ec); @@ -1211,13 +1267,21 @@ PassRefPtr<CanvasPattern> CanvasRenderingContext2D::createPattern(HTMLImageEleme if (!cachedImage || !image->cachedImage()->image()) return CanvasPattern::create(Image::nullImage(), repeatX, repeatY, true); +<<<<<<< HEAD bool originClean = !canvas()->document()->securityOrigin()->taintsCanvas(KURL(KURL(), cachedImage->url())) && cachedImage->image()->hasSingleSecurityOrigin(); +======= + bool originClean = !canvas()->securityOrigin().taintsCanvas(KURL(KURL(), cachedImage->url())) && cachedImage->image()->hasSingleSecurityOrigin(); +>>>>>>> webkit.org at r58033 return CanvasPattern::create(cachedImage->image(), repeatX, repeatY, originClean); } PassRefPtr<CanvasPattern> CanvasRenderingContext2D::createPattern(HTMLCanvasElement* canvas, const String& repetitionType, ExceptionCode& ec) { + if (!canvas) { + ec = TYPE_MISMATCH_ERR; + return 0; + } if (!canvas->width() || !canvas->height()) { ec = INVALID_STATE_ERR; return 0; @@ -1369,7 +1433,7 @@ String CanvasRenderingContext2D::font() const void CanvasRenderingContext2D::setFont(const String& newFont) { RefPtr<CSSMutableStyleDeclaration> tempDecl = CSSMutableStyleDeclaration::create(); - CSSParser parser(!canvas()->document()->inCompatMode()); // Use the parse mode of the canvas' document when parsing CSS. + CSSParser parser(!m_usesCSSCompatibilityParseMode); String declarationText("font: "); declarationText += newFont; @@ -1383,11 +1447,11 @@ void CanvasRenderingContext2D::setFont(const String& newFont) // Map the <canvas> font into the text style. If the font uses keywords like larger/smaller, these will work // relative to the canvas. RefPtr<RenderStyle> newStyle = RenderStyle::create(); - if (canvas()->computedStyle()) - newStyle->setFontDescription(canvas()->computedStyle()->fontDescription()); + if (RenderStyle* computedStyle = canvas()->computedStyle()) + newStyle->setFontDescription(computedStyle->fontDescription()); // Now map the font property into the style. - CSSStyleSelector* styleSelector = canvas()->document()->styleSelector(); + CSSStyleSelector* styleSelector = canvas()->styleSelector(); styleSelector->applyPropertyToStyle(CSSPropertyFont, tempDecl->getPropertyCSSValue(CSSPropertyFont).get(), newStyle.get()); state().m_font = newStyle->font(); @@ -1461,8 +1525,9 @@ void CanvasRenderingContext2D::drawTextInternal(const String& text, float x, flo // FIXME: Handle maxWidth. // FIXME: Need to turn off font smoothing. - bool rtl = canvas()->computedStyle() ? canvas()->computedStyle()->direction() == RTL : false; - bool override = canvas()->computedStyle() ? canvas()->computedStyle()->unicodeBidi() == Override : false; + RenderStyle* computedStyle = canvas()->computedStyle(); + bool rtl = computedStyle ? computedStyle->direction() == RTL : false; + bool override = computedStyle ? computedStyle->unicodeBidi() == Override : false; unsigned length = text.length(); const UChar* string = text.characters(); diff --git a/WebCore/html/canvas/CanvasRenderingContext2D.h b/WebCore/html/canvas/CanvasRenderingContext2D.h index 553ffd2..2bac902 100644 --- a/WebCore/html/canvas/CanvasRenderingContext2D.h +++ b/WebCore/html/canvas/CanvasRenderingContext2D.h @@ -57,7 +57,7 @@ namespace WebCore { class CanvasRenderingContext2D : public CanvasRenderingContext { public: - CanvasRenderingContext2D(HTMLCanvasElement*); + CanvasRenderingContext2D(HTMLCanvasElement*, bool usesCSSCompatibilityParseMode, bool usesDashboardCompatibilityMode); virtual ~CanvasRenderingContext2D(); @@ -154,15 +154,18 @@ namespace WebCore { void clearShadow(); - void drawImage(HTMLImageElement*, float x, float y); + void drawImage(HTMLImageElement*, float x, float y, ExceptionCode&); void drawImage(HTMLImageElement*, float x, float y, float width, float height, ExceptionCode&); + void drawImage(HTMLImageElement*, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh, ExceptionCode&); void drawImage(HTMLImageElement*, const FloatRect& srcRect, const FloatRect& dstRect, ExceptionCode&); - void drawImage(HTMLCanvasElement*, float x, float y); + void drawImage(HTMLCanvasElement*, float x, float y, ExceptionCode&); void drawImage(HTMLCanvasElement*, float x, float y, float width, float height, ExceptionCode&); + void drawImage(HTMLCanvasElement*, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh, ExceptionCode&); void drawImage(HTMLCanvasElement*, const FloatRect& srcRect, const FloatRect& dstRect, ExceptionCode&); #if ENABLE(VIDEO) - void drawImage(HTMLVideoElement*, float x, float y); + void drawImage(HTMLVideoElement*, float x, float y, ExceptionCode&); void drawImage(HTMLVideoElement*, float x, float y, float width, float height, ExceptionCode&); + void drawImage(HTMLVideoElement*, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh, ExceptionCode&); void drawImage(HTMLVideoElement*, const FloatRect& srcRect, const FloatRect& dstRect, ExceptionCode&); #endif @@ -263,6 +266,10 @@ namespace WebCore { void checkOrigin(const String&); Vector<State, 1> m_stateStack; + bool m_usesCSSCompatibilityParseMode; +#if ENABLE(DASHBOARD_SUPPORT) + bool m_usesDashboardCompatibilityMode; +#endif }; } // namespace WebCore diff --git a/WebCore/html/canvas/CanvasRenderingContext2D.idl b/WebCore/html/canvas/CanvasRenderingContext2D.idl index f93a752..a3c83ca 100644 --- a/WebCore/html/canvas/CanvasRenderingContext2D.idl +++ b/WebCore/html/canvas/CanvasRenderingContext2D.idl @@ -20,7 +20,7 @@ * 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. + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ module html { @@ -82,8 +82,7 @@ module html { attribute DOMString font; attribute DOMString textAlign; attribute DOMString textBaseline; - [Custom] void fillText(/* 4 */); - [Custom] void strokeText(/* 4 */); + TextMetrics measureText(in DOMString text); // other @@ -98,6 +97,61 @@ module html { void clearShadow(); +#if defined(V8_BINDING) && V8_BINDING + void fillText(in DOMString text, in float x, in float y, in [Optional] float maxWidth); + void strokeText(in DOMString text, in float x, in float y, in [Optional] float maxWidth); + + void setStrokeColor(in DOMString color, in [Optional] float alpha); + void setStrokeColor(in float grayLevel, in [Optional] float alpha); + void setStrokeColor(in float r, in float g, in float b, in float a); + void setStrokeColor(in float c, in float m, in float y, in float k, in float a); + + void setFillColor(in DOMString color, in [Optional] float alpha); + void setFillColor(in float grayLevel, in [Optional] float alpha); + void setFillColor(in float r, in float g, in float b, in float a); + void setFillColor(in float c, in float m, in float y, in float k, in float a); + + void strokeRect(in float x, in float y, in float width, in float height, in [Optional] float lineWidth); + + void drawImage(in HTMLImageElement image, in float x, in float y) + raises (DOMException); + void drawImage(in HTMLImageElement image, in float x, in float y, in float width, in float height) + raises (DOMException); + void drawImage(in HTMLImageElement image, in float sx, in float sy, in float sw, in float sh, in float dx, in float dy, in float dw, in float dh) + raises (DOMException); + void drawImage(in HTMLCanvasElement canvas, in float x, in float y) + raises (DOMException); + void drawImage(in HTMLCanvasElement canvas, in float x, in float y, in float width, in float height) + raises (DOMException); + void drawImage(in HTMLCanvasElement canvas, in float sx, in float sy, in float sw, in float sh, in float dx, in float dy, in float dw, in float dh) + raises (DOMException); +#if defined(ENABLE_VIDEO) && ENABLE_VIDEO + void drawImage(in HTMLVideoElement video, in float x, in float y) + raises (DOMException); + void drawImage(in HTMLVideoElement video, in float x, in float y, in float width, in float height) + raises (DOMException); + void drawImage(in HTMLVideoElement video, in float sx, in float sy, in float sw, in float sh, in float dx, in float dy, in float dw, in float dh) + raises (DOMException); +#endif + void drawImageFromRect(in HTMLImageElement image, + in float sx, in float sy, in float sw, in float sh, + in float dx, in float dy, in float dw, in float dh, in DOMString compositeOperation); + + void setShadow(in float width, in float height, in float blur, in [Optional] DOMString color, in [Optional] float alpha); + void setShadow(in float width, in float height, in float blur, in float grayLevel, in [Optional] float alpha); + void setShadow(in float width, in float height, in float blur, in float r, in float g, in float b, in float a); + void setShadow(in float width, in float height, in float blur, in float c, in float m, in float y, in float k, in float a); + + CanvasPattern createPattern(in HTMLCanvasElement canvas, in [ConvertNullToNullString] DOMString repetitionType) + raises (DOMException); + CanvasPattern createPattern(in HTMLImageElement image, in [ConvertNullToNullString] DOMString repetitionType) + raises (DOMException); + void putImageData(in ImageData imagedata, in float dx, in float dy, in [Optional] float dirtyX, in float dirtyY, in float dirtyWidth, in float dirtyHeight) + raises(DOMException); +#else + // FIXME: Remove 'else' once JSC supports overloads too. + [Custom] void fillText(/* 4 */); + [Custom] void strokeText(/* 4 */); [Custom] void setStrokeColor(/* 1 */); [Custom] void setFillColor(/* 1 */); [Custom] void strokeRect(/* 4 */); @@ -105,16 +159,17 @@ module html { [Custom] void drawImageFromRect(/* 10 */); [Custom] void setShadow(/* 3 */); [Custom] void createPattern(/* 2 */); - + [Custom] void putImageData(/* in ImageData imagedata, in float dx, in float dy [, in float dirtyX, in float dirtyY, in float dirtyWidth, in float dirtyHeight] */); +#endif // defined(V8_BINDING) + attribute [Custom] custom strokeStyle; attribute [Custom] custom fillStyle; - + // pixel manipulation ImageData createImageData(in float sw, in float sh) raises (DOMException); ImageData getImageData(in float sx, in float sy, in float sw, in float sh) raises(DOMException); - [Custom] void putImageData(/* in ImageData imagedata, in float dx, in float dy [, in float dirtyX, in float dirtyY, in float dirtyWidth, in float dirtyHeight] */); }; } diff --git a/WebCore/html/canvas/CanvasStyle.cpp b/WebCore/html/canvas/CanvasStyle.cpp index 5352473..3515e03 100644 --- a/WebCore/html/canvas/CanvasStyle.cpp +++ b/WebCore/html/canvas/CanvasStyle.cpp @@ -173,22 +173,12 @@ void CanvasStyle::applyFillColor(GraphicsContext* context) return; switch (m_type) { case ColorString: { - Color c = Color(m_color); - if (c.isValid()) { - context->setFillColor(c.rgb(), DeviceColorSpace); - break; - } RGBA32 rgba = 0; // default is transparent black if (CSSParser::parseColor(rgba, m_color)) context->setFillColor(rgba, DeviceColorSpace); break; } case ColorStringWithAlpha: { - Color c = Color(m_color); - if (c.isValid()) { - context->setFillColor(colorWithOverrideAlpha(c.rgb(), m_alpha), DeviceColorSpace); - break; - } RGBA32 color = 0; // default is transparent black if (CSSParser::parseColor(color, m_color)) context->setFillColor(colorWithOverrideAlpha(color, m_alpha), DeviceColorSpace); diff --git a/WebCore/html/canvas/WebGLArray.cpp b/WebCore/html/canvas/WebGLArray.cpp index c5a712d..038aea4 100644 --- a/WebCore/html/canvas/WebGLArray.cpp +++ b/WebCore/html/canvas/WebGLArray.cpp @@ -46,13 +46,33 @@ WebGLArray::~WebGLArray() void WebGLArray::setImpl(WebGLArray* array, unsigned byteOffset, ExceptionCode& ec) { - if (byteOffset + array->byteLength() > byteLength()) { + if (byteOffset > byteLength() || + byteOffset + array->byteLength() > byteLength() || + byteOffset + array->byteLength() < byteOffset) { + // Out of range offset or overflow ec = INDEX_SIZE_ERR; return; } char* base = static_cast<char*>(baseAddress()); - memcpy(base + byteOffset, array->baseAddress(), array->byteLength()); + memmove(base + byteOffset, array->baseAddress(), array->byteLength()); +} + +void WebGLArray::calculateOffsetAndLength(int start, int end, unsigned arraySize, + unsigned* offset, unsigned* length) +{ + if (start < 0) + start += arraySize; + if (start < 0) + start = 0; + if (end < 0) + end += arraySize; + if (end < 0) + end = 0; + if (end < start) + end = start; + *offset = static_cast<unsigned>(start); + *length = static_cast<unsigned>(end - start); } } diff --git a/WebCore/html/canvas/WebGLArray.h b/WebCore/html/canvas/WebGLArray.h index 11065cc..7d67474 100644 --- a/WebCore/html/canvas/WebGLArray.h +++ b/WebCore/html/canvas/WebGLArray.h @@ -26,7 +26,9 @@ #ifndef WebGLArray_h #define WebGLArray_h +#include <algorithm> #include "ExceptionCode.h" +#include <limits.h> #include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> #include <wtf/RefPtr.h> @@ -58,7 +60,7 @@ class WebGLArray : public RefCounted<WebGLArray> { virtual unsigned length() const = 0; virtual unsigned byteLength() const = 0; - virtual PassRefPtr<WebGLArray> slice(unsigned offset, unsigned length) = 0; + virtual PassRefPtr<WebGLArray> slice(int start, int end) = 0; virtual ~WebGLArray(); @@ -67,6 +69,48 @@ class WebGLArray : public RefCounted<WebGLArray> { void setImpl(WebGLArray* array, unsigned byteOffset, ExceptionCode& ec); + void calculateOffsetAndLength(int start, int end, unsigned arraySize, + unsigned* offset, unsigned* length); + + // Helper to verify that a given sub-range of an ArrayBuffer is + // within range. + template <typename T> + static bool verifySubRange(PassRefPtr<WebGLArrayBuffer> buffer, + unsigned byteOffset, + unsigned numElements) + { + if (!buffer) + return false; + if (sizeof(T) > 1 && byteOffset % sizeof(T)) + return false; + if (byteOffset > buffer->byteLength()) + return false; + unsigned remainingElements = (buffer->byteLength() - byteOffset) / sizeof(T); + if (numElements > remainingElements) + return false; + return true; + } + + // Input offset is in number of elements from this array's view; + // output offset is in number of bytes from the underlying buffer's view. + template <typename T> + static void clampOffsetAndNumElements(PassRefPtr<WebGLArrayBuffer> buffer, + unsigned arrayByteOffset, + unsigned *offset, + unsigned *numElements) + { + unsigned maxOffset = (UINT_MAX - arrayByteOffset) / sizeof(T); + if (*offset > maxOffset) { + *offset = buffer->byteLength(); + *numElements = 0; + return; + } + *offset = arrayByteOffset + *offset * sizeof(T); + *offset = std::min(buffer->byteLength(), *offset); + unsigned remainingElements = (buffer->byteLength() - *offset) / sizeof(T); + *numElements = std::min(remainingElements, *numElements); + } + // This is the address of the WebGLArrayBuffer's storage, plus the byte offset. void* m_baseAddress; diff --git a/WebCore/html/canvas/WebGLArray.idl b/WebCore/html/canvas/WebGLArray.idl index 02e1f51..2cc00d0 100644 --- a/WebCore/html/canvas/WebGLArray.idl +++ b/WebCore/html/canvas/WebGLArray.idl @@ -30,6 +30,6 @@ module html { readonly attribute unsigned long byteLength; readonly attribute unsigned long length; - WebGLArray slice(in unsigned long offset, in unsigned long length); + [Custom] WebGLArray slice(in long start, in long end); }; } diff --git a/WebCore/html/canvas/WebGLArrayBuffer.cpp b/WebCore/html/canvas/WebGLArrayBuffer.cpp index c565691..7d3cd33 100644 --- a/WebCore/html/canvas/WebGLArrayBuffer.cpp +++ b/WebCore/html/canvas/WebGLArrayBuffer.cpp @@ -33,21 +33,27 @@ namespace WebCore { -PassRefPtr<WebGLArrayBuffer> WebGLArrayBuffer::create(unsigned sizeInBytes) +PassRefPtr<WebGLArrayBuffer> WebGLArrayBuffer::create(unsigned numElements, unsigned elementByteSize) { - return adoptRef(new WebGLArrayBuffer(sizeInBytes)); + void* data = tryAllocate(numElements, elementByteSize); + if (!data) + return 0; + return adoptRef(new WebGLArrayBuffer(data, numElements * elementByteSize)); } PassRefPtr<WebGLArrayBuffer> WebGLArrayBuffer::create(WebGLArrayBuffer* other) { - RefPtr<WebGLArrayBuffer> buffer = adoptRef(new WebGLArrayBuffer(other->byteLength())); + void* data = tryAllocate(other->byteLength(), 1); + if (!data) + return 0; + RefPtr<WebGLArrayBuffer> buffer = adoptRef(new WebGLArrayBuffer(data, other->byteLength())); memcpy(buffer->data(), other->data(), other->byteLength()); return buffer.release(); } -WebGLArrayBuffer::WebGLArrayBuffer(unsigned sizeInBytes) { - m_sizeInBytes = sizeInBytes; - m_data = WTF::fastZeroedMalloc(sizeInBytes); +WebGLArrayBuffer::WebGLArrayBuffer(void* data, unsigned sizeInBytes) + : m_sizeInBytes(sizeInBytes) + , m_data(data) { } void* WebGLArrayBuffer::data() { @@ -66,6 +72,19 @@ WebGLArrayBuffer::~WebGLArrayBuffer() { WTF::fastFree(m_data); } +void* WebGLArrayBuffer::tryAllocate(unsigned numElements, unsigned elementByteSize) { + void* result; + // Do not allow 32-bit overflow of the total size + if (numElements) { + unsigned totalSize = numElements * elementByteSize; + if (totalSize / numElements != elementByteSize) + return 0; + } + if (WTF::tryFastCalloc(numElements, elementByteSize).getValue(result)) + return result; + return 0; +} + } #endif // ENABLE(3D_CANVAS) diff --git a/WebCore/html/canvas/WebGLArrayBuffer.h b/WebCore/html/canvas/WebGLArrayBuffer.h index a076e16..59e0ddd 100644 --- a/WebCore/html/canvas/WebGLArrayBuffer.h +++ b/WebCore/html/canvas/WebGLArrayBuffer.h @@ -33,7 +33,7 @@ namespace WebCore { class WebGLArrayBuffer : public RefCounted<WebGLArrayBuffer> { public: - static PassRefPtr<WebGLArrayBuffer> create(unsigned sizeInBytes); + static PassRefPtr<WebGLArrayBuffer> create(unsigned numElements, unsigned elementByteSize); static PassRefPtr<WebGLArrayBuffer> create(WebGLArrayBuffer*); void* data(); @@ -43,7 +43,9 @@ class WebGLArrayBuffer : public RefCounted<WebGLArrayBuffer> { ~WebGLArrayBuffer(); private: - WebGLArrayBuffer(unsigned sizeInBytes); + WebGLArrayBuffer(void* data, unsigned sizeInBytes); + WebGLArrayBuffer(unsigned numElements, unsigned elementByteSize); + static void* tryAllocate(unsigned numElements, unsigned elementByteSize); unsigned m_sizeInBytes; void* m_data; }; diff --git a/WebCore/html/canvas/WebGLByteArray.cpp b/WebCore/html/canvas/WebGLByteArray.cpp index 1c2849b..603e4d1 100644 --- a/WebCore/html/canvas/WebGLByteArray.cpp +++ b/WebCore/html/canvas/WebGLByteArray.cpp @@ -35,7 +35,7 @@ namespace WebCore { PassRefPtr<WebGLByteArray> WebGLByteArray::create(unsigned length) { - RefPtr<WebGLArrayBuffer> buffer = WebGLArrayBuffer::create(length * sizeof(signed char)); + RefPtr<WebGLArrayBuffer> buffer = WebGLArrayBuffer::create(length, sizeof(signed char)); return create(buffer, 0, length); } @@ -47,19 +47,16 @@ PassRefPtr<WebGLByteArray> WebGLByteArray::create(signed char* array, unsigned l return a; } -PassRefPtr<WebGLByteArray> WebGLByteArray::create(PassRefPtr<WebGLArrayBuffer> buffer, int byteOffset, unsigned length) +PassRefPtr<WebGLByteArray> WebGLByteArray::create(PassRefPtr<WebGLArrayBuffer> buffer, unsigned byteOffset, unsigned length) { - if (buffer) { - // Check to make sure we are talking about a valid region of - // the given WebGLArrayBuffer's storage. - if ((byteOffset + (length * sizeof(signed char))) > buffer->byteLength()) - return NULL; - } + RefPtr<WebGLArrayBuffer> buf(buffer); + if (!verifySubRange<signed char>(buf, byteOffset, length)) + return 0; - return adoptRef(new WebGLByteArray(buffer, byteOffset, length)); + return adoptRef(new WebGLByteArray(buf, byteOffset, length)); } -WebGLByteArray::WebGLByteArray(PassRefPtr<WebGLArrayBuffer> buffer, int offset, unsigned length) +WebGLByteArray::WebGLByteArray(PassRefPtr<WebGLArrayBuffer> buffer, unsigned offset, unsigned length) : WebGLArray(buffer, offset) , m_size(length) { @@ -73,15 +70,12 @@ unsigned WebGLByteArray::byteLength() const { return m_size * sizeof(signed char); } -PassRefPtr<WebGLArray> WebGLByteArray::slice(unsigned offset, unsigned length) { - // Check to make sure the specified region is within the bounds of - // the WebGLArrayBuffer. - unsigned startByte = m_byteOffset + offset * sizeof(signed char); - unsigned limitByte = startByte + length * sizeof(signed char); - unsigned bufferLength = buffer()->byteLength(); - if (startByte >= bufferLength || limitByte > bufferLength) - return 0; - return create(buffer(), startByte, length); +PassRefPtr<WebGLArray> WebGLByteArray::slice(int start, int end) +{ + unsigned offset, length; + calculateOffsetAndLength(start, end, m_size, &offset, &length); + clampOffsetAndNumElements<signed char>(buffer().get(), m_byteOffset, &offset, &length); + return create(buffer(), offset, length); } void WebGLByteArray::set(WebGLByteArray* array, unsigned offset, ExceptionCode& ec) { diff --git a/WebCore/html/canvas/WebGLByteArray.h b/WebCore/html/canvas/WebGLByteArray.h index c517c03..60d301c 100644 --- a/WebCore/html/canvas/WebGLByteArray.h +++ b/WebCore/html/canvas/WebGLByteArray.h @@ -43,13 +43,13 @@ class WebGLByteArray : public WebGLArray { static PassRefPtr<WebGLByteArray> create(unsigned length); static PassRefPtr<WebGLByteArray> create(signed char* array, unsigned length); - static PassRefPtr<WebGLByteArray> create(PassRefPtr<WebGLArrayBuffer> buffer, int byteOffset, unsigned length); + static PassRefPtr<WebGLByteArray> create(PassRefPtr<WebGLArrayBuffer> buffer, unsigned byteOffset, unsigned length); char* data() { return static_cast<char*>(baseAddress()); } virtual unsigned length() const; virtual unsigned byteLength() const; - virtual PassRefPtr<WebGLArray> slice(unsigned offset, unsigned length); + virtual PassRefPtr<WebGLArray> slice(int start, int end); void set(unsigned index, double value) { @@ -90,7 +90,7 @@ class WebGLByteArray : public WebGLArray { private: WebGLByteArray(PassRefPtr<WebGLArrayBuffer> buffer, - int offset, + unsigned offset, unsigned length); unsigned m_size; }; diff --git a/WebCore/html/canvas/WebGLFloatArray.cpp b/WebCore/html/canvas/WebGLFloatArray.cpp index 6192898..ca93c4c 100644 --- a/WebCore/html/canvas/WebGLFloatArray.cpp +++ b/WebCore/html/canvas/WebGLFloatArray.cpp @@ -34,7 +34,7 @@ namespace WebCore { PassRefPtr<WebGLFloatArray> WebGLFloatArray::create(unsigned length) { - RefPtr<WebGLArrayBuffer> buffer = WebGLArrayBuffer::create(length * sizeof(float)); + RefPtr<WebGLArrayBuffer> buffer = WebGLArrayBuffer::create(length, sizeof(float)); return create(buffer, 0, length); } @@ -46,22 +46,16 @@ PassRefPtr<WebGLFloatArray> WebGLFloatArray::create(float* array, unsigned lengt return a; } -PassRefPtr<WebGLFloatArray> WebGLFloatArray::create(PassRefPtr<WebGLArrayBuffer> buffer, int byteOffset, unsigned length) +PassRefPtr<WebGLFloatArray> WebGLFloatArray::create(PassRefPtr<WebGLArrayBuffer> buffer, unsigned byteOffset, unsigned length) { - // Make sure the offset results in valid alignment. - if ((byteOffset % sizeof(float)) != 0) - return NULL; + RefPtr<WebGLArrayBuffer> buf(buffer); + if (!verifySubRange<float>(buf, byteOffset, length)) + return 0; - if (buffer) { - // Check to make sure we are talking about a valid region of - // the given WebGLArrayBuffer's storage. - if ((byteOffset + (length * sizeof(float))) > buffer->byteLength()) - return NULL; - } - return adoptRef(new WebGLFloatArray(buffer, byteOffset, length)); + return adoptRef(new WebGLFloatArray(buf, byteOffset, length)); } -WebGLFloatArray::WebGLFloatArray(PassRefPtr<WebGLArrayBuffer> buffer, int byteOffset, unsigned length) +WebGLFloatArray::WebGLFloatArray(PassRefPtr<WebGLArrayBuffer> buffer, unsigned byteOffset, unsigned length) : WebGLArray(buffer, byteOffset) , m_size(length) { @@ -75,15 +69,12 @@ unsigned WebGLFloatArray::byteLength() const { return m_size * sizeof(float); } -PassRefPtr<WebGLArray> WebGLFloatArray::slice(unsigned offset, unsigned length) { - // Check to make sure the specified region is within the bounds of - // the WebGLArrayBuffer. - unsigned startByte = m_byteOffset + offset * sizeof(float); - unsigned limitByte = startByte + length * sizeof(float); - unsigned bufferLength = buffer()->byteLength(); - if (startByte >= bufferLength || limitByte > bufferLength) - return 0; - return create(buffer(), startByte, length); +PassRefPtr<WebGLArray> WebGLFloatArray::slice(int start, int end) +{ + unsigned offset, length; + calculateOffsetAndLength(start, end, m_size, &offset, &length); + clampOffsetAndNumElements<float>(buffer(), m_byteOffset, &offset, &length); + return create(buffer(), offset, length); } void WebGLFloatArray::set(WebGLFloatArray* array, unsigned offset, ExceptionCode& ec) { diff --git a/WebCore/html/canvas/WebGLFloatArray.h b/WebCore/html/canvas/WebGLFloatArray.h index 4607962..5b4e6c9 100644 --- a/WebCore/html/canvas/WebGLFloatArray.h +++ b/WebCore/html/canvas/WebGLFloatArray.h @@ -40,13 +40,13 @@ class WebGLFloatArray : public WebGLArray { static PassRefPtr<WebGLFloatArray> create(unsigned length); static PassRefPtr<WebGLFloatArray> create(float* array, unsigned length); - static PassRefPtr<WebGLFloatArray> create(PassRefPtr<WebGLArrayBuffer> buffer, int byteOffset, unsigned length); + static PassRefPtr<WebGLFloatArray> create(PassRefPtr<WebGLArrayBuffer> buffer, unsigned byteOffset, unsigned length); float* data() { return static_cast<float*>(baseAddress()); } virtual unsigned length() const; virtual unsigned byteLength() const; - virtual PassRefPtr<WebGLArray> slice(unsigned offset, unsigned length); + virtual PassRefPtr<WebGLArray> slice(int start, int end); void set(unsigned index, double value) { @@ -86,7 +86,7 @@ class WebGLFloatArray : public WebGLArray { void set(WebGLFloatArray* array, unsigned offset, ExceptionCode& ec); private: - WebGLFloatArray(PassRefPtr<WebGLArrayBuffer> buffer, int byteOffset, unsigned length); + WebGLFloatArray(PassRefPtr<WebGLArrayBuffer> buffer, unsigned byteOffset, unsigned length); unsigned m_size; }; diff --git a/WebCore/html/canvas/WebGLFramebuffer.cpp b/WebCore/html/canvas/WebGLFramebuffer.cpp index 7ade990..614437b 100644 --- a/WebCore/html/canvas/WebGLFramebuffer.cpp +++ b/WebCore/html/canvas/WebGLFramebuffer.cpp @@ -39,10 +39,28 @@ PassRefPtr<WebGLFramebuffer> WebGLFramebuffer::create(WebGLRenderingContext* ctx WebGLFramebuffer::WebGLFramebuffer(WebGLRenderingContext* ctx) : CanvasObject(ctx) + , m_isDepthAttached(false) + , m_isStencilAttached(false) + , m_isDepthStencilAttached(false) { setObject(context()->graphicsContext3D()->createFramebuffer()); } +void WebGLFramebuffer::setIsAttached(unsigned long attachment, bool isAttached) +{ + switch (attachment) { + case GraphicsContext3D::DEPTH_ATTACHMENT: + m_isDepthAttached = isAttached; + break; + case GraphicsContext3D::STENCIL_ATTACHMENT: + m_isStencilAttached = isAttached; + break; + case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT: + m_isDepthStencilAttached = isAttached; + break; + } +} + void WebGLFramebuffer::_deleteObject(Platform3DObject object) { context()->graphicsContext3D()->deleteFramebuffer(object); diff --git a/WebCore/html/canvas/WebGLFramebuffer.h b/WebCore/html/canvas/WebGLFramebuffer.h index 10b6772..b9402a0 100644 --- a/WebCore/html/canvas/WebGLFramebuffer.h +++ b/WebCore/html/canvas/WebGLFramebuffer.h @@ -39,10 +39,21 @@ namespace WebCore { static PassRefPtr<WebGLFramebuffer> create(WebGLRenderingContext*); + void setIsAttached(unsigned long attachment, bool isAttached); + + bool isDepthAttached() const { return m_isDepthAttached; } + bool isStencilAttached() const { return m_isStencilAttached; } + bool isDepthStencilAttached() const { return m_isDepthStencilAttached; } + protected: WebGLFramebuffer(WebGLRenderingContext*); virtual void _deleteObject(Platform3DObject); + + private: + bool m_isDepthAttached; + bool m_isStencilAttached; + bool m_isDepthStencilAttached; }; } // namespace WebCore diff --git a/WebCore/html/canvas/WebGLIntArray.cpp b/WebCore/html/canvas/WebGLIntArray.cpp index 4617010..21b7a88 100644 --- a/WebCore/html/canvas/WebGLIntArray.cpp +++ b/WebCore/html/canvas/WebGLIntArray.cpp @@ -35,7 +35,7 @@ namespace WebCore { PassRefPtr<WebGLIntArray> WebGLIntArray::create(unsigned length) { - RefPtr<WebGLArrayBuffer> buffer = WebGLArrayBuffer::create(length * sizeof(int)); + RefPtr<WebGLArrayBuffer> buffer = WebGLArrayBuffer::create(length, sizeof(int)); return create(buffer, 0, length); } @@ -48,24 +48,17 @@ PassRefPtr<WebGLIntArray> WebGLIntArray::create(int* array, unsigned length) } PassRefPtr<WebGLIntArray> WebGLIntArray::create(PassRefPtr<WebGLArrayBuffer> buffer, - int byteOffset, + unsigned byteOffset, unsigned length) { - // Make sure the offset results in valid alignment. - if ((byteOffset % sizeof(int)) != 0) - return NULL; - - if (buffer) { - // Check to make sure we are talking about a valid region of - // the given WebGLArrayBuffer's storage. - if ((byteOffset + (length * sizeof(int))) > buffer->byteLength()) - return NULL; - } + RefPtr<WebGLArrayBuffer> buf(buffer); + if (!verifySubRange<int>(buf, byteOffset, length)) + return 0; - return adoptRef(new WebGLIntArray(buffer, byteOffset, length)); + return adoptRef(new WebGLIntArray(buf, byteOffset, length)); } -WebGLIntArray::WebGLIntArray(PassRefPtr<WebGLArrayBuffer> buffer, int byteOffset, unsigned length) +WebGLIntArray::WebGLIntArray(PassRefPtr<WebGLArrayBuffer> buffer, unsigned byteOffset, unsigned length) : WebGLArray(buffer, byteOffset) , m_size(length) { @@ -79,15 +72,12 @@ unsigned WebGLIntArray::byteLength() const { return m_size * sizeof(int); } -PassRefPtr<WebGLArray> WebGLIntArray::slice(unsigned offset, unsigned length) { - // Check to make sure the specified region is within the bounds of - // the WebGLArrayBuffer. - unsigned startByte = m_byteOffset + offset * sizeof(int); - unsigned limitByte = startByte + length * sizeof(int); - unsigned bufferLength = buffer()->byteLength(); - if (startByte >= bufferLength || limitByte > bufferLength) - return 0; - return create(buffer(), startByte, length); +PassRefPtr<WebGLArray> WebGLIntArray::slice(int start, int end) +{ + unsigned offset, length; + calculateOffsetAndLength(start, end, m_size, &offset, &length); + clampOffsetAndNumElements<int>(buffer(), m_byteOffset, &offset, &length); + return create(buffer(), offset, length); } void WebGLIntArray::set(WebGLIntArray* array, unsigned offset, ExceptionCode& ec) { diff --git a/WebCore/html/canvas/WebGLIntArray.h b/WebCore/html/canvas/WebGLIntArray.h index 25108ac..5929e75 100644 --- a/WebCore/html/canvas/WebGLIntArray.h +++ b/WebCore/html/canvas/WebGLIntArray.h @@ -41,13 +41,13 @@ class WebGLIntArray : public WebGLArray { static PassRefPtr<WebGLIntArray> create(unsigned length); static PassRefPtr<WebGLIntArray> create(int* array, unsigned length); - static PassRefPtr<WebGLIntArray> create(PassRefPtr<WebGLArrayBuffer> buffer, int byteOffset, unsigned length); + static PassRefPtr<WebGLIntArray> create(PassRefPtr<WebGLArrayBuffer> buffer, unsigned byteOffset, unsigned length); int* data() { return static_cast<int*>(baseAddress()); } virtual unsigned length() const; virtual unsigned byteLength() const; - virtual PassRefPtr<WebGLArray> slice(unsigned offset, unsigned length); + virtual PassRefPtr<WebGLArray> slice(int start, int end); void set(unsigned index, double value) { @@ -87,7 +87,7 @@ class WebGLIntArray : public WebGLArray { private: WebGLIntArray(PassRefPtr<WebGLArrayBuffer> buffer, - int byteOffset, + unsigned byteOffset, unsigned length); unsigned m_size; }; diff --git a/WebCore/html/canvas/WebGLProgram.cpp b/WebCore/html/canvas/WebGLProgram.cpp index c2606c1..750df45 100644 --- a/WebCore/html/canvas/WebGLProgram.cpp +++ b/WebCore/html/canvas/WebGLProgram.cpp @@ -48,6 +48,41 @@ void WebGLProgram::_deleteObject(Platform3DObject object) context()->graphicsContext3D()->deleteProgram(object); } +bool WebGLProgram::cacheActiveAttribLocations() +{ + m_activeAttribLocations.clear(); + if (!object()) + return false; + GraphicsContext3D* context3d = context()->graphicsContext3D(); + int linkStatus; + context3d->getProgramiv(this, GraphicsContext3D::LINK_STATUS, &linkStatus); + if (!linkStatus) + return false; + + int numAttribs = 0; + context3d->getProgramiv(this, GraphicsContext3D::ACTIVE_ATTRIBUTES, &numAttribs); + m_activeAttribLocations.resize(static_cast<size_t>(numAttribs)); + for (int i = 0; i < numAttribs; ++i) { + ActiveInfo info; + context3d->getActiveAttrib(this, i, info); + m_activeAttribLocations[i] = context3d->getAttribLocation(this, info.name.charactersWithNullTermination()); + } + + return true; +} + +int WebGLProgram::numActiveAttribLocations() +{ + return static_cast<int>(m_activeAttribLocations.size()); +} + +int WebGLProgram::getActiveAttribLocation(int index) +{ + if (index < 0 || index >= numActiveAttribLocations()) + return -1; + return m_activeAttribLocations[static_cast<size_t>(index)]; +} + } #endif // ENABLE(3D_CANVAS) diff --git a/WebCore/html/canvas/WebGLProgram.h b/WebCore/html/canvas/WebGLProgram.h index 8804d39..56bce15 100644 --- a/WebCore/html/canvas/WebGLProgram.h +++ b/WebCore/html/canvas/WebGLProgram.h @@ -30,6 +30,7 @@ #include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> +#include <wtf/Vector.h> namespace WebCore { @@ -38,11 +39,20 @@ namespace WebCore { virtual ~WebGLProgram() { deleteObject(); } static PassRefPtr<WebGLProgram> create(WebGLRenderingContext*); + + // cacheActiveAttribLocation() is only called once after linkProgram() + // succeeds. + bool cacheActiveAttribLocations(); + int numActiveAttribLocations(); + int getActiveAttribLocation(int index); protected: WebGLProgram(WebGLRenderingContext*); virtual void _deleteObject(Platform3DObject); + + private: + Vector<int> m_activeAttribLocations; }; } // namespace WebCore diff --git a/WebCore/html/canvas/WebGLRenderbuffer.cpp b/WebCore/html/canvas/WebGLRenderbuffer.cpp index 286ad2e..cad4298 100644 --- a/WebCore/html/canvas/WebGLRenderbuffer.cpp +++ b/WebCore/html/canvas/WebGLRenderbuffer.cpp @@ -44,12 +44,14 @@ PassRefPtr<WebGLRenderbuffer> WebGLRenderbuffer::create(WebGLRenderingContext* c WebGLRenderbuffer::WebGLRenderbuffer(WebGLRenderingContext* ctx) : CanvasObject(ctx) + , m_internalformat(GraphicsContext3D::RGBA4) { setObject(context()->graphicsContext3D()->createRenderbuffer()); } WebGLRenderbuffer::WebGLRenderbuffer(WebGLRenderingContext* ctx, Platform3DObject obj) : CanvasObject(ctx) + , m_internalformat(GraphicsContext3D::RGBA4) { setObject(obj, false); } diff --git a/WebCore/html/canvas/WebGLRenderbuffer.h b/WebCore/html/canvas/WebGLRenderbuffer.h index 790fdcd..1bdf1b7 100644 --- a/WebCore/html/canvas/WebGLRenderbuffer.h +++ b/WebCore/html/canvas/WebGLRenderbuffer.h @@ -43,11 +43,17 @@ namespace WebCore { // FIXME: should consider canonicalizing these objects static PassRefPtr<WebGLRenderbuffer> create(WebGLRenderingContext*, Platform3DObject renderbuffer); + void setInternalformat(unsigned long internalformat) { m_internalformat = internalformat; } + unsigned long getInternalformat() const { return m_internalformat; } + protected: WebGLRenderbuffer(WebGLRenderingContext*); WebGLRenderbuffer(WebGLRenderingContext*, Platform3DObject); virtual void _deleteObject(Platform3DObject); + + private: + unsigned long m_internalformat; }; } // namespace WebCore diff --git a/WebCore/html/canvas/WebGLRenderingContext.cpp b/WebCore/html/canvas/WebGLRenderingContext.cpp index 6cb3348..d9af757 100644 --- a/WebCore/html/canvas/WebGLRenderingContext.cpp +++ b/WebCore/html/canvas/WebGLRenderingContext.cpp @@ -30,6 +30,7 @@ #include "WebGLRenderingContext.h" #include "CanvasPixelArray.h" +#include "FrameView.h" #include "HTMLCanvasElement.h" #include "HTMLImageElement.h" #include "ImageBuffer.h" @@ -38,6 +39,7 @@ #include "RenderBox.h" #include "RenderLayer.h" #include "WebGLActiveInfo.h" +#include "WebGLUnsignedShortArray.h" #include "WebGLBuffer.h" #include "WebGLContextAttributes.h" #include "WebGLFramebuffer.h" @@ -46,12 +48,6 @@ #include "WebGLTexture.h" #include "WebGLShader.h" #include "WebGLUniformLocation.h" -#include "HTMLCanvasElement.h" -#include "HTMLImageElement.h" -#include "ImageBuffer.h" -#include "NotImplemented.h" -#include "RenderBox.h" -#include "RenderLayer.h" #include <wtf/ByteArray.h> @@ -78,7 +74,9 @@ private: PassOwnPtr<WebGLRenderingContext> WebGLRenderingContext::create(HTMLCanvasElement* canvas, WebGLContextAttributes* attrs) { - OwnPtr<GraphicsContext3D> context(GraphicsContext3D::create(attrs->attributes())); + HostWindow* hostWindow = canvas->document()->view()->root()->hostWindow(); + OwnPtr<GraphicsContext3D> context(GraphicsContext3D::create(attrs->attributes(), hostWindow)); + if (!context) return 0; @@ -91,12 +89,23 @@ WebGLRenderingContext::WebGLRenderingContext(HTMLCanvasElement* passedCanvas, Pa , m_needsUpdate(true) , m_markedCanvasDirty(false) , m_activeTextureUnit(0) + , m_packAlignment(4) + , m_unpackAlignment(4) { ASSERT(m_context); int numVertexAttribs = 0; m_context->getIntegerv(GraphicsContext3D::MAX_VERTEX_ATTRIBS, &numVertexAttribs); m_maxVertexAttribs = numVertexAttribs; + int implementationColorReadFormat = GraphicsContext3D::RGBA; + m_context->getIntegerv(GraphicsContext3D::IMPLEMENTATION_COLOR_READ_FORMAT, &implementationColorReadFormat); + m_implementationColorReadFormat = implementationColorReadFormat; + int implementationColorReadType = GraphicsContext3D::UNSIGNED_BYTE; + m_context->getIntegerv(GraphicsContext3D::IMPLEMENTATION_COLOR_READ_TYPE, &implementationColorReadType); + // FIXME: remove the getError() when IMPLEMENTATION_COLOR_READ_FORMAT/TYPE are supported. + m_context->getError(); + m_implementationColorReadType = implementationColorReadType; m_context->reshape(canvas()->width(), canvas()->height()); + m_context->viewport(0, 0, canvas()->width(), canvas()->height()); } WebGLRenderingContext::~WebGLRenderingContext() @@ -107,9 +116,10 @@ WebGLRenderingContext::~WebGLRenderingContext() void WebGLRenderingContext::markContextChanged() { #if USE(ACCELERATED_COMPOSITING) - if (canvas()->renderBox() && canvas()->renderBox()->hasLayer()) { - canvas()->renderBox()->layer()->rendererContentChanged(); - } else { + RenderBox* renderBox = canvas()->renderBox(); + if (renderBox && renderBox->hasLayer() && renderBox->layer()->hasAcceleratedCompositing()) + renderBox->layer()->rendererContentChanged(); + else { #endif if (!m_markedCanvasDirty) { // Make sure the canvas's image buffer is allocated. @@ -141,8 +151,9 @@ void WebGLRenderingContext::reshape(int width, int height) { if (m_needsUpdate) { #if USE(ACCELERATED_COMPOSITING) - if (canvas()->renderBox() && canvas()->renderBox()->hasLayer()) - canvas()->renderBox()->layer()->rendererContentChanged(); + RenderBox* renderBox = canvas()->renderBox(); + if (renderBox && renderBox->hasLayer()) + renderBox->layer()->rendererContentChanged(); #endif m_needsUpdate = false; } @@ -186,10 +197,8 @@ void WebGLRenderingContext::attachShader(WebGLProgram* program, WebGLShader* sha void WebGLRenderingContext::bindAttribLocation(WebGLProgram* program, unsigned long index, const String& name, ExceptionCode& ec) { UNUSED_PARAM(ec); - if (!program || program->context() != this) { - m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); + if (!validateWebGLObject(program)) return; - } m_context->bindAttribLocation(program, index, name); cleanupAfterGraphicsCall(false); } @@ -412,10 +421,8 @@ void WebGLRenderingContext::colorMask(bool red, bool green, bool blue, bool alph void WebGLRenderingContext::compileShader(WebGLShader* shader, ExceptionCode& ec) { UNUSED_PARAM(ec); - if (!shader || shader->context() != this) { - m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); + if (!validateWebGLObject(shader)) return; - } m_context->compileShader(shader); cleanupAfterGraphicsCall(false); } @@ -555,10 +562,8 @@ void WebGLRenderingContext::depthRange(double zNear, double zFar) void WebGLRenderingContext::detachShader(WebGLProgram* program, WebGLShader* shader, ExceptionCode& ec) { UNUSED_PARAM(ec); - if (!program || program->context() != this || !shader || shader->context() != this) { - m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); + if (!validateWebGLObject(program) || !validateWebGLObject(shader)) return; - } m_context->detachShader(program, shader); cleanupAfterGraphicsCall(false); } @@ -691,12 +696,20 @@ bool WebGLRenderingContext::validateIndexArrayPrecise(unsigned long count, unsig bool WebGLRenderingContext::validateRenderingState(long numElementsRequired) { + if (!m_currentProgram) + return false; + // Look in each enabled vertex attrib and find the smallest buffer size long smallestNumElements = LONG_MAX; - for (unsigned i = 0; i < m_vertexAttribState.size(); ++i) { - const VertexAttribState& state = m_vertexAttribState[i]; - if (state.enabled && state.numElements < smallestNumElements) - smallestNumElements = state.numElements; + int numActiveAttribLocations = m_currentProgram->numActiveAttribLocations(); + int numAttribStates = static_cast<int>(m_vertexAttribState.size()); + for (int i = 0; i < numActiveAttribLocations; ++i) { + int loc = m_currentProgram->getActiveAttribLocation(i); + if (loc >=0 && loc < numAttribStates) { + const VertexAttribState& state = m_vertexAttribState[loc]; + if (state.enabled && state.numElements < smallestNumElements) + smallestNumElements = state.numElements; + } } if (smallestNumElements == LONG_MAX) @@ -705,6 +718,19 @@ bool WebGLRenderingContext::validateRenderingState(long numElementsRequired) return numElementsRequired <= smallestNumElements; } +bool WebGLRenderingContext::validateWebGLObject(CanvasObject* object) +{ + if (!object) { + m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); + return false; + } + if (object->context() != this) { + m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); + return false; + } + return true; +} + void WebGLRenderingContext::drawArrays(unsigned long mode, long first, long count, ExceptionCode& ec) { UNUSED_PARAM(ec); @@ -789,6 +815,45 @@ void WebGLRenderingContext::framebufferRenderbuffer(unsigned long target, unsign m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); return; } + if (buffer->object()) { + bool isConflicted = false; + bool isDepthOrStencil = true; + switch (attachment) { + case GraphicsContext3D::DEPTH_ATTACHMENT: + if (m_framebufferBinding->isDepthStencilAttached() || m_framebufferBinding->isStencilAttached()) + isConflicted = true; + if (buffer->getInternalformat() != GraphicsContext3D::DEPTH_COMPONENT16) + isConflicted = true; + break; + case GraphicsContext3D::STENCIL_ATTACHMENT: + if (m_framebufferBinding->isDepthStencilAttached() || m_framebufferBinding->isDepthAttached()) + isConflicted = true; + if (buffer->getInternalformat() != GraphicsContext3D::STENCIL_INDEX8) + isConflicted = true; + break; + case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT: + if (m_framebufferBinding->isDepthAttached() || m_framebufferBinding->isStencilAttached()) + isConflicted = true; + if (buffer->getInternalformat() != GraphicsContext3D::DEPTH_STENCIL) + isConflicted = true; + break; + default: + isDepthOrStencil = false; + } + if (isConflicted) { + m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); + return; + } + if (isDepthOrStencil) + m_framebufferBinding->setIsAttached(attachment, true); + } else { // Detach + switch (attachment) { + case GraphicsContext3D::DEPTH_ATTACHMENT: + case GraphicsContext3D::STENCIL_ATTACHMENT: + case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT: + m_framebufferBinding->setIsAttached(attachment, false); + } + } m_context->framebufferRenderbuffer(target, attachment, renderbuffertarget, buffer); cleanupAfterGraphicsCall(false); } @@ -827,10 +892,8 @@ PassRefPtr<WebGLActiveInfo> WebGLRenderingContext::getActiveAttrib(WebGLProgram* { UNUSED_PARAM(ec); ActiveInfo info; - if (!program || program->context() != this) { - m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); + if (!validateWebGLObject(program)) return 0; - } if (!m_context->getActiveAttrib(program, index, info)) { return 0; } @@ -841,10 +904,8 @@ PassRefPtr<WebGLActiveInfo> WebGLRenderingContext::getActiveUniform(WebGLProgram { UNUSED_PARAM(ec); ActiveInfo info; - if (!program || program->context() != this) { - m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); + if (!validateWebGLObject(program)) return 0; - } if (!m_context->getActiveUniform(program, index, info)) { return 0; } @@ -896,7 +957,8 @@ WebGLGetInfo WebGLRenderingContext::getFramebufferAttachmentParameter(unsigned l if (target != GraphicsContext3D::FRAMEBUFFER || (attachment != GraphicsContext3D::COLOR_ATTACHMENT0 && attachment != GraphicsContext3D::DEPTH_ATTACHMENT - && attachment != GraphicsContext3D::STENCIL_ATTACHMENT) + && attachment != GraphicsContext3D::STENCIL_ATTACHMENT + && attachment != GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT) || (pname != GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE && pname != GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_NAME && pname != GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL @@ -1115,10 +1177,8 @@ WebGLGetInfo WebGLRenderingContext::getParameter(unsigned long pname, ExceptionC WebGLGetInfo WebGLRenderingContext::getProgramParameter(WebGLProgram* program, unsigned long pname, ExceptionCode& ec) { UNUSED_PARAM(ec); - if (!program || program->context() != this) { - m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); + if (!validateWebGLObject(program)) return WebGLGetInfo(); - } WebGLStateRestorer(this, false); int value = 0; @@ -1145,10 +1205,8 @@ WebGLGetInfo WebGLRenderingContext::getProgramParameter(WebGLProgram* program, u String WebGLRenderingContext::getProgramInfoLog(WebGLProgram* program, ExceptionCode& ec) { UNUSED_PARAM(ec); - if (!program || program->context() != this) { - m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); + if (!validateWebGLObject(program)) return ""; - } WebGLStateRestorer(this, false); return m_context->getProgramInfoLog(program); } @@ -1175,8 +1233,11 @@ WebGLGetInfo WebGLRenderingContext::getRenderbufferParameter(unsigned long targe m_context->getRenderbufferParameteriv(target, pname, &value); return WebGLGetInfo(static_cast<long>(value)); case GraphicsContext3D::RENDERBUFFER_INTERNAL_FORMAT: - m_context->getRenderbufferParameteriv(target, pname, &value); - return WebGLGetInfo(static_cast<unsigned long>(value)); + if (!m_renderbufferBinding) { + m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); + return WebGLGetInfo(); + } + return WebGLGetInfo(m_renderbufferBinding->getInternalformat()); default: m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM); return WebGLGetInfo(); @@ -1186,10 +1247,8 @@ WebGLGetInfo WebGLRenderingContext::getRenderbufferParameter(unsigned long targe WebGLGetInfo WebGLRenderingContext::getShaderParameter(WebGLShader* shader, unsigned long pname, ExceptionCode& ec) { UNUSED_PARAM(ec); - if (!shader || shader->context() != this) { - m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); + if (!validateWebGLObject(shader)) return WebGLGetInfo(); - } WebGLStateRestorer(this, false); int value = 0; switch (pname) { @@ -1213,10 +1272,8 @@ WebGLGetInfo WebGLRenderingContext::getShaderParameter(WebGLShader* shader, unsi String WebGLRenderingContext::getShaderInfoLog(WebGLShader* shader, ExceptionCode& ec) { UNUSED_PARAM(ec); - if (!shader || shader->context() != this) { - m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); + if (!validateWebGLObject(shader)) return ""; - } WebGLStateRestorer(this, false); return m_context->getShaderInfoLog(shader); } @@ -1224,10 +1281,8 @@ String WebGLRenderingContext::getShaderInfoLog(WebGLShader* shader, ExceptionCod String WebGLRenderingContext::getShaderSource(WebGLShader* shader, ExceptionCode& ec) { UNUSED_PARAM(ec); - if (!shader || shader->context() != this) { - m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); + if (!validateWebGLObject(shader)) return ""; - } WebGLStateRestorer(this, false); return m_context->getShaderSource(shader); } @@ -1264,7 +1319,9 @@ WebGLGetInfo WebGLRenderingContext::getTexParameter(unsigned long target, unsign WebGLGetInfo WebGLRenderingContext::getUniform(WebGLProgram* program, const WebGLUniformLocation* uniformLocation, ExceptionCode& ec) { UNUSED_PARAM(ec); - if (!program || uniformLocation->program() != program || program->context() != this) { + if (!validateWebGLObject(program)) + return WebGLGetInfo(); + if (uniformLocation->program() != program) { m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); return WebGLGetInfo(); } @@ -1393,12 +1450,13 @@ WebGLGetInfo WebGLRenderingContext::getUniform(WebGLProgram* program, const WebG PassRefPtr<WebGLUniformLocation> WebGLRenderingContext::getUniformLocation(WebGLProgram* program, const String& name, ExceptionCode& ec) { UNUSED_PARAM(ec); - if (!program || program->context() != this) { - m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); + if (!validateWebGLObject(program)) return 0; - } WebGLStateRestorer(this, false); - return WebGLUniformLocation::create(program, m_context->getUniformLocation(program, name)); + long uniformLocation = m_context->getUniformLocation(program, name); + if (uniformLocation == -1) + return 0; + return WebGLUniformLocation::create(program, uniformLocation); } WebGLGetInfo WebGLRenderingContext::getVertexAttrib(unsigned long index, unsigned long pname, ExceptionCode& ec) @@ -1519,18 +1577,26 @@ void WebGLRenderingContext::lineWidth(double width) void WebGLRenderingContext::linkProgram(WebGLProgram* program, ExceptionCode& ec) { UNUSED_PARAM(ec); - if (!program || program->context() != this) { - m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); + if (!validateWebGLObject(program)) return; - } - m_context->linkProgram(program); + program->cacheActiveAttribLocations(); cleanupAfterGraphicsCall(false); } void WebGLRenderingContext::pixelStorei(unsigned long pname, long param) { m_context->pixelStorei(pname, param); + if (param == 1 || param == 2 || param == 4 || param == 8) { + switch (pname) { + case GraphicsContext3D::PACK_ALIGNMENT: + m_packAlignment = static_cast<int>(param); + break; + case GraphicsContext3D::UNPACK_ALIGNMENT: + m_unpackAlignment = static_cast<int>(param); + break; + } + } cleanupAfterGraphicsCall(false); } @@ -1542,7 +1608,76 @@ void WebGLRenderingContext::polygonOffset(double factor, double units) PassRefPtr<WebGLArray> WebGLRenderingContext::readPixels(long x, long y, unsigned long width, unsigned long height, unsigned long format, unsigned long type) { - RefPtr<WebGLArray> array = m_context->readPixels(x, y, width, height, format, type); + // Validate enums. + unsigned long componentsPerPixel = 0; + switch (format) { + case GraphicsContext3D::ALPHA: + componentsPerPixel = 1; + break; + case GraphicsContext3D::RGB: + componentsPerPixel = 3; + break; + case GraphicsContext3D::RGBA: + componentsPerPixel = 4; + break; + default: + m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM); + return 0; + } + unsigned long bytesPerComponent = 0; + switch (type) { + case GraphicsContext3D::UNSIGNED_BYTE: + bytesPerComponent = sizeof(unsigned char); + break; + case GraphicsContext3D::UNSIGNED_SHORT_5_6_5: + case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4: + case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1: + componentsPerPixel = 1; + bytesPerComponent = sizeof(unsigned short); + break; + default: + m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM); + return 0; + } + if (!(format == GraphicsContext3D::RGBA && type == GraphicsContext3D::UNSIGNED_BYTE || format == m_implementationColorReadFormat && type == m_implementationColorReadFormat)) { + m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); + return 0; + } + // Calculate array size, taking into consideration of PACK_ALIGNMENT. + unsigned long bytesPerRow = componentsPerPixel * bytesPerComponent * width; + unsigned long padding = 0; + unsigned long residualBytes = bytesPerRow % m_packAlignment; + if (residualBytes) { + padding = m_packAlignment - residualBytes; + bytesPerRow += padding; + } + // The last row needs no padding. + unsigned long totalBytes = bytesPerRow * height - padding; + unsigned long num = totalBytes / bytesPerComponent; + RefPtr<WebGLArray> array; + if (type == GraphicsContext3D::UNSIGNED_BYTE) + array = WebGLUnsignedByteArray::create(num); + else + array = WebGLUnsignedShortArray::create(num); + void* data = array->baseAddress(); + m_context->readPixels(x, y, width, height, format, type, data); +#if PLATFORM(CG) + // 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. + if ((format == GraphicsContext3D::ALPHA || format == GraphicsContext3D::RGBA) && !m_context->getContextAttributes().alpha) { + if (type == GraphicsContext3D::UNSIGNED_BYTE) { + unsigned char* pixels = reinterpret_cast<unsigned char*>(data); + for (unsigned long iy = 0; iy < height; ++iy) { + for (unsigned long ix = 0; ix < width; ++ix) { + pixels[componentsPerPixel - 1] = 255; + pixels += componentsPerPixel; + } + pixels += padding; + } + } + // FIXME: check whether we need to do the same with UNSIGNED_SHORT. + } +#endif cleanupAfterGraphicsCall(false); return array; } @@ -1555,8 +1690,21 @@ void WebGLRenderingContext::releaseShaderCompiler() void WebGLRenderingContext::renderbufferStorage(unsigned long target, unsigned long internalformat, unsigned long width, unsigned long height) { - m_context->renderbufferStorage(target, internalformat, width, height); - cleanupAfterGraphicsCall(false); + switch (internalformat) { + case GraphicsContext3D::DEPTH_COMPONENT16: + case GraphicsContext3D::RGBA4: + case GraphicsContext3D::RGB5_A1: + case GraphicsContext3D::RGB565: + case GraphicsContext3D::STENCIL_INDEX8: + case GraphicsContext3D::DEPTH_STENCIL: + m_context->renderbufferStorage(target, internalformat, width, height); + if (m_renderbufferBinding) + m_renderbufferBinding->setInternalformat(internalformat); + cleanupAfterGraphicsCall(false); + break; + default: + m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM); + } } void WebGLRenderingContext::sampleCoverage(double value, bool invert) @@ -1574,10 +1722,8 @@ void WebGLRenderingContext::scissor(long x, long y, unsigned long width, unsigne void WebGLRenderingContext::shaderSource(WebGLShader* shader, const String& string, ExceptionCode& ec) { UNUSED_PARAM(ec); - if (!shader || shader->context() != this) { - m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); + if (!validateWebGLObject(shader)) return; - } m_context->shaderSource(shader, string); cleanupAfterGraphicsCall(false); } @@ -1634,12 +1780,10 @@ void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, ImageDat bool flipY, bool premultiplyAlpha, ExceptionCode& ec) { // FIXME: For now we ignore any errors returned - // FIXME: Need a form of this call that can take both a pixel buffer and flipY and premultiplyAlpha flags - UNUSED_PARAM(flipY); - UNUSED_PARAM(premultiplyAlpha); ec = 0; - m_context->texImage2D(target, level, GraphicsContext3D::RGBA, pixels->width(), pixels->height(), 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, pixels->data()->data()->data()); - //RLP: m_context->texImage2D(target, level, pixels, flipY, premultiplyAlpha); + Vector<uint8_t> data; + m_context->extractImageData(pixels, flipY, premultiplyAlpha, data); + m_context->texImage2D(target, level, GraphicsContext3D::RGBA, pixels->width(), pixels->height(), 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, data.data()); cleanupAfterGraphicsCall(false); } @@ -1724,11 +1868,10 @@ void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, unsig ImageData* pixels, bool flipY, bool premultiplyAlpha, ExceptionCode& ec) { // FIXME: For now we ignore any errors returned - UNUSED_PARAM(flipY); - UNUSED_PARAM(premultiplyAlpha); ec = 0; - m_context->texSubImage2D(target, level, xoffset, yoffset, pixels->width(), pixels->height(), GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, pixels->data()->data()->data()); - //RLP: m_context->texSubImage2D(target, level, xoffset, yoffset, pixels, flipY, premultiplyAlpha); + Vector<uint8_t> data; + m_context->extractImageData(pixels, flipY, premultiplyAlpha, data); + m_context->texSubImage2D(target, level, xoffset, yoffset, pixels->width(), pixels->height(), GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, data.data()); cleanupAfterGraphicsCall(false); } @@ -1790,7 +1933,12 @@ void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, unsig void WebGLRenderingContext::uniform1f(const WebGLUniformLocation* location, float x, ExceptionCode& ec) { UNUSED_PARAM(ec); - if (!location || location->program() != m_currentProgram) { + if (!location) { + m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); + return; + } + + if (location->program() != m_currentProgram) { m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); return; } @@ -1802,7 +1950,12 @@ void WebGLRenderingContext::uniform1f(const WebGLUniformLocation* location, floa void WebGLRenderingContext::uniform1fv(const WebGLUniformLocation* location, WebGLFloatArray* v, ExceptionCode& ec) { UNUSED_PARAM(ec); - if (!location || location->program() != m_currentProgram) { + if (!location) { + m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); + return; + } + + if (location->program() != m_currentProgram) { m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); return; } @@ -1818,7 +1971,12 @@ void WebGLRenderingContext::uniform1fv(const WebGLUniformLocation* location, Web void WebGLRenderingContext::uniform1fv(const WebGLUniformLocation* location, float* v, int size, ExceptionCode& ec) { UNUSED_PARAM(ec); - if (!location || location->program() != m_currentProgram) { + if (!location) { + m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); + return; + } + + if (location->program() != m_currentProgram) { m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); return; } @@ -1834,7 +1992,12 @@ void WebGLRenderingContext::uniform1fv(const WebGLUniformLocation* location, flo void WebGLRenderingContext::uniform1i(const WebGLUniformLocation* location, int x, ExceptionCode& ec) { UNUSED_PARAM(ec); - if (!location || location->program() != m_currentProgram) { + if (!location) { + m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); + return; + } + + if (location->program() != m_currentProgram) { m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); return; } @@ -1846,7 +2009,12 @@ void WebGLRenderingContext::uniform1i(const WebGLUniformLocation* location, int void WebGLRenderingContext::uniform1iv(const WebGLUniformLocation* location, WebGLIntArray* v, ExceptionCode& ec) { UNUSED_PARAM(ec); - if (!location || location->program() != m_currentProgram) { + if (!location) { + m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); + return; + } + + if (location->program() != m_currentProgram) { m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); return; } @@ -1862,7 +2030,12 @@ void WebGLRenderingContext::uniform1iv(const WebGLUniformLocation* location, Web void WebGLRenderingContext::uniform1iv(const WebGLUniformLocation* location, int* v, int size, ExceptionCode& ec) { UNUSED_PARAM(ec); - if (!location || location->program() != m_currentProgram) { + if (!location) { + m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); + return; + } + + if (location->program() != m_currentProgram) { m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); return; } @@ -1878,7 +2051,12 @@ void WebGLRenderingContext::uniform1iv(const WebGLUniformLocation* location, int void WebGLRenderingContext::uniform2f(const WebGLUniformLocation* location, float x, float y, ExceptionCode& ec) { UNUSED_PARAM(ec); - if (!location || location->program() != m_currentProgram) { + if (!location) { + m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); + return; + } + + if (location->program() != m_currentProgram) { m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); return; } @@ -1890,7 +2068,12 @@ void WebGLRenderingContext::uniform2f(const WebGLUniformLocation* location, floa void WebGLRenderingContext::uniform2fv(const WebGLUniformLocation* location, WebGLFloatArray* v, ExceptionCode& ec) { UNUSED_PARAM(ec); - if (!location || location->program() != m_currentProgram) { + if (!location) { + m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); + return; + } + + if (location->program() != m_currentProgram) { m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); return; } @@ -1907,7 +2090,12 @@ void WebGLRenderingContext::uniform2fv(const WebGLUniformLocation* location, Web void WebGLRenderingContext::uniform2fv(const WebGLUniformLocation* location, float* v, int size, ExceptionCode& ec) { UNUSED_PARAM(ec); - if (!location || location->program() != m_currentProgram) { + if (!location) { + m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); + return; + } + + if (location->program() != m_currentProgram) { m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); return; } @@ -1924,7 +2112,12 @@ void WebGLRenderingContext::uniform2fv(const WebGLUniformLocation* location, flo void WebGLRenderingContext::uniform2i(const WebGLUniformLocation* location, int x, int y, ExceptionCode& ec) { UNUSED_PARAM(ec); - if (!location || location->program() != m_currentProgram) { + if (!location) { + m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); + return; + } + + if (location->program() != m_currentProgram) { m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); return; } @@ -1936,7 +2129,12 @@ void WebGLRenderingContext::uniform2i(const WebGLUniformLocation* location, int void WebGLRenderingContext::uniform2iv(const WebGLUniformLocation* location, WebGLIntArray* v, ExceptionCode& ec) { UNUSED_PARAM(ec); - if (!location || location->program() != m_currentProgram) { + if (!location) { + m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); + return; + } + + if (location->program() != m_currentProgram) { m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); return; } @@ -1953,7 +2151,12 @@ void WebGLRenderingContext::uniform2iv(const WebGLUniformLocation* location, Web void WebGLRenderingContext::uniform2iv(const WebGLUniformLocation* location, int* v, int size, ExceptionCode& ec) { UNUSED_PARAM(ec); - if (!location || location->program() != m_currentProgram) { + if (!location) { + m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); + return; + } + + if (location->program() != m_currentProgram) { m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); return; } @@ -1970,7 +2173,12 @@ void WebGLRenderingContext::uniform2iv(const WebGLUniformLocation* location, int void WebGLRenderingContext::uniform3f(const WebGLUniformLocation* location, float x, float y, float z, ExceptionCode& ec) { UNUSED_PARAM(ec); - if (!location || location->program() != m_currentProgram) { + if (!location) { + m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); + return; + } + + if (location->program() != m_currentProgram) { m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); return; } @@ -1982,7 +2190,12 @@ void WebGLRenderingContext::uniform3f(const WebGLUniformLocation* location, floa void WebGLRenderingContext::uniform3fv(const WebGLUniformLocation* location, WebGLFloatArray* v, ExceptionCode& ec) { UNUSED_PARAM(ec); - if (!location || location->program() != m_currentProgram) { + if (!location) { + m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); + return; + } + + if (location->program() != m_currentProgram) { m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); return; } @@ -1999,7 +2212,12 @@ void WebGLRenderingContext::uniform3fv(const WebGLUniformLocation* location, Web void WebGLRenderingContext::uniform3fv(const WebGLUniformLocation* location, float* v, int size, ExceptionCode& ec) { UNUSED_PARAM(ec); - if (!location || location->program() != m_currentProgram) { + if (!location) { + m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); + return; + } + + if (location->program() != m_currentProgram) { m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); return; } @@ -2016,7 +2234,12 @@ void WebGLRenderingContext::uniform3fv(const WebGLUniformLocation* location, flo void WebGLRenderingContext::uniform3i(const WebGLUniformLocation* location, int x, int y, int z, ExceptionCode& ec) { UNUSED_PARAM(ec); - if (!location || location->program() != m_currentProgram) { + if (!location) { + m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); + return; + } + + if (location->program() != m_currentProgram) { m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); return; } @@ -2028,7 +2251,12 @@ void WebGLRenderingContext::uniform3i(const WebGLUniformLocation* location, int void WebGLRenderingContext::uniform3iv(const WebGLUniformLocation* location, WebGLIntArray* v, ExceptionCode& ec) { UNUSED_PARAM(ec); - if (!location || location->program() != m_currentProgram) { + if (!location) { + m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); + return; + } + + if (location->program() != m_currentProgram) { m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); return; } @@ -2045,7 +2273,12 @@ void WebGLRenderingContext::uniform3iv(const WebGLUniformLocation* location, Web void WebGLRenderingContext::uniform3iv(const WebGLUniformLocation* location, int* v, int size, ExceptionCode& ec) { UNUSED_PARAM(ec); - if (!location || location->program() != m_currentProgram) { + if (!location) { + m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); + return; + } + + if (location->program() != m_currentProgram) { m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); return; } @@ -2062,7 +2295,12 @@ void WebGLRenderingContext::uniform3iv(const WebGLUniformLocation* location, int void WebGLRenderingContext::uniform4f(const WebGLUniformLocation* location, float x, float y, float z, float w, ExceptionCode& ec) { UNUSED_PARAM(ec); - if (!location || location->program() != m_currentProgram) { + if (!location) { + m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); + return; + } + + if (location->program() != m_currentProgram) { m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); return; } @@ -2074,7 +2312,12 @@ void WebGLRenderingContext::uniform4f(const WebGLUniformLocation* location, floa void WebGLRenderingContext::uniform4fv(const WebGLUniformLocation* location, WebGLFloatArray* v, ExceptionCode& ec) { UNUSED_PARAM(ec); - if (!location || location->program() != m_currentProgram) { + if (!location) { + m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); + return; + } + + if (location->program() != m_currentProgram) { m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); return; } @@ -2091,7 +2334,12 @@ void WebGLRenderingContext::uniform4fv(const WebGLUniformLocation* location, Web void WebGLRenderingContext::uniform4fv(const WebGLUniformLocation* location, float* v, int size, ExceptionCode& ec) { UNUSED_PARAM(ec); - if (!location || location->program() != m_currentProgram) { + if (!location) { + m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); + return; + } + + if (location->program() != m_currentProgram) { m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); return; } @@ -2108,7 +2356,12 @@ void WebGLRenderingContext::uniform4fv(const WebGLUniformLocation* location, flo void WebGLRenderingContext::uniform4i(const WebGLUniformLocation* location, int x, int y, int z, int w, ExceptionCode& ec) { UNUSED_PARAM(ec); - if (!location || location->program() != m_currentProgram) { + if (!location) { + m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); + return; + } + + if (location->program() != m_currentProgram) { m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); return; } @@ -2120,7 +2373,12 @@ void WebGLRenderingContext::uniform4i(const WebGLUniformLocation* location, int void WebGLRenderingContext::uniform4iv(const WebGLUniformLocation* location, WebGLIntArray* v, ExceptionCode& ec) { UNUSED_PARAM(ec); - if (!location || location->program() != m_currentProgram) { + if (!location) { + m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); + return; + } + + if (location->program() != m_currentProgram) { m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); return; } @@ -2137,7 +2395,12 @@ void WebGLRenderingContext::uniform4iv(const WebGLUniformLocation* location, Web void WebGLRenderingContext::uniform4iv(const WebGLUniformLocation* location, int* v, int size, ExceptionCode& ec) { UNUSED_PARAM(ec); - if (!location || location->program() != m_currentProgram) { + if (!location) { + m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); + return; + } + + if (location->program() != m_currentProgram) { m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); return; } @@ -2154,7 +2417,12 @@ void WebGLRenderingContext::uniform4iv(const WebGLUniformLocation* location, int void WebGLRenderingContext::uniformMatrix2fv(const WebGLUniformLocation* location, bool transpose, WebGLFloatArray* v, ExceptionCode& ec) { UNUSED_PARAM(ec); - if (!location || location->program() != m_currentProgram) { + if (!location) { + m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); + return; + } + + if (location->program() != m_currentProgram) { m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); return; } @@ -2171,7 +2439,12 @@ void WebGLRenderingContext::uniformMatrix2fv(const WebGLUniformLocation* locatio void WebGLRenderingContext::uniformMatrix2fv(const WebGLUniformLocation* location, bool transpose, float* v, int size, ExceptionCode& ec) { UNUSED_PARAM(ec); - if (!location || location->program() != m_currentProgram) { + if (!location) { + m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); + return; + } + + if (location->program() != m_currentProgram) { m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); return; } @@ -2188,7 +2461,12 @@ void WebGLRenderingContext::uniformMatrix2fv(const WebGLUniformLocation* locatio void WebGLRenderingContext::uniformMatrix3fv(const WebGLUniformLocation* location, bool transpose, WebGLFloatArray* v, ExceptionCode& ec) { UNUSED_PARAM(ec); - if (!location || location->program() != m_currentProgram) { + if (!location) { + m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); + return; + } + + if (location->program() != m_currentProgram) { m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); return; } @@ -2205,7 +2483,12 @@ void WebGLRenderingContext::uniformMatrix3fv(const WebGLUniformLocation* locatio void WebGLRenderingContext::uniformMatrix3fv(const WebGLUniformLocation* location, bool transpose, float* v, int size, ExceptionCode& ec) { UNUSED_PARAM(ec); - if (!location || location->program() != m_currentProgram) { + if (!location) { + m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); + return; + } + + if (location->program() != m_currentProgram) { m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); return; } @@ -2222,7 +2505,12 @@ void WebGLRenderingContext::uniformMatrix3fv(const WebGLUniformLocation* locatio void WebGLRenderingContext::uniformMatrix4fv(const WebGLUniformLocation* location, bool transpose, WebGLFloatArray* v, ExceptionCode& ec) { UNUSED_PARAM(ec); - if (!location || location->program() != m_currentProgram) { + if (!location) { + m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); + return; + } + + if (location->program() != m_currentProgram) { m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); return; } @@ -2239,7 +2527,12 @@ void WebGLRenderingContext::uniformMatrix4fv(const WebGLUniformLocation* locatio void WebGLRenderingContext::uniformMatrix4fv(const WebGLUniformLocation* location, bool transpose, float* v, int size, ExceptionCode& ec) { UNUSED_PARAM(ec); - if (!location || location->program() != m_currentProgram) { + if (!location) { + m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); + return; + } + + if (location->program() != m_currentProgram) { m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); return; } diff --git a/WebCore/html/canvas/WebGLRenderingContext.h b/WebCore/html/canvas/WebGLRenderingContext.h index 90d4fab..9c58a53 100644 --- a/WebCore/html/canvas/WebGLRenderingContext.h +++ b/WebCore/html/canvas/WebGLRenderingContext.h @@ -309,6 +309,8 @@ class WebKitCSSMatrix; bool validateIndexArrayPrecise(unsigned long count, unsigned long type, long offset, long& numElementsRequired); bool validateRenderingState(long numElements); + bool validateWebGLObject(CanvasObject* object); + OwnPtr<GraphicsContext3D> m_context; bool m_needsUpdate; bool m_markedCanvasDirty; @@ -342,6 +344,11 @@ class WebKitCSSMatrix; TextureUnitState m_textureUnits[32]; unsigned long m_activeTextureUnit; + int m_packAlignment; + int m_unpackAlignment; + unsigned long m_implementationColorReadFormat; + unsigned long m_implementationColorReadType; + // Helpers for getParameter and others WebGLGetInfo getBooleanParameter(unsigned long pname); WebGLGetInfo getFloatParameter(unsigned long pname); diff --git a/WebCore/html/canvas/WebGLRenderingContext.idl b/WebCore/html/canvas/WebGLRenderingContext.idl index ce01f43..a257452 100644 --- a/WebCore/html/canvas/WebGLRenderingContext.idl +++ b/WebCore/html/canvas/WebGLRenderingContext.idl @@ -423,6 +423,7 @@ module html { const unsigned int DEPTH_COMPONENT16 = 0x81A5; const unsigned int STENCIL_INDEX = 0x1901; const unsigned int STENCIL_INDEX8 = 0x8D48; + const unsigned int DEPTH_STENCIL = 0x84F9; const unsigned int RENDERBUFFER_WIDTH = 0x8D42; const unsigned int RENDERBUFFER_HEIGHT = 0x8D43; @@ -442,6 +443,7 @@ module html { const unsigned int COLOR_ATTACHMENT0 = 0x8CE0; const unsigned int DEPTH_ATTACHMENT = 0x8D00; const unsigned int STENCIL_ATTACHMENT = 0x8D20; + const unsigned int DEPTH_STENCIL_ATTACHMENT = 0x821A; const unsigned int NONE = 0; @@ -518,7 +520,7 @@ module html { void disable(in unsigned long cap); void disableVertexAttribArray(in unsigned long index) raises(DOMException); void drawArrays(in unsigned long mode, in long first, in unsigned long count) raises(DOMException); - void drawElements (in unsigned long mode, in long count, in unsigned long type, in unsigned long offset) raises(DOMException); + void drawElements(in unsigned long mode, in long count, in unsigned long type, in unsigned long offset) raises(DOMException); void enable(in unsigned long cap); void enableVertexAttribArray(in unsigned long index) raises(DOMException); diff --git a/WebCore/html/canvas/WebGLShortArray.cpp b/WebCore/html/canvas/WebGLShortArray.cpp index f96a290..a9b0f0d 100644 --- a/WebCore/html/canvas/WebGLShortArray.cpp +++ b/WebCore/html/canvas/WebGLShortArray.cpp @@ -34,7 +34,7 @@ namespace WebCore { PassRefPtr<WebGLShortArray> WebGLShortArray::create(unsigned length) { - RefPtr<WebGLArrayBuffer> buffer = WebGLArrayBuffer::create(length * sizeof(short)); + RefPtr<WebGLArrayBuffer> buffer = WebGLArrayBuffer::create(length, sizeof(short)); return create(buffer, 0, length); } @@ -47,24 +47,17 @@ PassRefPtr<WebGLShortArray> WebGLShortArray::create(short* array, unsigned lengt } PassRefPtr<WebGLShortArray> WebGLShortArray::create(PassRefPtr<WebGLArrayBuffer> buffer, - int byteOffset, + unsigned byteOffset, unsigned length) { - // Make sure the offset results in valid alignment. - if ((byteOffset % sizeof(short)) != 0) - return NULL; - - if (buffer) { - // Check to make sure we are talking about a valid region of - // the given WebGLArrayBuffer's storage. - if ((byteOffset + (length * sizeof(short))) > buffer->byteLength()) - return NULL; - } + RefPtr<WebGLArrayBuffer> buf(buffer); + if (!verifySubRange<short>(buf, byteOffset, length)) + return 0; - return adoptRef(new WebGLShortArray(buffer, byteOffset, length)); + return adoptRef(new WebGLShortArray(buf, byteOffset, length)); } -WebGLShortArray::WebGLShortArray(PassRefPtr<WebGLArrayBuffer> buffer, int byteOffset, unsigned length) +WebGLShortArray::WebGLShortArray(PassRefPtr<WebGLArrayBuffer> buffer, unsigned byteOffset, unsigned length) : WebGLArray(buffer, byteOffset) , m_size(length) { @@ -78,15 +71,12 @@ unsigned WebGLShortArray::byteLength() const { return m_size * sizeof(short); } -PassRefPtr<WebGLArray> WebGLShortArray::slice(unsigned offset, unsigned length) { - // Check to make sure the specified region is within the bounds of - // the WebGLArrayBuffer. - unsigned startByte = m_byteOffset + offset * sizeof(short); - unsigned limitByte = startByte + length * sizeof(short); - unsigned bufferLength = buffer()->byteLength(); - if (startByte >= bufferLength || limitByte > bufferLength) - return 0; - return create(buffer(), startByte, length); +PassRefPtr<WebGLArray> WebGLShortArray::slice(int start, int end) +{ + unsigned offset, length; + calculateOffsetAndLength(start, end, m_size, &offset, &length); + clampOffsetAndNumElements<short>(buffer(), m_byteOffset, &offset, &length); + return create(buffer(), offset, length); } void WebGLShortArray::set(WebGLShortArray* array, unsigned offset, ExceptionCode& ec) { diff --git a/WebCore/html/canvas/WebGLShortArray.h b/WebCore/html/canvas/WebGLShortArray.h index 70c66ca..af4befb 100644 --- a/WebCore/html/canvas/WebGLShortArray.h +++ b/WebCore/html/canvas/WebGLShortArray.h @@ -40,13 +40,13 @@ class WebGLShortArray : public WebGLArray { static PassRefPtr<WebGLShortArray> create(unsigned length); static PassRefPtr<WebGLShortArray> create(short* array, unsigned length); - static PassRefPtr<WebGLShortArray> create(PassRefPtr<WebGLArrayBuffer> buffer, int byteOffset, unsigned length); + static PassRefPtr<WebGLShortArray> create(PassRefPtr<WebGLArrayBuffer> buffer, unsigned byteOffset, unsigned length); short* data() { return static_cast<short*>(baseAddress()); } virtual unsigned length() const; virtual unsigned byteLength() const; - virtual PassRefPtr<WebGLArray> slice(unsigned offset, unsigned length); + virtual PassRefPtr<WebGLArray> slice(int start, int end); void set(unsigned index, double value) { @@ -85,7 +85,7 @@ class WebGLShortArray : public WebGLArray { void set(WebGLShortArray* array, unsigned offset, ExceptionCode& ec); private: - WebGLShortArray(PassRefPtr<WebGLArrayBuffer> buffer, int byteOffset, unsigned length); + WebGLShortArray(PassRefPtr<WebGLArrayBuffer> buffer, unsigned byteOffset, unsigned length); unsigned m_size; }; diff --git a/WebCore/html/canvas/WebGLUnsignedByteArray.cpp b/WebCore/html/canvas/WebGLUnsignedByteArray.cpp index 3fd1b50..81e0135 100644 --- a/WebCore/html/canvas/WebGLUnsignedByteArray.cpp +++ b/WebCore/html/canvas/WebGLUnsignedByteArray.cpp @@ -35,7 +35,7 @@ namespace WebCore { PassRefPtr<WebGLUnsignedByteArray> WebGLUnsignedByteArray::create(unsigned length) { - RefPtr<WebGLArrayBuffer> buffer = WebGLArrayBuffer::create(length * sizeof(unsigned char)); + RefPtr<WebGLArrayBuffer> buffer = WebGLArrayBuffer::create(length, sizeof(unsigned char)); return create(buffer, 0, length); } @@ -48,20 +48,17 @@ PassRefPtr<WebGLUnsignedByteArray> WebGLUnsignedByteArray::create(unsigned char* } PassRefPtr<WebGLUnsignedByteArray> WebGLUnsignedByteArray::create(PassRefPtr<WebGLArrayBuffer> buffer, - int byteOffset, + unsigned byteOffset, unsigned length) { - if (buffer) { - // Check to make sure we are talking about a valid region of - // the given WebGLArrayBuffer's storage. - if ((byteOffset + (length * sizeof(unsigned char))) > buffer->byteLength()) - return NULL; - } + RefPtr<WebGLArrayBuffer> buf(buffer); + if (!verifySubRange<unsigned char>(buf, byteOffset, length)) + return 0; - return adoptRef(new WebGLUnsignedByteArray(buffer, byteOffset, length)); + return adoptRef(new WebGLUnsignedByteArray(buf, byteOffset, length)); } -WebGLUnsignedByteArray::WebGLUnsignedByteArray(PassRefPtr<WebGLArrayBuffer> buffer, int byteOffset, unsigned length) +WebGLUnsignedByteArray::WebGLUnsignedByteArray(PassRefPtr<WebGLArrayBuffer> buffer, unsigned byteOffset, unsigned length) : WebGLArray(buffer, byteOffset) , m_size(length) { @@ -75,15 +72,12 @@ unsigned WebGLUnsignedByteArray::byteLength() const { return m_size * sizeof(unsigned char); } -PassRefPtr<WebGLArray> WebGLUnsignedByteArray::slice(unsigned offset, unsigned length) { - // Check to make sure the specified region is within the bounds of - // the WebGLArrayBuffer. - unsigned startByte = m_byteOffset + offset * sizeof(unsigned char); - unsigned limitByte = startByte + length * sizeof(unsigned char); - unsigned bufferLength = buffer()->byteLength(); - if (startByte >= bufferLength || limitByte > bufferLength) - return 0; - return create(buffer(), startByte, length); +PassRefPtr<WebGLArray> WebGLUnsignedByteArray::slice(int start, int end) +{ + unsigned offset, length; + calculateOffsetAndLength(start, end, m_size, &offset, &length); + clampOffsetAndNumElements<unsigned char>(buffer(), m_byteOffset, &offset, &length); + return create(buffer(), offset, length); } void WebGLUnsignedByteArray::set(WebGLUnsignedByteArray* array, unsigned offset, ExceptionCode& ec) { diff --git a/WebCore/html/canvas/WebGLUnsignedByteArray.h b/WebCore/html/canvas/WebGLUnsignedByteArray.h index 6909de5..505b2fd 100644 --- a/WebCore/html/canvas/WebGLUnsignedByteArray.h +++ b/WebCore/html/canvas/WebGLUnsignedByteArray.h @@ -41,13 +41,13 @@ class WebGLUnsignedByteArray : public WebGLArray { static PassRefPtr<WebGLUnsignedByteArray> create(unsigned length); static PassRefPtr<WebGLUnsignedByteArray> create(unsigned char* array, unsigned length); - static PassRefPtr<WebGLUnsignedByteArray> create(PassRefPtr<WebGLArrayBuffer> buffer, int byteOffset, unsigned length); + static PassRefPtr<WebGLUnsignedByteArray> create(PassRefPtr<WebGLArrayBuffer> buffer, unsigned byteOffset, unsigned length); unsigned char* data() { return static_cast<unsigned char*>(baseAddress()); } virtual unsigned length() const; virtual unsigned byteLength() const; - virtual PassRefPtr<WebGLArray> slice(unsigned offset, unsigned length); + virtual PassRefPtr<WebGLArray> slice(int start, int end); void set(unsigned index, double value) { @@ -86,7 +86,7 @@ class WebGLUnsignedByteArray : public WebGLArray { void set(WebGLUnsignedByteArray* array, unsigned offset, ExceptionCode& ec); private: - WebGLUnsignedByteArray(PassRefPtr<WebGLArrayBuffer> buffer, int byteOffset, unsigned length); + WebGLUnsignedByteArray(PassRefPtr<WebGLArrayBuffer> buffer, unsigned byteOffset, unsigned length); unsigned m_size; }; diff --git a/WebCore/html/canvas/WebGLUnsignedIntArray.cpp b/WebCore/html/canvas/WebGLUnsignedIntArray.cpp index 97910f9..59d895f 100644 --- a/WebCore/html/canvas/WebGLUnsignedIntArray.cpp +++ b/WebCore/html/canvas/WebGLUnsignedIntArray.cpp @@ -35,7 +35,7 @@ namespace WebCore { PassRefPtr<WebGLUnsignedIntArray> WebGLUnsignedIntArray::create(unsigned length) { - RefPtr<WebGLArrayBuffer> buffer = WebGLArrayBuffer::create(length * sizeof(unsigned int)); + RefPtr<WebGLArrayBuffer> buffer = WebGLArrayBuffer::create(length, sizeof(unsigned int)); return create(buffer, 0, length); } @@ -48,25 +48,17 @@ PassRefPtr<WebGLUnsignedIntArray> WebGLUnsignedIntArray::create(unsigned int* ar } PassRefPtr<WebGLUnsignedIntArray> WebGLUnsignedIntArray::create(PassRefPtr<WebGLArrayBuffer> buffer, - int byteOffset, + unsigned byteOffset, unsigned length) { - // Make sure the offset results in valid alignment. - if ((byteOffset % sizeof(unsigned int)) != 0) { - return NULL; - } - - if (buffer) { - // Check to make sure we are talking about a valid region of - // the given WebGLArrayBuffer's storage. - if ((byteOffset + (length * sizeof(unsigned int))) > buffer->byteLength()) - return NULL; - } + RefPtr<WebGLArrayBuffer> buf(buffer); + if (!verifySubRange<unsigned int>(buf, byteOffset, length)) + return 0; - return adoptRef(new WebGLUnsignedIntArray(buffer, byteOffset, length)); + return adoptRef(new WebGLUnsignedIntArray(buf, byteOffset, length)); } -WebGLUnsignedIntArray::WebGLUnsignedIntArray(PassRefPtr<WebGLArrayBuffer> buffer, int byteOffset, unsigned length) +WebGLUnsignedIntArray::WebGLUnsignedIntArray(PassRefPtr<WebGLArrayBuffer> buffer, unsigned byteOffset, unsigned length) : WebGLArray(buffer, byteOffset) , m_size(length) { @@ -80,15 +72,12 @@ unsigned WebGLUnsignedIntArray::byteLength() const { return m_size * sizeof(unsigned int); } -PassRefPtr<WebGLArray> WebGLUnsignedIntArray::slice(unsigned offset, unsigned length) { - // Check to make sure the specified region is within the bounds of - // the WebGLArrayBuffer. - unsigned startByte = m_byteOffset + offset * sizeof(unsigned int); - unsigned limitByte = startByte + length * sizeof(unsigned int); - unsigned bufferLength = buffer()->byteLength(); - if (startByte >= bufferLength || limitByte > bufferLength) - return 0; - return create(buffer(), startByte, length); +PassRefPtr<WebGLArray> WebGLUnsignedIntArray::slice(int start, int end) +{ + unsigned offset, length; + calculateOffsetAndLength(start, end, m_size, &offset, &length); + clampOffsetAndNumElements<unsigned int>(buffer(), m_byteOffset, &offset, &length); + return create(buffer(), offset, length); } void WebGLUnsignedIntArray::set(WebGLUnsignedIntArray* array, unsigned offset, ExceptionCode& ec) { diff --git a/WebCore/html/canvas/WebGLUnsignedIntArray.h b/WebCore/html/canvas/WebGLUnsignedIntArray.h index b0d9b65..6e9b220 100644 --- a/WebCore/html/canvas/WebGLUnsignedIntArray.h +++ b/WebCore/html/canvas/WebGLUnsignedIntArray.h @@ -41,13 +41,13 @@ class WebGLUnsignedIntArray : public WebGLArray { static PassRefPtr<WebGLUnsignedIntArray> create(unsigned length); static PassRefPtr<WebGLUnsignedIntArray> create(unsigned int* array, unsigned length); - static PassRefPtr<WebGLUnsignedIntArray> create(PassRefPtr<WebGLArrayBuffer> buffer, int byteOffset, unsigned length); + static PassRefPtr<WebGLUnsignedIntArray> create(PassRefPtr<WebGLArrayBuffer> buffer, unsigned byteOffset, unsigned length); unsigned int* data() { return static_cast<unsigned int*>(baseAddress()); } virtual unsigned length() const; virtual unsigned byteLength() const; - virtual PassRefPtr<WebGLArray> slice(unsigned offset, unsigned length); + virtual PassRefPtr<WebGLArray> slice(int start, int end); void set(unsigned index, double value) { @@ -86,7 +86,7 @@ class WebGLUnsignedIntArray : public WebGLArray { void set(WebGLUnsignedIntArray* array, unsigned offset, ExceptionCode& ec); private: - WebGLUnsignedIntArray(PassRefPtr<WebGLArrayBuffer> buffer, int byteOffset, unsigned length); + WebGLUnsignedIntArray(PassRefPtr<WebGLArrayBuffer> buffer, unsigned byteOffset, unsigned length); unsigned m_size; }; diff --git a/WebCore/html/canvas/WebGLUnsignedShortArray.cpp b/WebCore/html/canvas/WebGLUnsignedShortArray.cpp index 86fae8c..c283a81 100644 --- a/WebCore/html/canvas/WebGLUnsignedShortArray.cpp +++ b/WebCore/html/canvas/WebGLUnsignedShortArray.cpp @@ -35,7 +35,7 @@ namespace WebCore { PassRefPtr<WebGLUnsignedShortArray> WebGLUnsignedShortArray::create(unsigned length) { - RefPtr<WebGLArrayBuffer> buffer = WebGLArrayBuffer::create(length * sizeof(unsigned short)); + RefPtr<WebGLArrayBuffer> buffer = WebGLArrayBuffer::create(length, sizeof(unsigned short)); return create(buffer, 0, length); } @@ -48,26 +48,18 @@ PassRefPtr<WebGLUnsignedShortArray> WebGLUnsignedShortArray::create(unsigned sho } PassRefPtr<WebGLUnsignedShortArray> WebGLUnsignedShortArray::create(PassRefPtr<WebGLArrayBuffer> buffer, - int byteOffset, + unsigned byteOffset, unsigned length) { - // Make sure the offset results in valid alignment. - if ((byteOffset % sizeof(unsigned short)) != 0) { - return NULL; - } - - if (buffer) { - // Check to make sure we are talking about a valid region of - // the given WebGLArrayBuffer's storage. - if ((byteOffset + (length * sizeof(unsigned short))) > buffer->byteLength()) - return NULL; - } + RefPtr<WebGLArrayBuffer> buf(buffer); + if (!verifySubRange<unsigned short>(buf, byteOffset, length)) + return 0; - return adoptRef(new WebGLUnsignedShortArray(buffer, byteOffset, length)); + return adoptRef(new WebGLUnsignedShortArray(buf, byteOffset, length)); } WebGLUnsignedShortArray::WebGLUnsignedShortArray(PassRefPtr<WebGLArrayBuffer> buffer, - int byteOffset, + unsigned byteOffset, unsigned length) : WebGLArray(buffer, byteOffset) , m_size(length) @@ -82,15 +74,12 @@ unsigned WebGLUnsignedShortArray::byteLength() const { return m_size * sizeof(unsigned short); } -PassRefPtr<WebGLArray> WebGLUnsignedShortArray::slice(unsigned offset, unsigned length) { - // Check to make sure the specified region is within the bounds of - // the WebGLArrayBuffer. - unsigned startByte = m_byteOffset + offset * sizeof(unsigned short); - unsigned limitByte = startByte + length * sizeof(unsigned short); - unsigned bufferLength = buffer()->byteLength(); - if (startByte >= bufferLength || limitByte > bufferLength) - return 0; - return create(buffer(), startByte, length); +PassRefPtr<WebGLArray> WebGLUnsignedShortArray::slice(int start, int end) +{ + unsigned offset, length; + calculateOffsetAndLength(start, end, m_size, &offset, &length); + clampOffsetAndNumElements<unsigned short>(buffer(), m_byteOffset, &offset, &length); + return create(buffer(), offset, length); } void WebGLUnsignedShortArray::set(WebGLUnsignedShortArray* array, unsigned offset, ExceptionCode& ec) { diff --git a/WebCore/html/canvas/WebGLUnsignedShortArray.h b/WebCore/html/canvas/WebGLUnsignedShortArray.h index 3bad1b6..94b428a 100644 --- a/WebCore/html/canvas/WebGLUnsignedShortArray.h +++ b/WebCore/html/canvas/WebGLUnsignedShortArray.h @@ -41,13 +41,13 @@ class WebGLUnsignedShortArray : public WebGLArray { static PassRefPtr<WebGLUnsignedShortArray> create(unsigned length); static PassRefPtr<WebGLUnsignedShortArray> create(unsigned short* array, unsigned length); - static PassRefPtr<WebGLUnsignedShortArray> create(PassRefPtr<WebGLArrayBuffer> buffer, int byteOffset, unsigned length); + static PassRefPtr<WebGLUnsignedShortArray> create(PassRefPtr<WebGLArrayBuffer> buffer, unsigned byteOffset, unsigned length); unsigned short* data() { return static_cast<unsigned short*>(baseAddress()); } virtual unsigned length() const; virtual unsigned byteLength() const; - virtual PassRefPtr<WebGLArray> slice(unsigned offset, unsigned length); + virtual PassRefPtr<WebGLArray> slice(int start, int end); void set(unsigned index, double value) { @@ -87,7 +87,7 @@ class WebGLUnsignedShortArray : public WebGLArray { void set(WebGLUnsignedShortArray* array, unsigned offset, ExceptionCode& ec); private: - WebGLUnsignedShortArray(PassRefPtr<WebGLArrayBuffer> buffer,int byteOffset,unsigned length); + WebGLUnsignedShortArray(PassRefPtr<WebGLArrayBuffer> buffer, unsigned byteOffset,unsigned length); unsigned m_size; }; |