2013-08-20 19:36:19 +04:00
|
|
|
/* -*- 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 "WebGLContext.h"
|
2014-11-14 07:03:50 +03:00
|
|
|
|
2013-09-04 16:14:52 +04:00
|
|
|
#include "GLContext.h"
|
2013-08-20 19:36:19 +04:00
|
|
|
#include "WebGLBuffer.h"
|
|
|
|
#include "WebGLVertexArray.h"
|
|
|
|
|
2014-11-14 07:03:50 +03:00
|
|
|
namespace mozilla {
|
2013-08-20 19:36:19 +04:00
|
|
|
|
2016-09-10 07:02:54 +03:00
|
|
|
WebGLRefPtr<WebGLBuffer>*
|
|
|
|
WebGLContext::ValidateBufferSlot(const char* funcName, GLenum target)
|
2014-12-05 10:04:55 +03:00
|
|
|
{
|
2016-09-10 07:02:54 +03:00
|
|
|
WebGLRefPtr<WebGLBuffer>* slot = nullptr;
|
2014-12-05 10:04:55 +03:00
|
|
|
|
2016-09-10 07:02:54 +03:00
|
|
|
switch (target) {
|
|
|
|
case LOCAL_GL_ARRAY_BUFFER:
|
|
|
|
slot = &mBoundArrayBuffer;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case LOCAL_GL_ELEMENT_ARRAY_BUFFER:
|
|
|
|
slot = &(mBoundVertexArray->mElementArrayBuffer);
|
|
|
|
break;
|
|
|
|
}
|
2014-12-05 10:04:55 +03:00
|
|
|
|
2016-09-10 07:02:54 +03:00
|
|
|
if (IsWebGL2()) {
|
|
|
|
switch (target) {
|
|
|
|
case LOCAL_GL_COPY_READ_BUFFER:
|
|
|
|
slot = &mBoundCopyReadBuffer;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case LOCAL_GL_COPY_WRITE_BUFFER:
|
|
|
|
slot = &mBoundCopyWriteBuffer;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case LOCAL_GL_PIXEL_PACK_BUFFER:
|
|
|
|
slot = &mBoundPixelPackBuffer;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case LOCAL_GL_PIXEL_UNPACK_BUFFER:
|
|
|
|
slot = &mBoundPixelUnpackBuffer;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER:
|
|
|
|
slot = &(mBoundTransformFeedback->mGenericBufferBinding);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case LOCAL_GL_UNIFORM_BUFFER:
|
|
|
|
slot = &mBoundUniformBuffer;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!slot) {
|
|
|
|
ErrorInvalidEnum("%s: Bad `target`: 0x%04x", funcName, target);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return slot;
|
2014-12-05 10:04:55 +03:00
|
|
|
}
|
|
|
|
|
2016-09-10 07:02:54 +03:00
|
|
|
WebGLBuffer*
|
|
|
|
WebGLContext::ValidateBufferSelection(const char* funcName, GLenum target)
|
|
|
|
{
|
|
|
|
const auto& slot = ValidateBufferSlot(funcName, target);
|
|
|
|
if (!slot)
|
|
|
|
return nullptr;
|
|
|
|
const auto& buffer = *slot;
|
|
|
|
|
|
|
|
if (!buffer) {
|
|
|
|
ErrorInvalidOperation("%s: Buffer for `target` is null.", funcName);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return buffer.get();
|
|
|
|
}
|
|
|
|
|
|
|
|
IndexedBufferBinding*
|
|
|
|
WebGLContext::ValidateIndexedBufferSlot(const char* funcName, GLenum target, GLuint index)
|
2014-12-05 10:04:55 +03:00
|
|
|
{
|
2016-09-10 07:02:54 +03:00
|
|
|
decltype(mIndexedUniformBufferBindings)* bindings;
|
|
|
|
const char* maxIndexEnum;
|
|
|
|
switch (target) {
|
|
|
|
case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER:
|
|
|
|
bindings = &(mBoundTransformFeedback->mIndexedBindings);
|
|
|
|
maxIndexEnum = "MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case LOCAL_GL_UNIFORM_BUFFER:
|
|
|
|
bindings = &mIndexedUniformBufferBindings;
|
|
|
|
maxIndexEnum = "MAX_UNIFORM_BUFFER_BINDINGS";
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
ErrorInvalidEnum("%s: Bad `target`: 0x%04x", funcName, target);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (index >= bindings->size()) {
|
|
|
|
ErrorInvalidOperation("%s: `index` >= %s.", funcName, maxIndexEnum);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return &(*bindings)[index];
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////
|
|
|
|
|
2013-08-20 19:36:19 +04:00
|
|
|
void
|
2014-11-14 07:03:50 +03:00
|
|
|
WebGLContext::BindBuffer(GLenum target, WebGLBuffer* buffer)
|
2013-08-20 19:36:19 +04:00
|
|
|
{
|
2016-09-10 07:02:54 +03:00
|
|
|
const char funcName[] = "bindBuffer";
|
2013-09-04 16:14:44 +04:00
|
|
|
if (IsContextLost())
|
2013-08-20 19:36:19 +04:00
|
|
|
return;
|
|
|
|
|
2016-09-10 07:02:54 +03:00
|
|
|
if (!ValidateObjectAllowDeletedOrNull(funcName, buffer))
|
2013-08-20 19:36:19 +04:00
|
|
|
return;
|
|
|
|
|
|
|
|
if (buffer && buffer->IsDeleted())
|
2016-11-16 05:12:10 +03:00
|
|
|
return ErrorInvalidOperation("%s: Cannot bind a deleted object.", funcName);
|
2013-08-20 19:36:19 +04:00
|
|
|
|
2016-09-10 07:02:54 +03:00
|
|
|
const auto& slot = ValidateBufferSlot(funcName, target);
|
|
|
|
if (!slot)
|
2013-08-20 19:36:19 +04:00
|
|
|
return;
|
|
|
|
|
2016-09-18 02:44:56 +03:00
|
|
|
if (buffer && !buffer->ValidateCanBindToTarget(funcName, target))
|
2014-12-05 10:04:55 +03:00
|
|
|
return;
|
2013-08-20 19:36:19 +04:00
|
|
|
|
2016-09-10 07:02:54 +03:00
|
|
|
gl->MakeCurrent();
|
|
|
|
gl->fBindBuffer(target, buffer ? buffer->mGLName : 0);
|
|
|
|
|
|
|
|
*slot = buffer;
|
|
|
|
if (buffer) {
|
|
|
|
buffer->SetContentAfterBind(target);
|
|
|
|
}
|
2016-09-26 23:38:56 +03:00
|
|
|
|
|
|
|
switch (target) {
|
|
|
|
case LOCAL_GL_PIXEL_PACK_BUFFER:
|
|
|
|
case LOCAL_GL_PIXEL_UNPACK_BUFFER:
|
|
|
|
gl->fBindBuffer(target, 0);
|
|
|
|
break;
|
|
|
|
}
|
2016-09-10 07:02:54 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////
|
2013-08-20 19:36:19 +04:00
|
|
|
|
2016-09-10 07:02:54 +03:00
|
|
|
bool
|
|
|
|
WebGLContext::ValidateIndexedBufferBinding(const char* funcName, GLenum target,
|
|
|
|
GLuint index,
|
|
|
|
WebGLRefPtr<WebGLBuffer>** const out_genericBinding,
|
|
|
|
IndexedBufferBinding** const out_indexedBinding)
|
|
|
|
{
|
|
|
|
*out_genericBinding = ValidateBufferSlot(funcName, target);
|
|
|
|
if (!*out_genericBinding)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
*out_indexedBinding = ValidateIndexedBufferSlot(funcName, target, index);
|
|
|
|
if (!*out_indexedBinding)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (target == LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER &&
|
|
|
|
mBoundTransformFeedback->mIsActive)
|
|
|
|
{
|
|
|
|
ErrorInvalidOperation("%s: Cannot update indexed buffer bindings on active"
|
|
|
|
" transform feedback objects.",
|
|
|
|
funcName);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
2013-08-20 19:36:19 +04:00
|
|
|
}
|
|
|
|
|
2013-08-20 19:36:20 +04:00
|
|
|
void
|
2013-09-04 16:14:43 +04:00
|
|
|
WebGLContext::BindBufferBase(GLenum target, GLuint index, WebGLBuffer* buffer)
|
2013-08-20 19:36:20 +04:00
|
|
|
{
|
2016-09-10 07:02:54 +03:00
|
|
|
const char funcName[] = "bindBufferBase";
|
2013-09-04 16:14:44 +04:00
|
|
|
if (IsContextLost())
|
2013-08-20 19:36:20 +04:00
|
|
|
return;
|
|
|
|
|
2016-09-10 07:02:54 +03:00
|
|
|
if (!ValidateObjectAllowDeletedOrNull(funcName, buffer))
|
2013-08-20 19:36:20 +04:00
|
|
|
return;
|
|
|
|
|
2014-12-05 10:04:55 +03:00
|
|
|
if (buffer && buffer->IsDeleted())
|
2016-11-16 05:12:10 +03:00
|
|
|
return ErrorInvalidOperation("%s: Cannot bind a deleted object.", funcName);
|
2013-08-20 19:36:20 +04:00
|
|
|
|
2016-09-10 07:02:54 +03:00
|
|
|
WebGLRefPtr<WebGLBuffer>* genericBinding;
|
|
|
|
IndexedBufferBinding* indexedBinding;
|
|
|
|
if (!ValidateIndexedBufferBinding(funcName, target, index, &genericBinding,
|
|
|
|
&indexedBinding))
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2013-08-20 19:36:20 +04:00
|
|
|
|
2016-09-18 02:44:56 +03:00
|
|
|
if (buffer && !buffer->ValidateCanBindToTarget(funcName, target))
|
|
|
|
return;
|
|
|
|
|
2016-09-10 07:02:54 +03:00
|
|
|
////
|
2014-05-07 07:11:18 +04:00
|
|
|
|
2016-09-10 07:02:54 +03:00
|
|
|
gl->MakeCurrent();
|
|
|
|
gl->fBindBufferBase(target, index, buffer ? buffer->mGLName : 0);
|
2013-08-20 19:36:20 +04:00
|
|
|
|
2016-09-10 07:02:54 +03:00
|
|
|
////
|
2013-08-20 19:36:20 +04:00
|
|
|
|
2016-09-10 07:02:54 +03:00
|
|
|
*genericBinding = buffer;
|
|
|
|
indexedBinding->mBufferBinding = buffer;
|
|
|
|
indexedBinding->mRangeStart = 0;
|
|
|
|
indexedBinding->mRangeSize = 0;
|
2013-08-20 19:36:20 +04:00
|
|
|
|
2016-09-10 07:02:54 +03:00
|
|
|
if (buffer) {
|
|
|
|
buffer->SetContentAfterBind(target);
|
|
|
|
}
|
2013-08-20 19:36:20 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2013-09-04 16:14:43 +04:00
|
|
|
WebGLContext::BindBufferRange(GLenum target, GLuint index, WebGLBuffer* buffer,
|
2013-08-20 19:36:20 +04:00
|
|
|
WebGLintptr offset, WebGLsizeiptr size)
|
|
|
|
{
|
2016-09-10 07:02:54 +03:00
|
|
|
const char funcName[] = "bindBufferRange";
|
2013-09-04 16:14:44 +04:00
|
|
|
if (IsContextLost())
|
2013-08-20 19:36:20 +04:00
|
|
|
return;
|
|
|
|
|
2016-09-10 07:02:54 +03:00
|
|
|
if (!ValidateObjectAllowDeletedOrNull(funcName, buffer))
|
2013-08-20 19:36:20 +04:00
|
|
|
return;
|
|
|
|
|
|
|
|
if (buffer && buffer->IsDeleted())
|
2016-11-16 05:12:10 +03:00
|
|
|
return ErrorInvalidOperation("%s: Cannot bind a deleted object.", funcName);
|
2013-08-20 19:36:20 +04:00
|
|
|
|
2016-09-10 07:02:54 +03:00
|
|
|
if (!ValidateNonNegative(funcName, "offset", offset) ||
|
|
|
|
!ValidateNonNegative(funcName, "size", size))
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
WebGLRefPtr<WebGLBuffer>* genericBinding;
|
|
|
|
IndexedBufferBinding* indexedBinding;
|
|
|
|
if (!ValidateIndexedBufferBinding(funcName, target, index, &genericBinding,
|
|
|
|
&indexedBinding))
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-09-18 02:44:56 +03:00
|
|
|
if (buffer && !buffer->ValidateCanBindToTarget(funcName, target))
|
|
|
|
return;
|
|
|
|
|
|
|
|
////
|
|
|
|
|
2016-09-10 07:02:54 +03:00
|
|
|
gl->MakeCurrent();
|
|
|
|
|
2014-11-26 05:00:06 +03:00
|
|
|
switch (target) {
|
|
|
|
case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER:
|
2016-09-10 07:02:54 +03:00
|
|
|
if (offset % 4 != 0 || size % 4 != 0) {
|
|
|
|
ErrorInvalidValue("%s: For %s, `offset` and `size` must be multiples of 4.",
|
|
|
|
funcName, "TRANSFORM_FEEDBACK_BUFFER");
|
|
|
|
return;
|
|
|
|
}
|
2015-04-21 04:02:34 +03:00
|
|
|
break;
|
2014-11-26 05:00:06 +03:00
|
|
|
|
2014-12-05 10:04:55 +03:00
|
|
|
case LOCAL_GL_UNIFORM_BUFFER:
|
2016-09-10 07:02:54 +03:00
|
|
|
{
|
|
|
|
GLuint offsetAlignment = 0;
|
|
|
|
gl->GetUIntegerv(LOCAL_GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &offsetAlignment);
|
|
|
|
if (offset % offsetAlignment != 0) {
|
|
|
|
ErrorInvalidValue("%s: For %s, `offset` must be a multiple of %s.",
|
|
|
|
funcName, "UNIFORM_BUFFER",
|
|
|
|
"UNIFORM_BUFFER_OFFSET_ALIGNMENT");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2015-04-21 04:02:34 +03:00
|
|
|
break;
|
2016-09-10 07:02:54 +03:00
|
|
|
}
|
2015-04-21 04:02:34 +03:00
|
|
|
|
2016-09-10 07:02:54 +03:00
|
|
|
////
|
|
|
|
|
|
|
|
#ifdef XP_MACOSX
|
|
|
|
if (buffer && buffer->Content() == WebGLBuffer::Kind::Undefined &&
|
|
|
|
gl->WorkAroundDriverBugs())
|
|
|
|
{
|
|
|
|
// BindBufferRange will fail if the buffer's contents is undefined.
|
|
|
|
// Bind so driver initializes the buffer.
|
|
|
|
gl->fBindBuffer(target, buffer->mGLName);
|
2014-11-26 05:00:06 +03:00
|
|
|
}
|
2016-09-10 07:02:54 +03:00
|
|
|
#endif
|
2014-11-26 05:00:06 +03:00
|
|
|
|
2016-09-10 07:02:54 +03:00
|
|
|
gl->fBindBufferRange(target, index, buffer ? buffer->mGLName : 0, offset, size);
|
|
|
|
|
|
|
|
////
|
2013-08-20 19:36:20 +04:00
|
|
|
|
2016-09-10 07:02:54 +03:00
|
|
|
*genericBinding = buffer;
|
|
|
|
indexedBinding->mBufferBinding = buffer;
|
|
|
|
indexedBinding->mRangeStart = offset;
|
|
|
|
indexedBinding->mRangeSize = size;
|
2013-08-20 19:36:20 +04:00
|
|
|
|
2016-09-10 07:02:54 +03:00
|
|
|
if (buffer) {
|
|
|
|
buffer->SetContentAfterBind(target);
|
|
|
|
}
|
2013-08-20 19:36:20 +04:00
|
|
|
}
|
|
|
|
|
2016-09-10 07:02:54 +03:00
|
|
|
////////////////////////////////////////
|
|
|
|
|
2013-08-20 19:36:19 +04:00
|
|
|
void
|
2016-10-12 01:40:34 +03:00
|
|
|
WebGLContext::BufferDataImpl(GLenum target, size_t dataLen, const uint8_t* data,
|
|
|
|
GLenum usage)
|
2013-08-20 19:36:19 +04:00
|
|
|
{
|
2016-09-10 07:02:54 +03:00
|
|
|
const char funcName[] = "bufferData";
|
2013-09-04 16:14:39 +04:00
|
|
|
|
2016-09-10 07:02:54 +03:00
|
|
|
const auto& buffer = ValidateBufferSelection(funcName, target);
|
|
|
|
if (!buffer)
|
|
|
|
return;
|
2013-08-20 19:36:20 +04:00
|
|
|
|
2016-10-12 01:40:34 +03:00
|
|
|
buffer->BufferData(target, dataLen, data, usage);
|
2013-08-20 19:36:19 +04:00
|
|
|
}
|
|
|
|
|
2016-10-12 01:40:34 +03:00
|
|
|
////
|
|
|
|
|
2013-08-20 19:36:19 +04:00
|
|
|
void
|
2016-10-12 01:40:34 +03:00
|
|
|
WebGLContext::BufferData(GLenum target, WebGLsizeiptr size, GLenum usage)
|
2013-08-20 19:36:19 +04:00
|
|
|
{
|
2016-09-10 07:02:54 +03:00
|
|
|
const char funcName[] = "bufferData";
|
2013-09-04 16:14:44 +04:00
|
|
|
if (IsContextLost())
|
2013-08-20 19:36:19 +04:00
|
|
|
return;
|
|
|
|
|
2016-10-12 01:40:34 +03:00
|
|
|
if (!ValidateNonNegative(funcName, "size", size))
|
|
|
|
return;
|
2013-08-20 19:36:20 +04:00
|
|
|
|
2016-10-12 01:40:34 +03:00
|
|
|
////
|
2013-09-04 16:14:39 +04:00
|
|
|
|
2016-10-12 01:40:34 +03:00
|
|
|
const UniqueBuffer zeroBuffer(calloc(size, 1));
|
|
|
|
if (!zeroBuffer)
|
|
|
|
return ErrorOutOfMemory("%s: Failed to allocate zeros.", funcName);
|
2016-01-01 22:00:48 +03:00
|
|
|
|
2016-10-12 03:38:45 +03:00
|
|
|
BufferDataImpl(target, size_t(size), (const uint8_t*)zeroBuffer.get(), usage);
|
2013-08-20 19:36:19 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2016-10-12 01:40:34 +03:00
|
|
|
WebGLContext::BufferData(GLenum target, const dom::SharedArrayBuffer& src, GLenum usage)
|
2013-08-20 19:36:19 +04:00
|
|
|
{
|
2016-10-12 01:40:34 +03:00
|
|
|
if (IsContextLost())
|
|
|
|
return;
|
|
|
|
|
|
|
|
src.ComputeLengthAndData();
|
|
|
|
BufferDataImpl(target, src.LengthAllowShared(), src.DataAllowShared(), usage);
|
2015-10-14 08:48:19 +03:00
|
|
|
}
|
2013-08-20 19:36:19 +04:00
|
|
|
|
2015-10-14 08:48:19 +03:00
|
|
|
void
|
2016-10-12 01:40:34 +03:00
|
|
|
WebGLContext::BufferData(GLenum target, const dom::Nullable<dom::ArrayBuffer>& maybeSrc,
|
2015-10-14 08:48:19 +03:00
|
|
|
GLenum usage)
|
|
|
|
{
|
2016-10-12 01:40:34 +03:00
|
|
|
if (IsContextLost())
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (maybeSrc.IsNull())
|
2015-10-14 08:48:19 +03:00
|
|
|
return ErrorInvalidValue("bufferData: null object passed");
|
2016-10-12 01:40:34 +03:00
|
|
|
auto& src = maybeSrc.Value();
|
|
|
|
|
|
|
|
src.ComputeLengthAndData();
|
|
|
|
BufferDataImpl(target, src.LengthAllowShared(), src.DataAllowShared(), usage);
|
2015-10-14 08:48:19 +03:00
|
|
|
}
|
2013-08-20 19:36:19 +04:00
|
|
|
|
2015-10-14 08:48:19 +03:00
|
|
|
void
|
2016-10-12 01:40:34 +03:00
|
|
|
WebGLContext::BufferData(GLenum target, const dom::ArrayBufferView& src, GLenum usage,
|
|
|
|
GLuint srcElemOffset, GLuint srcElemCountOverride)
|
2015-10-14 08:48:19 +03:00
|
|
|
{
|
2016-10-12 01:40:34 +03:00
|
|
|
const char funcName[] = "bufferData";
|
|
|
|
if (IsContextLost())
|
|
|
|
return;
|
|
|
|
|
|
|
|
uint8_t* bytes;
|
|
|
|
size_t byteLen;
|
|
|
|
if (!ValidateArrayBufferView(funcName, src, srcElemOffset, srcElemCountOverride,
|
|
|
|
&bytes, &byteLen))
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
BufferDataImpl(target, byteLen, bytes, usage);
|
2013-08-20 19:36:19 +04:00
|
|
|
}
|
|
|
|
|
2016-09-10 07:02:54 +03:00
|
|
|
////////////////////////////////////////
|
|
|
|
|
2015-10-14 08:48:19 +03:00
|
|
|
void
|
2016-10-12 01:40:34 +03:00
|
|
|
WebGLContext::BufferSubDataImpl(GLenum target, WebGLsizeiptr dstByteOffset,
|
|
|
|
size_t dataLen, const uint8_t* data)
|
2015-10-14 08:48:19 +03:00
|
|
|
{
|
2016-09-10 07:02:54 +03:00
|
|
|
const char funcName[] = "bufferSubData";
|
2013-08-20 19:36:19 +04:00
|
|
|
|
2016-10-12 01:40:34 +03:00
|
|
|
if (!ValidateNonNegative(funcName, "byteOffset", dstByteOffset))
|
2013-08-20 19:36:20 +04:00
|
|
|
return;
|
2013-08-20 19:36:19 +04:00
|
|
|
|
2016-09-10 07:02:54 +03:00
|
|
|
const auto& buffer = ValidateBufferSelection(funcName, target);
|
|
|
|
if (!buffer)
|
|
|
|
return;
|
2013-08-20 19:36:19 +04:00
|
|
|
|
2016-09-10 07:02:54 +03:00
|
|
|
if (buffer->mNumActiveTFOs) {
|
|
|
|
ErrorInvalidOperation("%s: Buffer is bound to an active transform feedback"
|
|
|
|
" object.",
|
|
|
|
"bufferSubData");
|
|
|
|
return;
|
|
|
|
}
|
2013-08-20 19:36:19 +04:00
|
|
|
|
2016-10-12 01:40:34 +03:00
|
|
|
if (!buffer->ValidateRange(funcName, dstByteOffset, dataLen))
|
2014-11-14 07:03:50 +03:00
|
|
|
return;
|
2013-08-20 19:36:19 +04:00
|
|
|
|
2016-10-12 01:40:34 +03:00
|
|
|
if (!CheckedInt<GLintptr>(dataLen).isValid()) {
|
|
|
|
ErrorOutOfMemory("%s: Size too large.", funcName);
|
2014-11-14 07:03:50 +03:00
|
|
|
return;
|
|
|
|
}
|
2016-10-12 01:40:34 +03:00
|
|
|
const GLintptr glDataLen(dataLen);
|
|
|
|
|
|
|
|
////
|
2013-08-20 19:36:19 +04:00
|
|
|
|
2016-09-10 07:02:54 +03:00
|
|
|
MakeContextCurrent();
|
2016-09-26 23:38:56 +03:00
|
|
|
const ScopedLazyBind lazyBind(gl, target, buffer);
|
|
|
|
|
2015-11-26 14:47:53 +03:00
|
|
|
// Warning: Possibly shared memory. See bug 1225033.
|
2016-10-12 01:40:34 +03:00
|
|
|
gl->fBufferSubData(target, dstByteOffset, glDataLen, data);
|
2013-08-20 19:36:19 +04:00
|
|
|
|
2015-11-26 14:47:53 +03:00
|
|
|
// Warning: Possibly shared memory. See bug 1225033.
|
2016-10-12 01:40:34 +03:00
|
|
|
buffer->ElementArrayCacheBufferSubData(dstByteOffset, data, size_t(glDataLen));
|
2013-08-20 19:36:19 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2016-10-12 01:40:34 +03:00
|
|
|
WebGLContext::BufferSubData(GLenum target, WebGLsizeiptr dstByteOffset,
|
|
|
|
const dom::Nullable<dom::ArrayBuffer>& maybeSrc)
|
2013-08-20 19:36:19 +04:00
|
|
|
{
|
2016-10-12 01:40:34 +03:00
|
|
|
if (IsContextLost())
|
2014-11-14 07:03:50 +03:00
|
|
|
return;
|
2016-10-12 01:40:34 +03:00
|
|
|
|
|
|
|
if (maybeSrc.IsNull())
|
|
|
|
return ErrorInvalidValue("BufferSubData: returnedData is null.");
|
|
|
|
auto& src = maybeSrc.Value();
|
|
|
|
|
|
|
|
src.ComputeLengthAndData();
|
|
|
|
BufferSubDataImpl(target, dstByteOffset, src.LengthAllowShared(),
|
|
|
|
src.DataAllowShared());
|
2015-10-14 08:48:19 +03:00
|
|
|
}
|
2013-08-20 19:36:19 +04:00
|
|
|
|
2015-10-14 08:48:19 +03:00
|
|
|
void
|
2016-10-12 01:40:34 +03:00
|
|
|
WebGLContext::BufferSubData(GLenum target, WebGLsizeiptr dstByteOffset,
|
|
|
|
const dom::SharedArrayBuffer& src)
|
2015-10-14 08:48:19 +03:00
|
|
|
{
|
2016-10-12 01:40:34 +03:00
|
|
|
if (IsContextLost())
|
|
|
|
return;
|
|
|
|
|
|
|
|
src.ComputeLengthAndData();
|
|
|
|
BufferSubDataImpl(target, dstByteOffset, src.LengthAllowShared(),
|
|
|
|
src.DataAllowShared());
|
2015-10-14 08:48:19 +03:00
|
|
|
}
|
2013-08-20 19:36:19 +04:00
|
|
|
|
2015-10-14 08:48:19 +03:00
|
|
|
void
|
2016-10-12 01:40:34 +03:00
|
|
|
WebGLContext::BufferSubData(GLenum target, WebGLsizeiptr dstByteOffset,
|
|
|
|
const dom::ArrayBufferView& src, GLuint srcElemOffset,
|
|
|
|
GLuint srcElemCountOverride)
|
2015-10-14 08:48:19 +03:00
|
|
|
{
|
2016-10-12 01:40:34 +03:00
|
|
|
const char funcName[] = "bufferSubData";
|
|
|
|
if (IsContextLost())
|
|
|
|
return;
|
|
|
|
|
|
|
|
uint8_t* bytes;
|
|
|
|
size_t byteLen;
|
|
|
|
if (!ValidateArrayBufferView(funcName, src, srcElemOffset, srcElemCountOverride,
|
|
|
|
&bytes, &byteLen))
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
BufferSubDataImpl(target, dstByteOffset, byteLen, bytes);
|
2015-10-14 08:48:19 +03:00
|
|
|
}
|
2013-08-20 19:36:19 +04:00
|
|
|
|
2016-09-10 07:02:54 +03:00
|
|
|
////////////////////////////////////////
|
|
|
|
|
2013-08-20 19:36:19 +04:00
|
|
|
already_AddRefed<WebGLBuffer>
|
|
|
|
WebGLContext::CreateBuffer()
|
|
|
|
{
|
2013-09-04 16:14:44 +04:00
|
|
|
if (IsContextLost())
|
2013-08-20 19:36:19 +04:00
|
|
|
return nullptr;
|
|
|
|
|
2014-11-17 05:21:04 +03:00
|
|
|
GLuint buf = 0;
|
|
|
|
MakeContextCurrent();
|
|
|
|
gl->fGenBuffers(1, &buf);
|
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<WebGLBuffer> globj = new WebGLBuffer(this, buf);
|
2013-08-20 19:36:19 +04:00
|
|
|
return globj.forget();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2014-11-14 07:03:50 +03:00
|
|
|
WebGLContext::DeleteBuffer(WebGLBuffer* buffer)
|
2013-08-20 19:36:19 +04:00
|
|
|
{
|
2013-09-04 16:14:44 +04:00
|
|
|
if (IsContextLost())
|
2013-08-20 19:36:19 +04:00
|
|
|
return;
|
|
|
|
|
|
|
|
if (!ValidateObjectAllowDeletedOrNull("deleteBuffer", buffer))
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (!buffer || buffer->IsDeleted())
|
|
|
|
return;
|
|
|
|
|
2016-09-10 07:02:54 +03:00
|
|
|
////
|
2013-08-20 19:36:19 +04:00
|
|
|
|
2016-09-10 07:02:54 +03:00
|
|
|
const auto fnClearIfBuffer = [&](WebGLRefPtr<WebGLBuffer>& bindPoint) {
|
|
|
|
if (bindPoint == buffer) {
|
|
|
|
bindPoint = nullptr;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
fnClearIfBuffer(mBoundArrayBuffer);
|
|
|
|
fnClearIfBuffer(mBoundVertexArray->mElementArrayBuffer);
|
2015-06-02 04:08:55 +03:00
|
|
|
|
|
|
|
// WebGL binding points
|
|
|
|
if (IsWebGL2()) {
|
2016-09-10 07:02:54 +03:00
|
|
|
fnClearIfBuffer(mBoundCopyReadBuffer);
|
|
|
|
fnClearIfBuffer(mBoundCopyWriteBuffer);
|
|
|
|
fnClearIfBuffer(mBoundPixelPackBuffer);
|
|
|
|
fnClearIfBuffer(mBoundPixelUnpackBuffer);
|
|
|
|
fnClearIfBuffer(mBoundUniformBuffer);
|
|
|
|
fnClearIfBuffer(mBoundTransformFeedback->mGenericBufferBinding);
|
|
|
|
|
2016-09-19 23:25:06 +03:00
|
|
|
if (!mBoundTransformFeedback->mIsActive) {
|
|
|
|
for (auto& binding : mBoundTransformFeedback->mIndexedBindings) {
|
|
|
|
fnClearIfBuffer(binding.mBufferBinding);
|
|
|
|
}
|
2015-06-02 04:08:55 +03:00
|
|
|
}
|
|
|
|
|
2016-09-10 07:02:54 +03:00
|
|
|
for (auto& binding : mIndexedUniformBufferBindings) {
|
|
|
|
fnClearIfBuffer(binding.mBufferBinding);
|
2015-06-02 04:08:55 +03:00
|
|
|
}
|
2013-08-20 19:36:19 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
for (int32_t i = 0; i < mGLMaxVertexAttribs; i++) {
|
2016-09-10 07:02:54 +03:00
|
|
|
if (mBoundVertexArray->HasAttrib(i)) {
|
2016-09-24 03:28:58 +03:00
|
|
|
fnClearIfBuffer(mBoundVertexArray->mAttribs[i].mBuf);
|
2014-11-14 07:03:50 +03:00
|
|
|
}
|
2013-08-20 19:36:19 +04:00
|
|
|
}
|
|
|
|
|
2016-09-10 07:02:54 +03:00
|
|
|
////
|
|
|
|
|
2013-08-20 19:36:19 +04:00
|
|
|
buffer->RequestDelete();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2014-11-14 07:03:50 +03:00
|
|
|
WebGLContext::IsBuffer(WebGLBuffer* buffer)
|
2013-08-20 19:36:19 +04:00
|
|
|
{
|
2013-09-04 16:14:44 +04:00
|
|
|
if (IsContextLost())
|
2013-08-20 19:36:19 +04:00
|
|
|
return false;
|
|
|
|
|
2015-05-21 02:59:14 +03:00
|
|
|
if (!ValidateObjectAllowDeleted("isBuffer", buffer))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (buffer->IsDeleted())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
MakeContextCurrent();
|
|
|
|
return gl->fIsBuffer(buffer->mGLName);
|
|
|
|
}
|
|
|
|
|
2014-11-14 07:03:50 +03:00
|
|
|
} // namespace mozilla
|