Backed out changeset 7b83373f7a9e (bug 1883860) for causing build bustages @ caps...
[gecko.git] / dom / canvas / WebGL2ContextBuffers.cpp
blobebbda995ee552514154a593ab5be7e2cae21354a
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "WebGL2Context.h"
8 #include "ClientWebGLContext.h"
9 #include "GLContext.h"
10 #include "WebGLBuffer.h"
11 #include "WebGLTransformFeedback.h"
13 namespace mozilla {
15 // -------------------------------------------------------------------------
16 // Buffer objects
18 void WebGL2Context::CopyBufferSubData(GLenum readTarget, GLenum writeTarget,
19 uint64_t readOffset, uint64_t writeOffset,
20 uint64_t size) const {
21 const FuncScope funcScope(*this, "copyBufferSubData");
22 if (IsContextLost()) return;
24 const auto& readBuffer = ValidateBufferSelection(readTarget);
25 if (!readBuffer) return;
27 const auto& writeBuffer = ValidateBufferSelection(writeTarget);
28 if (!writeBuffer) return;
30 if (!CheckedInt<GLintptr>(readOffset).isValid() ||
31 !CheckedInt<GLintptr>(writeOffset).isValid() ||
32 !CheckedInt<GLsizeiptr>(size).isValid())
33 return ErrorOutOfMemory("offset or size too large for platform.");
35 const auto fnValidateOffsetSize = [&](const char* info, WebGLintptr offset,
36 const WebGLBuffer* buffer) {
37 const auto neededBytes = CheckedInt<uint64_t>(offset) + size;
38 if (!neededBytes.isValid() || neededBytes.value() > buffer->ByteLength()) {
39 ErrorInvalidValue("Invalid %s range.", info);
40 return false;
42 return true;
45 if (!fnValidateOffsetSize("read", readOffset, readBuffer) ||
46 !fnValidateOffsetSize("write", writeOffset, writeBuffer)) {
47 return;
50 if (readBuffer == writeBuffer) {
51 const bool separate =
52 (readOffset + size <= writeOffset || writeOffset + size <= readOffset);
53 if (!separate) {
54 ErrorInvalidValue(
55 "Ranges [readOffset, readOffset + size) and"
56 " [writeOffset, writeOffset + size) overlap.");
57 return;
61 const auto& readType = readBuffer->Content();
62 const auto& writeType = writeBuffer->Content();
63 MOZ_ASSERT(readType != WebGLBuffer::Kind::Undefined);
64 MOZ_ASSERT(writeType != WebGLBuffer::Kind::Undefined);
65 if (writeType != readType) {
66 ErrorInvalidOperation(
67 "Can't copy %s data to %s data.",
68 (readType == WebGLBuffer::Kind::OtherData) ? "other" : "element",
69 (writeType == WebGLBuffer::Kind::OtherData) ? "other" : "element");
70 return;
73 const ScopedLazyBind readBind(gl, readTarget, readBuffer);
74 const ScopedLazyBind writeBind(gl, writeTarget, writeBuffer);
75 gl->fCopyBufferSubData(readTarget, writeTarget, readOffset, writeOffset,
76 size);
78 writeBuffer->ResetLastUpdateFenceId();
81 bool WebGL2Context::GetBufferSubData(GLenum target, uint64_t srcByteOffset,
82 const Range<uint8_t>& dest) const {
83 const FuncScope funcScope(*this, "getBufferSubData");
84 if (IsContextLost()) return false;
86 const auto& buffer = ValidateBufferSelection(target);
87 if (!buffer) return false;
89 const auto byteLen = dest.length();
90 if (!buffer->ValidateRange(srcByteOffset, byteLen)) return false;
92 ////
94 if (!CheckedInt<GLintptr>(srcByteOffset).isValid() ||
95 !CheckedInt<GLsizeiptr>(byteLen).isValid()) {
96 ErrorOutOfMemory("offset or size too large for platform.");
97 return false;
99 const GLsizeiptr glByteLen(byteLen);
101 ////
103 switch (buffer->mUsage) {
104 case LOCAL_GL_STATIC_READ:
105 case LOCAL_GL_STREAM_READ:
106 case LOCAL_GL_DYNAMIC_READ:
107 if (mCompletedFenceId < buffer->mLastUpdateFenceId) {
108 GenerateWarning(
109 "Reading from a buffer without checking for previous"
110 " command completion likely causes pipeline stalls."
111 " Please use FenceSync.");
113 break;
114 default:
115 GenerateWarning(
116 "Reading from a buffer with usage other than *_READ"
117 " causes pipeline stalls. Copy through a STREAM_READ buffer.");
118 break;
121 ////
123 const ScopedLazyBind readBind(gl, target, buffer);
125 if (byteLen) {
126 const bool isTF = (target == LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER);
127 GLenum mapTarget = target;
128 if (isTF) {
129 gl->fBindTransformFeedback(LOCAL_GL_TRANSFORM_FEEDBACK, mEmptyTFO);
130 gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, buffer->mGLName);
131 mapTarget = LOCAL_GL_ARRAY_BUFFER;
134 const auto mappedBytes = gl->fMapBufferRange(
135 mapTarget, srcByteOffset, glByteLen, LOCAL_GL_MAP_READ_BIT);
136 memcpy(dest.begin().get(), mappedBytes, dest.length());
137 gl->fUnmapBuffer(mapTarget);
139 if (isTF) {
140 const GLuint vbo = (mBoundArrayBuffer ? mBoundArrayBuffer->mGLName : 0);
141 gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, vbo);
142 const GLuint tfo =
143 (mBoundTransformFeedback ? mBoundTransformFeedback->mGLName : 0);
144 gl->fBindTransformFeedback(LOCAL_GL_TRANSFORM_FEEDBACK, tfo);
147 return true;
150 } // namespace mozilla