Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; 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/. */
5 :
6 : #include "mozilla/UniquePtr.h"
7 :
8 : #include "GLContext.h"
9 : #include "ScopedGLHelpers.h"
10 :
11 : namespace mozilla {
12 : namespace gl {
13 :
14 : #ifdef DEBUG
15 : bool
16 0 : IsContextCurrent(GLContext* gl)
17 : {
18 0 : return gl->IsCurrent();
19 : }
20 : #endif
21 :
22 : /* ScopedGLState - Wraps glEnable/glDisable. **********************************/
23 :
24 : // Use |newState = true| to enable, |false| to disable.
25 0 : ScopedGLState::ScopedGLState(GLContext* aGL, GLenum aCapability, bool aNewState)
26 : : ScopedGLWrapper<ScopedGLState>(aGL)
27 0 : , mCapability(aCapability)
28 : {
29 0 : mOldState = mGL->fIsEnabled(mCapability);
30 :
31 : // Early out if we're already in the right state.
32 0 : if (aNewState == mOldState)
33 0 : return;
34 :
35 0 : if (aNewState) {
36 0 : mGL->fEnable(mCapability);
37 : } else {
38 0 : mGL->fDisable(mCapability);
39 : }
40 : }
41 :
42 0 : ScopedGLState::ScopedGLState(GLContext* aGL, GLenum aCapability)
43 : : ScopedGLWrapper<ScopedGLState>(aGL)
44 0 : , mCapability(aCapability)
45 : {
46 0 : mOldState = mGL->fIsEnabled(mCapability);
47 0 : }
48 :
49 : void
50 0 : ScopedGLState::UnwrapImpl()
51 : {
52 0 : if (mOldState) {
53 0 : mGL->fEnable(mCapability);
54 : } else {
55 0 : mGL->fDisable(mCapability);
56 : }
57 0 : }
58 :
59 :
60 : /* ScopedBindFramebuffer - Saves and restores with GetUserBoundFB and BindUserFB. */
61 :
62 : void
63 0 : ScopedBindFramebuffer::Init()
64 : {
65 0 : if (mGL->IsSupported(GLFeature::split_framebuffer)) {
66 0 : mOldReadFB = mGL->GetReadFB();
67 0 : mOldDrawFB = mGL->GetDrawFB();
68 : } else {
69 0 : mOldReadFB = mOldDrawFB = mGL->GetFB();
70 : }
71 0 : }
72 :
73 0 : ScopedBindFramebuffer::ScopedBindFramebuffer(GLContext* aGL)
74 0 : : ScopedGLWrapper<ScopedBindFramebuffer>(aGL)
75 : {
76 0 : Init();
77 0 : }
78 :
79 0 : ScopedBindFramebuffer::ScopedBindFramebuffer(GLContext* aGL, GLuint aNewFB)
80 0 : : ScopedGLWrapper<ScopedBindFramebuffer>(aGL)
81 : {
82 0 : Init();
83 0 : mGL->BindFB(aNewFB);
84 0 : }
85 :
86 : void
87 0 : ScopedBindFramebuffer::UnwrapImpl()
88 : {
89 0 : if (mOldReadFB == mOldDrawFB) {
90 0 : mGL->BindFB(mOldDrawFB);
91 : } else {
92 0 : mGL->BindDrawFB(mOldDrawFB);
93 0 : mGL->BindReadFB(mOldReadFB);
94 : }
95 0 : }
96 :
97 :
98 : /* ScopedBindTextureUnit ******************************************************/
99 :
100 0 : ScopedBindTextureUnit::ScopedBindTextureUnit(GLContext* aGL, GLenum aTexUnit)
101 0 : : ScopedGLWrapper<ScopedBindTextureUnit>(aGL)
102 : {
103 0 : MOZ_ASSERT(aTexUnit >= LOCAL_GL_TEXTURE0);
104 0 : mGL->GetUIntegerv(LOCAL_GL_ACTIVE_TEXTURE, &mOldTexUnit);
105 0 : mGL->fActiveTexture(aTexUnit);
106 0 : }
107 :
108 : void
109 0 : ScopedBindTextureUnit::UnwrapImpl() {
110 0 : mGL->fActiveTexture(mOldTexUnit);
111 0 : }
112 :
113 :
114 : /* ScopedTexture **************************************************************/
115 :
116 0 : ScopedTexture::ScopedTexture(GLContext* aGL)
117 0 : : ScopedGLWrapper<ScopedTexture>(aGL)
118 : {
119 0 : mGL->fGenTextures(1, &mTexture);
120 0 : }
121 :
122 : void
123 0 : ScopedTexture::UnwrapImpl()
124 : {
125 0 : mGL->fDeleteTextures(1, &mTexture);
126 0 : }
127 :
128 : /* ScopedFramebuffer **************************************************************/
129 :
130 0 : ScopedFramebuffer::ScopedFramebuffer(GLContext* aGL)
131 0 : : ScopedGLWrapper<ScopedFramebuffer>(aGL)
132 : {
133 0 : mGL->fGenFramebuffers(1, &mFB);
134 0 : }
135 :
136 : void
137 0 : ScopedFramebuffer::UnwrapImpl()
138 : {
139 0 : mGL->fDeleteFramebuffers(1, &mFB);
140 0 : }
141 :
142 :
143 : /* ScopedRenderbuffer **************************************************************/
144 :
145 0 : ScopedRenderbuffer::ScopedRenderbuffer(GLContext* aGL)
146 0 : : ScopedGLWrapper<ScopedRenderbuffer>(aGL)
147 : {
148 0 : mGL->fGenRenderbuffers(1, &mRB);
149 0 : }
150 :
151 : void
152 0 : ScopedRenderbuffer::UnwrapImpl()
153 : {
154 0 : mGL->fDeleteRenderbuffers(1, &mRB);
155 0 : }
156 :
157 : /* ScopedBindTexture **********************************************************/
158 :
159 : static GLuint
160 0 : GetBoundTexture(GLContext* gl, GLenum texTarget)
161 : {
162 : GLenum bindingTarget;
163 0 : switch (texTarget) {
164 : case LOCAL_GL_TEXTURE_2D:
165 0 : bindingTarget = LOCAL_GL_TEXTURE_BINDING_2D;
166 0 : break;
167 :
168 : case LOCAL_GL_TEXTURE_CUBE_MAP:
169 0 : bindingTarget = LOCAL_GL_TEXTURE_BINDING_CUBE_MAP;
170 0 : break;
171 :
172 : case LOCAL_GL_TEXTURE_3D:
173 0 : bindingTarget = LOCAL_GL_TEXTURE_BINDING_3D;
174 0 : break;
175 :
176 : case LOCAL_GL_TEXTURE_2D_ARRAY:
177 0 : bindingTarget = LOCAL_GL_TEXTURE_BINDING_2D_ARRAY;
178 0 : break;
179 :
180 : case LOCAL_GL_TEXTURE_RECTANGLE_ARB:
181 0 : bindingTarget = LOCAL_GL_TEXTURE_BINDING_RECTANGLE_ARB;
182 0 : break;
183 :
184 : case LOCAL_GL_TEXTURE_EXTERNAL:
185 0 : bindingTarget = LOCAL_GL_TEXTURE_BINDING_EXTERNAL;
186 0 : break;
187 :
188 : default:
189 0 : MOZ_CRASH("bad texTarget");
190 : }
191 :
192 0 : GLuint ret = 0;
193 0 : gl->GetUIntegerv(bindingTarget, &ret);
194 0 : return ret;
195 : }
196 :
197 0 : ScopedBindTexture::ScopedBindTexture(GLContext* aGL, GLuint aNewTex, GLenum aTarget)
198 : : ScopedGLWrapper<ScopedBindTexture>(aGL)
199 : , mTarget(aTarget)
200 0 : , mOldTex(GetBoundTexture(aGL, aTarget))
201 : {
202 0 : mGL->fBindTexture(mTarget, aNewTex);
203 0 : }
204 :
205 : void
206 0 : ScopedBindTexture::UnwrapImpl()
207 : {
208 0 : mGL->fBindTexture(mTarget, mOldTex);
209 0 : }
210 :
211 :
212 : /* ScopedBindRenderbuffer *****************************************************/
213 :
214 : void
215 0 : ScopedBindRenderbuffer::Init()
216 : {
217 0 : mOldRB = 0;
218 0 : mGL->GetUIntegerv(LOCAL_GL_RENDERBUFFER_BINDING, &mOldRB);
219 0 : }
220 :
221 0 : ScopedBindRenderbuffer::ScopedBindRenderbuffer(GLContext* aGL)
222 0 : : ScopedGLWrapper<ScopedBindRenderbuffer>(aGL)
223 : {
224 0 : Init();
225 0 : }
226 :
227 0 : ScopedBindRenderbuffer::ScopedBindRenderbuffer(GLContext* aGL, GLuint aNewRB)
228 0 : : ScopedGLWrapper<ScopedBindRenderbuffer>(aGL)
229 : {
230 0 : Init();
231 0 : mGL->fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, aNewRB);
232 0 : }
233 :
234 : void
235 0 : ScopedBindRenderbuffer::UnwrapImpl()
236 : {
237 0 : mGL->fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, mOldRB);
238 0 : }
239 :
240 :
241 : /* ScopedFramebufferForTexture ************************************************/
242 0 : ScopedFramebufferForTexture::ScopedFramebufferForTexture(GLContext* aGL,
243 : GLuint aTexture,
244 0 : GLenum aTarget)
245 : : ScopedGLWrapper<ScopedFramebufferForTexture>(aGL)
246 : , mComplete(false)
247 0 : , mFB(0)
248 : {
249 0 : mGL->fGenFramebuffers(1, &mFB);
250 0 : ScopedBindFramebuffer autoFB(aGL, mFB);
251 0 : mGL->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER,
252 : LOCAL_GL_COLOR_ATTACHMENT0,
253 : aTarget,
254 : aTexture,
255 0 : 0);
256 :
257 0 : GLenum status = mGL->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
258 0 : if (status == LOCAL_GL_FRAMEBUFFER_COMPLETE) {
259 0 : mComplete = true;
260 : } else {
261 0 : mGL->fDeleteFramebuffers(1, &mFB);
262 0 : mFB = 0;
263 : }
264 0 : }
265 :
266 0 : void ScopedFramebufferForTexture::UnwrapImpl()
267 : {
268 0 : if (!mFB)
269 0 : return;
270 :
271 0 : mGL->fDeleteFramebuffers(1, &mFB);
272 0 : mFB = 0;
273 : }
274 :
275 :
276 : /* ScopedFramebufferForRenderbuffer *******************************************/
277 :
278 :
279 0 : ScopedFramebufferForRenderbuffer::ScopedFramebufferForRenderbuffer(GLContext* aGL,
280 0 : GLuint aRB)
281 : : ScopedGLWrapper<ScopedFramebufferForRenderbuffer>(aGL)
282 : , mComplete(false)
283 0 : , mFB(0)
284 : {
285 0 : mGL->fGenFramebuffers(1, &mFB);
286 0 : ScopedBindFramebuffer autoFB(aGL, mFB);
287 0 : mGL->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
288 : LOCAL_GL_COLOR_ATTACHMENT0,
289 : LOCAL_GL_RENDERBUFFER,
290 0 : aRB);
291 :
292 0 : GLenum status = mGL->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
293 0 : if (status == LOCAL_GL_FRAMEBUFFER_COMPLETE) {
294 0 : mComplete = true;
295 : } else {
296 0 : mGL->fDeleteFramebuffers(1, &mFB);
297 0 : mFB = 0;
298 : }
299 0 : }
300 :
301 : void
302 0 : ScopedFramebufferForRenderbuffer::UnwrapImpl()
303 : {
304 0 : if (!mFB)
305 0 : return;
306 :
307 0 : mGL->fDeleteFramebuffers(1, &mFB);
308 0 : mFB = 0;
309 : }
310 :
311 : /* ScopedViewportRect *********************************************************/
312 :
313 0 : ScopedViewportRect::ScopedViewportRect(GLContext* aGL,
314 : GLint x, GLint y,
315 0 : GLsizei width, GLsizei height)
316 0 : : ScopedGLWrapper<ScopedViewportRect>(aGL)
317 : {
318 0 : mGL->fGetIntegerv(LOCAL_GL_VIEWPORT, mSavedViewportRect);
319 0 : mGL->fViewport(x, y, width, height);
320 0 : }
321 :
322 0 : void ScopedViewportRect::UnwrapImpl()
323 : {
324 0 : mGL->fViewport(mSavedViewportRect[0],
325 : mSavedViewportRect[1],
326 : mSavedViewportRect[2],
327 0 : mSavedViewportRect[3]);
328 0 : }
329 :
330 : /* ScopedScissorRect **********************************************************/
331 :
332 0 : ScopedScissorRect::ScopedScissorRect(GLContext* aGL,
333 : GLint x, GLint y,
334 0 : GLsizei width, GLsizei height)
335 0 : : ScopedGLWrapper<ScopedScissorRect>(aGL)
336 : {
337 0 : mGL->fGetIntegerv(LOCAL_GL_SCISSOR_BOX, mSavedScissorRect);
338 0 : mGL->fScissor(x, y, width, height);
339 0 : }
340 :
341 0 : ScopedScissorRect::ScopedScissorRect(GLContext* aGL)
342 0 : : ScopedGLWrapper<ScopedScissorRect>(aGL)
343 : {
344 0 : mGL->fGetIntegerv(LOCAL_GL_SCISSOR_BOX, mSavedScissorRect);
345 0 : }
346 :
347 0 : void ScopedScissorRect::UnwrapImpl()
348 : {
349 0 : mGL->fScissor(mSavedScissorRect[0],
350 : mSavedScissorRect[1],
351 : mSavedScissorRect[2],
352 0 : mSavedScissorRect[3]);
353 0 : }
354 :
355 : /* ScopedVertexAttribPointer **************************************************/
356 :
357 0 : ScopedVertexAttribPointer::ScopedVertexAttribPointer(GLContext* aGL,
358 : GLuint index,
359 : GLint size,
360 : GLenum type,
361 : realGLboolean normalized,
362 : GLsizei stride,
363 : GLuint buffer,
364 0 : const GLvoid* pointer)
365 0 : : ScopedGLWrapper<ScopedVertexAttribPointer>(aGL)
366 : {
367 0 : WrapImpl(index);
368 0 : mGL->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, buffer);
369 0 : mGL->fVertexAttribPointer(index, size, type, normalized, stride, pointer);
370 0 : mGL->fEnableVertexAttribArray(index);
371 0 : }
372 :
373 0 : ScopedVertexAttribPointer::ScopedVertexAttribPointer(GLContext* aGL,
374 0 : GLuint index)
375 0 : : ScopedGLWrapper<ScopedVertexAttribPointer>(aGL)
376 : {
377 0 : WrapImpl(index);
378 0 : }
379 :
380 : void
381 0 : ScopedVertexAttribPointer::WrapImpl(GLuint index)
382 : {
383 0 : mAttribIndex = index;
384 :
385 : /*
386 : * mGL->fGetVertexAttribiv takes:
387 : * VERTEX_ATTRIB_ARRAY_ENABLED
388 : * VERTEX_ATTRIB_ARRAY_SIZE,
389 : * VERTEX_ATTRIB_ARRAY_STRIDE,
390 : * VERTEX_ATTRIB_ARRAY_TYPE,
391 : * VERTEX_ATTRIB_ARRAY_NORMALIZED,
392 : * VERTEX_ATTRIB_ARRAY_BUFFER_BINDING,
393 : * CURRENT_VERTEX_ATTRIB
394 : *
395 : * CURRENT_VERTEX_ATTRIB is vertex shader state. \o/
396 : * Others appear to be vertex array state,
397 : * or alternatively in the internal vertex array state
398 : * for a buffer object.
399 : */
400 :
401 0 : mGL->fGetVertexAttribiv(mAttribIndex, LOCAL_GL_VERTEX_ATTRIB_ARRAY_ENABLED, &mAttribEnabled);
402 0 : mGL->fGetVertexAttribiv(mAttribIndex, LOCAL_GL_VERTEX_ATTRIB_ARRAY_SIZE, &mAttribSize);
403 0 : mGL->fGetVertexAttribiv(mAttribIndex, LOCAL_GL_VERTEX_ATTRIB_ARRAY_STRIDE, &mAttribStride);
404 0 : mGL->fGetVertexAttribiv(mAttribIndex, LOCAL_GL_VERTEX_ATTRIB_ARRAY_TYPE, &mAttribType);
405 0 : mGL->fGetVertexAttribiv(mAttribIndex, LOCAL_GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, &mAttribNormalized);
406 0 : mGL->fGetVertexAttribiv(mAttribIndex, LOCAL_GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &mAttribBufferBinding);
407 0 : mGL->fGetVertexAttribPointerv(mAttribIndex, LOCAL_GL_VERTEX_ATTRIB_ARRAY_POINTER, &mAttribPointer);
408 :
409 : // Note that uniform values are program state, so we don't need to rebind those.
410 :
411 0 : mGL->GetUIntegerv(LOCAL_GL_ARRAY_BUFFER_BINDING, &mBoundBuffer);
412 0 : }
413 :
414 : void
415 0 : ScopedVertexAttribPointer::UnwrapImpl()
416 : {
417 0 : mGL->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mAttribBufferBinding);
418 0 : mGL->fVertexAttribPointer(mAttribIndex, mAttribSize, mAttribType, mAttribNormalized, mAttribStride, mAttribPointer);
419 0 : if (mAttribEnabled)
420 0 : mGL->fEnableVertexAttribArray(mAttribIndex);
421 : else
422 0 : mGL->fDisableVertexAttribArray(mAttribIndex);
423 0 : mGL->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mBoundBuffer);
424 0 : }
425 :
426 0 : ScopedGLDrawState::ScopedGLDrawState(GLContext* aGL)
427 : : blend (aGL, LOCAL_GL_BLEND, false)
428 : , cullFace (aGL, LOCAL_GL_CULL_FACE, false)
429 : , depthTest (aGL, LOCAL_GL_DEPTH_TEST, false)
430 : , dither (aGL, LOCAL_GL_DITHER, false)
431 : , polyOffsFill(aGL, LOCAL_GL_POLYGON_OFFSET_FILL, false)
432 : , sampleAToC (aGL, LOCAL_GL_SAMPLE_ALPHA_TO_COVERAGE, false)
433 : , sampleCover (aGL, LOCAL_GL_SAMPLE_COVERAGE, false)
434 : , scissor (aGL, LOCAL_GL_SCISSOR_TEST, false)
435 : , stencil (aGL, LOCAL_GL_STENCIL_TEST, false)
436 0 : , mGL(aGL)
437 : {
438 0 : mGL->GetUIntegerv(LOCAL_GL_CURRENT_PROGRAM, &boundProgram);
439 0 : mGL->GetUIntegerv(LOCAL_GL_ARRAY_BUFFER_BINDING, &boundBuffer);
440 0 : mGL->GetUIntegerv(LOCAL_GL_MAX_VERTEX_ATTRIBS, &maxAttrib);
441 0 : attrib_enabled = MakeUnique<GLint[]>(maxAttrib);
442 :
443 0 : for (GLuint i = 0; i < maxAttrib; i++) {
444 0 : mGL->fGetVertexAttribiv(i, LOCAL_GL_VERTEX_ATTRIB_ARRAY_ENABLED, &attrib_enabled[i]);
445 0 : mGL->fDisableVertexAttribArray(i);
446 : }
447 : // Only Attrib0's client side state affected
448 0 : mGL->fGetVertexAttribiv(0, LOCAL_GL_VERTEX_ATTRIB_ARRAY_SIZE, &attrib0_size);
449 0 : mGL->fGetVertexAttribiv(0, LOCAL_GL_VERTEX_ATTRIB_ARRAY_STRIDE, &attrib0_stride);
450 0 : mGL->fGetVertexAttribiv(0, LOCAL_GL_VERTEX_ATTRIB_ARRAY_TYPE, &attrib0_type);
451 0 : mGL->fGetVertexAttribiv(0, LOCAL_GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, &attrib0_normalized);
452 0 : mGL->fGetVertexAttribiv(0, LOCAL_GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &attrib0_bufferBinding);
453 0 : mGL->fGetVertexAttribPointerv(0, LOCAL_GL_VERTEX_ATTRIB_ARRAY_POINTER, &attrib0_pointer);
454 0 : mGL->fGetBooleanv(LOCAL_GL_COLOR_WRITEMASK, colorMask);
455 0 : mGL->fGetIntegerv(LOCAL_GL_VIEWPORT, viewport);
456 0 : mGL->fGetIntegerv(LOCAL_GL_SCISSOR_BOX, scissorBox);
457 0 : }
458 :
459 0 : ScopedGLDrawState::~ScopedGLDrawState()
460 : {
461 0 : MOZ_ASSERT(mGL->IsCurrent());
462 :
463 0 : mGL->fScissor(scissorBox[0], scissorBox[1],
464 0 : scissorBox[2], scissorBox[3]);
465 :
466 0 : mGL->fViewport(viewport[0], viewport[1],
467 0 : viewport[2], viewport[3]);
468 :
469 0 : mGL->fColorMask(colorMask[0],
470 0 : colorMask[1],
471 0 : colorMask[2],
472 0 : colorMask[3]);
473 :
474 0 : for (unsigned int i = 0; i < maxAttrib; i++) {
475 0 : if (attrib_enabled[i])
476 0 : mGL->fEnableVertexAttribArray(i);
477 : else
478 0 : mGL->fDisableVertexAttribArray(i);
479 : }
480 :
481 :
482 0 : mGL->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, attrib0_bufferBinding);
483 0 : mGL->fVertexAttribPointer(0,
484 : attrib0_size,
485 0 : attrib0_type,
486 0 : attrib0_normalized,
487 : attrib0_stride,
488 0 : attrib0_pointer);
489 :
490 0 : mGL->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, boundBuffer);
491 :
492 0 : mGL->fUseProgram(boundProgram);
493 0 : }
494 :
495 : ////////////////////////////////////////////////////////////////////////
496 : // ScopedPackState
497 :
498 0 : ScopedPackState::ScopedPackState(GLContext* gl)
499 0 : : ScopedGLWrapper<ScopedPackState>(gl)
500 : {
501 0 : mGL->fGetIntegerv(LOCAL_GL_PACK_ALIGNMENT, &mAlignment);
502 :
503 0 : if (mAlignment != 4) mGL->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, 4);
504 :
505 0 : if (!mGL->HasPBOState())
506 0 : return;
507 :
508 0 : mGL->fGetIntegerv(LOCAL_GL_PIXEL_PACK_BUFFER_BINDING, (GLint*)&mPixelBuffer);
509 0 : mGL->fGetIntegerv(LOCAL_GL_PACK_ROW_LENGTH, &mRowLength);
510 0 : mGL->fGetIntegerv(LOCAL_GL_PACK_SKIP_PIXELS, &mSkipPixels);
511 0 : mGL->fGetIntegerv(LOCAL_GL_PACK_SKIP_ROWS, &mSkipRows);
512 :
513 0 : if (mPixelBuffer != 0) mGL->fBindBuffer(LOCAL_GL_PIXEL_PACK_BUFFER, 0);
514 0 : if (mRowLength != 0) mGL->fPixelStorei(LOCAL_GL_PACK_ROW_LENGTH, 0);
515 0 : if (mSkipPixels != 0) mGL->fPixelStorei(LOCAL_GL_PACK_SKIP_PIXELS, 0);
516 0 : if (mSkipRows != 0) mGL->fPixelStorei(LOCAL_GL_PACK_SKIP_ROWS, 0);
517 : }
518 :
519 : void
520 0 : ScopedPackState::UnwrapImpl()
521 : {
522 0 : mGL->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, mAlignment);
523 :
524 0 : if (!mGL->HasPBOState())
525 0 : return;
526 :
527 0 : mGL->fBindBuffer(LOCAL_GL_PIXEL_PACK_BUFFER, mPixelBuffer);
528 0 : mGL->fPixelStorei(LOCAL_GL_PACK_ROW_LENGTH, mRowLength);
529 0 : mGL->fPixelStorei(LOCAL_GL_PACK_SKIP_PIXELS, mSkipPixels);
530 0 : mGL->fPixelStorei(LOCAL_GL_PACK_SKIP_ROWS, mSkipRows);
531 : }
532 :
533 : ////////////////////////////////////////////////////////////////////////
534 : // ResetUnpackState
535 :
536 0 : ResetUnpackState::ResetUnpackState(GLContext* gl)
537 0 : : ScopedGLWrapper<ResetUnpackState>(gl)
538 : {
539 0 : const auto fnReset = [&](GLenum pname, GLuint val, GLuint* const out_old) {
540 0 : mGL->GetUIntegerv(pname, out_old);
541 0 : if (*out_old != val) {
542 0 : mGL->fPixelStorei(pname, val);
543 : }
544 0 : };
545 :
546 : // Default is 4, but 1 is more useful.
547 0 : fnReset(LOCAL_GL_UNPACK_ALIGNMENT, 1, &mAlignment);
548 :
549 0 : if (!mGL->HasPBOState())
550 0 : return;
551 :
552 0 : mGL->GetUIntegerv(LOCAL_GL_PIXEL_UNPACK_BUFFER_BINDING, &mPBO);
553 0 : if (mPBO != 0) mGL->fBindBuffer(LOCAL_GL_PIXEL_UNPACK_BUFFER, 0);
554 :
555 0 : fnReset(LOCAL_GL_UNPACK_ROW_LENGTH , 0, &mRowLength);
556 0 : fnReset(LOCAL_GL_UNPACK_IMAGE_HEIGHT, 0, &mImageHeight);
557 0 : fnReset(LOCAL_GL_UNPACK_SKIP_PIXELS , 0, &mSkipPixels);
558 0 : fnReset(LOCAL_GL_UNPACK_SKIP_ROWS , 0, &mSkipRows);
559 0 : fnReset(LOCAL_GL_UNPACK_SKIP_IMAGES , 0, &mSkipImages);
560 : }
561 :
562 : void
563 0 : ResetUnpackState::UnwrapImpl()
564 : {
565 0 : mGL->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, mAlignment);
566 :
567 0 : if (!mGL->HasPBOState())
568 0 : return;
569 :
570 0 : mGL->fBindBuffer(LOCAL_GL_PIXEL_UNPACK_BUFFER, mPBO);
571 :
572 0 : mGL->fPixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH, mRowLength);
573 0 : mGL->fPixelStorei(LOCAL_GL_UNPACK_IMAGE_HEIGHT, mImageHeight);
574 0 : mGL->fPixelStorei(LOCAL_GL_UNPACK_SKIP_PIXELS, mSkipPixels);
575 0 : mGL->fPixelStorei(LOCAL_GL_UNPACK_SKIP_ROWS, mSkipRows);
576 0 : mGL->fPixelStorei(LOCAL_GL_UNPACK_SKIP_IMAGES, mSkipImages);
577 : }
578 :
579 : ////////////////////////////////////////////////////////////////////////
580 : // ScopedBindPBO
581 :
582 : static GLuint
583 0 : GetPBOBinding(GLContext* gl, GLenum target)
584 : {
585 0 : if (!gl->HasPBOState())
586 0 : return 0;
587 :
588 : GLenum targetBinding;
589 0 : switch (target) {
590 : case LOCAL_GL_PIXEL_PACK_BUFFER:
591 0 : targetBinding = LOCAL_GL_PIXEL_PACK_BUFFER_BINDING;
592 0 : break;
593 :
594 : case LOCAL_GL_PIXEL_UNPACK_BUFFER:
595 0 : targetBinding = LOCAL_GL_PIXEL_UNPACK_BUFFER_BINDING;
596 0 : break;
597 :
598 : default:
599 0 : MOZ_CRASH();
600 : }
601 :
602 0 : return gl->GetIntAs<GLuint>(targetBinding);
603 : }
604 :
605 0 : ScopedBindPBO::ScopedBindPBO(GLContext* gl, GLenum target)
606 : : ScopedGLWrapper<ScopedBindPBO>(gl)
607 : , mTarget(target)
608 0 : , mPBO(GetPBOBinding(mGL, mTarget))
609 0 : { }
610 :
611 : void
612 0 : ScopedBindPBO::UnwrapImpl()
613 : {
614 0 : if (!mGL->HasPBOState())
615 0 : return;
616 :
617 0 : mGL->fBindBuffer(mTarget, mPBO);
618 : }
619 :
620 : } /* namespace gl */
621 : } /* namespace mozilla */
|