Bug 1048724 - [WebGL2] Transform Feedback. r=jgilbert,smaug

--HG--
extra : rebase_source : 40fe3ec66b091ced40f5a773fdc23d06bf6abc11
This commit is contained in:
Dan Glastonbury 2014-11-26 12:00:06 +10:00
Родитель 73ffa2d5f9
Коммит baf3f4332f
16 изменённых файлов: 402 добавлений и 115 удалений

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

@ -31,6 +31,8 @@ public:
private: private:
virtual bool ValidateAttribPointerType(bool integerMode, GLenum type, GLsizei* alignment, const char* info) MOZ_OVERRIDE; 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;
}; };
} // namespace mozilla } // namespace mozilla

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

@ -0,0 +1,36 @@
/* -*- 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 "WebGL1Context.h"
#include "WebGLBuffer.h"
#include "GLContext.h"
using namespace mozilla;
using namespace mozilla::dom;
// -------------------------------------------------------------------------
// Buffer objects
/** Target validation for BindBuffer, etc */
bool
WebGL1Context::ValidateBufferTarget(GLenum target, const char* info)
{
switch (target) {
case LOCAL_GL_ARRAY_BUFFER:
case LOCAL_GL_ELEMENT_ARRAY_BUFFER:
return true;
default:
ErrorInvalidEnumInfo(info, target);
return false;
}
}
bool
WebGL1Context::ValidateBufferIndexedTarget(GLenum target, const char* info)
{
ErrorInvalidEnumInfo(info, target);
return false;
}

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

@ -6,6 +6,8 @@
#include "WebGL2Context.h" #include "WebGL2Context.h"
#include "GLContext.h" #include "GLContext.h"
#include "WebGLBuffer.h"
#include "WebGLTransformFeedback.h"
#include "mozilla/dom/WebGL2RenderingContextBinding.h" #include "mozilla/dom/WebGL2RenderingContextBinding.h"
#include "mozilla/Preferences.h" #include "mozilla/Preferences.h"
#include "mozilla/Telemetry.h" #include "mozilla/Telemetry.h"
@ -117,6 +119,11 @@ WebGLContext::InitWebGL2()
gl->GetUIntegerv(LOCAL_GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, gl->GetUIntegerv(LOCAL_GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS,
&mGLMaxTransformFeedbackSeparateAttribs); &mGLMaxTransformFeedbackSeparateAttribs);
mDefaultTransformFeedback = new WebGLTransformFeedback(this, 0);
mBoundTransformFeedback = mDefaultTransformFeedback;
auto xfBuffers = new WebGLRefPtr<WebGLBuffer>[mGLMaxTransformFeedbackSeparateAttribs];
mBoundTransformFeedbackBuffers.reset(xfBuffers);
return true; return true;
} }

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

@ -215,14 +215,13 @@ public:
already_AddRefed<WebGLTransformFeedback> CreateTransformFeedback(); already_AddRefed<WebGLTransformFeedback> CreateTransformFeedback();
void DeleteTransformFeedback(WebGLTransformFeedback* tf); void DeleteTransformFeedback(WebGLTransformFeedback* tf);
bool IsTransformFeedback(WebGLTransformFeedback* tf); bool IsTransformFeedback(WebGLTransformFeedback* tf);
void BindTransformFeedback(GLenum target, GLuint id); void BindTransformFeedback(GLenum target, WebGLTransformFeedback* tf);
void BeginTransformFeedback(GLenum primitiveMode); void BeginTransformFeedback(GLenum primitiveMode);
void EndTransformFeedback(); void EndTransformFeedback();
void TransformFeedbackVaryings(WebGLProgram* program, GLsizei count,
const dom::Sequence<nsString>& varyings, GLenum bufferMode);
already_AddRefed<WebGLActiveInfo> GetTransformFeedbackVarying(WebGLProgram* program, GLuint index);
void PauseTransformFeedback(); void PauseTransformFeedback();
void ResumeTransformFeedback(); void ResumeTransformFeedback();
void TransformFeedbackVaryings(WebGLProgram* program, const dom::Sequence<nsString>& varyings, GLenum bufferMode);
already_AddRefed<WebGLActiveInfo> GetTransformFeedbackVarying(WebGLProgram* program, GLuint index);
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
@ -263,6 +262,8 @@ private:
const char* info); const char* info);
virtual bool ValidateAttribPointerType(bool integerMode, GLenum type, GLsizei* alignment, const char* info) MOZ_OVERRIDE; 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;
}; };
} // namespace mozilla } // namespace mozilla

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

@ -9,6 +9,35 @@
using namespace mozilla; using namespace mozilla;
using namespace mozilla::dom; using namespace mozilla::dom;
bool
WebGL2Context::ValidateBufferTarget(GLenum target, const char* info)
{
switch (target) {
case LOCAL_GL_ARRAY_BUFFER:
case LOCAL_GL_ELEMENT_ARRAY_BUFFER:
case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER:
return true;
default:
ErrorInvalidEnumInfo(info, target);
return false;
}
}
bool
WebGL2Context::ValidateBufferIndexedTarget(GLenum target, const char* info)
{
switch (target) {
case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER:
case LOCAL_GL_UNIFORM_BUFFER:
return true;
default:
ErrorInvalidEnumInfo(info, target);
return false;
}
}
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// Buffer objects // Buffer objects

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

@ -4,6 +4,9 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "WebGL2Context.h" #include "WebGL2Context.h"
#include "WebGLActiveInfo.h"
#include "WebGLProgram.h"
#include "WebGLTransformFeedback.h"
#include "GLContext.h" #include "GLContext.h"
using namespace mozilla; using namespace mozilla;
@ -15,64 +18,237 @@ using namespace mozilla::dom;
already_AddRefed<WebGLTransformFeedback> already_AddRefed<WebGLTransformFeedback>
WebGL2Context::CreateTransformFeedback() WebGL2Context::CreateTransformFeedback()
{ {
MOZ_CRASH("Not Implemented."); if (IsContextLost())
return nullptr; return nullptr;
GLuint tf = 0;
MakeContextCurrent();
gl->fGenTransformFeedbacks(1, &tf);
nsRefPtr<WebGLTransformFeedback> globj = new WebGLTransformFeedback(this, tf);
return globj.forget();
} }
void void
WebGL2Context::DeleteTransformFeedback(WebGLTransformFeedback* tf) WebGL2Context::DeleteTransformFeedback(WebGLTransformFeedback* tf)
{ {
MOZ_CRASH("Not Implemented."); if (IsContextLost())
return;
if (!ValidateObjectAllowDeletedOrNull("deleteTransformFeedback", tf))
return;
if (!tf || tf->IsDeleted())
return;
if (mBoundTransformFeedback == tf)
BindTransformFeedback(LOCAL_GL_TRANSFORM_FEEDBACK, tf);
tf->RequestDelete();
} }
bool bool
WebGL2Context::IsTransformFeedback(WebGLTransformFeedback* tf) WebGL2Context::IsTransformFeedback(WebGLTransformFeedback* tf)
{ {
MOZ_CRASH("Not Implemented."); if (IsContextLost())
return false; return false;
if (!ValidateObjectAllowDeleted("isTransformFeedback", tf))
return false;
if (tf->IsDeleted())
return false;
MakeContextCurrent();
return gl->fIsTransformFeedback(tf->GLName());
} }
void void
WebGL2Context::BindTransformFeedback(GLenum target, GLuint id) WebGL2Context::BindTransformFeedback(GLenum target, WebGLTransformFeedback* tf)
{ {
MOZ_CRASH("Not Implemented."); if (IsContextLost())
return;
if (!ValidateObjectAllowDeletedOrNull("bindTransformFeedback", tf))
return;
if (target != LOCAL_GL_TRANSFORM_FEEDBACK)
return ErrorInvalidEnum("bindTransformFeedback: target must be TRANSFORM_FEEDBACK");
WebGLRefPtr<WebGLTransformFeedback> currentTF = mBoundTransformFeedback;
if (currentTF && currentTF->mIsActive && !currentTF->mIsPaused) {
return ErrorInvalidOperation("bindTransformFeedback: Currently bound transform "
"feedback is active and not paused");
}
if (tf && tf->IsDeleted())
return ErrorInvalidOperation("bindTransformFeedback: Attempt to bind deleted id");
if (tf)
tf->BindTo(LOCAL_GL_TRANSFORM_FEEDBACK);
MakeContextCurrent();
gl->fBindTransformFeedback(target, tf ? tf->GLName() : 0);
if (tf)
mBoundTransformFeedback = tf;
else
mBoundTransformFeedback = mDefaultTransformFeedback;
} }
void void
WebGL2Context::BeginTransformFeedback(GLenum primitiveMode) WebGL2Context::BeginTransformFeedback(GLenum primitiveMode)
{ {
MOZ_CRASH("Not Implemented."); if (IsContextLost())
return;
WebGLTransformFeedback* tf = mBoundTransformFeedback;
MOZ_ASSERT(tf);
if (!tf)
return;
if (tf->mIsActive)
return ErrorInvalidOperation("beginTransformFeedback: transform feedback is active");
const GLenum mode = tf->mMode;
if (mode != LOCAL_GL_POINTS && mode != LOCAL_GL_LINES && mode != LOCAL_GL_TRIANGLES)
return ErrorInvalidEnum("beginTransformFeedback: primitive must be one of POINTS, LINES, or TRIANGLES");
// TODO:
// GL_INVALID_OPERATION is generated by glBeginTransformFeedback
// if any binding point used in transform feedback mode does not
// have a buffer object bound. In interleaved mode, only the first
// buffer object binding point is ever written to.
// GL_INVALID_OPERATION is generated by glBeginTransformFeedback
// if no binding points would be used, either because no program
// object is active of because the active program object has
// specified no varying variables to record.
if (!mCurrentProgram)
return ErrorInvalidOperation("beginTransformFeedback: no program is active");
MakeContextCurrent();
gl->fBeginTransformFeedback(primitiveMode);
tf->mIsActive = true;
tf->mIsPaused = false;
} }
void void
WebGL2Context::EndTransformFeedback() WebGL2Context::EndTransformFeedback()
{ {
MOZ_CRASH("Not Implemented."); if (IsContextLost())
return;
WebGLTransformFeedback* tf = mBoundTransformFeedback;
MOZ_ASSERT(tf);
if (!tf)
return;
if (!tf->mIsActive)
return ErrorInvalidOperation("%s: transform feedback in not active",
"endTransformFeedback");
MakeContextCurrent();
gl->fEndTransformFeedback();
tf->mIsActive = false;
tf->mIsPaused = false;
} }
void void
WebGL2Context::TransformFeedbackVaryings(WebGLProgram* program, GLsizei count, WebGL2Context::PauseTransformFeedback()
const dom::Sequence<nsString>& varyings, GLenum bufferMode)
{ {
MOZ_CRASH("Not Implemented."); if (IsContextLost())
return;
WebGLTransformFeedback* tf = mBoundTransformFeedback;
MOZ_ASSERT(tf);
if (!tf)
return;
if (!tf->mIsActive || tf->mIsPaused) {
return ErrorInvalidOperation("%s: transform feedback is not active or is paused",
"pauseTransformFeedback");
}
MakeContextCurrent();
gl->fPauseTransformFeedback();
tf->mIsPaused = true;
}
void
WebGL2Context::ResumeTransformFeedback()
{
if (IsContextLost())
return;
WebGLTransformFeedback* tf = mBoundTransformFeedback;
MOZ_ASSERT(tf);
if (!tf)
return;
if (!tf->mIsActive || !tf->mIsPaused)
return ErrorInvalidOperation("resumeTransformFeedback: transform feedback is not active or is not paused");
MakeContextCurrent();
gl->fResumeTransformFeedback();
tf->mIsPaused = false;
}
void
WebGL2Context::TransformFeedbackVaryings(WebGLProgram* program,
const dom::Sequence<nsString>& varyings,
GLenum bufferMode)
{
if (IsContextLost())
return;
if (!ValidateObject("transformFeedbackVaryings: program", program))
return;
GLsizei count = varyings.Length();
GLchar** tmpVaryings = (GLchar**) nsMemory::Alloc(count * sizeof(GLchar*));
for (GLsizei n = 0; n < count; n++) {
tmpVaryings[n] = (GLchar*) ToNewCString(varyings[n]);
}
GLuint progname = program->GLName();
MakeContextCurrent();
gl->fTransformFeedbackVaryings(progname, count, tmpVaryings, bufferMode);
NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(count, tmpVaryings);
} }
already_AddRefed<WebGLActiveInfo> already_AddRefed<WebGLActiveInfo>
WebGL2Context::GetTransformFeedbackVarying(WebGLProgram* program, GLuint index) WebGL2Context::GetTransformFeedbackVarying(WebGLProgram* program, GLuint index)
{ {
MOZ_CRASH("Not Implemented."); if (IsContextLost())
return nullptr; return nullptr;
}
void if (!ValidateObject("getTransformFeedbackVarying: program", program))
WebGL2Context::PauseTransformFeedback() return nullptr;
{
MOZ_CRASH("Not Implemented.");
}
void MakeContextCurrent();
WebGL2Context::ResumeTransformFeedback()
{ GLint len = 0;
MOZ_CRASH("Not Implemented."); GLuint progname = program->GLName();
gl->fGetProgramiv(progname, LOCAL_GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH, &len);
if (!len)
return nullptr;
UniquePtr<char[]> name(new char[len]);
GLint tfsize = 0;
GLuint tftype = 0;
gl->fGetTransformFeedbackVarying(progname, index, len, &len, &tfsize, &tftype, name.get());
if (len == 0 || tfsize == 0 || tftype == 0)
return nullptr;
// TODO(djg): Reverse lookup of name
// nsCString reverseMappedName;
// prog->ReverveMapIdentifier(nsDependentCString(name), &reverseMappedName);
nsRefPtr<WebGLActiveInfo> result = new WebGLActiveInfo(tfsize, tftype, nsDependentCString(name.get()));
return result.forget();
} }

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

@ -54,6 +54,7 @@
#include "WebGLObjectModel.h" #include "WebGLObjectModel.h"
#include "WebGLQuery.h" #include "WebGLQuery.h"
#include "WebGLSampler.h" #include "WebGLSampler.h"
#include "WebGLTransformFeedback.h"
#include "WebGLVertexArray.h" #include "WebGLVertexArray.h"
#include "WebGLVertexAttribData.h" #include "WebGLVertexAttribData.h"
@ -328,6 +329,14 @@ WebGLContext::DestroyResourcesAndContext()
mBoundRenderbuffer = nullptr; mBoundRenderbuffer = nullptr;
mBoundVertexArray = nullptr; mBoundVertexArray = nullptr;
mDefaultVertexArray = nullptr; mDefaultVertexArray = nullptr;
mBoundTransformFeedback = nullptr;
mDefaultTransformFeedback = nullptr;
if (mBoundTransformFeedbackBuffers) {
for (GLuint i = 0; i < mGLMaxTransformFeedbackSeparateAttribs; i++) {
mBoundTransformFeedbackBuffers[i] = nullptr;
}
}
while (!mTextures.isEmpty()) while (!mTextures.isEmpty())
mTextures.getLast()->DeleteOnce(); mTextures.getLast()->DeleteOnce();
@ -347,6 +356,8 @@ WebGLContext::DestroyResourcesAndContext()
mQueries.getLast()->DeleteOnce(); mQueries.getLast()->DeleteOnce();
while (!mSamplers.isEmpty()) while (!mSamplers.isEmpty())
mSamplers.getLast()->DeleteOnce(); mSamplers.getLast()->DeleteOnce();
while (!mTransformFeedbacks.isEmpty())
mTransformFeedbacks.getLast()->DeleteOnce();
mBlackOpaqueTexture2D = nullptr; mBlackOpaqueTexture2D = nullptr;
mBlackOpaqueTextureCubeMap = nullptr; mBlackOpaqueTextureCubeMap = nullptr;

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

@ -80,6 +80,7 @@ class WebGLSampler;
class WebGLShader; class WebGLShader;
class WebGLShaderPrecisionFormat; class WebGLShaderPrecisionFormat;
class WebGLTexture; class WebGLTexture;
class WebGLTransformFeedback;
class WebGLUniformLocation; class WebGLUniformLocation;
class WebGLVertexArray; class WebGLVertexArray;
struct WebGLVertexAttribData; struct WebGLVertexAttribData;
@ -881,19 +882,16 @@ public:
void DeleteBuffer(WebGLBuffer* buf); void DeleteBuffer(WebGLBuffer* buf);
bool IsBuffer(WebGLBuffer* buf); bool IsBuffer(WebGLBuffer* buf);
private: protected:
// ARRAY_BUFFER slot // bound buffer state
WebGLRefPtr<WebGLBuffer> mBoundArrayBuffer; WebGLRefPtr<WebGLBuffer> mBoundArrayBuffer;
// TRANSFORM_FEEDBACK_BUFFER slot
WebGLRefPtr<WebGLBuffer> mBoundTransformFeedbackBuffer; WebGLRefPtr<WebGLBuffer> mBoundTransformFeedbackBuffer;
// these two functions emit INVALID_ENUM for invalid `target`. UniquePtr<WebGLRefPtr<WebGLBuffer>[]> mBoundTransformFeedbackBuffers;
WebGLRefPtr<WebGLBuffer>* GetBufferSlotByTarget(GLenum target,
const char* info); WebGLRefPtr<WebGLBuffer>* GetBufferSlotByTarget(GLenum target);
WebGLRefPtr<WebGLBuffer>* GetBufferSlotByTargetIndexed(GLenum target, WebGLRefPtr<WebGLBuffer>* GetBufferSlotByTargetIndexed(GLenum target,
GLuint index, GLuint index);
const char* info);
bool ValidateBufferUsageEnum(GLenum target, const char* info); bool ValidateBufferUsageEnum(GLenum target, const char* info);
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -1114,7 +1112,7 @@ protected:
int32_t mGLMaxVertexUniformVectors; int32_t mGLMaxVertexUniformVectors;
int32_t mGLMaxColorAttachments; int32_t mGLMaxColorAttachments;
int32_t mGLMaxDrawBuffers; int32_t mGLMaxDrawBuffers;
uint32_t mGLMaxTransformFeedbackSeparateAttribs; GLuint mGLMaxTransformFeedbackSeparateAttribs;
public: public:
GLuint MaxVertexAttribs() const { GLuint MaxVertexAttribs() const {
@ -1339,6 +1337,8 @@ private:
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// Context customization points // Context customization points
virtual bool ValidateAttribPointerType(bool integerMode, GLenum type, GLsizei* alignment, const char* info) = 0; 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;
protected: protected:
int32_t MaxTextureSizeForTarget(TexTarget target) const { int32_t MaxTextureSizeForTarget(TexTarget target) const {
@ -1380,6 +1380,7 @@ protected:
WebGLRefPtr<WebGLFramebuffer> mBoundFramebuffer; WebGLRefPtr<WebGLFramebuffer> mBoundFramebuffer;
WebGLRefPtr<WebGLRenderbuffer> mBoundRenderbuffer; WebGLRefPtr<WebGLRenderbuffer> mBoundRenderbuffer;
WebGLRefPtr<WebGLTransformFeedback> mBoundTransformFeedback;
WebGLRefPtr<WebGLVertexArray> mBoundVertexArray; WebGLRefPtr<WebGLVertexArray> mBoundVertexArray;
LinkedList<WebGLTexture> mTextures; LinkedList<WebGLTexture> mTextures;
@ -1393,8 +1394,10 @@ protected:
// TODO(djg): Does this need a rethink? Should it be WebGL2Context? // TODO(djg): Does this need a rethink? Should it be WebGL2Context?
LinkedList<WebGLSampler> mSamplers; LinkedList<WebGLSampler> mSamplers;
LinkedList<WebGLTransformFeedback> mTransformFeedbacks;
WebGLRefPtr<WebGLVertexArray> mDefaultVertexArray; WebGLRefPtr<WebGLVertexArray> mDefaultVertexArray;
WebGLRefPtr<WebGLTransformFeedback> mDefaultTransformFeedback;
// PixelStore parameters // PixelStore parameters
uint32_t mPixelStorePackAlignment; uint32_t mPixelStorePackAlignment;
@ -1518,6 +1521,7 @@ public:
friend class WebGLBuffer; friend class WebGLBuffer;
friend class WebGLSampler; friend class WebGLSampler;
friend class WebGLShader; friend class WebGLShader;
friend class WebGLTransformFeedback;
friend class WebGLUniformLocation; friend class WebGLUniformLocation;
friend class WebGLVertexArray; friend class WebGLVertexArray;
friend class WebGLVertexArrayFake; friend class WebGLVertexArrayFake;

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

@ -24,11 +24,12 @@ WebGLContext::BindBuffer(GLenum target, WebGLBuffer* buffer)
if (buffer && buffer->IsDeleted()) if (buffer && buffer->IsDeleted())
return; return;
WebGLRefPtr<WebGLBuffer>* bufferSlot = GetBufferSlotByTarget(target, if (!ValidateBufferTarget(target, "bindBuffer"))
"bindBuffer");
if (!bufferSlot)
return; return;
WebGLRefPtr<WebGLBuffer>* bufferSlot = GetBufferSlotByTarget(target);
MOZ_ASSERT(bufferSlot);
if (buffer) { if (buffer) {
if (!buffer->HasEverBeenBound()) { if (!buffer->HasEverBeenBound()) {
buffer->BindTo(target); buffer->BindTo(target);
@ -60,11 +61,19 @@ WebGLContext::BindBufferBase(GLenum target, GLuint index, WebGLBuffer* buffer)
return; return;
} }
// ValidateBufferTarget
switch (target) {
case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER:
if (index >= mGLMaxTransformFeedbackSeparateAttribs)
return ErrorInvalidValue("bindBufferBase: index should be less than "
"MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS");
default:
return ErrorInvalidEnumInfo("bindBufferBase: target", target);
}
WebGLRefPtr<WebGLBuffer>* indexedBufferSlot; WebGLRefPtr<WebGLBuffer>* indexedBufferSlot;
indexedBufferSlot = GetBufferSlotByTargetIndexed(target, index, indexedBufferSlot = GetBufferSlotByTargetIndexed(target, index);
"bindBufferBase"); MOZ_ASSERT(indexedBufferSlot);
if (!indexedBufferSlot)
return;
if (buffer) { if (buffer) {
if (!buffer->HasEverBeenBound()) if (!buffer->HasEverBeenBound())
@ -77,9 +86,7 @@ WebGLContext::BindBufferBase(GLenum target, GLuint index, WebGLBuffer* buffer)
} }
} }
WebGLRefPtr<WebGLBuffer>* bufferSlot = GetBufferSlotByTarget(target, WebGLRefPtr<WebGLBuffer>* bufferSlot = GetBufferSlotByTarget(target);
"bindBufferBase");
MOZ_ASSERT(bufferSlot, "GetBufferSlotByTarget(Indexed) mismatch"); MOZ_ASSERT(bufferSlot, "GetBufferSlotByTarget(Indexed) mismatch");
*indexedBufferSlot = buffer; *indexedBufferSlot = buffer;
@ -104,11 +111,20 @@ WebGLContext::BindBufferRange(GLenum target, GLuint index, WebGLBuffer* buffer,
if (buffer && buffer->IsDeleted()) if (buffer && buffer->IsDeleted())
return; return;
// ValidateBufferTarget
switch (target) {
case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER:
if (index >= mGLMaxTransformFeedbackSeparateAttribs)
return ErrorInvalidValue("bindBufferRange: index should be less than "
"MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS");
default:
return ErrorInvalidEnumInfo("bindBufferRange: target", target);
}
WebGLRefPtr<WebGLBuffer>* indexedBufferSlot; WebGLRefPtr<WebGLBuffer>* indexedBufferSlot;
indexedBufferSlot = GetBufferSlotByTargetIndexed(target, index, indexedBufferSlot = GetBufferSlotByTargetIndexed(target, index);
"bindBufferRange"); MOZ_ASSERT(indexedBufferSlot);
if (!indexedBufferSlot)
return;
if (buffer) { if (buffer) {
if (!buffer->HasEverBeenBound()) if (!buffer->HasEverBeenBound())
@ -128,9 +144,7 @@ WebGLContext::BindBufferRange(GLenum target, GLuint index, WebGLBuffer* buffer,
} }
} }
WebGLRefPtr<WebGLBuffer>* bufferSlot = GetBufferSlotByTarget(target, WebGLRefPtr<WebGLBuffer>* bufferSlot = GetBufferSlotByTarget(target);
"BindBufferRange");
MOZ_ASSERT(bufferSlot, "GetBufferSlotByTarget(Indexed) mismatch"); MOZ_ASSERT(bufferSlot, "GetBufferSlotByTarget(Indexed) mismatch");
*indexedBufferSlot = buffer; *indexedBufferSlot = buffer;
@ -148,11 +162,12 @@ WebGLContext::BufferData(GLenum target, WebGLsizeiptr size, GLenum usage)
if (IsContextLost()) if (IsContextLost())
return; return;
WebGLRefPtr<WebGLBuffer>* bufferSlot = GetBufferSlotByTarget(target, if (!ValidateBufferTarget(target, "bufferData"))
"bufferData");
if (!bufferSlot)
return; return;
WebGLRefPtr<WebGLBuffer>* bufferSlot = GetBufferSlotByTarget(target);
MOZ_ASSERT(bufferSlot);
if (size < 0) if (size < 0)
return ErrorInvalidValue("bufferData: negative size"); return ErrorInvalidValue("bufferData: negative size");
@ -201,11 +216,12 @@ WebGLContext::BufferData(GLenum target,
return ErrorInvalidValue("bufferData: null object passed"); return ErrorInvalidValue("bufferData: null object passed");
} }
WebGLRefPtr<WebGLBuffer>* bufferSlot = GetBufferSlotByTarget(target, if (!ValidateBufferTarget(target, "bufferData"))
"bufferData");
if (!bufferSlot)
return; return;
WebGLRefPtr<WebGLBuffer>* bufferSlot = GetBufferSlotByTarget(target);
MOZ_ASSERT(bufferSlot);
const dom::ArrayBuffer& data = maybeData.Value(); const dom::ArrayBuffer& data = maybeData.Value();
data.ComputeLengthAndData(); data.ComputeLengthAndData();
@ -244,11 +260,12 @@ WebGLContext::BufferData(GLenum target, const dom::ArrayBufferView& data,
if (IsContextLost()) if (IsContextLost())
return; return;
WebGLRefPtr<WebGLBuffer>* bufferSlot = GetBufferSlotByTarget(target, if (!ValidateBufferTarget(target, "bufferData"))
"bufferSubData");
if (!bufferSlot)
return; return;
WebGLRefPtr<WebGLBuffer>* bufferSlot = GetBufferSlotByTarget(target);
MOZ_ASSERT(bufferSlot);
if (!ValidateBufferUsageEnum(usage, "bufferData: usage")) if (!ValidateBufferUsageEnum(usage, "bufferData: usage"))
return; return;
@ -290,11 +307,12 @@ WebGLContext::BufferSubData(GLenum target, WebGLsizeiptr byteOffset,
return; return;
} }
WebGLRefPtr<WebGLBuffer>* bufferSlot = GetBufferSlotByTarget(target, if (!ValidateBufferTarget(target, "bufferSubData"))
"bufferSubData");
if (!bufferSlot)
return; return;
WebGLRefPtr<WebGLBuffer>* bufferSlot = GetBufferSlotByTarget(target);
MOZ_ASSERT(bufferSlot);
if (byteOffset < 0) if (byteOffset < 0)
return ErrorInvalidValue("bufferSubData: negative offset"); return ErrorInvalidValue("bufferSubData: negative offset");
@ -335,11 +353,12 @@ WebGLContext::BufferSubData(GLenum target, WebGLsizeiptr byteOffset,
if (IsContextLost()) if (IsContextLost())
return; return;
WebGLRefPtr<WebGLBuffer>* bufferSlot = GetBufferSlotByTarget(target, if (!ValidateBufferTarget(target, "bufferSubData"))
"bufferSubData");
if (!bufferSlot)
return; return;
WebGLRefPtr<WebGLBuffer>* bufferSlot = GetBufferSlotByTarget(target);
MOZ_ASSERT(bufferSlot);
if (byteOffset < 0) if (byteOffset < 0)
return ErrorInvalidValue("bufferSubData: negative offset"); return ErrorInvalidValue("bufferSubData: negative offset");
@ -445,48 +464,35 @@ WebGLContext::ValidateBufferUsageEnum(GLenum target, const char* info)
} }
WebGLRefPtr<WebGLBuffer>* WebGLRefPtr<WebGLBuffer>*
WebGLContext::GetBufferSlotByTarget(GLenum target, const char* info) WebGLContext::GetBufferSlotByTarget(GLenum target)
{ {
/* This function assumes that target has been validated for either WebGL1 or WebGL. */
switch (target) { switch (target) {
case LOCAL_GL_ARRAY_BUFFER: case LOCAL_GL_ARRAY_BUFFER:
return &mBoundArrayBuffer; return &mBoundArrayBuffer;
case LOCAL_GL_ELEMENT_ARRAY_BUFFER: case LOCAL_GL_ELEMENT_ARRAY_BUFFER:
return &mBoundVertexArray->mElementArrayBuffer; return &mBoundVertexArray->mElementArrayBuffer;
case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER: case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER:
if (!IsWebGL2()) { return &mBoundTransformFeedbackBuffer;
break;
}
return &mBoundTransformFeedbackBuffer;
default: default:
break; return nullptr;
} }
ErrorInvalidEnum("%s: target: Invalid enum value 0x%x.", info, target);
return nullptr;
} }
WebGLRefPtr<WebGLBuffer>* WebGLRefPtr<WebGLBuffer>*
WebGLContext::GetBufferSlotByTargetIndexed(GLenum target, GLuint index, WebGLContext::GetBufferSlotByTargetIndexed(GLenum target, GLuint index)
const char* info)
{ {
/* This function assumes that target has been validated for either WebGL1 or WebGL. */
switch (target) { switch (target) {
case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER: case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER:
if (index >= mGLMaxTransformFeedbackSeparateAttribs) { MOZ_ASSERT(index < mGLMaxTransformFeedbackSeparateAttribs);
ErrorInvalidValue("%s: `index` should be less than" return &mBoundTransformFeedbackBuffers[index];
" MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS.", info,
index);
return nullptr;
}
return nullptr; // See bug 903594
default:
break;
} }
ErrorInvalidEnum("%s: target: invalid enum value 0x%x", info, target); MOZ_CRASH("Should not get here.");
return nullptr; return nullptr;
} }

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

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

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

@ -11,27 +11,37 @@
namespace mozilla { namespace mozilla {
WebGLTransformFeedback::WebGLTransformFeedback(WebGLContext* webgl) WebGLTransformFeedback::WebGLTransformFeedback(WebGLContext* context,
: WebGLBindableName<GLenum>(0) GLuint tf)
, WebGLContextBoundObject(webgl) : WebGLBindableName<GLenum>(tf)
, WebGLContextBoundObject(context)
, mMode(LOCAL_GL_NONE)
, mIsActive(false)
, mIsPaused(false)
{ {
MOZ_CRASH("Not Implemented."); context->mTransformFeedbacks.insertBack(this);
} }
WebGLTransformFeedback::~WebGLTransformFeedback() WebGLTransformFeedback::~WebGLTransformFeedback()
{} {
mMode = LOCAL_GL_NONE;
mIsActive = false;
mIsPaused = false;
DeleteOnce();
}
void void
WebGLTransformFeedback::Delete() WebGLTransformFeedback::Delete()
{ {
MOZ_CRASH("Not Implemented."); mContext->MakeContextCurrent();
mContext->gl->fDeleteTransformFeedbacks(1, &mGLName);
removeFrom(mContext->mTransformFeedbacks);
} }
WebGLContext* WebGLContext*
WebGLTransformFeedback::GetParentObject() const WebGLTransformFeedback::GetParentObject() const
{ {
MOZ_CRASH("Not Implemented."); return Context();
return nullptr;
} }
JSObject* JSObject*

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

@ -21,9 +21,10 @@ class WebGLTransformFeedback MOZ_FINAL
, public WebGLContextBoundObject , public WebGLContextBoundObject
{ {
friend class WebGLContext; friend class WebGLContext;
friend class WebGL2Context;
public: public:
explicit WebGLTransformFeedback(WebGLContext* webgl); explicit WebGLTransformFeedback(WebGLContext* webgl, GLuint tf);
void Delete(); void Delete();
WebGLContext* GetParentObject() const; WebGLContext* GetParentObject() const;
@ -34,6 +35,9 @@ public:
private: private:
~WebGLTransformFeedback(); ~WebGLTransformFeedback();
GLenum mMode;
bool mIsActive;
bool mIsPaused;
}; };
} // namespace mozilla } // namespace mozilla

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

@ -42,6 +42,7 @@ UNIFIED_SOURCES += [
UNIFIED_SOURCES += [ UNIFIED_SOURCES += [
'MurmurHash3.cpp', 'MurmurHash3.cpp',
'WebGL1Context.cpp', 'WebGL1Context.cpp',
'WebGL1ContextBuffers.cpp',
'WebGL1ContextUniforms.cpp', 'WebGL1ContextUniforms.cpp',
'WebGL2Context.cpp', 'WebGL2Context.cpp',
'WebGL2ContextBuffers.cpp', 'WebGL2ContextBuffers.cpp',

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

@ -443,10 +443,10 @@ interface WebGL2RenderingContext : WebGLRenderingContext
WebGLTransformFeedback? createTransformFeedback(); WebGLTransformFeedback? createTransformFeedback();
void deleteTransformFeedback(WebGLTransformFeedback? tf); void deleteTransformFeedback(WebGLTransformFeedback? tf);
[WebGLHandlesContextLoss] GLboolean isTransformFeedback(WebGLTransformFeedback? tf); [WebGLHandlesContextLoss] GLboolean isTransformFeedback(WebGLTransformFeedback? tf);
void bindTransformFeedback(GLenum target, GLuint id); void bindTransformFeedback(GLenum target, WebGLTransformFeedback? tf);
void beginTransformFeedback(GLenum primitiveMode); void beginTransformFeedback(GLenum primitiveMode);
void endTransformFeedback(); void endTransformFeedback();
void transformFeedbackVaryings(WebGLProgram? program, GLsizei count, sequence<DOMString> varyings, GLenum bufferMode); void transformFeedbackVaryings(WebGLProgram? program, sequence<DOMString> varyings, GLenum bufferMode);
[NewObject] WebGLActiveInfo? getTransformFeedbackVarying(WebGLProgram? program, GLuint index); [NewObject] WebGLActiveInfo? getTransformFeedbackVarying(WebGLProgram? program, GLuint index);
void pauseTransformFeedback(); void pauseTransformFeedback();
void resumeTransformFeedback(); void resumeTransformFeedback();

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

@ -2730,7 +2730,7 @@ public:
AFTER_GL_CALL; AFTER_GL_CALL;
} }
void fDeleteTransformFeedbacks(GLsizei n, GLuint* ids) void fDeleteTransformFeedbacks(GLsizei n, const GLuint* ids)
{ {
BEFORE_GL_CALL; BEFORE_GL_CALL;
ASSERT_SYMBOL_PRESENT(fDeleteTransformFeedbacks); ASSERT_SYMBOL_PRESENT(fDeleteTransformFeedbacks);

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

@ -487,7 +487,7 @@ struct GLContextSymbols
typedef void (GLAPIENTRY * PFNGLGENTRANSFORMFEEDBACKSPROC) (GLsizei n, GLuint* ids); typedef void (GLAPIENTRY * PFNGLGENTRANSFORMFEEDBACKSPROC) (GLsizei n, GLuint* ids);
PFNGLGENTRANSFORMFEEDBACKSPROC fGenTransformFeedbacks; PFNGLGENTRANSFORMFEEDBACKSPROC fGenTransformFeedbacks;
typedef void (GLAPIENTRY * PFNGLDELETETRANSFORMFEEDBACKSPROC) (GLsizei n, GLuint* ids); typedef void (GLAPIENTRY * PFNGLDELETETRANSFORMFEEDBACKSPROC) (GLsizei n, const GLuint* ids);
PFNGLDELETETRANSFORMFEEDBACKSPROC fDeleteTransformFeedbacks; PFNGLDELETETRANSFORMFEEDBACKSPROC fDeleteTransformFeedbacks;
typedef realGLboolean (GLAPIENTRY * PFNGLISTRANSFORMFEEDBACKPROC) (GLuint id); typedef realGLboolean (GLAPIENTRY * PFNGLISTRANSFORMFEEDBACKPROC) (GLuint id);
PFNGLISTRANSFORMFEEDBACKPROC fIsTransformFeedback; PFNGLISTRANSFORMFEEDBACKPROC fIsTransformFeedback;