зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1048731 - [WebGL2] Implement new buffer binding targets. r=jgilbert
--HG-- extra : rebase_source : cbba1bb1995a35e7238b40a6819274d2fb15a40c extra : source : 0f5fc69cd1f616e224ff5837f4c7486c126197e0
This commit is contained in:
Родитель
7e73cbee3b
Коммит
ebb118a497
|
@ -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())
|
||||
|
@ -1868,7 +1877,12 @@ NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(WebGLContext,
|
|||
mBoundCubeMapTextures,
|
||||
mBound3DTextures,
|
||||
mBoundArrayBuffer,
|
||||
mBoundCopyReadBuffer,
|
||||
mBoundCopyWriteBuffer,
|
||||
mBoundPixelPackBuffer,
|
||||
mBoundPixelUnpackBuffer,
|
||||
mBoundTransformFeedbackBuffer,
|
||||
mBoundUniformBuffer,
|
||||
mCurrentProgram,
|
||||
mBoundFramebuffer,
|
||||
mBoundRenderbuffer,
|
||||
|
|
|
@ -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 (buffer) {
|
||||
if (!buffer->HasEverBeenBound()) {
|
||||
buffer->BindTo(target);
|
||||
} else if (target != buffer->Target()) {
|
||||
ErrorInvalidOperation("bindBuffer: Buffer already bound to a"
|
||||
" different target.");
|
||||
if (!ValidateBufferForTarget(target, buffer, "bindBuffer"))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
*bufferSlot = buffer;
|
||||
WebGLContextUnchecked::BindBuffer(target, 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 (buffer) {
|
||||
if (!buffer->HasEverBeenBound())
|
||||
buffer->BindTo(target);
|
||||
|
||||
if (target != buffer->Target()) {
|
||||
ErrorInvalidOperation("bindBuffer: Buffer already bound to a"
|
||||
" different target.");
|
||||
if (!ValidateBufferForTarget(target, buffer, "bindBufferBase"))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
WebGLRefPtr<WebGLBuffer>* bufferSlot = GetBufferSlotByTarget(target);
|
||||
MOZ_ASSERT(bufferSlot, "GetBufferSlotByTarget(Indexed) mismatch");
|
||||
WebGLContextUnchecked::BindBufferBase(target, index, buffer);
|
||||
|
||||
*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 (buffer) {
|
||||
if (!buffer->HasEverBeenBound())
|
||||
buffer->BindTo(target);
|
||||
|
||||
if (target != buffer->Target()) {
|
||||
ErrorInvalidOperation("bindBuffer: Buffer already bound to a"
|
||||
" different target.");
|
||||
if (!ValidateBufferForTarget(target, buffer, "bindBufferRange"))
|
||||
return;
|
||||
}
|
||||
|
||||
CheckedInt<WebGLsizeiptr> checked_neededByteLength = CheckedInt<WebGLsizeiptr>(offset) + size;
|
||||
if (!checked_neededByteLength.isValid() ||
|
||||
checked_neededByteLength.value() > buffer->ByteLength())
|
||||
{
|
||||
return ErrorInvalidValue("bindBufferRange: invalid range");
|
||||
}
|
||||
}
|
||||
WebGLContextUnchecked::BindBufferRange(target, index, buffer, offset, size);
|
||||
|
||||
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;
|
||||
return mBoundArrayBuffer;
|
||||
|
||||
case LOCAL_GL_COPY_READ_BUFFER:
|
||||
return mBoundCopyReadBuffer;
|
||||
|
||||
case LOCAL_GL_COPY_WRITE_BUFFER:
|
||||
return mBoundCopyWriteBuffer;
|
||||
|
||||
case LOCAL_GL_ELEMENT_ARRAY_BUFFER:
|
||||
return &mBoundVertexArray->mElementArrayBuffer;
|
||||
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;
|
||||
return mBoundTransformFeedbackBuffer;
|
||||
|
||||
case LOCAL_GL_UNIFORM_BUFFER:
|
||||
return mBoundUniformBuffer;
|
||||
|
||||
default:
|
||||
return nullptr;
|
||||
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];
|
||||
|
||||
default:
|
||||
MOZ_CRASH("Should not get here.");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
|
|
Загрузка…
Ссылка в новой задаче