diff options
Diffstat (limited to 'Source/WebCore/html/canvas/WebGLBuffer.cpp')
-rw-r--r-- | Source/WebCore/html/canvas/WebGLBuffer.cpp | 142 |
1 files changed, 113 insertions, 29 deletions
diff --git a/Source/WebCore/html/canvas/WebGLBuffer.cpp b/Source/WebCore/html/canvas/WebGLBuffer.cpp index 3421e979c..bc914a4a7 100644 --- a/Source/WebCore/html/canvas/WebGLBuffer.cpp +++ b/Source/WebCore/html/canvas/WebGLBuffer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Apple Inc. All rights reserved. + * Copyright (C) 2009-2017 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -24,28 +24,24 @@ */ #include "config.h" +#include "WebGLBuffer.h" #if ENABLE(WEBGL) -#include "WebGLBuffer.h" - #include "WebGLContextGroup.h" -#include "WebGLRenderingContext.h" +#include "WebGLRenderingContextBase.h" namespace WebCore { -PassRefPtr<WebGLBuffer> WebGLBuffer::create(WebGLRenderingContext* ctx) +Ref<WebGLBuffer> WebGLBuffer::create(WebGLRenderingContextBase& ctx) { - return adoptRef(new WebGLBuffer(ctx)); + return adoptRef(*new WebGLBuffer(ctx)); } -WebGLBuffer::WebGLBuffer(WebGLRenderingContext* ctx) +WebGLBuffer::WebGLBuffer(WebGLRenderingContextBase& ctx) : WebGLSharedObject(ctx) - , m_target(0) - , m_byteLength(0) - , m_nextAvailableCacheEntry(0) { - setObject(ctx->graphicsContext3D()->createBuffer()); + setObject(ctx.graphicsContext3D()->createBuffer()); clearCachedMaxIndices(); } @@ -56,7 +52,7 @@ WebGLBuffer::~WebGLBuffer() void WebGLBuffer::deleteObjectImpl(GraphicsContext3D* context3d, Platform3DObject object) { - context3d->deleteBuffer(object); + context3d->deleteBuffer(object); } bool WebGLBuffer::associateBufferDataImpl(const void* data, GC3Dsizeiptr byteLength) @@ -69,7 +65,7 @@ bool WebGLBuffer::associateBufferDataImpl(const void* data, GC3Dsizeiptr byteLen m_byteLength = byteLength; clearCachedMaxIndices(); if (byteLength) { - m_elementArrayBuffer = ArrayBuffer::create(byteLength, 1); + m_elementArrayBuffer = ArrayBuffer::tryCreate(byteLength, 1); if (!m_elementArrayBuffer) { m_byteLength = 0; return false; @@ -81,19 +77,31 @@ bool WebGLBuffer::associateBufferDataImpl(const void* data, GC3Dsizeiptr byteLen memcpy(m_elementArrayBuffer->data(), data, byteLength); } } else - m_elementArrayBuffer = 0; + m_elementArrayBuffer = nullptr; return true; case GraphicsContext3D::ARRAY_BUFFER: m_byteLength = byteLength; return true; default: +#if ENABLE(WEBGL2) + switch (m_target) { + case GraphicsContext3D::COPY_READ_BUFFER: + case GraphicsContext3D::COPY_WRITE_BUFFER: + case GraphicsContext3D::PIXEL_PACK_BUFFER: + case GraphicsContext3D::PIXEL_UNPACK_BUFFER: + case GraphicsContext3D::TRANSFORM_FEEDBACK_BUFFER: + case GraphicsContext3D::UNIFORM_BUFFER: + m_byteLength = byteLength; + return true; + } +#endif return false; } } bool WebGLBuffer::associateBufferData(GC3Dsizeiptr size) { - return associateBufferDataImpl(0, size); + return associateBufferDataImpl(nullptr, size); } bool WebGLBuffer::associateBufferData(ArrayBuffer* array) @@ -135,6 +143,17 @@ bool WebGLBuffer::associateBufferSubDataImpl(GC3Dintptr offset, const void* data case GraphicsContext3D::ARRAY_BUFFER: return true; default: +#if ENABLE(WEBGL2) + switch (m_target) { + case GraphicsContext3D::COPY_READ_BUFFER: + case GraphicsContext3D::COPY_WRITE_BUFFER: + case GraphicsContext3D::PIXEL_PACK_BUFFER: + case GraphicsContext3D::PIXEL_UNPACK_BUFFER: + case GraphicsContext3D::TRANSFORM_FEEDBACK_BUFFER: + case GraphicsContext3D::UNIFORM_BUFFER: + return true; + } +#endif return false; } } @@ -153,39 +172,104 @@ bool WebGLBuffer::associateBufferSubData(GC3Dintptr offset, ArrayBufferView* arr return associateBufferSubDataImpl(offset, array->baseAddress(), array->byteLength()); } +bool WebGLBuffer::associateCopyBufferSubData(const WebGLBuffer& readBuffer, GC3Dintptr readOffset, GC3Dintptr writeOffset, GC3Dsizeiptr size) +{ + if (readOffset < 0 || writeOffset < 0 || size < 0) + return false; + + if (size) { + Checked<GC3Dintptr, RecordOverflow> checkedReadBufferOffset(readOffset); + Checked<GC3Dsizeiptr, RecordOverflow> checkedDataLength(size); + Checked<GC3Dintptr, RecordOverflow> checkedReadBufferMax = checkedReadBufferOffset + checkedDataLength; + if (checkedReadBufferMax.hasOverflowed() || readOffset > readBuffer.byteLength() || checkedReadBufferMax.unsafeGet() > readBuffer.byteLength()) + return false; + + Checked<GC3Dintptr, RecordOverflow> checkedWriteBufferOffset(writeOffset); + Checked<GC3Dintptr, RecordOverflow> checkedWriteBufferMax = checkedWriteBufferOffset + checkedDataLength; + if (checkedWriteBufferMax.hasOverflowed() || writeOffset > m_byteLength || checkedWriteBufferMax.unsafeGet() > m_byteLength) + return false; + } + + switch (m_target) { + case GraphicsContext3D::ELEMENT_ARRAY_BUFFER: + clearCachedMaxIndices(); + if (size) { + if (!m_elementArrayBuffer) + return false; + memcpy(static_cast<unsigned char*>(m_elementArrayBuffer->data()) + writeOffset, static_cast<const unsigned char*>(readBuffer.elementArrayBuffer()->data()) + readOffset, size); + } + return true; + case GraphicsContext3D::ARRAY_BUFFER: + return true; + default: +#if ENABLE(WEBGL2) + switch (m_target) { + case GraphicsContext3D::COPY_READ_BUFFER: + case GraphicsContext3D::COPY_WRITE_BUFFER: + case GraphicsContext3D::PIXEL_PACK_BUFFER: + case GraphicsContext3D::PIXEL_UNPACK_BUFFER: + case GraphicsContext3D::TRANSFORM_FEEDBACK_BUFFER: + case GraphicsContext3D::UNIFORM_BUFFER: + return true; + } +#endif + return false; + } +} + +void WebGLBuffer::disassociateBufferData() +{ + m_byteLength = 0; + clearCachedMaxIndices(); +} + GC3Dsizeiptr WebGLBuffer::byteLength() const { return m_byteLength; } -int WebGLBuffer::getCachedMaxIndex(GC3Denum type) +std::optional<unsigned> WebGLBuffer::getCachedMaxIndex(GC3Denum type) { - for (size_t i = 0; i < WTF_ARRAY_LENGTH(m_maxIndexCache); ++i) - if (m_maxIndexCache[i].type == type) - return m_maxIndexCache[i].maxIndex; - return -1; + for (auto& cache : m_maxIndexCache) { + if (cache.type == type) + return cache.maxIndex; + } + return std::nullopt; } -void WebGLBuffer::setCachedMaxIndex(GC3Denum type, int value) +void WebGLBuffer::setCachedMaxIndex(GC3Denum type, unsigned value) { - size_t numEntries = WTF_ARRAY_LENGTH(m_maxIndexCache); - for (size_t i = 0; i < numEntries; ++i) - if (m_maxIndexCache[i].type == type) { - m_maxIndexCache[i].maxIndex = value; + for (auto& cache : m_maxIndexCache) { + if (cache.type == type) { + cache.maxIndex = value; return; } + } m_maxIndexCache[m_nextAvailableCacheEntry].type = type; m_maxIndexCache[m_nextAvailableCacheEntry].maxIndex = value; - m_nextAvailableCacheEntry = (m_nextAvailableCacheEntry + 1) % numEntries; + m_nextAvailableCacheEntry = (m_nextAvailableCacheEntry + 1) % WTF_ARRAY_LENGTH(m_maxIndexCache); } -void WebGLBuffer::setTarget(GC3Denum target) +void WebGLBuffer::setTarget(GC3Denum target, bool forWebGL2) { // In WebGL, a buffer is bound to one target in its lifetime if (m_target) return; if (target == GraphicsContext3D::ARRAY_BUFFER || target == GraphicsContext3D::ELEMENT_ARRAY_BUFFER) m_target = target; + else if (forWebGL2) { +#if ENABLE(WEBGL2) + switch (target) { + case GraphicsContext3D::COPY_READ_BUFFER: + case GraphicsContext3D::COPY_WRITE_BUFFER: + case GraphicsContext3D::PIXEL_PACK_BUFFER: + case GraphicsContext3D::PIXEL_UNPACK_BUFFER: + case GraphicsContext3D::TRANSFORM_FEEDBACK_BUFFER: + case GraphicsContext3D::UNIFORM_BUFFER: + m_target = target; + } +#endif + } } void WebGLBuffer::clearCachedMaxIndices() |