// static angle::Result VertexDataManager::StoreStaticAttrib(const gl::Context *context, TranslatedAttribute *translated) { ASSERT(translated->attribute && translated->binding); const auto &attrib = *translated->attribute; const auto &binding = *translated->binding; gl::Buffer *buffer = binding.getBuffer().get(); ASSERT(buffer && attrib.enabled && !DirectStoragePossible(context, attrib, binding)); BufferD3D *bufferD3D = GetImplAs<BufferD3D>(buffer); // Compute source data pointer const uint8_t *sourceData = nullptr; const int offset = static_cast<int>(ComputeVertexAttributeOffset(attrib, binding)); ANGLE_TRY(bufferD3D->getData(context, &sourceData)); sourceData += offset; unsigned int streamOffset = 0; translated->storage = nullptr; ANGLE_TRY(bufferD3D->getFactory()->getVertexSpaceRequired(context, attrib, binding, 1, 0, &translated->stride)); auto *staticBuffer = bufferD3D->getStaticVertexBuffer(attrib, binding); ASSERT(staticBuffer); if (staticBuffer->empty()) { // Convert the entire buffer int totalCount = ElementsInBuffer(attrib, binding, static_cast<unsigned int>(bufferD3D->getSize())); int startIndex = offset / static_cast<int>(ComputeVertexAttributeStride(attrib, binding)); ANGLE_TRY(staticBuffer->storeStaticAttribute(context, attrib, binding, -startIndex, totalCount, 0, sourceData)); } unsigned int firstElementOffset = (static_cast<unsigned int>(offset) / static_cast<unsigned int>(ComputeVertexAttributeStride(attrib, binding))) * translated->stride; VertexBuffer *vertexBuffer = staticBuffer->getVertexBuffer(); CheckedNumeric<unsigned int> checkedOffset(streamOffset); checkedOffset += firstElementOffset; ANGLE_CHECK_HR_MATH(GetImplAs<ContextD3D>(context), checkedOffset.IsValid()); translated->vertexBuffer.set(vertexBuffer); translated->serial = vertexBuffer->getSerial(); translated->baseOffset = streamOffset + firstElementOffset; // Instanced vertices do not apply the 'start' offset translated->usesFirstVertexOffset = (binding.getDivisor() == 0); return angle::Result::Continue(); }
PassRefPtr<DataView> DataView::create(PassRefPtr<ArrayBuffer> buffer, unsigned byteOffset, unsigned byteLength) { RELEASE_ASSERT(byteOffset <= buffer->byteLength()); CheckedInt<uint32_t> checkedOffset(byteOffset); CheckedInt<uint32_t> checkedLength(byteLength); CheckedInt<uint32_t> checkedMax = checkedOffset + checkedLength; RELEASE_ASSERT(checkedMax.isValid()); RELEASE_ASSERT(checkedMax.value() <= buffer->byteLength()); return adoptRef(new DataView(buffer, byteOffset, byteLength)); }
PassRefPtr<DataView> DataView::create(PassRefPtr<ArrayBuffer> buffer, unsigned byteOffset, unsigned byteLength) { if (byteOffset > buffer->byteLength()) return 0; Checked<uint32_t, RecordOverflow> checkedOffset(byteOffset); Checked<uint32_t, RecordOverflow> checkedLength(byteLength); Checked<uint32_t, RecordOverflow> checkedMax = checkedOffset + checkedLength; if (checkedMax.hasOverflowed() || checkedMax.unsafeGet() > buffer->byteLength()) return 0; return adoptRef(new DataView(buffer, byteOffset, byteLength)); }
PassRefPtr<DataView> DataView::create(PassRefPtr<ArrayBuffer> buffer, unsigned byteOffset, unsigned byteLength) { if (byteOffset > buffer->byteLength()) return 0; CheckedInt<uint32_t> checkedOffset(byteOffset); CheckedInt<uint32_t> checkedLength(byteLength); CheckedInt<uint32_t> checkedMax = checkedOffset + checkedLength; if (!checkedMax.isValid() || checkedMax.value() > buffer->byteLength()) return 0; return adoptRef(new DataView(buffer, byteOffset, byteLength)); }
bool WebGLBuffer::associateBufferDataImpl(ArrayBuffer* array, GC3Dintptr byteOffset, GC3Dsizeiptr byteLength) { if (byteLength < 0 || byteOffset < 0) return false; if (array && byteLength) { CheckedInt<GC3Dintptr> checkedOffset(byteOffset); CheckedInt<GC3Dsizeiptr> checkedLength(byteLength); CheckedInt<GC3Dintptr> checkedMax = checkedOffset + checkedLength; if (!checkedMax.valid() || checkedMax.value() > static_cast<int32_t>(array->byteLength())) return false; } switch (m_target) { case GraphicsContext3D::ELEMENT_ARRAY_BUFFER: m_byteLength = byteLength; clearCachedMaxIndices(); if (byteLength) { m_elementArrayBuffer = ArrayBuffer::create(byteLength, 1); if (!m_elementArrayBuffer) { m_byteLength = 0; return false; } if (array) { // We must always clone the incoming data because client-side // modifications without calling bufferData or bufferSubData // must never be able to change the validation results. memcpy(static_cast<unsigned char*>(m_elementArrayBuffer->data()), static_cast<unsigned char*>(array->data()) + byteOffset, byteLength); } } else m_elementArrayBuffer = 0; return true; case GraphicsContext3D::ARRAY_BUFFER: m_byteLength = byteLength; return true; default: return false; } }