1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "WebGL2Context.h"
7 #include "WebGLActiveInfo.h"
8 #include "WebGLProgram.h"
9 #include "WebGLTransformFeedback.h"
10 #include "GLContext.h"
12 using namespace mozilla
;
13 using namespace mozilla::dom
;
15 // -------------------------------------------------------------------------
18 already_AddRefed
<WebGLTransformFeedback
>
19 WebGL2Context::CreateTransformFeedback()
26 gl
->fGenTransformFeedbacks(1, &tf
);
28 nsRefPtr
<WebGLTransformFeedback
> globj
= new WebGLTransformFeedback(this, tf
);
29 return globj
.forget();
33 WebGL2Context::DeleteTransformFeedback(WebGLTransformFeedback
* tf
)
38 if (!ValidateObjectAllowDeletedOrNull("deleteTransformFeedback", tf
))
41 if (!tf
|| tf
->IsDeleted())
44 if (mBoundTransformFeedback
== tf
)
45 BindTransformFeedback(LOCAL_GL_TRANSFORM_FEEDBACK
, tf
);
51 WebGL2Context::IsTransformFeedback(WebGLTransformFeedback
* tf
)
56 if (!ValidateObjectAllowDeleted("isTransformFeedback", tf
))
63 return gl
->fIsTransformFeedback(tf
->GLName());
67 WebGL2Context::BindTransformFeedback(GLenum target
, WebGLTransformFeedback
* tf
)
72 if (!ValidateObjectAllowDeletedOrNull("bindTransformFeedback", tf
))
75 if (target
!= LOCAL_GL_TRANSFORM_FEEDBACK
)
76 return ErrorInvalidEnum("bindTransformFeedback: target must be TRANSFORM_FEEDBACK");
78 WebGLRefPtr
<WebGLTransformFeedback
> currentTF
= mBoundTransformFeedback
;
79 if (currentTF
&& currentTF
->mIsActive
&& !currentTF
->mIsPaused
) {
80 return ErrorInvalidOperation("bindTransformFeedback: Currently bound transform "
81 "feedback is active and not paused");
84 if (tf
&& tf
->IsDeleted())
85 return ErrorInvalidOperation("bindTransformFeedback: Attempt to bind deleted id");
88 tf
->BindTo(LOCAL_GL_TRANSFORM_FEEDBACK
);
91 gl
->fBindTransformFeedback(target
, tf
? tf
->GLName() : 0);
93 mBoundTransformFeedback
= tf
;
95 mBoundTransformFeedback
= mDefaultTransformFeedback
;
99 WebGL2Context::BeginTransformFeedback(GLenum primitiveMode
)
104 WebGLTransformFeedback
* tf
= mBoundTransformFeedback
;
110 return ErrorInvalidOperation("beginTransformFeedback: transform feedback is active");
112 const GLenum mode
= tf
->mMode
;
113 if (mode
!= LOCAL_GL_POINTS
&& mode
!= LOCAL_GL_LINES
&& mode
!= LOCAL_GL_TRIANGLES
)
114 return ErrorInvalidEnum("beginTransformFeedback: primitive must be one of POINTS, LINES, or TRIANGLES");
117 // GL_INVALID_OPERATION is generated by glBeginTransformFeedback
118 // if any binding point used in transform feedback mode does not
119 // have a buffer object bound. In interleaved mode, only the first
120 // buffer object binding point is ever written to.
122 // GL_INVALID_OPERATION is generated by glBeginTransformFeedback
123 // if no binding points would be used, either because no program
124 // object is active of because the active program object has
125 // specified no varying variables to record.
126 if (!mCurrentProgram
)
127 return ErrorInvalidOperation("beginTransformFeedback: no program is active");
129 MakeContextCurrent();
130 gl
->fBeginTransformFeedback(primitiveMode
);
131 tf
->mIsActive
= true;
132 tf
->mIsPaused
= false;
136 WebGL2Context::EndTransformFeedback()
141 WebGLTransformFeedback
* tf
= mBoundTransformFeedback
;
148 return ErrorInvalidOperation("%s: transform feedback in not active",
149 "endTransformFeedback");
151 MakeContextCurrent();
152 gl
->fEndTransformFeedback();
153 tf
->mIsActive
= false;
154 tf
->mIsPaused
= false;
158 WebGL2Context::PauseTransformFeedback()
163 WebGLTransformFeedback
* tf
= mBoundTransformFeedback
;
168 if (!tf
->mIsActive
|| tf
->mIsPaused
) {
169 return ErrorInvalidOperation("%s: transform feedback is not active or is paused",
170 "pauseTransformFeedback");
173 MakeContextCurrent();
174 gl
->fPauseTransformFeedback();
175 tf
->mIsPaused
= true;
179 WebGL2Context::ResumeTransformFeedback()
184 WebGLTransformFeedback
* tf
= mBoundTransformFeedback
;
189 if (!tf
->mIsActive
|| !tf
->mIsPaused
)
190 return ErrorInvalidOperation("resumeTransformFeedback: transform feedback is not active or is not paused");
192 MakeContextCurrent();
193 gl
->fResumeTransformFeedback();
194 tf
->mIsPaused
= false;
198 WebGL2Context::TransformFeedbackVaryings(WebGLProgram
* program
,
199 const dom::Sequence
<nsString
>& varyings
,
205 if (!ValidateObject("transformFeedbackVaryings: program", program
))
208 GLsizei count
= varyings
.Length();
209 GLchar
** tmpVaryings
= (GLchar
**) nsMemory::Alloc(count
* sizeof(GLchar
*));
211 for (GLsizei n
= 0; n
< count
; n
++) {
212 tmpVaryings
[n
] = (GLchar
*) ToNewCString(varyings
[n
]);
215 GLuint progname
= program
->GLName();
216 MakeContextCurrent();
217 gl
->fTransformFeedbackVaryings(progname
, count
, tmpVaryings
, bufferMode
);
219 NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(count
, tmpVaryings
);
223 already_AddRefed
<WebGLActiveInfo
>
224 WebGL2Context::GetTransformFeedbackVarying(WebGLProgram
* program
, GLuint index
)
229 if (!ValidateObject("getTransformFeedbackVarying: program", program
))
232 MakeContextCurrent();
235 GLuint progname
= program
->GLName();
236 gl
->fGetProgramiv(progname
, LOCAL_GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH
, &len
);
240 UniquePtr
<char[]> name(new char[len
]);
244 gl
->fGetTransformFeedbackVarying(progname
, index
, len
, &len
, &tfsize
, &tftype
, name
.get());
245 if (len
== 0 || tfsize
== 0 || tftype
== 0)
248 // TODO(djg): Reverse lookup of name
249 // nsCString reverseMappedName;
250 // prog->ReverveMapIdentifier(nsDependentCString(name), &reverseMappedName);
252 nsRefPtr
<WebGLActiveInfo
> result
= new WebGLActiveInfo(tfsize
, tftype
, nsDependentCString(name
.get()));
253 return result
.forget();