mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1167504 - Part 11: Clean up buffer binding constraints. r=jgilbert
Checked against http://www.khronos.org/registry/webgl/sdk/tests/conformance2/buffers/
This commit is contained in:
parent
9ab81fee0a
commit
5b282e5258
@ -33,7 +33,6 @@ private:
|
||||
virtual bool ValidateAttribPointerType(bool integerMode, GLenum type, GLsizei* alignment, const char* info) override;
|
||||
virtual bool ValidateBufferTarget(GLenum target, const char* info) override;
|
||||
virtual bool ValidateBufferIndexedTarget(GLenum target, const char* info) override;
|
||||
virtual bool ValidateBufferForTarget(GLenum target, WebGLBuffer* buffer, const char* info) override;
|
||||
virtual bool ValidateBufferUsageEnum(GLenum usage, const char* info) override;
|
||||
virtual bool ValidateQueryTarget(GLenum target, const char* info) override;
|
||||
virtual bool ValidateUniformMatrixTranspose(bool transpose, const char* info) override;
|
||||
|
@ -35,22 +35,6 @@ WebGL1Context::ValidateBufferIndexedTarget(GLenum target, const char* info)
|
||||
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;
|
||||
}
|
||||
|
||||
bool
|
||||
WebGL1Context::ValidateBufferUsageEnum(GLenum usage, const char* info)
|
||||
{
|
||||
|
@ -370,7 +370,6 @@ private:
|
||||
virtual bool ValidateAttribPointerType(bool integerMode, GLenum type, GLsizei* alignment, const char* info) override;
|
||||
virtual bool ValidateBufferTarget(GLenum target, const char* info) override;
|
||||
virtual bool ValidateBufferIndexedTarget(GLenum target, const char* info) override;
|
||||
virtual bool ValidateBufferForTarget(GLenum target, WebGLBuffer* buffer, const char* info) override;
|
||||
virtual bool ValidateBufferUsageEnum(GLenum usage, const char* info) override;
|
||||
virtual bool ValidateQueryTarget(GLenum target, const char* info) override;
|
||||
virtual bool ValidateUniformMatrixTranspose(bool transpose, const char* info) override;
|
||||
|
@ -45,36 +45,6 @@ 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()));
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
WebGL2Context::ValidateBufferUsageEnum(GLenum usage, const char* info)
|
||||
{
|
||||
@ -123,7 +93,7 @@ WebGL2Context::CopyBufferSubData(GLenum readTarget, GLenum writeTarget,
|
||||
if (!readBuffer)
|
||||
return ErrorInvalidOperation("copyBufferSubData: No buffer bound to readTarget");
|
||||
|
||||
const WebGLBuffer* writeBuffer = writeBufferSlot.get();
|
||||
WebGLBuffer* writeBuffer = writeBufferSlot.get();
|
||||
if (!writeBuffer)
|
||||
return ErrorInvalidOperation("copyBufferSubData: No buffer bound to writeTarget");
|
||||
|
||||
@ -145,8 +115,27 @@ WebGL2Context::CopyBufferSubData(GLenum readTarget, GLenum writeTarget,
|
||||
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
|
||||
|
@ -15,7 +15,7 @@ namespace mozilla {
|
||||
WebGLBuffer::WebGLBuffer(WebGLContext* webgl, GLuint buf)
|
||||
: WebGLContextBoundObject(webgl)
|
||||
, mGLName(buf)
|
||||
, mTarget(LOCAL_GL_NONE)
|
||||
, mContent(Kind::Undefined)
|
||||
, mByteLength(0)
|
||||
{
|
||||
mContext->mBuffers.insertBack(this);
|
||||
@ -26,6 +26,34 @@ WebGLBuffer::~WebGLBuffer()
|
||||
DeleteOnce();
|
||||
}
|
||||
|
||||
void
|
||||
WebGLBuffer::BindTo(GLenum target)
|
||||
{
|
||||
switch (target) {
|
||||
case LOCAL_GL_ELEMENT_ARRAY_BUFFER:
|
||||
mContent = Kind::ElementArray;
|
||||
if (!mCache)
|
||||
mCache = new WebGLElementArrayCache;
|
||||
break;
|
||||
|
||||
case LOCAL_GL_ARRAY_BUFFER:
|
||||
case LOCAL_GL_PIXEL_PACK_BUFFER:
|
||||
case LOCAL_GL_PIXEL_UNPACK_BUFFER:
|
||||
case LOCAL_GL_UNIFORM_BUFFER:
|
||||
case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER:
|
||||
mContent = Kind::OtherData;
|
||||
break;
|
||||
|
||||
case LOCAL_GL_COPY_READ_BUFFER:
|
||||
case LOCAL_GL_COPY_WRITE_BUFFER:
|
||||
/* Do nothing. Doesn't set the type of the buffer contents. */
|
||||
break;
|
||||
|
||||
default:
|
||||
MOZ_CRASH();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WebGLBuffer::Delete()
|
||||
{
|
||||
@ -36,30 +64,11 @@ WebGLBuffer::Delete()
|
||||
LinkedListElement<WebGLBuffer>::remove(); // remove from mContext->mBuffers
|
||||
}
|
||||
|
||||
void
|
||||
WebGLBuffer::BindTo(GLenum target)
|
||||
{
|
||||
MOZ_ASSERT(target != LOCAL_GL_NONE, "Can't bind to GL_NONE.");
|
||||
MOZ_ASSERT(!HasEverBeenBound() || mTarget == target, "Rebinding is illegal.");
|
||||
|
||||
bool targetChanged = (target != mTarget);
|
||||
mTarget = target;
|
||||
if (targetChanged)
|
||||
OnTargetChanged();
|
||||
}
|
||||
|
||||
void
|
||||
WebGLBuffer::OnTargetChanged()
|
||||
{
|
||||
if (!mCache && mTarget == LOCAL_GL_ELEMENT_ARRAY_BUFFER)
|
||||
mCache = new WebGLElementArrayCache;
|
||||
}
|
||||
|
||||
bool
|
||||
WebGLBuffer::ElementArrayCacheBufferData(const void* ptr,
|
||||
size_t bufferSizeInBytes)
|
||||
{
|
||||
if (mTarget == LOCAL_GL_ELEMENT_ARRAY_BUFFER)
|
||||
if (mContent == Kind::ElementArray)
|
||||
return mCache->BufferData(ptr, bufferSizeInBytes);
|
||||
|
||||
return true;
|
||||
@ -69,7 +78,7 @@ void
|
||||
WebGLBuffer::ElementArrayCacheBufferSubData(size_t pos, const void* ptr,
|
||||
size_t updateSizeInBytes)
|
||||
{
|
||||
if (mTarget == LOCAL_GL_ELEMENT_ARRAY_BUFFER)
|
||||
if (mContent == Kind::ElementArray)
|
||||
mCache->BufferSubData(pos, ptr, updateSizeInBytes);
|
||||
}
|
||||
|
||||
|
@ -25,8 +25,18 @@ class WebGLBuffer final
|
||||
, public WebGLContextBoundObject
|
||||
{
|
||||
public:
|
||||
|
||||
enum class Kind {
|
||||
Undefined,
|
||||
ElementArray,
|
||||
OtherData
|
||||
};
|
||||
|
||||
explicit WebGLBuffer(WebGLContext* webgl, GLuint buf);
|
||||
|
||||
void BindTo(GLenum target);
|
||||
Kind Content() const { return mContent; }
|
||||
|
||||
void Delete();
|
||||
|
||||
size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
|
||||
@ -39,10 +49,6 @@ public:
|
||||
void ElementArrayCacheBufferSubData(size_t pos, const void* ptr,
|
||||
size_t updateSizeInBytes);
|
||||
|
||||
void BindTo(GLenum target);
|
||||
bool HasEverBeenBound() const { return mTarget != LOCAL_GL_NONE; }
|
||||
GLenum Target() const { return mTarget; }
|
||||
|
||||
bool Validate(GLenum type, uint32_t max_allowed, size_t first, size_t count,
|
||||
uint32_t* const out_upperBound);
|
||||
|
||||
@ -62,10 +68,7 @@ public:
|
||||
protected:
|
||||
~WebGLBuffer();
|
||||
|
||||
void OnTargetChanged();
|
||||
|
||||
GLenum mTarget;
|
||||
|
||||
Kind mContent;
|
||||
WebGLsizeiptr mByteLength;
|
||||
nsAutoPtr<WebGLElementArrayCache> mCache;
|
||||
};
|
||||
|
@ -939,6 +939,8 @@ protected:
|
||||
WebGLRefPtr<WebGLBuffer>& GetBufferSlotByTargetIndexed(GLenum target,
|
||||
GLuint index);
|
||||
|
||||
GLenum GetCurrentBinding(WebGLBuffer* buffer) const;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Queries (WebGL2ContextQueries.cpp)
|
||||
protected:
|
||||
@ -1395,7 +1397,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;
|
||||
virtual bool ValidateBufferForTarget(GLenum target, WebGLBuffer* buffer, const char* info);
|
||||
virtual bool ValidateBufferUsageEnum(GLenum usage, const char* info) = 0;
|
||||
virtual bool ValidateQueryTarget(GLenum usage, const char* info) = 0;
|
||||
virtual bool ValidateUniformMatrixTranspose(bool transpose, const char* info) = 0;
|
||||
|
@ -20,24 +20,7 @@ WebGLContext::UpdateBoundBuffer(GLenum target, WebGLBuffer* 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);
|
||||
buffer->BindTo(target);
|
||||
}
|
||||
|
||||
void
|
||||
@ -435,9 +418,89 @@ WebGLContext::IsBuffer(WebGLBuffer* buffer)
|
||||
if (IsContextLost())
|
||||
return false;
|
||||
|
||||
return ValidateObjectAllowDeleted("isBuffer", buffer) &&
|
||||
!buffer->IsDeleted() &&
|
||||
buffer->HasEverBeenBound();
|
||||
if (!ValidateObjectAllowDeleted("isBuffer", buffer))
|
||||
return false;
|
||||
|
||||
if (buffer->IsDeleted())
|
||||
return false;
|
||||
|
||||
MakeContextCurrent();
|
||||
return gl->fIsBuffer(buffer->mGLName);
|
||||
}
|
||||
|
||||
bool
|
||||
WebGLContext::ValidateBufferForTarget(GLenum target, WebGLBuffer* buffer,
|
||||
const char* info)
|
||||
{
|
||||
if (!buffer)
|
||||
return true;
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
GLenum boundTo = GetCurrentBinding(buffer);
|
||||
if (boundTo != LOCAL_GL_NONE) {
|
||||
if (target == LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER &&
|
||||
boundTo != LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER)
|
||||
{
|
||||
ErrorInvalidOperation("Can't bind buffer to TRANSFORM_FEEDBACK_BUFFER as the "
|
||||
"buffer is already bound to another bind point.");
|
||||
return false;
|
||||
}
|
||||
else if (target != LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER &&
|
||||
boundTo == LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER)
|
||||
{
|
||||
ErrorInvalidOperation("Can't bind buffer to bind point as it is currently "
|
||||
"bound to TRANSFORM_FEEDBACK_BUFFER.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
WebGLBuffer::Kind content = buffer->Content();
|
||||
if (content == WebGLBuffer::Kind::Undefined)
|
||||
return true;
|
||||
|
||||
switch (target) {
|
||||
case LOCAL_GL_COPY_READ_BUFFER:
|
||||
case LOCAL_GL_COPY_WRITE_BUFFER:
|
||||
return true;
|
||||
|
||||
case LOCAL_GL_ELEMENT_ARRAY_BUFFER:
|
||||
if (content == WebGLBuffer::Kind::ElementArray)
|
||||
return true;
|
||||
break;
|
||||
|
||||
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:
|
||||
if (content == WebGLBuffer::Kind::OtherData)
|
||||
return true;
|
||||
break;
|
||||
|
||||
default:
|
||||
MOZ_CRASH();
|
||||
}
|
||||
|
||||
ErrorInvalidOperation("%s: buffer already contains %s data.", info,
|
||||
content == WebGLBuffer::Kind::OtherData ? "other" : "element");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
@ -510,6 +573,37 @@ WebGLContext::GetBufferSlotByTargetIndexed(GLenum target, GLuint index)
|
||||
}
|
||||
}
|
||||
|
||||
GLenum
|
||||
WebGLContext::GetCurrentBinding(WebGLBuffer* buffer) const
|
||||
{
|
||||
if (mBoundArrayBuffer == buffer)
|
||||
return LOCAL_GL_ARRAY_BUFFER;
|
||||
|
||||
if (mBoundCopyReadBuffer == buffer)
|
||||
return LOCAL_GL_COPY_READ_BUFFER;
|
||||
|
||||
if (mBoundCopyWriteBuffer == buffer)
|
||||
return LOCAL_GL_COPY_WRITE_BUFFER;
|
||||
|
||||
if (mBoundPixelPackBuffer == buffer)
|
||||
return LOCAL_GL_PIXEL_PACK_BUFFER;
|
||||
|
||||
if (mBoundPixelUnpackBuffer == buffer)
|
||||
return LOCAL_GL_PIXEL_UNPACK_BUFFER;
|
||||
|
||||
if (mBoundTransformFeedbackBuffer == buffer ||
|
||||
mBoundTransformFeedbackBuffers.Contains(buffer)) {
|
||||
return LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER;
|
||||
}
|
||||
|
||||
if (mBoundUniformBuffer == buffer ||
|
||||
mBoundUniformBuffers.Contains(buffer)) {
|
||||
return LOCAL_GL_UNIFORM_BUFFER;
|
||||
}
|
||||
|
||||
return LOCAL_GL_NONE;
|
||||
}
|
||||
|
||||
GLenum
|
||||
WebGLContext::CheckedBufferData(GLenum target, GLsizeiptr size,
|
||||
const GLvoid* data, GLenum usage)
|
||||
|
@ -126,8 +126,7 @@ WebGLMemoryTracker::GetBufferCacheMemoryUsed()
|
||||
buffer;
|
||||
buffer = buffer->getNext())
|
||||
{
|
||||
if (buffer->HasEverBeenBound() &&
|
||||
buffer->Target() == LOCAL_GL_ELEMENT_ARRAY_BUFFER) {
|
||||
if (buffer->Content() == WebGLBuffer::Kind::ElementArray) {
|
||||
result += buffer->SizeOfIncludingThis(WebGLBufferMallocSizeOf);
|
||||
}
|
||||
}
|
||||
|
@ -38,6 +38,17 @@ void
|
||||
WebGLContextUnchecked::BindBufferRange(GLenum target, GLuint index, WebGLBuffer* buffer, WebGLintptr offset, WebGLsizeiptr size)
|
||||
{
|
||||
gl->MakeCurrent();
|
||||
|
||||
#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);
|
||||
}
|
||||
#endif
|
||||
|
||||
gl->fBindBufferRange(target, index, buffer ? buffer->mGLName : 0, offset, size);
|
||||
}
|
||||
|
||||
|
@ -266,8 +266,10 @@ WebGLContext::ValidateDataRanges(WebGLintptr readOffset, WebGLintptr writeOffset
|
||||
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");
|
||||
if (!separate) {
|
||||
ErrorInvalidValue("%s: ranges [readOffset, readOffset + size) and [writeOffset, "
|
||||
"writeOffset + size) overlap", info);
|
||||
}
|
||||
|
||||
return separate;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user