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:
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

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

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

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

@ -215,14 +215,13 @@ public:
already_AddRefed<WebGLTransformFeedback> CreateTransformFeedback();
void DeleteTransformFeedback(WebGLTransformFeedback* tf);
bool IsTransformFeedback(WebGLTransformFeedback* tf);
void BindTransformFeedback(GLenum target, GLuint id);
void BindTransformFeedback(GLenum target, WebGLTransformFeedback* tf);
void BeginTransformFeedback(GLenum primitiveMode);
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 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);
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

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

@ -9,6 +9,35 @@
using namespace mozilla;
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

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

@ -4,6 +4,9 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "WebGL2Context.h"
#include "WebGLActiveInfo.h"
#include "WebGLProgram.h"
#include "WebGLTransformFeedback.h"
#include "GLContext.h"
using namespace mozilla;
@ -15,64 +18,237 @@ using namespace mozilla::dom;
already_AddRefed<WebGLTransformFeedback>
WebGL2Context::CreateTransformFeedback()
{
MOZ_CRASH("Not Implemented.");
return nullptr;
if (IsContextLost())
return nullptr;
GLuint tf = 0;
MakeContextCurrent();
gl->fGenTransformFeedbacks(1, &tf);
nsRefPtr<WebGLTransformFeedback> globj = new WebGLTransformFeedback(this, tf);
return globj.forget();
}
void
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
WebGL2Context::IsTransformFeedback(WebGLTransformFeedback* tf)
{
MOZ_CRASH("Not Implemented.");
return false;
if (IsContextLost())
return false;
if (!ValidateObjectAllowDeleted("isTransformFeedback", tf))
return false;
if (tf->IsDeleted())
return false;
MakeContextCurrent();
return gl->fIsTransformFeedback(tf->GLName());
}
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
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
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
WebGL2Context::TransformFeedbackVaryings(WebGLProgram* program, GLsizei count,
const dom::Sequence<nsString>& varyings, GLenum bufferMode)
WebGL2Context::PauseTransformFeedback()
{
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>
WebGL2Context::GetTransformFeedbackVarying(WebGLProgram* program, GLuint index)
{
MOZ_CRASH("Not Implemented.");
return nullptr;
}
if (IsContextLost())
return nullptr;
void
WebGL2Context::PauseTransformFeedback()
{
MOZ_CRASH("Not Implemented.");
}
if (!ValidateObject("getTransformFeedbackVarying: program", program))
return nullptr;
void
WebGL2Context::ResumeTransformFeedback()
{
MOZ_CRASH("Not Implemented.");
MakeContextCurrent();
GLint len = 0;
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 "WebGLQuery.h"
#include "WebGLSampler.h"
#include "WebGLTransformFeedback.h"
#include "WebGLVertexArray.h"
#include "WebGLVertexAttribData.h"
@ -328,6 +329,14 @@ WebGLContext::DestroyResourcesAndContext()
mBoundRenderbuffer = nullptr;
mBoundVertexArray = nullptr;
mDefaultVertexArray = nullptr;
mBoundTransformFeedback = nullptr;
mDefaultTransformFeedback = nullptr;
if (mBoundTransformFeedbackBuffers) {
for (GLuint i = 0; i < mGLMaxTransformFeedbackSeparateAttribs; i++) {
mBoundTransformFeedbackBuffers[i] = nullptr;
}
}
while (!mTextures.isEmpty())
mTextures.getLast()->DeleteOnce();
@ -347,6 +356,8 @@ WebGLContext::DestroyResourcesAndContext()
mQueries.getLast()->DeleteOnce();
while (!mSamplers.isEmpty())
mSamplers.getLast()->DeleteOnce();
while (!mTransformFeedbacks.isEmpty())
mTransformFeedbacks.getLast()->DeleteOnce();
mBlackOpaqueTexture2D = nullptr;
mBlackOpaqueTextureCubeMap = nullptr;

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

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

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

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

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

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

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

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

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

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

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

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

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

@ -443,10 +443,10 @@ interface WebGL2RenderingContext : WebGLRenderingContext
WebGLTransformFeedback? createTransformFeedback();
void deleteTransformFeedback(WebGLTransformFeedback? tf);
[WebGLHandlesContextLoss] GLboolean isTransformFeedback(WebGLTransformFeedback? tf);
void bindTransformFeedback(GLenum target, GLuint id);
void bindTransformFeedback(GLenum target, WebGLTransformFeedback? tf);
void beginTransformFeedback(GLenum primitiveMode);
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);
void pauseTransformFeedback();
void resumeTransformFeedback();

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

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

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

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