void WebGL2Context::CopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size) { if (IsContextLost()) return; if (!ValidateBufferTarget(readTarget, "copyBufferSubData") || !ValidateBufferTarget(writeTarget, "copyBufferSubData")) { return; } const WebGLRefPtr<WebGLBuffer>& readBufferSlot = GetBufferSlotByTarget(readTarget); const WebGLRefPtr<WebGLBuffer>& writeBufferSlot = GetBufferSlotByTarget(writeTarget); if (!readBufferSlot || !writeBufferSlot) return; const WebGLBuffer* readBuffer = readBufferSlot.get(); if (!readBuffer) return ErrorInvalidOperation("copyBufferSubData: No buffer bound to readTarget"); WebGLBuffer* writeBuffer = writeBufferSlot.get(); if (!writeBuffer) return ErrorInvalidOperation("copyBufferSubData: No buffer bound to writeTarget"); if (!ValidateDataOffsetSize(readOffset, size, readBuffer->ByteLength(), "copyBufferSubData")) { return; } if (!ValidateDataOffsetSize(writeOffset, size, writeBuffer->ByteLength(), "copyBufferSubData")) { return; } if (readTarget == writeTarget && !ValidateDataRanges(readOffset, writeOffset, size, "copyBufferSubData")) { return; } WebGLBuffer::Kind readType = readBuffer->Content(); WebGLBuffer::Kind writeType = writeBuffer->Content(); if (readType != WebGLBuffer::Kind::Undefined && writeType != WebGLBuffer::Kind::Undefined && writeType != readType) { ErrorInvalidOperation("copyBufferSubData: Can't copy %s data to %s data", (readType == WebGLBuffer::Kind::OtherData) ? "other" : "element", (writeType == WebGLBuffer::Kind::OtherData) ? "other" : "element"); return; } WebGLContextUnchecked::CopyBufferSubData(readTarget, writeTarget, readOffset, writeOffset, size); if (writeType == WebGLBuffer::Kind::Undefined) { writeBuffer->BindTo( (readType == WebGLBuffer::Kind::OtherData) ? LOCAL_GL_ARRAY_BUFFER : LOCAL_GL_ELEMENT_ARRAY_BUFFER); } }
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 (readBuffer->mNumActiveTFOs || writeBuffer->mNumActiveTFOs) { ErrorInvalidOperation("%s: Buffer is bound to an active transform feedback" " object.", funcName); 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 && !ValidateDataRanges(readOffset, writeOffset, size, 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(); gl->fCopyBufferSubData(readTarget, writeTarget, readOffset, writeOffset, size); }