123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159 |
- /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
- /* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- #include "WebGL2Context.h"
- #include "GLContext.h"
- #include "WebGLBuffer.h"
- #include "WebGLTransformFeedback.h"
- namespace mozilla {
- // -------------------------------------------------------------------------
- // Buffer objects
- void
- WebGL2Context::CopyBufferSubData(GLenum readTarget, GLenum writeTarget,
- GLintptr readOffset, GLintptr writeOffset,
- GLsizeiptr size)
- {
- const char funcName[] = "copyBufferSubData";
- if (IsContextLost())
- return;
- const auto& readBuffer = ValidateBufferSelection(funcName, readTarget);
- if (!readBuffer)
- return;
- const auto& writeBuffer = ValidateBufferSelection(funcName, writeTarget);
- if (!writeBuffer)
- return;
- if (!ValidateNonNegative(funcName, "readOffset", readOffset) ||
- !ValidateNonNegative(funcName, "writeOffset", writeOffset) ||
- !ValidateNonNegative(funcName, "size", size))
- {
- return;
- }
- const auto fnValidateOffsetSize = [&](const char* info, GLintptr offset,
- const WebGLBuffer* buffer)
- {
- const auto neededBytes = CheckedInt<size_t>(offset) + size;
- if (!neededBytes.isValid() || neededBytes.value() > buffer->ByteLength()) {
- ErrorInvalidValue("%s: Invalid %s range.", funcName, info);
- return false;
- }
- return true;
- };
- if (!fnValidateOffsetSize("read", readOffset, readBuffer) ||
- !fnValidateOffsetSize("write", writeOffset, writeBuffer))
- {
- return;
- }
- if (readBuffer == writeBuffer) {
- MOZ_ASSERT((CheckedInt<WebGLsizeiptr>(readOffset) + size).isValid());
- MOZ_ASSERT((CheckedInt<WebGLsizeiptr>(writeOffset) + size).isValid());
- const bool separate = (readOffset + size <= writeOffset ||
- writeOffset + size <= readOffset);
- if (!separate) {
- ErrorInvalidValue("%s: ranges [readOffset, readOffset + size) and"
- " [writeOffset, writeOffset + size) overlap",
- funcName);
- return;
- }
- }
- const auto& readType = readBuffer->Content();
- const auto& writeType = writeBuffer->Content();
- MOZ_ASSERT(readType != WebGLBuffer::Kind::Undefined);
- MOZ_ASSERT(writeType != WebGLBuffer::Kind::Undefined);
- if (writeType != readType) {
- ErrorInvalidOperation("%s: Can't copy %s data to %s data.",
- funcName,
- (readType == WebGLBuffer::Kind::OtherData) ? "other"
- : "element",
- (writeType == WebGLBuffer::Kind::OtherData) ? "other"
- : "element");
- return;
- }
- gl->MakeCurrent();
- const ScopedLazyBind readBind(gl, readTarget, readBuffer);
- const ScopedLazyBind writeBind(gl, writeTarget, writeBuffer);
- gl->fCopyBufferSubData(readTarget, writeTarget, readOffset, writeOffset, size);
- }
- void
- WebGL2Context::GetBufferSubData(GLenum target, GLintptr srcByteOffset,
- const dom::ArrayBufferView& dstData, GLuint dstElemOffset,
- GLuint dstElemCountOverride)
- {
- const char funcName[] = "getBufferSubData";
- if (IsContextLost())
- return;
- if (!ValidateNonNegative(funcName, "srcByteOffset", srcByteOffset))
- return;
- uint8_t* bytes;
- size_t byteLen;
- if (!ValidateArrayBufferView(funcName, dstData, dstElemOffset, dstElemCountOverride,
- &bytes, &byteLen))
- {
- return;
- }
- ////
- const auto& buffer = ValidateBufferSelection(funcName, target);
- if (!buffer)
- return;
- if (!buffer->ValidateRange(funcName, srcByteOffset, byteLen))
- return;
- ////
- if (!CheckedInt<GLsizeiptr>(byteLen).isValid()) {
- ErrorOutOfMemory("%s: Size too large.", funcName);
- return;
- }
- const GLsizeiptr glByteLen(byteLen);
- ////
- gl->MakeCurrent();
- const ScopedLazyBind readBind(gl, target, buffer);
- if (byteLen) {
- const bool isTF = (target == LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER);
- GLenum mapTarget = target;
- if (isTF) {
- gl->fBindTransformFeedback(LOCAL_GL_TRANSFORM_FEEDBACK, mEmptyTFO);
- gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, buffer->mGLName);
- mapTarget = LOCAL_GL_ARRAY_BUFFER;
- }
- const auto mappedBytes = gl->fMapBufferRange(mapTarget, srcByteOffset, glByteLen,
- LOCAL_GL_MAP_READ_BIT);
- memcpy(bytes, mappedBytes, byteLen);
- gl->fUnmapBuffer(mapTarget);
- if (isTF) {
- const GLuint vbo = (mBoundArrayBuffer ? mBoundArrayBuffer->mGLName : 0);
- gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, vbo);
- const GLuint tfo = (mBoundTransformFeedback ? mBoundTransformFeedback->mGLName
- : 0);
- gl->fBindTransformFeedback(LOCAL_GL_TRANSFORM_FEEDBACK, tfo);
- }
- }
- }
- } // namespace mozilla
|