Bug 1048731 - [WebGL2] Implement new buffer binding targets. r=jgilbert

--HG--
extra : rebase_source : cbba1bb1995a35e7238b40a6819274d2fb15a40c
extra : source : 0f5fc69cd1f616e224ff5837f4c7486c126197e0
This commit is contained in:
Dan Glastonbury 2014-12-05 17:04:55 +10:00
Родитель 7e73cbee3b
Коммит ebb118a497
13 изменённых файлов: 384 добавлений и 153 удалений

Просмотреть файл

@ -33,6 +33,7 @@ private:
virtual bool ValidateAttribPointerType(bool integerMode, GLenum type, GLsizei* alignment, const char* info) MOZ_OVERRIDE;
virtual bool ValidateBufferTarget(GLenum target, const char* info) MOZ_OVERRIDE;
virtual bool ValidateBufferIndexedTarget(GLenum target, const char* info) MOZ_OVERRIDE;
virtual bool ValidateBufferForTarget(GLenum target, WebGLBuffer* buffer, const char* info) MOZ_OVERRIDE;
};
} // namespace mozilla

Просмотреть файл

@ -34,3 +34,19 @@ WebGL1Context::ValidateBufferIndexedTarget(GLenum target, const char* info)
ErrorInvalidEnumInfo(info, target);
return false;
}
/** Buffer and Target validation for BindBuffer */
bool
WebGL1Context::ValidateBufferForTarget(GLenum target, WebGLBuffer* buffer,
const char* info)
{
if (!buffer)
return true;
if (buffer->HasEverBeenBound() && target != buffer->Target()) {
ErrorInvalidOperation("%s: buffer already bound to a different target", info);
return false;
}
return true;
}

Просмотреть файл

@ -139,6 +139,13 @@ WebGLContext::InitWebGL2()
// we initialise WebGL 2 related stuff.
gl->GetUIntegerv(LOCAL_GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS,
&mGLMaxTransformFeedbackSeparateAttribs);
gl->GetUIntegerv(LOCAL_GL_MAX_UNIFORM_BUFFER_BINDINGS,
&mGLMaxUniformBufferBindings);
mBoundTransformFeedbackBuffers =
MakeUnique<WebGLRefPtr<WebGLBuffer>[]>(mGLMaxTransformFeedbackSeparateAttribs);
mBoundUniformBuffers =
MakeUnique<WebGLRefPtr<WebGLBuffer>[]>(mGLMaxUniformBufferBindings);
mDefaultTransformFeedback = new WebGLTransformFeedback(this, 0);
mBoundTransformFeedback = mDefaultTransformFeedback;

Просмотреть файл

@ -264,6 +264,7 @@ private:
virtual bool ValidateAttribPointerType(bool integerMode, GLenum type, GLsizei* alignment, const char* info) MOZ_OVERRIDE;
virtual bool ValidateBufferTarget(GLenum target, const char* info) MOZ_OVERRIDE;
virtual bool ValidateBufferIndexedTarget(GLenum target, const char* info) MOZ_OVERRIDE;
virtual bool ValidateBufferForTarget(GLenum target, WebGLBuffer* buffer, const char* info) MOZ_OVERRIDE;
};
} // namespace mozilla

Просмотреть файл

@ -4,7 +4,9 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "WebGL2Context.h"
#include "GLContext.h"
#include "WebGLBuffer.h"
using namespace mozilla;
using namespace mozilla::dom;
@ -14,8 +16,13 @@ WebGL2Context::ValidateBufferTarget(GLenum target, const char* info)
{
switch (target) {
case LOCAL_GL_ARRAY_BUFFER:
case LOCAL_GL_COPY_READ_BUFFER:
case LOCAL_GL_COPY_WRITE_BUFFER:
case LOCAL_GL_ELEMENT_ARRAY_BUFFER:
case LOCAL_GL_PIXEL_PACK_BUFFER:
case LOCAL_GL_PIXEL_UNPACK_BUFFER:
case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER:
case LOCAL_GL_UNIFORM_BUFFER:
return true;
default:
@ -38,25 +45,98 @@ WebGL2Context::ValidateBufferIndexedTarget(GLenum target, const char* info)
}
}
bool
WebGL2Context::ValidateBufferForTarget(GLenum target, WebGLBuffer* buffer,
const char* info)
{
if (!buffer)
return true;
switch (target) {
case LOCAL_GL_COPY_READ_BUFFER:
case LOCAL_GL_COPY_WRITE_BUFFER:
return true;
case LOCAL_GL_ELEMENT_ARRAY_BUFFER:
return !buffer->HasEverBeenBound() ||
buffer->Target() == LOCAL_GL_ELEMENT_ARRAY_BUFFER;
case LOCAL_GL_ARRAY_BUFFER:
case LOCAL_GL_PIXEL_PACK_BUFFER:
case LOCAL_GL_PIXEL_UNPACK_BUFFER:
case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER:
case LOCAL_GL_UNIFORM_BUFFER:
return !buffer->HasEverBeenBound() ||
buffer->Target() != LOCAL_GL_ELEMENT_ARRAY_BUFFER;
}
ErrorInvalidOperation("%s: buffer already bound to a incompatible target %s",
info, EnumName(buffer->Target().get()));
return false;
}
// -------------------------------------------------------------------------
// Buffer objects
void
WebGL2Context::CopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset,
GLintptr writeOffset, GLsizeiptr size)
WebGL2Context::CopyBufferSubData(GLenum readTarget, GLenum writeTarget,
GLintptr readOffset, GLintptr writeOffset,
GLsizeiptr size)
{
MakeContextCurrent();
gl->fCopyBufferSubData(readTarget, writeTarget, readOffset, writeOffset, 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");
const 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;
}
WebGLContextUnchecked::CopyBufferSubData(readTarget, writeTarget, readOffset,
writeOffset, size);
}
void
WebGL2Context::GetBufferSubData(GLenum target, GLintptr offset, const dom::ArrayBuffer& returnedData)
WebGL2Context::GetBufferSubData(GLenum target, GLintptr offset,
const dom::ArrayBuffer& returnedData)
{
MOZ_CRASH("Not Implemented.");
}
void
WebGL2Context::GetBufferSubData(GLenum target, GLintptr offset, const dom::ArrayBufferView& returnedData)
WebGL2Context::GetBufferSubData(GLenum target, GLintptr offset,
const dom::ArrayBufferView& returnedData)
{
MOZ_CRASH("Not Implemented.");
}

Просмотреть файл

@ -257,6 +257,7 @@ WebGLContext::WebGLContext()
mGLMaxColorAttachments = 1;
mGLMaxDrawBuffers = 1;
mGLMaxTransformFeedbackSeparateAttribs = 0;
mGLMaxUniformBufferBindings = 0;
// See OpenGL ES 2.0.25 spec, 6.2 State Tables, table 6.13
mPixelStorePackAlignment = 4;
@ -322,7 +323,12 @@ WebGLContext::DestroyResourcesAndContext()
mBoundCubeMapTextures.Clear();
mBound3DTextures.Clear();
mBoundArrayBuffer = nullptr;
mBoundCopyReadBuffer = nullptr;
mBoundCopyWriteBuffer = nullptr;
mBoundPixelPackBuffer = nullptr;
mBoundPixelUnpackBuffer = nullptr;
mBoundTransformFeedbackBuffer = nullptr;
mBoundUniformBuffer = nullptr;
mCurrentProgram = nullptr;
mBoundFramebuffer = nullptr;
mActiveOcclusionQuery = nullptr;
@ -338,6 +344,9 @@ WebGLContext::DestroyResourcesAndContext()
}
}
for (GLuint i = 0; i < mGLMaxUniformBufferBindings; i++)
mBoundUniformBuffers[i] = nullptr;
while (!mTextures.isEmpty())
mTextures.getLast()->DeleteOnce();
while (!mVertexArrays.isEmpty())
@ -1862,20 +1871,25 @@ NS_IMPL_CYCLE_COLLECTING_ADDREF(WebGLContext)
NS_IMPL_CYCLE_COLLECTING_RELEASE(WebGLContext)
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(WebGLContext,
mCanvasElement,
mExtensions,
mBound2DTextures,
mBoundCubeMapTextures,
mBound3DTextures,
mBoundArrayBuffer,
mBoundTransformFeedbackBuffer,
mCurrentProgram,
mBoundFramebuffer,
mBoundRenderbuffer,
mBoundVertexArray,
mDefaultVertexArray,
mActiveOcclusionQuery,
mActiveTransformFeedbackQuery)
mCanvasElement,
mExtensions,
mBound2DTextures,
mBoundCubeMapTextures,
mBound3DTextures,
mBoundArrayBuffer,
mBoundCopyReadBuffer,
mBoundCopyWriteBuffer,
mBoundPixelPackBuffer,
mBoundPixelUnpackBuffer,
mBoundTransformFeedbackBuffer,
mBoundUniformBuffer,
mCurrentProgram,
mBoundFramebuffer,
mBoundRenderbuffer,
mBoundVertexArray,
mDefaultVertexArray,
mActiveOcclusionQuery,
mActiveTransformFeedbackQuery)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WebGLContext)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY

Просмотреть файл

@ -864,16 +864,32 @@ public:
// -----------------------------------------------------------------------------
// Buffer Objects (WebGLContextBuffers.cpp)
private:
void UpdateBoundBuffer(GLenum target, WebGLBuffer* buffer);
void UpdateBoundBufferIndexed(GLenum target, GLuint index, WebGLBuffer* buffer);
public:
void BindBuffer(GLenum target, WebGLBuffer* buf);
void BindBuffer(GLenum target, WebGLBuffer* buffer);
void BindBufferBase(GLenum target, GLuint index, WebGLBuffer* buf);
void BindBufferRange(GLenum target, GLuint index, WebGLBuffer* buf,
WebGLintptr offset, WebGLsizeiptr size);
private:
void BufferDataUnchecked(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage);
void BufferData(GLenum target, WebGLsizeiptr size, void* data, GLenum usage);
public:
void BufferData(GLenum target, WebGLsizeiptr size, GLenum usage);
void BufferData(GLenum target, const dom::ArrayBufferView& data,
GLenum usage);
void BufferData(GLenum target, const Nullable<dom::ArrayBuffer>& maybeData,
GLenum usage);
private:
void BufferSubDataUnchecked(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data);
void BufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data);
public:
void BufferSubData(GLenum target, WebGLsizeiptr byteOffset,
const dom::ArrayBufferView& data);
void BufferSubData(GLenum target, WebGLsizeiptr byteOffset,
@ -885,12 +901,18 @@ public:
protected:
// bound buffer state
WebGLRefPtr<WebGLBuffer> mBoundArrayBuffer;
WebGLRefPtr<WebGLBuffer> mBoundCopyReadBuffer;
WebGLRefPtr<WebGLBuffer> mBoundCopyWriteBuffer;
WebGLRefPtr<WebGLBuffer> mBoundPixelPackBuffer;
WebGLRefPtr<WebGLBuffer> mBoundPixelUnpackBuffer;
WebGLRefPtr<WebGLBuffer> mBoundTransformFeedbackBuffer;
WebGLRefPtr<WebGLBuffer> mBoundUniformBuffer;
UniquePtr<WebGLRefPtr<WebGLBuffer>[]> mBoundUniformBuffers;
UniquePtr<WebGLRefPtr<WebGLBuffer>[]> mBoundTransformFeedbackBuffers;
WebGLRefPtr<WebGLBuffer>* GetBufferSlotByTarget(GLenum target);
WebGLRefPtr<WebGLBuffer>* GetBufferSlotByTargetIndexed(GLenum target,
WebGLRefPtr<WebGLBuffer>& GetBufferSlotByTarget(GLenum target);
WebGLRefPtr<WebGLBuffer>& GetBufferSlotByTargetIndexed(GLenum target,
GLuint index);
bool ValidateBufferUsageEnum(GLenum target, const char* info);
@ -1005,14 +1027,6 @@ private:
uint32_t mMaxFetchedVertices;
uint32_t mMaxFetchedInstances;
protected:
inline void InvalidateBufferFetching() {
mBufferFetchingIsVerified = false;
mBufferFetchingHasPerVertex = false;
mMaxFetchedVertices = 0;
mMaxFetchedInstances = 0;
}
bool DrawArrays_check(GLint first, GLsizei count, GLsizei primcount,
const char* info);
bool DrawElements_check(GLsizei count, GLenum type, WebGLintptr byteOffset,
@ -1066,6 +1080,14 @@ protected:
return ((x + y - 1) / y) * y;
}
inline void InvalidateBufferFetching()
{
mBufferFetchingIsVerified = false;
mBufferFetchingHasPerVertex = false;
mMaxFetchedVertices = 0;
mMaxFetchedInstances = 0;
}
CheckedUint32 mGeneration;
WebGLContextOptions mOptions;
@ -1113,6 +1135,7 @@ protected:
int32_t mGLMaxColorAttachments;
int32_t mGLMaxDrawBuffers;
GLuint mGLMaxTransformFeedbackSeparateAttribs;
GLuint mGLMaxUniformBufferBindings;
public:
GLuint MaxVertexAttribs() const {
@ -1185,6 +1208,8 @@ protected:
bool ValidateBlendFuncSrcEnum(GLenum mode, const char* info);
bool ValidateBlendFuncEnumsCompatibility(GLenum sfactor, GLenum dfactor,
const char* info);
bool ValidateDataOffsetSize(WebGLintptr offset, WebGLsizeiptr size, WebGLsizeiptr bufferSize, const char* info);
bool ValidateDataRanges(WebGLintptr readOffset, WebGLintptr writeOffset, WebGLsizeiptr size, const char* info);
bool ValidateTextureTargetEnum(GLenum target, const char* info);
bool ValidateComparisonEnum(GLenum target, const char* info);
bool ValidateStencilOpEnum(GLenum action, const char* info);
@ -1339,6 +1364,7 @@ private:
virtual bool ValidateAttribPointerType(bool integerMode, GLenum type, GLsizei* alignment, const char* info) = 0;
virtual bool ValidateBufferTarget(GLenum target, const char* info) = 0;
virtual bool ValidateBufferIndexedTarget(GLenum target, const char* info) = 0;
virtual bool ValidateBufferForTarget(GLenum target, WebGLBuffer* buffer, const char* info) = 0;
protected:
int32_t MaxTextureSizeForTarget(TexTarget target) const {
@ -1396,8 +1422,8 @@ protected:
LinkedList<WebGLSampler> mSamplers;
LinkedList<WebGLTransformFeedback> mTransformFeedbacks;
WebGLRefPtr<WebGLVertexArray> mDefaultVertexArray;
WebGLRefPtr<WebGLTransformFeedback> mDefaultTransformFeedback;
WebGLRefPtr<WebGLVertexArray> mDefaultVertexArray;
// PixelStore parameters
uint32_t mPixelStorePackAlignment;

Просмотреть файл

@ -11,6 +11,45 @@
namespace mozilla {
void
WebGLContext::UpdateBoundBuffer(GLenum target, WebGLBuffer* buffer)
{
WebGLRefPtr<WebGLBuffer>& bufferSlot = GetBufferSlotByTarget(target);
bufferSlot = buffer;
if (!buffer)
return;
/* https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.1
*
* In the WebGL 2 API, buffers have their WebGL buffer type
* initially set to undefined. Calling bindBuffer, bindBufferRange
* or bindBufferBase with the target argument set to any buffer
* binding point except COPY_READ_BUFFER or COPY_WRITE_BUFFER will
* then set the WebGL buffer type of the buffer being bound
* according to the table above.
*
* Any call to one of these functions which attempts to bind a
* WebGLBuffer that has the element array WebGL buffer type to a
* binding point that falls under other data, or bind a
* WebGLBuffer which has the other data WebGL buffer type to
* ELEMENT_ARRAY_BUFFER will generate an INVALID_OPERATION error,
* and the state of the binding point will remain untouched.
*/
if (target != LOCAL_GL_COPY_READ_BUFFER && target != LOCAL_GL_COPY_WRITE_BUFFER)
buffer->BindTo(target);
}
void
WebGLContext::UpdateBoundBufferIndexed(GLenum target, GLuint index, WebGLBuffer* buffer)
{
UpdateBoundBuffer(target, buffer);
WebGLRefPtr<WebGLBuffer>& bufferIndexSlot =
GetBufferSlotByTargetIndexed(target, index);
bufferIndexSlot = buffer;
}
void
WebGLContext::BindBuffer(GLenum target, WebGLBuffer* buffer)
{
@ -27,24 +66,12 @@ WebGLContext::BindBuffer(GLenum target, WebGLBuffer* buffer)
if (!ValidateBufferTarget(target, "bindBuffer"))
return;
WebGLRefPtr<WebGLBuffer>* bufferSlot = GetBufferSlotByTarget(target);
MOZ_ASSERT(bufferSlot);
if (!ValidateBufferForTarget(target, buffer, "bindBuffer"))
return;
if (buffer) {
if (!buffer->HasEverBeenBound()) {
buffer->BindTo(target);
} else if (target != buffer->Target()) {
ErrorInvalidOperation("bindBuffer: Buffer already bound to a"
" different target.");
return;
}
}
WebGLContextUnchecked::BindBuffer(target, buffer);
*bufferSlot = buffer;
MakeContextCurrent();
gl->fBindBuffer(target, buffer ? buffer->GLName() : 0);
UpdateBoundBuffer(target, buffer);
}
void
@ -57,9 +84,8 @@ WebGLContext::BindBufferBase(GLenum target, GLuint index, WebGLBuffer* buffer)
return;
// silently ignore a deleted buffer
if (buffer && buffer->IsDeleted()) {
if (buffer && buffer->IsDeleted())
return;
}
// ValidateBufferTarget
switch (target) {
@ -67,34 +93,22 @@ WebGLContext::BindBufferBase(GLenum target, GLuint index, WebGLBuffer* buffer)
if (index >= mGLMaxTransformFeedbackSeparateAttribs)
return ErrorInvalidValue("bindBufferBase: index should be less than "
"MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS");
case LOCAL_GL_UNIFORM_BUFFER:
if (index >= mGLMaxUniformBufferBindings)
return ErrorInvalidValue("bindBufferBase: index should be less than "
"MAX_UNIFORM_BUFFER_BINDINGS");
default:
return ErrorInvalidEnumInfo("bindBufferBase: target", target);
}
WebGLRefPtr<WebGLBuffer>* indexedBufferSlot;
indexedBufferSlot = GetBufferSlotByTargetIndexed(target, index);
MOZ_ASSERT(indexedBufferSlot);
if (!ValidateBufferForTarget(target, buffer, "bindBufferBase"))
return;
if (buffer) {
if (!buffer->HasEverBeenBound())
buffer->BindTo(target);
WebGLContextUnchecked::BindBufferBase(target, index, buffer);
if (target != buffer->Target()) {
ErrorInvalidOperation("bindBuffer: Buffer already bound to a"
" different target.");
return;
}
}
WebGLRefPtr<WebGLBuffer>* bufferSlot = GetBufferSlotByTarget(target);
MOZ_ASSERT(bufferSlot, "GetBufferSlotByTarget(Indexed) mismatch");
*indexedBufferSlot = buffer;
*bufferSlot = buffer;
MakeContextCurrent();
gl->fBindBufferBase(target, index, buffer ? buffer->GLName() : 0);
UpdateBoundBufferIndexed(target, index, buffer);
}
void
@ -118,42 +132,20 @@ WebGLContext::BindBufferRange(GLenum target, GLuint index, WebGLBuffer* buffer,
return ErrorInvalidValue("bindBufferRange: index should be less than "
"MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS");
case LOCAL_GL_UNIFORM_BUFFER:
if (index >= mGLMaxUniformBufferBindings)
return ErrorInvalidValue("bindBufferRange: index should be less than "
"MAX_UNIFORM_BUFFER_BINDINGS");
default:
return ErrorInvalidEnumInfo("bindBufferRange: target", target);
}
WebGLRefPtr<WebGLBuffer>* indexedBufferSlot;
indexedBufferSlot = GetBufferSlotByTargetIndexed(target, index);
MOZ_ASSERT(indexedBufferSlot);
if (!ValidateBufferForTarget(target, buffer, "bindBufferRange"))
return;
if (buffer) {
if (!buffer->HasEverBeenBound())
buffer->BindTo(target);
WebGLContextUnchecked::BindBufferRange(target, index, buffer, offset, size);
if (target != buffer->Target()) {
ErrorInvalidOperation("bindBuffer: Buffer already bound to a"
" different target.");
return;
}
CheckedInt<WebGLsizeiptr> checked_neededByteLength = CheckedInt<WebGLsizeiptr>(offset) + size;
if (!checked_neededByteLength.isValid() ||
checked_neededByteLength.value() > buffer->ByteLength())
{
return ErrorInvalidValue("bindBufferRange: invalid range");
}
}
WebGLRefPtr<WebGLBuffer>* bufferSlot = GetBufferSlotByTarget(target);
MOZ_ASSERT(bufferSlot, "GetBufferSlotByTarget(Indexed) mismatch");
*indexedBufferSlot = buffer;
*bufferSlot = buffer;
MakeContextCurrent();
gl->fBindBufferRange(target, index, buffer ? buffer->GLName() : 0, offset,
size);
UpdateBoundBufferIndexed(target, index, buffer);
}
void
@ -165,8 +157,7 @@ WebGLContext::BufferData(GLenum target, WebGLsizeiptr size, GLenum usage)
if (!ValidateBufferTarget(target, "bufferData"))
return;
WebGLRefPtr<WebGLBuffer>* bufferSlot = GetBufferSlotByTarget(target);
MOZ_ASSERT(bufferSlot);
WebGLRefPtr<WebGLBuffer>& bufferSlot = GetBufferSlotByTarget(target);
if (size < 0)
return ErrorInvalidValue("bufferData: negative size");
@ -178,7 +169,7 @@ WebGLContext::BufferData(GLenum target, WebGLsizeiptr size, GLenum usage)
if (!CheckedInt<GLsizeiptr>(size).isValid())
return ErrorOutOfMemory("bufferData: bad size");
WebGLBuffer* boundBuffer = bufferSlot->get();
WebGLBuffer* boundBuffer = bufferSlot.get();
if (!boundBuffer)
return ErrorInvalidOperation("bufferData: no buffer bound!");
@ -219,8 +210,7 @@ WebGLContext::BufferData(GLenum target,
if (!ValidateBufferTarget(target, "bufferData"))
return;
WebGLRefPtr<WebGLBuffer>* bufferSlot = GetBufferSlotByTarget(target);
MOZ_ASSERT(bufferSlot);
const WebGLRefPtr<WebGLBuffer>& bufferSlot = GetBufferSlotByTarget(target);
const dom::ArrayBuffer& data = maybeData.Value();
data.ComputeLengthAndData();
@ -233,7 +223,7 @@ WebGLContext::BufferData(GLenum target,
if (!ValidateBufferUsageEnum(usage, "bufferData: usage"))
return;
WebGLBuffer* boundBuffer = bufferSlot->get();
WebGLBuffer* boundBuffer = bufferSlot.get();
if (!boundBuffer)
return ErrorInvalidOperation("bufferData: no buffer bound!");
@ -263,14 +253,12 @@ WebGLContext::BufferData(GLenum target, const dom::ArrayBufferView& data,
if (!ValidateBufferTarget(target, "bufferData"))
return;
WebGLRefPtr<WebGLBuffer>* bufferSlot = GetBufferSlotByTarget(target);
MOZ_ASSERT(bufferSlot);
WebGLRefPtr<WebGLBuffer>& bufferSlot = GetBufferSlotByTarget(target);
if (!ValidateBufferUsageEnum(usage, "bufferData: usage"))
return;
WebGLBuffer* boundBuffer = bufferSlot->get();
WebGLBuffer* boundBuffer = bufferSlot.get();
if (!boundBuffer)
return ErrorInvalidOperation("bufferData: no buffer bound!");
@ -310,21 +298,21 @@ WebGLContext::BufferSubData(GLenum target, WebGLsizeiptr byteOffset,
if (!ValidateBufferTarget(target, "bufferSubData"))
return;
WebGLRefPtr<WebGLBuffer>* bufferSlot = GetBufferSlotByTarget(target);
MOZ_ASSERT(bufferSlot);
WebGLRefPtr<WebGLBuffer>& bufferSlot = GetBufferSlotByTarget(target);
if (byteOffset < 0)
return ErrorInvalidValue("bufferSubData: negative offset");
WebGLBuffer* boundBuffer = bufferSlot->get();
WebGLBuffer* boundBuffer = bufferSlot.get();
if (!boundBuffer)
return ErrorInvalidOperation("bufferData: no buffer bound!");
const dom::ArrayBuffer& data = maybeData.Value();
data.ComputeLengthAndData();
CheckedInt<WebGLsizeiptr> checked_neededByteLength = CheckedInt<WebGLsizeiptr>(byteOffset) + data.Length();
CheckedInt<WebGLsizeiptr> checked_neededByteLength =
CheckedInt<WebGLsizeiptr>(byteOffset) + data.Length();
if (!checked_neededByteLength.isValid()) {
ErrorInvalidValue("bufferSubData: Integer overflow computing the needed"
" byte length.");
@ -356,20 +344,20 @@ WebGLContext::BufferSubData(GLenum target, WebGLsizeiptr byteOffset,
if (!ValidateBufferTarget(target, "bufferSubData"))
return;
WebGLRefPtr<WebGLBuffer>* bufferSlot = GetBufferSlotByTarget(target);
MOZ_ASSERT(bufferSlot);
WebGLRefPtr<WebGLBuffer>& bufferSlot = GetBufferSlotByTarget(target);
if (byteOffset < 0)
return ErrorInvalidValue("bufferSubData: negative offset");
WebGLBuffer* boundBuffer = bufferSlot->get();
WebGLBuffer* boundBuffer = bufferSlot.get();
if (!boundBuffer)
return ErrorInvalidOperation("bufferSubData: no buffer bound!");
data.ComputeLengthAndData();
CheckedInt<WebGLsizeiptr> checked_neededByteLength = CheckedInt<WebGLsizeiptr>(byteOffset) + data.Length();
CheckedInt<WebGLsizeiptr> checked_neededByteLength =
CheckedInt<WebGLsizeiptr>(byteOffset) + data.Length();
if (!checked_neededByteLength.isValid()) {
ErrorInvalidValue("bufferSubData: Integer overflow computing the needed"
" byte length.");
@ -463,37 +451,57 @@ WebGLContext::ValidateBufferUsageEnum(GLenum target, const char* info)
return false;
}
WebGLRefPtr<WebGLBuffer>*
WebGLRefPtr<WebGLBuffer>&
WebGLContext::GetBufferSlotByTarget(GLenum target)
{
/* This function assumes that target has been validated for either WebGL1 or WebGL. */
/* This function assumes that target has been validated for either
* WebGL1 or WebGL2.
*/
switch (target) {
case LOCAL_GL_ARRAY_BUFFER:
return &mBoundArrayBuffer;
case LOCAL_GL_ARRAY_BUFFER:
return mBoundArrayBuffer;
case LOCAL_GL_ELEMENT_ARRAY_BUFFER:
return &mBoundVertexArray->mElementArrayBuffer;
case LOCAL_GL_COPY_READ_BUFFER:
return mBoundCopyReadBuffer;
case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER:
return &mBoundTransformFeedbackBuffer;
case LOCAL_GL_COPY_WRITE_BUFFER:
return mBoundCopyWriteBuffer;
default:
return nullptr;
case LOCAL_GL_ELEMENT_ARRAY_BUFFER:
return mBoundVertexArray->mElementArrayBuffer;
case LOCAL_GL_PIXEL_PACK_BUFFER:
return mBoundPixelPackBuffer;
case LOCAL_GL_PIXEL_UNPACK_BUFFER:
return mBoundPixelUnpackBuffer;
case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER:
return mBoundTransformFeedbackBuffer;
case LOCAL_GL_UNIFORM_BUFFER:
return mBoundUniformBuffer;
default:
MOZ_CRASH("Should not get here.");
}
}
WebGLRefPtr<WebGLBuffer>*
WebGLRefPtr<WebGLBuffer>&
WebGLContext::GetBufferSlotByTargetIndexed(GLenum target, GLuint index)
{
/* This function assumes that target has been validated for either WebGL1 or WebGL. */
switch (target) {
case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER:
MOZ_ASSERT(index < mGLMaxTransformFeedbackSeparateAttribs);
return &mBoundTransformFeedbackBuffers[index];
}
return mBoundTransformFeedbackBuffers[index];
case LOCAL_GL_UNIFORM_BUFFER:
MOZ_ASSERT(index < mGLMaxUniformBufferBindings);
return mBoundUniformBuffers[index];
MOZ_CRASH("Should not get here.");
return nullptr;
default:
MOZ_CRASH("Should not get here.");
}
}
GLenum
@ -503,7 +511,7 @@ WebGLContext::CheckedBufferData(GLenum target, GLsizeiptr size,
#ifdef XP_MACOSX
// bug 790879
if (gl->WorkAroundDriverBugs() &&
int64_t(size) > INT32_MAX) // the cast avoids a potential always-true warning on 32bit
int64_t(size) > INT32_MAX) // cast avoids a potential always-true warning on 32bit
{
GenerateWarning("Rejecting valid bufferData call with size %lu to avoid"
" a Mac bug", size);
@ -511,12 +519,8 @@ WebGLContext::CheckedBufferData(GLenum target, GLsizeiptr size,
}
#endif
WebGLBuffer* boundBuffer = nullptr;
if (target == LOCAL_GL_ARRAY_BUFFER) {
boundBuffer = mBoundArrayBuffer;
} else if (target == LOCAL_GL_ELEMENT_ARRAY_BUFFER) {
boundBuffer = mBoundVertexArray->mElementArrayBuffer;
}
WebGLRefPtr<WebGLBuffer>& bufferSlot = GetBufferSlotByTarget(target);
WebGLBuffer* boundBuffer = bufferSlot.get();
MOZ_ASSERT(boundBuffer, "No buffer bound for this target.");
bool sizeChanges = uint32_t(size) != boundBuffer->ByteLength();

Просмотреть файл

@ -1108,10 +1108,8 @@ WebGLContext::GetBufferParameter(GLenum target, GLenum pname)
if (!ValidateBufferTarget(target, "getBufferParameter"))
return JS::NullValue();
WebGLRefPtr<WebGLBuffer>* slot = GetBufferSlotByTarget(target);
MOZ_ASSERT(slot);
if (!*slot) {
WebGLRefPtr<WebGLBuffer>& slot = GetBufferSlotByTarget(target);
if (!slot) {
ErrorInvalidOperation("No buffer bound to `target` (0x%4x).", target);
return JS::NullValue();
}

Просмотреть файл

@ -7,6 +7,7 @@
#include "WebGLContextUnchecked.h"
#include "GLContext.h"
#include "WebGLBuffer.h"
#include "WebGLSampler.h"
namespace mozilla {
@ -16,6 +17,38 @@ WebGLContextUnchecked::WebGLContextUnchecked(gl::GLContext* gl)
{ }
// -----------------------------------------------------------------------------
// Buffer Objects
void
WebGLContextUnchecked::BindBuffer(GLenum target, WebGLBuffer* buffer)
{
gl->MakeCurrent();
gl->fBindBuffer(target, buffer ? buffer->GLName() : 0);
}
void
WebGLContextUnchecked::BindBufferBase(GLenum target, GLuint index, WebGLBuffer* buffer)
{
gl->MakeCurrent();
gl->fBindBufferBase(target, index, buffer ? buffer->GLName() : 0);
}
void
WebGLContextUnchecked::BindBufferRange(GLenum target, GLuint index, WebGLBuffer* buffer, WebGLintptr offset, WebGLsizeiptr size)
{
gl->MakeCurrent();
gl->fBindBufferRange(target, index, buffer ? buffer->GLName() : 0, offset, size);
}
void
WebGLContextUnchecked::CopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size)
{
gl->MakeCurrent();
gl->fCopyBufferSubData(readTarget, writeTarget, readOffset, writeOffset, size);
}
// -----------------------------------------------------------------------------
// Sampler Objects

Просмотреть файл

@ -8,12 +8,12 @@
#define WEBGLCONTEXTUNCHECKED_H
#include "GLDefs.h"
#include "nsRefPtr.h"
#include "WebGLTypes.h"
#include "nsAutoPtr.h"
#include "nsTArray.h"
namespace mozilla {
class WebGLBuffer;
class WebGLSampler;
namespace gl {
class GLContext;
@ -24,6 +24,13 @@ class WebGLContextUnchecked
public:
explicit WebGLContextUnchecked(gl::GLContext* gl);
// -------------------------------------------------------------------------
// Buffer Objects
void BindBuffer(GLenum target, WebGLBuffer* buffer);
void BindBufferBase(GLenum target, GLuint index, WebGLBuffer* buffer);
void BindBufferRange(GLenum taret, GLuint index, WebGLBuffer* buffer, WebGLintptr offset, WebGLsizeiptr size);
void CopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
// -------------------------------------------------------------------------
// Sampler Objects
void BindSampler(GLuint unit, WebGLSampler* sampler);

Просмотреть файл

@ -227,6 +227,50 @@ WebGLContext::ValidateBlendFuncEnumsCompatibility(GLenum sfactor,
return true;
}
bool
WebGLContext::ValidateDataOffsetSize(WebGLintptr offset, WebGLsizeiptr size, WebGLsizeiptr bufferSize, const char* info)
{
if (offset < 0) {
ErrorInvalidValue("%s: offset must be positive", info);
return false;
}
if (size < 0) {
ErrorInvalidValue("%s: size must be positive", info);
return false;
}
// *** Careful *** WebGLsizeiptr is always 64-bits but GLsizeiptr
// is like intptr_t. On some platforms it is 32-bits.
CheckedInt<GLsizeiptr> neededBytes = CheckedInt<GLsizeiptr>(offset) + size;
if (!neededBytes.isValid() || neededBytes.value() > bufferSize) {
ErrorInvalidValue("%s: invalid range", info);
return false;
}
return true;
}
/**
* Check data ranges [readOffset, readOffset + size] and [writeOffset,
* writeOffset + size] for overlap.
*
* It is assumed that offset and size have already been validated with
* ValidateDataOffsetSize().
*/
bool
WebGLContext::ValidateDataRanges(WebGLintptr readOffset, WebGLintptr writeOffset, WebGLsizeiptr size, const char* info)
{
MOZ_ASSERT((CheckedInt<WebGLsizeiptr>(readOffset) + size).isValid());
MOZ_ASSERT((CheckedInt<WebGLsizeiptr>(writeOffset) + size).isValid());
bool separate = (readOffset + size < writeOffset || writeOffset + size < readOffset);
if (!separate)
ErrorInvalidValue("%s: ranges [readOffset, readOffset + size) and [writeOffset, writeOffset + size) overlap");
return separate;
}
bool
WebGLContext::ValidateTextureTargetEnum(GLenum target, const char* info)
{

Просмотреть файл

@ -11,15 +11,15 @@
namespace mozilla {
WebGLTransformFeedback::WebGLTransformFeedback(WebGLContext* context,
WebGLTransformFeedback::WebGLTransformFeedback(WebGLContext* webgl,
GLuint tf)
: WebGLBindableName<GLenum>(tf)
, WebGLContextBoundObject(context)
, WebGLContextBoundObject(webgl)
, mMode(LOCAL_GL_NONE)
, mIsActive(false)
, mIsPaused(false)
{
context->mTransformFeedbacks.insertBack(this);
mContext->mTransformFeedbacks.insertBack(this);
}
WebGLTransformFeedback::~WebGLTransformFeedback()