Bug 754472 - Implement multiple plugin click-to-play UI. r=jaws r=margaret r=dietrich
[gecko.git] / gfx / gl / GLContext.h
blob1410c23a7e69923d7f7df9be668407a668ee2220
1 /* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */
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 #ifndef GLCONTEXT_H_
7 #define GLCONTEXT_H_
9 #include <stdio.h>
10 #if defined(XP_UNIX)
11 #include <stdint.h>
12 #endif
13 #include <string.h>
14 #include <ctype.h>
16 #ifdef WIN32
17 #include <windows.h>
18 #endif
20 #include "GLDefs.h"
21 #include "GLLibraryLoader.h"
22 #include "gfxASurface.h"
23 #include "gfxImageSurface.h"
24 #include "gfxContext.h"
25 #include "gfxRect.h"
26 #include "gfx3DMatrix.h"
27 #include "nsISupportsImpl.h"
28 #include "prlink.h"
30 #include "nsDataHashtable.h"
31 #include "nsHashKeys.h"
32 #include "nsRegion.h"
33 #include "nsAutoPtr.h"
34 #include "nsThreadUtils.h"
36 typedef char realGLboolean;
38 #include "GLContextSymbols.h"
40 #include "mozilla/mozalloc.h"
41 #include "mozilla/Preferences.h"
43 namespace android {
44 class GraphicBuffer;
47 namespace mozilla {
48 namespace layers {
49 class LayerManagerOGL;
50 class ColorTextureLayerProgram;
53 namespace gl {
54 class GLContext;
56 typedef uintptr_t SharedTextureHandle;
58 enum ShaderProgramType {
59 RGBALayerProgramType,
60 RGBALayerExternalProgramType,
61 BGRALayerProgramType,
62 RGBXLayerProgramType,
63 BGRXLayerProgramType,
64 RGBARectLayerProgramType,
65 RGBAExternalLayerProgramType,
66 ColorLayerProgramType,
67 YCbCrLayerProgramType,
68 ComponentAlphaPass1ProgramType,
69 ComponentAlphaPass2ProgramType,
70 Copy2DProgramType,
71 Copy2DRectProgramType,
72 NumProgramTypes
76 /**
77 * A TextureImage encapsulates a surface that can be drawn to by a
78 * Thebes gfxContext and (hopefully efficiently!) synchronized to a
79 * texture in the server. TextureImages are associated with one and
80 * only one GLContext.
82 * Implementation note: TextureImages attempt to unify two categories
83 * of backends
85 * (1) proxy to server-side object that can be bound to a texture;
86 * e.g. Pixmap on X11.
88 * (2) efficient manager of texture memory; e.g. by having clients draw
89 * into a scratch buffer which is then uploaded with
90 * glTexSubImage2D().
92 class TextureImage
94 NS_INLINE_DECL_REFCOUNTING(TextureImage)
95 public:
96 enum TextureState
98 Created, // Texture created, but has not had glTexImage called to initialize it.
99 Allocated, // Texture memory exists, but contents are invalid.
100 Valid // Texture fully ready to use.
103 enum Flags {
104 NoFlags = 0x0,
105 UseNearestFilter = 0x1,
106 NeedsYFlip = 0x2,
107 ForceSingleTile = 0x4
110 enum TextureShareType {
111 ThreadShared = 0x0,
112 ProcessShared = 0x1
115 typedef gfxASurface::gfxContentType ContentType;
117 virtual ~TextureImage() {}
120 * Returns a gfxASurface for updating |aRegion| of the client's
121 * image if successul, NULL if not. |aRegion|'s bounds must fit
122 * within Size(); its coordinate space (if any) is ignored. If
123 * the update begins successfully, the returned gfxASurface is
124 * owned by this. Otherwise, NULL is returned.
126 * |aRegion| is an inout param: the returned region is what the
127 * client must repaint. Category (1) regions above can
128 * efficiently handle repaints to "scattered" regions, while (2)
129 * can only efficiently handle repaints to rects.
131 * Painting the returned surface outside of |aRegion| results
132 * in undefined behavior.
134 * BeginUpdate() calls cannot be "nested", and each successful
135 * BeginUpdate() must be followed by exactly one EndUpdate() (see
136 * below). Failure to do so can leave this in a possibly
137 * inconsistent state. Unsuccessful BeginUpdate()s must not be
138 * followed by EndUpdate().
140 virtual gfxASurface* BeginUpdate(nsIntRegion& aRegion) = 0;
142 * Retrieves the region that will require updating, given a
143 * region that needs to be updated. This can be used for
144 * making decisions about updating before calling BeginUpdate().
146 * |aRegion| is an inout param.
148 virtual void GetUpdateRegion(nsIntRegion& aForRegion) {
151 * Finish the active update and synchronize with the server, if
152 * necessary.
154 * BeginUpdate() must have been called exactly once before
155 * EndUpdate().
157 virtual void EndUpdate() = 0;
160 * The Image may contain several textures for different regions (tiles).
161 * These functions iterate over each sub texture image tile.
163 virtual void BeginTileIteration() {
166 virtual bool NextTile() {
167 return false;
170 // Function prototype for a tile iteration callback. Returning false will
171 // cause iteration to be interrupted (i.e. the corresponding NextTile call
172 // will return false).
173 typedef bool (* TileIterationCallback)(TextureImage* aImage,
174 int aTileNumber,
175 void* aCallbackData);
177 // Sets a callback to be called every time NextTile is called.
178 virtual void SetIterationCallback(TileIterationCallback aCallback,
179 void* aCallbackData) {
182 virtual nsIntRect GetTileRect() {
183 return nsIntRect(nsIntPoint(0,0), mSize);
186 virtual GLuint GetTextureID() = 0;
188 virtual uint32_t GetTileCount() {
189 return 1;
193 * Set this TextureImage's size, and ensure a texture has been
194 * allocated. Must not be called between BeginUpdate and EndUpdate.
195 * After a resize, the contents are undefined.
197 * If this isn't implemented by a subclass, it will just perform
198 * a dummy BeginUpdate/EndUpdate pair.
200 virtual void Resize(const nsIntSize& aSize) {
201 mSize = aSize;
202 nsIntRegion r(nsIntRect(0, 0, aSize.width, aSize.height));
203 BeginUpdate(r);
204 EndUpdate();
208 * Mark this texture as having valid contents. Call this after modifying
209 * the texture contents externally.
211 virtual void MarkValid() {}
214 * aSurf - the source surface to update from
215 * aRegion - the region in this image to update
216 * aFrom - offset in the source to update from
218 virtual bool DirectUpdate(gfxASurface *aSurf, const nsIntRegion& aRegion, const nsIntPoint& aFrom = nsIntPoint(0,0)) = 0;
220 virtual void BindTexture(GLenum aTextureUnit) = 0;
221 virtual void ReleaseTexture() {}
223 void BindTextureAndApplyFilter(GLenum aTextureUnit) {
224 BindTexture(aTextureUnit);
225 ApplyFilter();
228 class ScopedBindTexture
230 public:
231 ScopedBindTexture(TextureImage *aTexture, GLenum aTextureUnit) :
232 mTexture(aTexture)
234 if (mTexture) {
235 mTexture->BindTexture(aTextureUnit);
239 ~ScopedBindTexture()
241 if (mTexture) {
242 mTexture->ReleaseTexture();
246 protected:
247 TextureImage *mTexture;
250 class ScopedBindTextureAndApplyFilter
251 : public ScopedBindTexture
253 public:
254 ScopedBindTextureAndApplyFilter(TextureImage *aTexture, GLenum aTextureUnit) :
255 ScopedBindTexture(aTexture, aTextureUnit)
257 if (mTexture) {
258 mTexture->ApplyFilter();
264 * Returns the shader program type that should be used to render
265 * this texture. Only valid after a matching BeginUpdate/EndUpdate
266 * pair have been called.
268 virtual ShaderProgramType GetShaderProgramType()
270 return mShaderType;
273 /** Can be called safely at any time. */
276 * If this TextureImage has a permanent gfxASurface backing,
277 * return it. Otherwise return NULL.
279 virtual already_AddRefed<gfxASurface> GetBackingSurface()
280 { return NULL; }
282 const nsIntSize& GetSize() const { return mSize; }
283 ContentType GetContentType() const { return mContentType; }
284 virtual bool InUpdate() const = 0;
285 GLenum GetWrapMode() const { return mWrapMode; }
287 void SetFilter(gfxPattern::GraphicsFilter aFilter) { mFilter = aFilter; }
290 * Applies this TextureImage's filter, assuming that its texture is
291 * the currently bound texture.
293 virtual void ApplyFilter() = 0;
295 protected:
296 friend class GLContext;
299 * After the ctor, the TextureImage is invalid. Implementations
300 * must allocate resources successfully before returning the new
301 * TextureImage from GLContext::CreateTextureImage(). That is,
302 * clients must not be given partially-constructed TextureImages.
304 TextureImage(const nsIntSize& aSize,
305 GLenum aWrapMode, ContentType aContentType,
306 Flags aFlags = NoFlags)
307 : mSize(aSize)
308 , mWrapMode(aWrapMode)
309 , mContentType(aContentType)
310 , mFilter(gfxPattern::FILTER_GOOD)
311 , mFlags(aFlags)
314 virtual nsIntRect GetSrcTileRect() {
315 return nsIntRect(nsIntPoint(0,0), mSize);
318 nsIntSize mSize;
319 GLenum mWrapMode;
320 ContentType mContentType;
321 ShaderProgramType mShaderType;
322 gfxPattern::GraphicsFilter mFilter;
323 Flags mFlags;
327 * BasicTextureImage is the baseline TextureImage implementation ---
328 * it updates its texture by allocating a scratch buffer for the
329 * client to draw into, then using glTexSubImage2D() to upload the new
330 * pixels. Platforms must provide the code to create a new surface
331 * into which the updated pixels will be drawn, and the code to
332 * convert the update surface's pixels into an image on which we can
333 * glTexSubImage2D().
335 class BasicTextureImage
336 : public TextureImage
338 public:
339 typedef gfxASurface::gfxImageFormat ImageFormat;
340 virtual ~BasicTextureImage();
342 BasicTextureImage(GLuint aTexture,
343 const nsIntSize& aSize,
344 GLenum aWrapMode,
345 ContentType aContentType,
346 GLContext* aContext,
347 TextureImage::Flags aFlags = TextureImage::NoFlags)
348 : TextureImage(aSize, aWrapMode, aContentType, aFlags)
349 , mTexture(aTexture)
350 , mTextureState(Created)
351 , mGLContext(aContext)
352 , mUpdateOffset(0, 0)
355 virtual void BindTexture(GLenum aTextureUnit);
357 virtual gfxASurface* BeginUpdate(nsIntRegion& aRegion);
358 virtual void GetUpdateRegion(nsIntRegion& aForRegion);
359 virtual void EndUpdate();
360 virtual bool DirectUpdate(gfxASurface* aSurf, const nsIntRegion& aRegion, const nsIntPoint& aFrom = nsIntPoint(0,0));
361 virtual GLuint GetTextureID() { return mTexture; }
362 // Returns a surface to draw into
363 virtual already_AddRefed<gfxASurface>
364 GetSurfaceForUpdate(const gfxIntSize& aSize, ImageFormat aFmt);
366 virtual void MarkValid() { mTextureState = Valid; }
368 // Call when drawing into the update surface is complete.
369 // Returns true if textures should be upload with a relative
370 // offset - See UploadSurfaceToTexture.
371 virtual bool FinishedSurfaceUpdate();
373 // Call after surface data has been uploaded to a texture.
374 virtual void FinishedSurfaceUpload();
376 virtual bool InUpdate() const { return !!mUpdateSurface; }
378 virtual void Resize(const nsIntSize& aSize);
380 virtual void ApplyFilter();
381 protected:
383 GLuint mTexture;
384 TextureState mTextureState;
385 GLContext* mGLContext;
386 nsRefPtr<gfxASurface> mUpdateSurface;
387 nsIntRegion mUpdateRegion;
389 // The offset into the update surface at which the update rect is located.
390 nsIntPoint mUpdateOffset;
394 * A container class that complements many sub TextureImages into a big TextureImage.
395 * Aims to behave just like the real thing.
398 class TiledTextureImage
399 : public TextureImage
401 public:
402 TiledTextureImage(GLContext* aGL, nsIntSize aSize,
403 TextureImage::ContentType, TextureImage::Flags aFlags = TextureImage::NoFlags);
404 ~TiledTextureImage();
405 void DumpDiv();
406 virtual gfxASurface* BeginUpdate(nsIntRegion& aRegion);
407 virtual void GetUpdateRegion(nsIntRegion& aForRegion);
408 virtual void EndUpdate();
409 virtual void Resize(const nsIntSize& aSize);
410 virtual uint32_t GetTileCount();
411 virtual void BeginTileIteration();
412 virtual bool NextTile();
413 virtual void SetIterationCallback(TileIterationCallback aCallback,
414 void* aCallbackData);
415 virtual nsIntRect GetTileRect();
416 virtual GLuint GetTextureID() {
417 return mImages[mCurrentImage]->GetTextureID();
419 virtual bool DirectUpdate(gfxASurface* aSurf, const nsIntRegion& aRegion, const nsIntPoint& aFrom = nsIntPoint(0,0));
420 virtual bool InUpdate() const { return mInUpdate; }
421 virtual void BindTexture(GLenum);
422 virtual void ApplyFilter();
424 protected:
425 virtual nsIntRect GetSrcTileRect();
427 unsigned int mCurrentImage;
428 TileIterationCallback mIterationCallback;
429 void* mIterationCallbackData;
430 nsTArray< nsRefPtr<TextureImage> > mImages;
431 bool mInUpdate;
432 nsIntSize mSize;
433 unsigned int mTileSize;
434 unsigned int mRows, mColumns;
435 GLContext* mGL;
436 // A temporary surface to faciliate cross-tile updates.
437 nsRefPtr<gfxASurface> mUpdateSurface;
438 // The region of update requested
439 nsIntRegion mUpdateRegion;
440 TextureState mTextureState;
443 struct THEBES_API ContextFormat
445 static const ContextFormat BasicRGBA32Format;
447 enum StandardContextFormat {
448 Empty,
449 BasicRGBA32,
450 StrictBasicRGBA32,
451 BasicRGB24,
452 StrictBasicRGB24,
453 BasicRGB16_565,
454 StrictBasicRGB16_565
457 ContextFormat() {
458 memset(this, 0, sizeof(ContextFormat));
461 ContextFormat(const StandardContextFormat cf) {
462 memset(this, 0, sizeof(ContextFormat));
463 switch (cf) {
464 case BasicRGBA32:
465 red = green = blue = alpha = 8;
466 minRed = minGreen = minBlue = minAlpha = 1;
467 break;
469 case StrictBasicRGBA32:
470 red = green = blue = alpha = 8;
471 minRed = minGreen = minBlue = minAlpha = 8;
472 break;
474 case BasicRGB24:
475 red = green = blue = 8;
476 minRed = minGreen = minBlue = 1;
477 break;
479 case StrictBasicRGB24:
480 red = green = blue = 8;
481 minRed = minGreen = minBlue = 8;
482 break;
484 case StrictBasicRGB16_565:
485 red = minRed = 5;
486 green = minGreen = 6;
487 blue = minBlue = 5;
488 break;
490 default:
491 break;
495 int depth, minDepth;
496 int stencil, minStencil;
497 int red, minRed;
498 int green, minGreen;
499 int blue, minBlue;
500 int alpha, minAlpha;
501 int samples;
503 int colorBits() const { return red + green + blue; }
506 class GLContext
507 : public GLLibraryLoader
509 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GLContext)
510 public:
511 GLContext(const ContextFormat& aFormat,
512 bool aIsOffscreen = false,
513 GLContext *aSharedContext = nullptr)
514 : mTexBlit_Buffer(0),
515 mTexBlit_VertShader(0),
516 mTexBlit_FragShader(0),
517 mTexBlit_Program(0),
518 mTexBlit_UseDrawNotCopy(false),
519 mUserBoundDrawFBO(0),
520 mUserBoundReadFBO(0),
521 mInternalBoundDrawFBO(0),
522 mInternalBoundReadFBO(0),
523 #ifdef DEBUG
524 mInInternalBindingMode_DrawFBO(true),
525 mInInternalBindingMode_ReadFBO(true),
526 #endif
527 mOffscreenFBOsDirty(false),
528 mInitialized(false),
529 mIsOffscreen(aIsOffscreen),
530 mIsGLES2(false),
531 mIsGlobalSharedContext(false),
532 mHasRobustness(false),
533 mContextLost(false),
534 mVendor(-1),
535 mRenderer(-1),
536 mCreationFormat(aFormat),
537 mSharedContext(aSharedContext),
538 mOffscreenTexture(0),
539 mFlipped(false),
540 mBlitProgram(0),
541 mBlitFramebuffer(0),
542 mOffscreenDrawFBO(0),
543 mOffscreenReadFBO(0),
544 mOffscreenColorRB(0),
545 mOffscreenDepthRB(0),
546 mOffscreenStencilRB(0),
547 mMaxTextureSize(0),
548 mMaxCubeMapTextureSize(0),
549 mMaxTextureImageSize(0),
550 mMaxRenderbufferSize(0),
551 mWorkAroundDriverBugs(true)
552 #ifdef DEBUG
553 , mGLError(LOCAL_GL_NO_ERROR)
554 #endif
556 mUserData.Init();
557 mOwningThread = NS_GetCurrentThread();
559 mTexBlit_UseDrawNotCopy = Preferences::GetBool("gl.blit-draw-not-copy", false);
562 virtual ~GLContext() {
563 NS_ASSERTION(IsDestroyed(), "GLContext implementation must call MarkDestroyed in destructor!");
564 #ifdef DEBUG
565 if (mSharedContext) {
566 GLContext *tip = mSharedContext;
567 while (tip->mSharedContext)
568 tip = tip->mSharedContext;
569 tip->SharedContextDestroyed(this);
570 tip->ReportOutstandingNames();
571 } else {
572 ReportOutstandingNames();
574 #endif
577 enum ContextFlags {
578 ContextFlagsNone = 0x0,
579 ContextFlagsGlobal = 0x1,
580 ContextFlagsMesaLLVMPipe = 0x2
583 enum GLContextType {
584 ContextTypeUnknown,
585 ContextTypeWGL,
586 ContextTypeCGL,
587 ContextTypeGLX,
588 ContextTypeEGL
591 virtual GLContextType GetContextType() { return ContextTypeUnknown; }
593 virtual bool MakeCurrentImpl(bool aForce = false) = 0;
595 #ifdef DEBUG
596 static void StaticInit() {
597 PR_NewThreadPrivateIndex(&sCurrentGLContextTLS, NULL);
599 #endif
601 bool MakeCurrent(bool aForce = false) {
602 #ifdef DEBUG
603 PR_SetThreadPrivate(sCurrentGLContextTLS, this);
605 // XXX this assertion is disabled because it's triggering on Mac;
606 // we need to figure out why and reenable it.
607 #if 0
608 // IsOwningThreadCurrent is a bit of a misnomer;
609 // the "owning thread" is the creation thread,
610 // and the only thread that can own this. We don't
611 // support contexts used on multiple threads.
612 NS_ASSERTION(IsOwningThreadCurrent(),
613 "MakeCurrent() called on different thread than this context was created on!");
614 #endif
615 #endif
616 return MakeCurrentImpl(aForce);
619 virtual bool IsCurrent() = 0;
621 bool IsContextLost() { return mContextLost; }
623 virtual bool SetupLookupFunction() = 0;
625 virtual void WindowDestroyed() {}
627 virtual void ReleaseSurface() {}
629 void *GetUserData(void *aKey) {
630 void *result = nullptr;
631 mUserData.Get(aKey, &result);
632 return result;
635 void SetUserData(void *aKey, void *aValue) {
636 mUserData.Put(aKey, aValue);
639 // Mark this context as destroyed. This will NULL out all
640 // the GL function pointers!
641 void THEBES_API MarkDestroyed();
643 bool IsDestroyed() {
644 // MarkDestroyed will mark all these as null.
645 return mSymbols.fUseProgram == nullptr;
648 enum NativeDataType {
649 NativeGLContext,
650 NativeImageSurface,
651 NativeThebesSurface,
652 NativeDataTypeMax
655 virtual void *GetNativeData(NativeDataType aType) { return NULL; }
656 GLContext *GetSharedContext() { return mSharedContext; }
658 bool IsGlobalSharedContext() { return mIsGlobalSharedContext; }
659 void SetIsGlobalSharedContext(bool aIsOne) { mIsGlobalSharedContext = aIsOne; }
662 * Returns true if the thread on which this context was created is the currently
663 * executing thread.
665 bool IsOwningThreadCurrent() { return NS_GetCurrentThread() == mOwningThread; }
667 void DispatchToOwningThread(nsIRunnable *event) {
668 // Before dispatching, we need to ensure we're not in the middle of
669 // shutting down. Dispatching runnables in the middle of shutdown
670 // (that is, when the main thread is no longer get-able) can cause them
671 // to leak. See Bug 741319, and Bug 744115.
672 nsCOMPtr<nsIThread> mainThread;
673 if (NS_SUCCEEDED(NS_GetMainThread(getter_AddRefs(mainThread)))) {
674 mOwningThread->Dispatch(event, NS_DISPATCH_NORMAL);
678 const ContextFormat& CreationFormat() { return mCreationFormat; }
679 const ContextFormat& ActualFormat() { return mActualFormat; }
682 * If this GL context has a D3D texture share handle, returns non-null.
684 virtual void *GetD3DShareHandle() { return nullptr; }
687 * If this context is double-buffered, returns TRUE.
689 virtual bool IsDoubleBuffered() { return false; }
692 * If this context is the GLES2 API, returns TRUE.
693 * This means that various GLES2 restrictions might be in effect (modulo
694 * extensions).
696 bool IsGLES2() const {
697 return mIsGLES2;
701 * Returns true if either this is the GLES2 API, or had the GL_ARB_ES2_compatibility extension
703 bool HasES2Compatibility() {
704 return mIsGLES2 || IsExtensionSupported(ARB_ES2_compatibility);
708 * Returns true if the context is using ANGLE. This should only be overridden for an ANGLE
709 * implementation.
711 virtual bool IsANGLE() {
712 return false;
716 * The derived class is expected to provide information on whether or not it
717 * supports robustness.
719 virtual bool SupportsRobustness() = 0;
721 enum {
722 VendorIntel,
723 VendorNVIDIA,
724 VendorATI,
725 VendorQualcomm,
726 VendorImagination,
727 VendorOther
730 enum {
731 RendererAdreno200,
732 RendererAdreno205,
733 RendererSGX530,
734 RendererSGX540,
735 RendererOther
738 int Vendor() const {
739 return mVendor;
742 int Renderer() const {
743 return mRenderer;
746 bool CanUploadSubTextures();
747 bool CanUploadNonPowerOfTwo();
748 bool WantsSmallTiles();
749 virtual bool HasLockSurface() { return false; }
752 * If this context wraps a double-buffered target, swap the back
753 * and front buffers. It should be assumed that after a swap, the
754 * contents of the new back buffer are undefined.
756 virtual bool SwapBuffers() { return false; }
759 * Defines a two-dimensional texture image for context target surface
761 virtual bool BindTexImage() { return false; }
763 * Releases a color buffer that is being used as a texture
765 virtual bool ReleaseTexImage() { return false; }
768 * Applies aFilter to the texture currently bound to GL_TEXTURE_2D.
770 void ApplyFilterToBoundTexture(gfxPattern::GraphicsFilter aFilter);
773 * Applies aFilter to the texture currently bound to aTarget.
775 void ApplyFilterToBoundTexture(GLuint aTarget,
776 gfxPattern::GraphicsFilter aFilter);
778 virtual bool BindExternalBuffer(GLuint texture, void* buffer) { return false; }
779 virtual bool UnbindExternalBuffer(GLuint texture) { return false; }
781 virtual already_AddRefed<TextureImage>
782 CreateDirectTextureImage(android::GraphicBuffer* aBuffer, GLenum aWrapMode)
783 { return nullptr; }
786 * Offscreen support API
790 * Bind aOffscreen's color buffer as a texture to the TEXTURE_2D
791 * target. Returns TRUE on success, otherwise FALSE. If
792 * aOffscreen is not an offscreen context, returns FALSE. If
793 * BindOffscreenNeedsTexture() returns TRUE, then you should have
794 * a 2D texture name bound whose image will be replaced by the
795 * contents of the offscreen context. If it returns FALSE,
796 * the current 2D texture binding will be replaced.
798 * After a successul call to BindTex2DOffscreen, UnbindTex2DOffscreen
799 * *must* be called once rendering is complete.
801 * The same texture unit must be active for Bind/Unbind of a given
802 * context.
804 virtual bool BindOffscreenNeedsTexture(GLContext *aOffscreen) {
805 return aOffscreen->mOffscreenTexture == 0;
808 virtual bool BindTex2DOffscreen(GLContext *aOffscreen) {
809 if (aOffscreen->GetContextType() != GetContextType()) {
810 return false;
813 if (!aOffscreen->mSharedContext ||
814 aOffscreen->mSharedContext != mSharedContext)
816 return false;
819 if (!aOffscreen->mOffscreenTexture) {
820 return false;
823 fBindTexture(LOCAL_GL_TEXTURE_2D, aOffscreen->mOffscreenTexture);
825 return true;
828 virtual void UnbindTex2DOffscreen(GLContext *aOffscreen) { }
830 bool IsOffscreen() {
831 return mIsOffscreen;
834 // Before reads from offscreen texture
835 void GuaranteeResolve() {
836 BlitDirtyFBOs();
837 fFinish();
840 protected:
841 GLuint mTexBlit_Buffer;
842 GLuint mTexBlit_VertShader;
843 GLuint mTexBlit_FragShader;
844 GLuint mTexBlit_Program;
846 bool mTexBlit_UseDrawNotCopy;
848 bool UseTexQuadProgram();
849 void DeleteTexBlitProgram();
851 public:
852 void BlitFramebufferToFramebuffer(GLuint srcFB, GLuint destFB,
853 const gfxIntSize& srcSize,
854 const gfxIntSize& destSize);
855 void BlitTextureToFramebuffer(GLuint srcTex, GLuint destFB,
856 const gfxIntSize& srcSize,
857 const gfxIntSize& destSize);
858 void BlitFramebufferToTexture(GLuint srcFB, GLuint destTex,
859 const gfxIntSize& srcSize,
860 const gfxIntSize& destSize);
861 void BlitTextureToTexture(GLuint srcTex, GLuint destTex,
862 const gfxIntSize& srcSize,
863 const gfxIntSize& destSize);
866 * Resize the current offscreen buffer. Returns true on success.
867 * If it returns false, the context should be treated as unusable
868 * and should be recreated. After the resize, the viewport is not
869 * changed; glViewport should be called as appropriate.
871 * Only valid if IsOffscreen() returns true.
873 virtual bool ResizeOffscreen(const gfxIntSize& aNewSize) {
874 if (mOffscreenDrawFBO || mOffscreenReadFBO)
875 return ResizeOffscreenFBOs(aNewSize, mOffscreenReadFBO != 0);
876 return false;
880 * Return size of this offscreen context.
882 * Only valid if IsOffscreen() returns true.
884 gfxIntSize OffscreenSize() {
885 return mOffscreenSize;
889 * In some cases, we have to allocate a bigger offscreen buffer
890 * than what's requested. This is the bigger size.
892 * Only valid if IsOffscreen() returns true.
894 gfxIntSize OffscreenActualSize() {
895 return mOffscreenActualSize;
899 * If this context is FBO-backed, return the FBO or the color
900 * buffer texture. If the context is not FBO-backed, 0 is
901 * returned (which is also a valid FBO binding).
903 * Only valid if IsOffscreen() returns true.
905 GLuint GetOffscreenFBO() {
906 // 0 is interpreted as (off)screen, whether for read or draw operations
907 return 0;
910 GLuint GetOffscreenTexture() {
911 return mOffscreenTexture;
914 virtual bool SupportsFramebufferMultisample() {
915 return IsExtensionSupported(EXT_framebuffer_multisample) || IsExtensionSupported(ANGLE_framebuffer_multisample);
918 virtual bool SupportsOffscreenSplit() {
919 return IsExtensionSupported(EXT_framebuffer_blit) || IsExtensionSupported(ANGLE_framebuffer_blit);
922 enum SharedTextureBufferType {
923 TextureID
924 #ifdef MOZ_WIDGET_ANDROID
925 , SurfaceTexture
926 #endif
930 * Create new shared GLContext content handle, must be released by ReleaseSharedHandle.
932 virtual SharedTextureHandle CreateSharedHandle(TextureImage::TextureShareType aType) { return 0; }
934 * Create a new shared GLContext content handle, using the passed buffer as a source.
935 * Must be released by ReleaseSharedHandle. UpdateSharedHandle will have no effect
936 * on handles created with this method, as the caller owns the source (the passed buffer)
937 * and is responsible for updating it accordingly.
939 virtual SharedTextureHandle CreateSharedHandle(TextureImage::TextureShareType aType,
940 void* aBuffer,
941 SharedTextureBufferType aBufferType) { return 0; }
943 * Publish GLContext content to intermediate buffer attached to shared handle.
944 * Shared handle content is ready to be used after call returns, and no need extra Flush/Finish are required.
945 * GLContext must be current before this call
947 virtual void UpdateSharedHandle(TextureImage::TextureShareType aType,
948 SharedTextureHandle aSharedHandle) { }
950 * - It is better to call ReleaseSharedHandle before original GLContext destroyed,
951 * otherwise warning will be thrown on attempt to destroy Texture associated with SharedHandle, depends on backend implementation.
952 * - It does not require to be called on context where it was created,
953 * because SharedHandle suppose to keep Context reference internally,
954 * or don't require specific context at all, for example IPC SharedHandle.
955 * - Not recommended to call this between AttachSharedHandle and Draw Target call.
956 * if it is really required for some special backend, then DetachSharedHandle API must be added with related implementation.
957 * - It is recommended to stop any possible access to SharedHandle (Attachments, pending GL calls) before calling Release,
958 * otherwise some artifacts might appear or even crash if API backend implementation does not expect that.
959 * SharedHandle (currently EGLImage) does not require GLContext because it is EGL call, and can be destroyed
960 * at any time, unless EGLImage have siblings (which are not expected with current API).
962 virtual void ReleaseSharedHandle(TextureImage::TextureShareType aType,
963 SharedTextureHandle aSharedHandle) { }
966 typedef struct {
967 GLenum mTarget;
968 ShaderProgramType mProgramType;
969 gfx3DMatrix mTextureTransform;
970 } SharedHandleDetails;
973 * Returns information necessary for rendering a shared handle.
974 * These values change depending on what sharing mechanism is in use
976 virtual bool GetSharedHandleDetails(TextureImage::TextureShareType aType,
977 SharedTextureHandle aSharedHandle,
978 SharedHandleDetails& aDetails) { return false; }
980 * Attach Shared GL Handle to GL_TEXTURE_2D target
981 * GLContext must be current before this call
983 virtual bool AttachSharedHandle(TextureImage::TextureShareType aType,
984 SharedTextureHandle aSharedHandle) { return false; }
987 * Detach Shared GL Handle from GL_TEXTURE_2D target
989 virtual void DetachSharedHandle(TextureImage::TextureShareType aType,
990 SharedTextureHandle aSharedHandle) { return; }
992 private:
993 GLuint mUserBoundDrawFBO;
994 GLuint mUserBoundReadFBO;
995 GLuint mInternalBoundDrawFBO;
996 GLuint mInternalBoundReadFBO;
998 public:
999 void fBindFramebuffer(GLenum target, GLuint framebuffer) {
1000 switch (target) {
1001 case LOCAL_GL_DRAW_FRAMEBUFFER_EXT:
1002 mUserBoundDrawFBO = framebuffer;
1004 if (framebuffer == 0) {
1005 mInternalBoundDrawFBO = mOffscreenDrawFBO;
1006 } else {
1007 mInternalBoundDrawFBO = mUserBoundDrawFBO;
1010 raw_fBindFramebuffer(LOCAL_GL_DRAW_FRAMEBUFFER_EXT,
1011 mInternalBoundDrawFBO);
1012 break;
1014 case LOCAL_GL_READ_FRAMEBUFFER_EXT:
1015 mUserBoundReadFBO = framebuffer;
1017 if (framebuffer == 0) {
1018 mInternalBoundReadFBO = mOffscreenReadFBO;
1019 } else {
1020 mInternalBoundReadFBO = mUserBoundReadFBO;
1023 raw_fBindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER_EXT,
1024 mInternalBoundReadFBO);
1025 break;
1027 case LOCAL_GL_FRAMEBUFFER:
1028 mUserBoundDrawFBO = mUserBoundReadFBO = framebuffer;
1030 if (framebuffer == 0) {
1031 mInternalBoundDrawFBO = mOffscreenDrawFBO;
1032 mInternalBoundReadFBO = mOffscreenReadFBO;
1033 } else {
1034 mInternalBoundDrawFBO = mUserBoundDrawFBO;
1035 mInternalBoundReadFBO = mUserBoundReadFBO;
1038 if (SupportsOffscreenSplit()) {
1039 raw_fBindFramebuffer(LOCAL_GL_DRAW_FRAMEBUFFER_EXT,
1040 mInternalBoundDrawFBO);
1041 raw_fBindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER_EXT,
1042 mInternalBoundReadFBO);
1043 } else {
1044 raw_fBindFramebuffer(LOCAL_GL_FRAMEBUFFER,
1045 mInternalBoundDrawFBO);
1048 break;
1050 default:
1051 raw_fBindFramebuffer(target, framebuffer);
1052 break;
1056 void fGetIntegerv(GLenum pname, GLint *params) {
1057 switch (pname)
1059 // LOCAL_GL_FRAMEBUFFER_BINDING is equal to
1060 // LOCAL_GL_DRAW_FRAMEBUFFER_BINDING_EXT, so we don't need two
1061 // cases.
1062 case LOCAL_GL_FRAMEBUFFER_BINDING:
1063 *params = GetUserBoundDrawFBO();
1064 break;
1066 case LOCAL_GL_READ_FRAMEBUFFER_BINDING_EXT:
1067 *params = GetUserBoundReadFBO();
1068 break;
1070 default:
1071 raw_fGetIntegerv(pname, params);
1072 break;
1076 #ifdef DEBUG
1077 // See comment near BindInternalDrawFBO()
1078 bool mInInternalBindingMode_DrawFBO;
1079 bool mInInternalBindingMode_ReadFBO;
1080 #endif
1082 GLuint GetUserBoundDrawFBO() {
1083 #ifdef DEBUG
1084 MOZ_ASSERT(IsCurrent());
1086 GLint ret = 0;
1087 // Don't need a branch here, because:
1088 // LOCAL_GL_DRAW_FRAMEBUFFER_BINDING_EXT == LOCAL_GL_FRAMEBUFFER_BINDING == 0x8CA6
1089 // We use raw_ here because this is debug code and we need to see what
1090 // the driver thinks.
1091 raw_fGetIntegerv(LOCAL_GL_DRAW_FRAMEBUFFER_BINDING_EXT, &ret);
1093 bool abort = false;
1095 if (mInInternalBindingMode_DrawFBO) {
1096 NS_ERROR("Draw FBO still bound internally!");
1097 printf_stderr("Current internal draw FBO: %d, user: %d)\n", ret, mUserBoundDrawFBO);
1098 abort = true;
1101 if (mInternalBoundDrawFBO != (GLuint)ret) {
1102 NS_ERROR("Draw FBO binding misprediction!");
1103 printf_stderr("Bound draw FBO was: %d, Expected: %d\n", ret, mInternalBoundDrawFBO);
1104 abort = true;
1107 if (abort)
1108 NS_ABORT();
1109 #endif
1111 // We only ever expose the user's bound FBOs
1112 return mUserBoundDrawFBO;
1115 GLuint GetUserBoundReadFBO() {
1116 #ifdef DEBUG
1117 MOZ_ASSERT(IsCurrent());
1119 GLint ret = 0;
1120 // We use raw_ here because this is debug code and we need to see what
1121 // the driver thinks.
1122 if (SupportsOffscreenSplit())
1123 raw_fGetIntegerv(LOCAL_GL_READ_FRAMEBUFFER_BINDING_EXT, &ret);
1124 else
1125 raw_fGetIntegerv(LOCAL_GL_FRAMEBUFFER_BINDING, &ret);
1127 bool abort = false;
1129 if (mInInternalBindingMode_ReadFBO) {
1130 NS_ERROR("Read FBO still bound internally!");
1131 printf_stderr("Current internal read FBO: %d, user: %d)\n", ret, mUserBoundReadFBO);
1132 abort = true;
1135 if (mInternalBoundReadFBO != (GLuint)ret) {
1136 NS_ERROR("Read FBO binding misprediction!");
1137 printf_stderr("Bound read FBO was: %d, Expected: %d\n", ret, mInternalBoundReadFBO);
1138 abort = true;
1141 if (abort)
1142 NS_ABORT();
1143 #endif
1145 // We only ever expose the user's bound FBOs
1146 return mUserBoundReadFBO;
1149 void BindUserDrawFBO(GLuint name) {
1150 if (SupportsOffscreenSplit())
1151 fBindFramebuffer(LOCAL_GL_DRAW_FRAMEBUFFER_EXT, name);
1152 else
1153 fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, name);
1154 #ifdef DEBUG
1155 mInInternalBindingMode_DrawFBO = false;
1156 #endif
1159 void BindUserReadFBO(GLuint name) {
1160 if (SupportsOffscreenSplit())
1161 fBindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER_EXT, name);
1162 else
1163 fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, name);
1164 #ifdef DEBUG
1165 mInInternalBindingMode_ReadFBO = false;
1166 #endif
1169 GLuint GetUserBoundFBO() {
1170 MOZ_ASSERT(GetUserBoundDrawFBO() == GetUserBoundReadFBO());
1171 return GetUserBoundReadFBO();
1174 void BindUserFBO(GLuint name) {
1175 fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, name);
1178 // BindInternalDraw/ReadFBO() switch us over into 'internal binding mode'
1179 // for the corresponding Draw or Read binding.
1180 // To exit internal binding mode, use BindUserDraw/ReadFBO().
1181 // While in internal binding mode for Draw/Read, the corresponding
1182 // GetBoundUserDraw/ReadFBO() is undefined, and will trigger ABORT in DEBUG builds.
1183 void BindInternalDrawFBO(GLuint name) {
1184 #ifdef DEBUG
1185 mInInternalBindingMode_DrawFBO = true;
1186 #endif
1187 if (SupportsOffscreenSplit())
1188 raw_fBindFramebuffer(LOCAL_GL_DRAW_FRAMEBUFFER_EXT, name);
1189 else
1190 raw_fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, name);
1192 mInternalBoundDrawFBO = name;
1195 void BindInternalReadFBO(GLuint name) {
1196 #ifdef DEBUG
1197 mInInternalBindingMode_ReadFBO = true;
1198 #endif
1199 if (SupportsOffscreenSplit())
1200 raw_fBindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER_EXT, name);
1201 else
1202 raw_fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, name);
1204 mInternalBoundReadFBO = name;
1207 void BindInternalFBO(GLuint name) {
1208 BindInternalDrawFBO(name);
1209 BindInternalReadFBO(name);
1212 void InitFramebuffers() {
1213 MakeCurrent();
1214 BindUserDrawFBO(0);
1215 BindUserReadFBO(0);
1218 GLuint SwapUserDrawFBO(GLuint name) {
1219 GLuint prev = GetUserBoundDrawFBO();
1220 BindUserDrawFBO(name);
1221 return prev;
1224 GLuint SwapUserReadFBO(GLuint name) {
1225 GLuint prev = GetUserBoundReadFBO();
1226 BindUserReadFBO(name);
1227 return prev;
1230 private:
1231 bool mOffscreenFBOsDirty;
1233 void GetShaderPrecisionFormatNonES2(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) {
1234 switch (precisiontype) {
1235 case LOCAL_GL_LOW_FLOAT:
1236 case LOCAL_GL_MEDIUM_FLOAT:
1237 case LOCAL_GL_HIGH_FLOAT:
1238 // Assume IEEE 754 precision
1239 range[0] = 127;
1240 range[1] = 127;
1241 *precision = 23;
1242 break;
1243 case LOCAL_GL_LOW_INT:
1244 case LOCAL_GL_MEDIUM_INT:
1245 case LOCAL_GL_HIGH_INT:
1246 // Some (most) hardware only supports single-precision floating-point numbers,
1247 // which can accurately represent integers up to +/-16777216
1248 range[0] = 24;
1249 range[1] = 24;
1250 *precision = 0;
1251 break;
1255 // Do whatever setup is necessary to draw to our offscreen FBO, if it's
1256 // bound.
1257 void BeforeGLDrawCall() {
1258 if (mInternalBoundDrawFBO != mOffscreenDrawFBO)
1259 return;
1261 if (mOffscreenDrawFBO == mOffscreenReadFBO)
1262 return;
1264 mOffscreenFBOsDirty = true;
1267 // Do whatever tear-down is necessary after drawing to our offscreen FBO,
1268 // if it's bound.
1269 void AfterGLDrawCall() {
1272 // Do whatever setup is necessary to read from our offscreen FBO, if it's
1273 // bound.
1274 void BeforeGLReadCall() {
1275 if (mInternalBoundReadFBO != mOffscreenReadFBO)
1276 return;
1278 if (mOffscreenDrawFBO == mOffscreenReadFBO)
1279 return;
1281 // If we're not dirty, there's no need to blit
1282 if (!mOffscreenFBOsDirty)
1283 return;
1285 const bool scissor = fIsEnabled(LOCAL_GL_SCISSOR_TEST);
1286 if (scissor)
1287 fDisable(LOCAL_GL_SCISSOR_TEST);
1289 // Store current bindings for restoring later
1290 GLuint prevDraw = GetUserBoundDrawFBO();
1291 GLuint prevRead = GetUserBoundReadFBO();
1293 NS_ABORT_IF_FALSE(SupportsOffscreenSplit(), "Doesn't support offscreen split?");
1295 // Manually setting internal bindings, entering internal mode
1296 // Flip read/draw for blitting
1297 BindInternalDrawFBO(mOffscreenReadFBO);
1298 BindInternalReadFBO(mOffscreenDrawFBO);
1300 GLint width = mOffscreenActualSize.width;
1301 GLint height = mOffscreenActualSize.height;
1302 raw_fBlitFramebuffer(0, 0, width, height,
1303 0, 0, width, height,
1304 LOCAL_GL_COLOR_BUFFER_BIT,
1305 LOCAL_GL_NEAREST);
1307 // Reset to emulated user binding, exiting internal mode
1308 BindUserDrawFBO(prevDraw);
1309 BindUserReadFBO(prevRead);
1311 if (scissor)
1312 fEnable(LOCAL_GL_SCISSOR_TEST);
1314 mOffscreenFBOsDirty = false;
1317 // Do whatever tear-down is necessary after reading from our offscreen FBO,
1318 // if it's bound.
1319 void AfterGLReadCall() {
1322 public:
1323 // Draw call hooks:
1324 void fClear(GLbitfield mask) {
1325 BeforeGLDrawCall();
1326 raw_fClear(mask);
1327 AfterGLDrawCall();
1330 void fDrawArrays(GLenum mode, GLint first, GLsizei count) {
1331 BeforeGLDrawCall();
1332 raw_fDrawArrays(mode, first, count);
1333 AfterGLDrawCall();
1336 void fDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices) {
1337 BeforeGLDrawCall();
1338 raw_fDrawElements(mode, count, type, indices);
1339 AfterGLDrawCall();
1342 // Read call hooks:
1343 void fReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels) {
1344 BeforeGLReadCall();
1345 raw_fReadPixels(x, y, width, height, format, type, pixels);
1346 AfterGLReadCall();
1349 void fCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) {
1350 BeforeGLReadCall();
1351 raw_fCopyTexImage2D(target, level, internalformat,
1352 x, y, width, height, border);
1353 AfterGLReadCall();
1356 void fCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) {
1357 BeforeGLReadCall();
1358 raw_fCopyTexSubImage2D(target, level, xoffset, yoffset,
1359 x, y, width, height);
1360 AfterGLReadCall();
1363 void ForceDirtyFBOs() {
1364 GLuint draw = SwapUserDrawFBO(0);
1366 BeforeGLDrawCall();
1367 // no-op; just pretend we did something
1368 AfterGLDrawCall();
1370 BindUserDrawFBO(draw);
1373 void BlitDirtyFBOs() {
1374 GLuint read = SwapUserReadFBO(0);
1376 BeforeGLReadCall();
1377 // no-op; we just want to make sure the Read FBO is updated if it needs to be
1378 AfterGLReadCall();
1380 BindUserReadFBO(read);
1383 // Draw/Read
1384 void fBlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) {
1385 BeforeGLDrawCall();
1386 BeforeGLReadCall();
1387 raw_fBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
1388 AfterGLReadCall();
1389 AfterGLDrawCall();
1392 #if defined(MOZ_X11) && defined(MOZ_EGL_XRENDER_COMPOSITE)
1393 virtual gfxASurface* GetOffscreenPixmapSurface()
1395 return 0;
1398 virtual bool WaitNative() { return false; }
1399 #endif
1401 virtual bool TextureImageSupportsGetBackingSurface() {
1402 return false;
1405 virtual bool RenewSurface() { return false; }
1407 /**`
1408 * Return a valid, allocated TextureImage of |aSize| with
1409 * |aContentType|. The TextureImage's texture is configured to
1410 * use |aWrapMode| (usually GL_CLAMP_TO_EDGE or GL_REPEAT) and by
1411 * default, GL_LINEAR filtering. Specify
1412 * |aFlags=UseNearestFilter| for GL_NEAREST filtering. Specify
1413 * |aFlags=NeedsYFlip| if the image is flipped. Return
1414 * NULL if creating the TextureImage fails.
1416 * The returned TextureImage may only be used with this GLContext.
1417 * Attempting to use the returned TextureImage after this
1418 * GLContext is destroyed will result in undefined (and likely
1419 * crashy) behavior.
1421 virtual already_AddRefed<TextureImage>
1422 CreateTextureImage(const nsIntSize& aSize,
1423 TextureImage::ContentType aContentType,
1424 GLenum aWrapMode,
1425 TextureImage::Flags aFlags = TextureImage::NoFlags);
1428 * In EGL we want to use Tiled Texture Images, which we return
1429 * from CreateTextureImage above.
1430 * Inside TiledTextureImage we need to create actual images and to
1431 * prevent infinite recursion we need to differentiate the two
1432 * functions.
1434 virtual already_AddRefed<TextureImage>
1435 TileGenFunc(const nsIntSize& aSize,
1436 TextureImage::ContentType aContentType,
1437 TextureImage::Flags aFlags = TextureImage::NoFlags)
1439 return nullptr;
1443 * Read the image data contained in aTexture, and return it as an ImageSurface.
1444 * If GL_RGBA is given as the format, a ImageFormatARGB32 surface is returned.
1445 * Not implemented yet:
1446 * If GL_RGB is given as the format, a ImageFormatRGB24 surface is returned.
1447 * If GL_LUMINANCE is given as the format, a ImageFormatA8 surface is returned.
1449 * THIS IS EXPENSIVE. It is ridiculously expensive. Only do this
1450 * if you absolutely positively must, and never in any performance
1451 * critical path.
1453 already_AddRefed<gfxImageSurface> ReadTextureImage(GLuint aTexture,
1454 const gfxIntSize& aSize,
1455 GLenum aTextureFormat,
1456 bool aYInvert = false);
1458 already_AddRefed<gfxImageSurface> GetTexImage(GLuint aTexture, bool aYInvert, ShaderProgramType aShader);
1461 * Call ReadPixels into an existing gfxImageSurface.
1462 * The image surface must be using image format RGBA32 or RGB24,
1463 * and must have stride == width*4.
1464 * Note that neither ReadPixelsIntoImageSurface nor
1465 * ReadScreenIntoImageSurface call dest->Flush/MarkDirty.
1467 void THEBES_API ReadPixelsIntoImageSurface(gfxImageSurface* dest);
1469 // Similar to ReadPixelsIntoImageSurface, but pulls from the screen
1470 // instead of the currently bound framebuffer.
1471 void ReadScreenIntoImageSurface(gfxImageSurface* dest);
1474 * Copy a rectangle from one TextureImage into another. The
1475 * source and destination are given in integer coordinates, and
1476 * will be converted to texture coordinates.
1478 * For the source texture, the wrap modes DO apply -- it's valid
1479 * to use REPEAT or PAD and expect appropriate behaviour if the source
1480 * rectangle extends beyond its bounds.
1482 * For the destination texture, the wrap modes DO NOT apply -- the
1483 * destination will be clipped by the bounds of the texture.
1485 * Note: calling this function will cause the following OpenGL state
1486 * to be changed:
1488 * - current program
1489 * - framebuffer binding
1490 * - viewport
1491 * - blend state (will be enabled at end)
1492 * - scissor state (will be enabled at end)
1493 * - vertex attrib 0 and 1 (pointer and enable state [enable state will be disabled at exit])
1494 * - array buffer binding (will be 0)
1495 * - active texture (will be 0)
1496 * - texture 0 binding
1498 void BlitTextureImage(TextureImage *aSrc, const nsIntRect& aSrcRect,
1499 TextureImage *aDst, const nsIntRect& aDstRect);
1502 * Creates a RGB/RGBA texture (or uses one provided) and uploads the surface
1503 * contents to it within aSrcRect.
1505 * aSrcRect.x/y will be uploaded to 0/0 in the texture, and the size
1506 * of the texture with be aSrcRect.width/height.
1508 * If an existing texture is passed through aTexture, it is assumed it
1509 * has already been initialised with glTexImage2D (or this function),
1510 * and that its size is equal to or greater than aSrcRect + aDstPoint.
1511 * You can alternatively set the overwrite flag to true and have a new
1512 * texture memory block allocated.
1514 * The aDstPoint parameter is ignored if no texture was provided
1515 * or aOverwrite is true.
1517 * \param aSurface Surface to upload.
1518 * \param aDstRegion Region of texture to upload to.
1519 * \param aTexture Texture to use, or 0 to have one created for you.
1520 * \param aOverwrite Over an existing texture with a new one.
1521 * \param aSrcPoint Offset into aSrc where the region's bound's
1522 * TopLeft() sits.
1523 * \param aPixelBuffer Pass true to upload texture data with an
1524 * offset from the base data (generally for pixel buffer objects),
1525 * otherwise textures are upload with an absolute pointer to the data.
1526 * \param aTextureUnit, the texture unit used temporarily to upload the
1527 * surface. This testure may be overridden, clients should not rely on
1528 * the contents of this texture after this call or even on this
1529 * texture unit being active.
1530 * \return Shader program needed to render this texture.
1532 ShaderProgramType UploadSurfaceToTexture(gfxASurface *aSurface,
1533 const nsIntRegion& aDstRegion,
1534 GLuint& aTexture,
1535 bool aOverwrite = false,
1536 const nsIntPoint& aSrcPoint = nsIntPoint(0, 0),
1537 bool aPixelBuffer = false,
1538 GLenum aTextureUnit = LOCAL_GL_TEXTURE0);
1541 void TexImage2D(GLenum target, GLint level, GLint internalformat,
1542 GLsizei width, GLsizei height, GLsizei stride,
1543 GLint pixelsize, GLint border, GLenum format,
1544 GLenum type, const GLvoid *pixels);
1546 void TexSubImage2D(GLenum target, GLint level,
1547 GLint xoffset, GLint yoffset,
1548 GLsizei width, GLsizei height, GLsizei stride,
1549 GLint pixelsize, GLenum format,
1550 GLenum type, const GLvoid* pixels);
1553 * Uses the Khronos GL_EXT_unpack_subimage extension, working around
1554 * quirks in the Tegra implementation of this extension.
1556 void TexSubImage2DWithUnpackSubimageGLES(GLenum target, GLint level,
1557 GLint xoffset, GLint yoffset,
1558 GLsizei width, GLsizei height,
1559 GLsizei stride, GLint pixelsize,
1560 GLenum format, GLenum type,
1561 const GLvoid* pixels);
1563 void TexSubImage2DWithoutUnpackSubimage(GLenum target, GLint level,
1564 GLint xoffset, GLint yoffset,
1565 GLsizei width, GLsizei height,
1566 GLsizei stride, GLint pixelsize,
1567 GLenum format, GLenum type,
1568 const GLvoid* pixels);
1570 /** Helper for DecomposeIntoNoRepeatTriangles
1572 struct RectTriangles {
1573 RectTriangles() { }
1575 // Always pass texture coordinates upright. If you want to flip the
1576 // texture coordinates emitted to the tex_coords array, set flip_y to
1577 // true.
1578 void addRect(GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1,
1579 GLfloat tx0, GLfloat ty0, GLfloat tx1, GLfloat ty1,
1580 bool flip_y = false);
1583 * these return a float pointer to the start of each array respectively.
1584 * Use it for glVertexAttribPointer calls.
1585 * We can return NULL if we choose to use Vertex Buffer Objects here.
1587 float* vertexPointer() {
1588 return &vertexCoords[0].x;
1591 float* texCoordPointer() {
1592 return &texCoords[0].u;
1595 unsigned int elements() {
1596 return vertexCoords.Length();
1599 typedef struct { GLfloat x,y; } vert_coord;
1600 typedef struct { GLfloat u,v; } tex_coord;
1601 private:
1602 // default is 4 rectangles, each made up of 2 triangles (3 coord vertices each)
1603 nsAutoTArray<vert_coord, 6> vertexCoords;
1604 nsAutoTArray<tex_coord, 6> texCoords;
1608 * Decompose drawing the possibly-wrapped aTexCoordRect rectangle
1609 * of a texture of aTexSize into one or more rectangles (represented
1610 * as 2 triangles) and associated tex coordinates, such that
1611 * we don't have to use the REPEAT wrap mode. If aFlipY is true, the
1612 * texture coordinates will be specified vertically flipped.
1614 * The resulting triangle vertex coordinates will be in the space of
1615 * (0.0, 0.0) to (1.0, 1.0) -- transform the coordinates appropriately
1616 * if you need a different space.
1618 * The resulting vertex coordinates should be drawn using GL_TRIANGLES,
1619 * and rects.numRects * 3 * 6
1621 static void DecomposeIntoNoRepeatTriangles(const nsIntRect& aTexCoordRect,
1622 const nsIntSize& aTexSize,
1623 RectTriangles& aRects,
1624 bool aFlipY = false);
1628 * Known GL extensions that can be queried by
1629 * IsExtensionSupported. The results of this are cached, and as
1630 * such it's safe to use this even in performance critical code.
1631 * If you add to this array, remember to add to the string names
1632 * in GLContext.cpp.
1634 enum GLExtensions {
1635 EXT_framebuffer_object,
1636 ARB_framebuffer_object,
1637 ARB_texture_rectangle,
1638 EXT_bgra,
1639 EXT_texture_format_BGRA8888,
1640 OES_depth24,
1641 OES_depth32,
1642 OES_stencil8,
1643 OES_texture_npot,
1644 OES_depth_texture,
1645 OES_packed_depth_stencil,
1646 IMG_read_format,
1647 EXT_read_format_bgra,
1648 APPLE_client_storage,
1649 ARB_texture_non_power_of_two,
1650 ARB_pixel_buffer_object,
1651 ARB_ES2_compatibility,
1652 OES_texture_float,
1653 ARB_texture_float,
1654 EXT_unpack_subimage,
1655 OES_standard_derivatives,
1656 EXT_texture_filter_anisotropic,
1657 EXT_texture_compression_s3tc,
1658 EXT_texture_compression_dxt1,
1659 ANGLE_texture_compression_dxt3,
1660 ANGLE_texture_compression_dxt5,
1661 AMD_compressed_ATC_texture,
1662 IMG_texture_compression_pvrtc,
1663 EXT_framebuffer_blit,
1664 ANGLE_framebuffer_blit,
1665 EXT_framebuffer_multisample,
1666 ANGLE_framebuffer_multisample,
1667 OES_rgb8_rgba8,
1668 ARB_robustness,
1669 EXT_robustness,
1670 ARB_sync,
1671 OES_EGL_image,
1672 OES_EGL_sync,
1673 OES_EGL_image_external,
1674 EXT_packed_depth_stencil,
1675 Extensions_Max
1678 bool IsExtensionSupported(GLExtensions aKnownExtension) {
1679 return mAvailableExtensions[aKnownExtension];
1682 void MarkExtensionUnsupported(GLExtensions aKnownExtension) {
1683 mAvailableExtensions[aKnownExtension] = 0;
1686 // Shared code for GL extensions and GLX extensions.
1687 static bool ListHasExtension(const GLubyte *extensions,
1688 const char *extension);
1690 GLint GetMaxTextureSize() { return mMaxTextureSize; }
1691 GLint GetMaxTextureImageSize() { return mMaxTextureImageSize; }
1692 void SetFlipped(bool aFlipped) { mFlipped = aFlipped; }
1694 // this should just be a std::bitset, but that ended up breaking
1695 // MacOS X builds; see bug 584919. We can replace this with one
1696 // later on. This is handy to use in WebGL contexts as well,
1697 // so making it public.
1698 template<size_t Size>
1699 struct ExtensionBitset {
1700 ExtensionBitset() {
1701 for (size_t i = 0; i < Size; ++i)
1702 extensions[i] = false;
1705 void Load(const char* extStr, const char** extList, bool verbose = false) {
1706 char* exts = strdup(extStr);
1708 if (verbose)
1709 printf_stderr("Extensions: %s\n", exts);
1711 char* cur = exts;
1712 bool done = false;
1713 while (!done) {
1714 char* space = strchr(cur, ' ');
1715 if (space) {
1716 *space = '\0';
1717 } else {
1718 done = true;
1721 for (int i = 0; extList[i]; ++i) {
1722 if (strcmp(cur, extList[i]) == 0) {
1723 if (verbose)
1724 printf_stderr("Found extension %s\n", cur);
1725 extensions[i] = 1;
1729 cur = space + 1;
1732 free(exts);
1735 bool& operator[](size_t index) {
1736 MOZ_ASSERT(index < Size, "out of range");
1737 return extensions[index];
1740 bool extensions[Size];
1743 protected:
1744 ExtensionBitset<Extensions_Max> mAvailableExtensions;
1746 public:
1748 * Context reset constants.
1749 * These are used to determine who is guilty when a context reset
1750 * happens.
1752 enum ContextResetARB {
1753 CONTEXT_NO_ERROR = 0,
1754 CONTEXT_GUILTY_CONTEXT_RESET_ARB = 0x8253,
1755 CONTEXT_INNOCENT_CONTEXT_RESET_ARB = 0x8254,
1756 CONTEXT_UNKNOWN_CONTEXT_RESET_ARB = 0x8255
1759 bool HasRobustness() {
1760 return mHasRobustness;
1763 protected:
1764 bool mInitialized;
1765 bool mIsOffscreen;
1766 bool mIsGLES2;
1767 bool mIsGlobalSharedContext;
1768 bool mHasRobustness;
1769 bool mContextLost;
1771 int32_t mVendor;
1772 int32_t mRenderer;
1774 public:
1775 enum {
1776 DebugEnabled = 1 << 0,
1777 DebugTrace = 1 << 1,
1778 DebugAbortOnError = 1 << 2
1781 static uint32_t sDebugMode;
1783 static uint32_t DebugMode() {
1784 #ifdef DEBUG
1785 return sDebugMode;
1786 #else
1787 return 0;
1788 #endif
1791 protected:
1793 ContextFormat mCreationFormat;
1794 nsRefPtr<GLContext> mSharedContext;
1796 // The thread on which this context was created.
1797 nsCOMPtr<nsIThread> mOwningThread;
1799 GLContextSymbols mSymbols;
1801 #ifdef DEBUG
1802 // GLDebugMode will check that we don't send call
1803 // to a GLContext that isn't current on the current
1804 // thread.
1805 // Store the current context when binding to thread local
1806 // storage to support DebugMode on an arbitrary thread.
1807 static unsigned sCurrentGLContextTLS;
1808 #endif
1810 void UpdateActualFormat();
1811 ContextFormat mActualFormat;
1813 gfxIntSize mOffscreenSize;
1814 gfxIntSize mOffscreenActualSize;
1815 GLuint mOffscreenTexture;
1816 bool mFlipped;
1818 // lazy-initialized things
1819 GLuint mBlitProgram, mBlitFramebuffer;
1820 void UseBlitProgram();
1821 void SetBlitFramebufferForDestTexture(GLuint aTexture);
1823 // Helper to create/resize an offscreen FBO,
1824 // for offscreen implementations that use FBOs.
1825 // Note that it does -not- clear the resized buffers.
1826 bool ResizeOffscreenFBOs(const ContextFormat& aCF, const gfxIntSize& aSize, const bool aNeedsReadBuffer);
1827 bool ResizeOffscreenFBOs(const gfxIntSize& aSize, const bool aNeedsReadBuffer) {
1828 if (!IsOffscreenSizeAllowed(aSize))
1829 return false;
1831 ContextFormat format(mCreationFormat);
1833 if (format.samples) {
1834 // AA path
1835 if (ResizeOffscreenFBOs(format, aSize, aNeedsReadBuffer))
1836 return true;
1838 NS_WARNING("ResizeOffscreenFBOs failed to resize an AA context! Falling back to no AA...");
1839 format.samples = 0;
1842 if (ResizeOffscreenFBOs(format, aSize, aNeedsReadBuffer))
1843 return true;
1845 NS_WARNING("ResizeOffscreenFBOs failed to resize non-AA context!");
1846 return false;
1849 struct GLFormats {
1850 GLFormats()
1851 : texColor(0)
1852 , texColorType(0)
1853 , rbColor(0)
1854 , depthStencil(0)
1855 , depth(0)
1856 , stencil(0)
1857 , samples(0)
1860 GLenum texColor;
1861 GLenum texColorType;
1862 GLenum rbColor;
1863 GLenum depthStencil;
1864 GLenum depth;
1865 GLenum stencil;
1866 GLsizei samples;
1869 enum ColorByteOrder {
1870 ForceRGBA,
1871 DefaultByteOrder
1874 GLFormats ChooseGLFormats(ContextFormat& aCF, GLContext::ColorByteOrder aByteOrder = GLContext::DefaultByteOrder);
1875 void CreateTextureForOffscreen(const GLFormats& aFormats, const gfxIntSize& aSize,
1876 GLuint& texture);
1877 void CreateRenderbuffersForOffscreen(const GLContext::GLFormats& aFormats, const gfxIntSize& aSize,
1878 GLuint& colorMSRB, GLuint& depthRB, GLuint& stencilRB);
1879 bool AssembleOffscreenFBOs(const GLuint colorMSRB,
1880 const GLuint depthRB,
1881 const GLuint stencilRB,
1882 const GLuint texture,
1883 GLuint& drawFBO,
1884 GLuint& readFBO);
1886 void DeleteOffscreenFBOs();
1888 GLuint mOffscreenDrawFBO;
1889 GLuint mOffscreenReadFBO;
1890 GLuint mOffscreenColorRB;
1891 GLuint mOffscreenDepthRB;
1892 GLuint mOffscreenStencilRB;
1894 // Clear to transparent black, with 0 depth and stencil,
1895 // while preserving current ClearColor etc. values.
1896 // Useful for resizing offscreen buffers.
1897 public:
1898 void ClearSafely();
1900 bool WorkAroundDriverBugs() const { return mWorkAroundDriverBugs; }
1902 protected:
1904 nsDataHashtable<nsPtrHashKey<void>, void*> mUserData;
1906 void SetIsGLES2(bool aIsGLES2) {
1907 NS_ASSERTION(!mInitialized, "SetIsGLES2 can only be called before initialization!");
1908 mIsGLES2 = aIsGLES2;
1911 bool InitWithPrefix(const char *prefix, bool trygl);
1913 void InitExtensions();
1915 virtual already_AddRefed<TextureImage>
1916 CreateBasicTextureImage(GLuint aTexture,
1917 const nsIntSize& aSize,
1918 GLenum aWrapMode,
1919 TextureImage::ContentType aContentType,
1920 GLContext* aContext,
1921 TextureImage::Flags aFlags = TextureImage::NoFlags)
1923 nsRefPtr<BasicTextureImage> teximage(
1924 new BasicTextureImage(aTexture, aSize, aWrapMode, aContentType, aContext, aFlags));
1925 return teximage.forget();
1928 bool IsOffscreenSizeAllowed(const gfxIntSize& aSize) const {
1929 int32_t biggerDimension = NS_MAX(aSize.width, aSize.height);
1930 int32_t maxAllowed = NS_MIN(mMaxRenderbufferSize, mMaxTextureSize);
1931 return biggerDimension <= maxAllowed;
1934 nsTArray<nsIntRect> mViewportStack;
1935 nsTArray<nsIntRect> mScissorStack;
1937 GLint mMaxTextureSize;
1938 GLint mMaxCubeMapTextureSize;
1939 GLint mMaxTextureImageSize;
1940 GLint mMaxRenderbufferSize;
1941 bool mWorkAroundDriverBugs;
1943 bool IsTextureSizeSafeToPassToDriver(GLenum target, GLsizei width, GLsizei height) const {
1944 #ifdef XP_MACOSX
1945 if (mWorkAroundDriverBugs &&
1946 mVendor == VendorIntel) {
1947 // see bug 737182 for 2D textures, bug 684822 for cube map textures.
1948 // some drivers handle incorrectly some large texture sizes that are below the
1949 // max texture size that they report. So we check ourselves against our own values
1950 // (mMax[CubeMap]TextureSize).
1951 GLsizei maxSize = target == LOCAL_GL_TEXTURE_CUBE_MAP ||
1952 (target >= LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X &&
1953 target <= LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
1954 ? mMaxCubeMapTextureSize
1955 : mMaxTextureSize;
1956 return width <= maxSize && height <= maxSize;
1958 #endif
1959 return true;
1962 public:
1964 /** \returns the first GL error, and guarantees that all GL error flags are cleared,
1965 * i.e. that a subsequent GetError call will return NO_ERROR
1967 GLenum GetAndClearError() {
1968 // the first error is what we want to return
1969 GLenum error = fGetError();
1971 if (error) {
1972 // clear all pending errors
1973 while(fGetError()) {}
1976 return error;
1979 #ifdef DEBUG
1981 #ifndef MOZ_FUNCTION_NAME
1982 # ifdef __GNUC__
1983 # define MOZ_FUNCTION_NAME __PRETTY_FUNCTION__
1984 # elif defined(_MSC_VER)
1985 # define MOZ_FUNCTION_NAME __FUNCTION__
1986 # else
1987 # define MOZ_FUNCTION_NAME __func__ // defined in C99, supported in various C++ compilers. Just raw function name.
1988 # endif
1989 #endif
1991 protected:
1992 GLenum mGLError;
1994 public:
1996 void BeforeGLCall(const char* glFunction) {
1997 if (DebugMode()) {
1998 GLContext *currentGLContext = NULL;
2000 currentGLContext = (GLContext*)PR_GetThreadPrivate(sCurrentGLContextTLS);
2002 if (DebugMode() & DebugTrace)
2003 printf_stderr("[gl:%p] > %s\n", this, glFunction);
2004 if (this != currentGLContext) {
2005 printf_stderr("Fatal: %s called on non-current context %p. "
2006 "The current context for this thread is %p.\n",
2007 glFunction, this, currentGLContext);
2008 NS_ABORT();
2013 void AfterGLCall(const char* glFunction) {
2014 if (DebugMode()) {
2015 // calling fFinish() immediately after every GL call makes sure that if this GL command crashes,
2016 // the stack trace will actually point to it. Otherwise, OpenGL being an asynchronous API, stack traces
2017 // tend to be meaningless
2018 mSymbols.fFinish();
2019 mGLError = mSymbols.fGetError();
2020 if (DebugMode() & DebugTrace)
2021 printf_stderr("[gl:%p] < %s [0x%04x]\n", this, glFunction, mGLError);
2022 if (mGLError != LOCAL_GL_NO_ERROR) {
2023 printf_stderr("GL ERROR: %s generated GL error %s(0x%04x)\n",
2024 glFunction,
2025 GLErrorToString(mGLError),
2026 mGLError);
2027 if (DebugMode() & DebugAbortOnError)
2028 NS_ABORT();
2033 const char* GLErrorToString(GLenum aError)
2035 switch (aError) {
2036 case LOCAL_GL_INVALID_ENUM:
2037 return "GL_INVALID_ENUM";
2038 case LOCAL_GL_INVALID_VALUE:
2039 return "GL_INVALID_VALUE";
2040 case LOCAL_GL_INVALID_OPERATION:
2041 return "GL_INVALID_OPERATION";
2042 case LOCAL_GL_STACK_OVERFLOW:
2043 return "GL_STACK_OVERFLOW";
2044 case LOCAL_GL_STACK_UNDERFLOW:
2045 return "GL_STACK_UNDERFLOW";
2046 case LOCAL_GL_OUT_OF_MEMORY:
2047 return "GL_OUT_OF_MEMORY";
2048 case LOCAL_GL_TABLE_TOO_LARGE:
2049 return "GL_TABLE_TOO_LARGE";
2050 case LOCAL_GL_INVALID_FRAMEBUFFER_OPERATION:
2051 return "GL_INVALID_FRAMEBUFFER_OPERATION";
2052 default:
2053 return "";
2057 #define BEFORE_GL_CALL do { \
2058 BeforeGLCall(MOZ_FUNCTION_NAME); \
2059 } while (0)
2061 #define AFTER_GL_CALL do { \
2062 AfterGLCall(MOZ_FUNCTION_NAME); \
2063 } while (0)
2065 #else
2067 #define BEFORE_GL_CALL do { } while (0)
2068 #define AFTER_GL_CALL do { } while (0)
2070 #endif
2072 /*** In GL debug mode, we completely override glGetError ***/
2074 GLenum fGetError() {
2075 #ifdef DEBUG
2076 // debug mode ends up eating the error in AFTER_GL_CALL
2077 if (DebugMode()) {
2078 GLenum err = mGLError;
2079 mGLError = LOCAL_GL_NO_ERROR;
2080 return err;
2082 #endif
2084 return mSymbols.fGetError();
2088 /*** Scissor functions ***/
2090 protected:
2092 GLint FixYValue(GLint y, GLint height)
2094 return mFlipped ? ViewportRect().height - (height + y) : y;
2097 // only does the glScissor call, no ScissorRect business
2098 void raw_fScissor(GLint x, GLint y, GLsizei width, GLsizei height) {
2099 BEFORE_GL_CALL;
2100 // GL's coordinate system is flipped compared to ours (in the Y axis),
2101 // so we may need to flip our rectangle.
2102 mSymbols.fScissor(x,
2103 FixYValue(y, height),
2104 width,
2105 height);
2106 AFTER_GL_CALL;
2109 public:
2111 // but let GL-using code use that instead, updating the ScissorRect
2112 void fScissor(GLint x, GLint y, GLsizei width, GLsizei height) {
2113 ScissorRect().SetRect(x, y, width, height);
2114 raw_fScissor(x, y, width, height);
2117 nsIntRect& ScissorRect() {
2118 return mScissorStack[mScissorStack.Length()-1];
2121 void PushScissorRect() {
2122 nsIntRect copy(ScissorRect());
2123 mScissorStack.AppendElement(copy);
2126 void PushScissorRect(const nsIntRect& aRect) {
2127 mScissorStack.AppendElement(aRect);
2128 raw_fScissor(aRect.x, aRect.y, aRect.width, aRect.height);
2131 void PopScissorRect() {
2132 if (mScissorStack.Length() < 2) {
2133 NS_WARNING("PopScissorRect with Length < 2!");
2134 return;
2137 nsIntRect thisRect = ScissorRect();
2138 mScissorStack.TruncateLength(mScissorStack.Length() - 1);
2139 if (!thisRect.IsEqualInterior(ScissorRect())) {
2140 raw_fScissor(ScissorRect().x, ScissorRect().y,
2141 ScissorRect().width, ScissorRect().height);
2145 /*** Viewport functions ***/
2147 protected:
2149 // only does the glViewport call, no ViewportRect business
2150 void raw_fViewport(GLint x, GLint y, GLsizei width, GLsizei height) {
2151 BEFORE_GL_CALL;
2152 // XXX: Flipping should really happen using the destination height, but
2153 // we use viewport instead and assume viewport size matches the
2154 // destination. If we ever try use partial viewports for layers we need
2155 // to fix this, and remove the assertion.
2156 NS_ASSERTION(!mFlipped || (x == 0 && y == 0), "TODO: Need to flip the viewport rect");
2157 mSymbols.fViewport(x, y, width, height);
2158 AFTER_GL_CALL;
2161 public:
2163 void fViewport(GLint x, GLint y, GLsizei width, GLsizei height) {
2164 ViewportRect().SetRect(x, y, width, height);
2165 raw_fViewport(x, y, width, height);
2168 nsIntRect& ViewportRect() {
2169 return mViewportStack[mViewportStack.Length()-1];
2172 void PushViewportRect() {
2173 nsIntRect copy(ViewportRect());
2174 mViewportStack.AppendElement(copy);
2177 void PushViewportRect(const nsIntRect& aRect) {
2178 mViewportStack.AppendElement(aRect);
2179 raw_fViewport(aRect.x, aRect.y, aRect.width, aRect.height);
2182 void PopViewportRect() {
2183 if (mViewportStack.Length() < 2) {
2184 NS_WARNING("PopViewportRect with Length < 2!");
2185 return;
2188 nsIntRect thisRect = ViewportRect();
2189 mViewportStack.TruncateLength(mViewportStack.Length() - 1);
2190 if (!thisRect.IsEqualInterior(ViewportRect())) {
2191 raw_fViewport(ViewportRect().x, ViewportRect().y,
2192 ViewportRect().width, ViewportRect().height);
2196 /*** other GL functions ***/
2198 void fActiveTexture(GLenum texture) {
2199 BEFORE_GL_CALL;
2200 mSymbols.fActiveTexture(texture);
2201 AFTER_GL_CALL;
2204 void fAttachShader(GLuint program, GLuint shader) {
2205 BEFORE_GL_CALL;
2206 mSymbols.fAttachShader(program, shader);
2207 AFTER_GL_CALL;
2210 void fBindAttribLocation(GLuint program, GLuint index, const GLchar* name) {
2211 BEFORE_GL_CALL;
2212 mSymbols.fBindAttribLocation(program, index, name);
2213 AFTER_GL_CALL;
2216 void fBindBuffer(GLenum target, GLuint buffer) {
2217 BEFORE_GL_CALL;
2218 mSymbols.fBindBuffer(target, buffer);
2219 AFTER_GL_CALL;
2222 void fBindTexture(GLenum target, GLuint texture) {
2223 BEFORE_GL_CALL;
2224 mSymbols.fBindTexture(target, texture);
2225 AFTER_GL_CALL;
2228 void fBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {
2229 BEFORE_GL_CALL;
2230 mSymbols.fBlendColor(red, green, blue, alpha);
2231 AFTER_GL_CALL;
2234 void fBlendEquation(GLenum mode) {
2235 BEFORE_GL_CALL;
2236 mSymbols.fBlendEquation(mode);
2237 AFTER_GL_CALL;
2240 void fBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha) {
2241 BEFORE_GL_CALL;
2242 mSymbols.fBlendEquationSeparate(modeRGB, modeAlpha);
2243 AFTER_GL_CALL;
2246 void fBlendFunc(GLenum sfactor, GLenum dfactor) {
2247 BEFORE_GL_CALL;
2248 mSymbols.fBlendFunc(sfactor, dfactor);
2249 AFTER_GL_CALL;
2252 void fBlendFuncSeparate(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha) {
2253 BEFORE_GL_CALL;
2254 mSymbols.fBlendFuncSeparate(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha);
2255 AFTER_GL_CALL;
2258 void fBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage) {
2259 BEFORE_GL_CALL;
2260 mSymbols.fBufferData(target, size, data, usage);
2262 // bug 744888
2263 if (WorkAroundDriverBugs() &&
2264 !data &&
2265 Vendor() == VendorNVIDIA)
2267 char c = 0;
2268 mSymbols.fBufferSubData(target, size-1, 1, &c);
2271 AFTER_GL_CALL;
2274 void fBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data) {
2275 BEFORE_GL_CALL;
2276 mSymbols.fBufferSubData(target, offset, size, data);
2277 AFTER_GL_CALL;
2280 void raw_fClear(GLbitfield mask) {
2281 BEFORE_GL_CALL;
2282 mSymbols.fClear(mask);
2283 AFTER_GL_CALL;
2286 void fClearColor(GLclampf r, GLclampf g, GLclampf b, GLclampf a) {
2287 BEFORE_GL_CALL;
2288 mSymbols.fClearColor(r, g, b, a);
2289 AFTER_GL_CALL;
2292 void fClearStencil(GLint s) {
2293 BEFORE_GL_CALL;
2294 mSymbols.fClearStencil(s);
2295 AFTER_GL_CALL;
2298 void fColorMask(realGLboolean red, realGLboolean green, realGLboolean blue, realGLboolean alpha) {
2299 BEFORE_GL_CALL;
2300 mSymbols.fColorMask(red, green, blue, alpha);
2301 AFTER_GL_CALL;
2304 void fCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *pixels) {
2305 BEFORE_GL_CALL;
2306 mSymbols.fCompressedTexImage2D(target, level, internalformat, width, height, border, imageSize, pixels);
2307 AFTER_GL_CALL;
2310 void fCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *pixels) {
2311 BEFORE_GL_CALL;
2312 mSymbols.fCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, pixels);
2313 AFTER_GL_CALL;
2316 void fCullFace(GLenum mode) {
2317 BEFORE_GL_CALL;
2318 mSymbols.fCullFace(mode);
2319 AFTER_GL_CALL;
2322 void fDetachShader(GLuint program, GLuint shader) {
2323 BEFORE_GL_CALL;
2324 mSymbols.fDetachShader(program, shader);
2325 AFTER_GL_CALL;
2328 void fDepthFunc(GLenum func) {
2329 BEFORE_GL_CALL;
2330 mSymbols.fDepthFunc(func);
2331 AFTER_GL_CALL;
2334 void fDepthMask(realGLboolean flag) {
2335 BEFORE_GL_CALL;
2336 mSymbols.fDepthMask(flag);
2337 AFTER_GL_CALL;
2340 void fDisable(GLenum capability) {
2341 BEFORE_GL_CALL;
2342 mSymbols.fDisable(capability);
2343 AFTER_GL_CALL;
2346 void fDisableVertexAttribArray(GLuint index) {
2347 BEFORE_GL_CALL;
2348 mSymbols.fDisableVertexAttribArray(index);
2349 AFTER_GL_CALL;
2352 void raw_fDrawArrays(GLenum mode, GLint first, GLsizei count) {
2353 BEFORE_GL_CALL;
2354 mSymbols.fDrawArrays(mode, first, count);
2355 AFTER_GL_CALL;
2358 void raw_fDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices) {
2359 BEFORE_GL_CALL;
2360 mSymbols.fDrawElements(mode, count, type, indices);
2361 AFTER_GL_CALL;
2364 void fEnable(GLenum capability) {
2365 BEFORE_GL_CALL;
2366 mSymbols.fEnable(capability);
2367 AFTER_GL_CALL;
2370 void fEnableVertexAttribArray(GLuint index) {
2371 BEFORE_GL_CALL;
2372 mSymbols.fEnableVertexAttribArray(index);
2373 AFTER_GL_CALL;
2376 void fFinish() {
2377 BEFORE_GL_CALL;
2378 mSymbols.fFinish();
2379 AFTER_GL_CALL;
2382 void fFlush() {
2383 BEFORE_GL_CALL;
2384 mSymbols.fFlush();
2385 AFTER_GL_CALL;
2388 void fFrontFace(GLenum face) {
2389 BEFORE_GL_CALL;
2390 mSymbols.fFrontFace(face);
2391 AFTER_GL_CALL;
2394 void fGetActiveAttrib(GLuint program, GLuint index, GLsizei maxLength, GLsizei* length, GLint* size, GLenum* type, GLchar* name) {
2395 BEFORE_GL_CALL;
2396 mSymbols.fGetActiveAttrib(program, index, maxLength, length, size, type, name);
2397 AFTER_GL_CALL;
2400 void fGetActiveUniform(GLuint program, GLuint index, GLsizei maxLength, GLsizei* length, GLint* size, GLenum* type, GLchar* name) {
2401 BEFORE_GL_CALL;
2402 mSymbols.fGetActiveUniform(program, index, maxLength, length, size, type, name);
2403 AFTER_GL_CALL;
2406 void fGetAttachedShaders(GLuint program, GLsizei maxCount, GLsizei* count, GLuint* shaders) {
2407 BEFORE_GL_CALL;
2408 mSymbols.fGetAttachedShaders(program, maxCount, count, shaders);
2409 AFTER_GL_CALL;
2412 GLint fGetAttribLocation (GLuint program, const GLchar* name) {
2413 BEFORE_GL_CALL;
2414 GLint retval = mSymbols.fGetAttribLocation(program, name);
2415 AFTER_GL_CALL;
2416 return retval;
2419 private:
2420 void raw_fGetIntegerv(GLenum pname, GLint *params) {
2421 BEFORE_GL_CALL;
2422 mSymbols.fGetIntegerv(pname, params);
2423 AFTER_GL_CALL;
2426 public:
2427 void GetUIntegerv(GLenum pname, GLuint *params) {
2428 fGetIntegerv(pname, reinterpret_cast<GLint*>(params));
2431 void fGetFloatv(GLenum pname, GLfloat *params) {
2432 BEFORE_GL_CALL;
2433 mSymbols.fGetFloatv(pname, params);
2434 AFTER_GL_CALL;
2437 void fGetBooleanv(GLenum pname, realGLboolean *params) {
2438 BEFORE_GL_CALL;
2439 mSymbols.fGetBooleanv(pname, params);
2440 AFTER_GL_CALL;
2443 void fGetBufferParameteriv(GLenum target, GLenum pname, GLint* params) {
2444 BEFORE_GL_CALL;
2445 mSymbols.fGetBufferParameteriv(target, pname, params);
2446 AFTER_GL_CALL;
2449 void fGenerateMipmap(GLenum target) {
2450 BEFORE_GL_CALL;
2451 mSymbols.fGenerateMipmap(target);
2452 AFTER_GL_CALL;
2455 void fGetProgramiv(GLuint program, GLenum pname, GLint* param) {
2456 BEFORE_GL_CALL;
2457 mSymbols.fGetProgramiv(program, pname, param);
2458 AFTER_GL_CALL;
2461 void fGetProgramInfoLog(GLuint program, GLsizei bufSize, GLsizei* length, GLchar* infoLog) {
2462 BEFORE_GL_CALL;
2463 mSymbols.fGetProgramInfoLog(program, bufSize, length, infoLog);
2464 AFTER_GL_CALL;
2467 void fTexParameteri(GLenum target, GLenum pname, GLint param) {
2468 BEFORE_GL_CALL;
2469 mSymbols.fTexParameteri(target, pname, param);
2470 AFTER_GL_CALL;
2473 void fTexParameterf(GLenum target, GLenum pname, GLfloat param) {
2474 BEFORE_GL_CALL;
2475 mSymbols.fTexParameterf(target, pname, param);
2476 AFTER_GL_CALL;
2479 const GLubyte* fGetString(GLenum name) {
2480 BEFORE_GL_CALL;
2481 const GLubyte *result = mSymbols.fGetString(name);
2482 AFTER_GL_CALL;
2483 return result;
2486 void fGetTexImage(GLenum target, GLint level, GLenum format, GLenum type, GLvoid *img) {
2487 if (!mSymbols.fGetTexImage) {
2488 return;
2490 BEFORE_GL_CALL;
2491 mSymbols.fGetTexImage(target, level, format, type, img);
2492 AFTER_GL_CALL;
2495 void fGetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint *params)
2497 if (!mSymbols.fGetTexLevelParameteriv) {
2498 *params = 0;
2499 return;
2501 BEFORE_GL_CALL;
2502 mSymbols.fGetTexLevelParameteriv(target, level, pname, params);
2503 AFTER_GL_CALL;
2506 void fGetTexParameterfv(GLenum target, GLenum pname, const GLfloat *params) {
2507 BEFORE_GL_CALL;
2508 mSymbols.fGetTexParameterfv(target, pname, params);
2509 AFTER_GL_CALL;
2512 void fGetTexParameteriv(GLenum target, GLenum pname, const GLint *params) {
2513 BEFORE_GL_CALL;
2514 mSymbols.fGetTexParameteriv(target, pname, params);
2515 AFTER_GL_CALL;
2518 void fGetUniformfv(GLuint program, GLint location, GLfloat* params) {
2519 BEFORE_GL_CALL;
2520 mSymbols.fGetUniformfv(program, location, params);
2521 AFTER_GL_CALL;
2524 void fGetUniformiv(GLuint program, GLint location, GLint* params) {
2525 BEFORE_GL_CALL;
2526 mSymbols.fGetUniformiv(program, location, params);
2527 AFTER_GL_CALL;
2530 GLint fGetUniformLocation (GLint programObj, const GLchar* name) {
2531 BEFORE_GL_CALL;
2532 GLint retval = mSymbols.fGetUniformLocation(programObj, name);
2533 AFTER_GL_CALL;
2534 return retval;
2537 void fGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* retval) {
2538 BEFORE_GL_CALL;
2539 mSymbols.fGetVertexAttribfv(index, pname, retval);
2540 AFTER_GL_CALL;
2543 void fGetVertexAttribiv(GLuint index, GLenum pname, GLint* retval) {
2544 BEFORE_GL_CALL;
2545 mSymbols.fGetVertexAttribiv(index, pname, retval);
2546 AFTER_GL_CALL;
2549 void fGetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** retval) {
2550 BEFORE_GL_CALL;
2551 mSymbols.fGetVertexAttribPointerv(index, pname, retval);
2552 AFTER_GL_CALL;
2555 void fHint(GLenum target, GLenum mode) {
2556 BEFORE_GL_CALL;
2557 mSymbols.fHint(target, mode);
2558 AFTER_GL_CALL;
2561 realGLboolean fIsBuffer(GLuint buffer) {
2562 BEFORE_GL_CALL;
2563 realGLboolean retval = mSymbols.fIsBuffer(buffer);
2564 AFTER_GL_CALL;
2565 return retval;
2568 realGLboolean fIsEnabled (GLenum capability) {
2569 BEFORE_GL_CALL;
2570 realGLboolean retval = mSymbols.fIsEnabled(capability);
2571 AFTER_GL_CALL;
2572 return retval;
2575 realGLboolean fIsProgram (GLuint program) {
2576 BEFORE_GL_CALL;
2577 realGLboolean retval = mSymbols.fIsProgram(program);
2578 AFTER_GL_CALL;
2579 return retval;
2582 realGLboolean fIsShader (GLuint shader) {
2583 BEFORE_GL_CALL;
2584 realGLboolean retval = mSymbols.fIsShader(shader);
2585 AFTER_GL_CALL;
2586 return retval;
2589 realGLboolean fIsTexture (GLuint texture) {
2590 BEFORE_GL_CALL;
2591 realGLboolean retval = mSymbols.fIsTexture(texture);
2592 AFTER_GL_CALL;
2593 return retval;
2596 void fLineWidth(GLfloat width) {
2597 BEFORE_GL_CALL;
2598 mSymbols.fLineWidth(width);
2599 AFTER_GL_CALL;
2602 void fLinkProgram(GLuint program) {
2603 BEFORE_GL_CALL;
2604 mSymbols.fLinkProgram(program);
2605 AFTER_GL_CALL;
2608 void fPixelStorei(GLenum pname, GLint param) {
2609 BEFORE_GL_CALL;
2610 mSymbols.fPixelStorei(pname, param);
2611 AFTER_GL_CALL;
2614 void fPointParameterf(GLenum pname, GLfloat param) {
2615 BEFORE_GL_CALL;
2616 mSymbols.fPointParameterf(pname, param);
2617 AFTER_GL_CALL;
2620 void fPolygonOffset(GLfloat factor, GLfloat bias) {
2621 BEFORE_GL_CALL;
2622 mSymbols.fPolygonOffset(factor, bias);
2623 AFTER_GL_CALL;
2626 void fReadBuffer(GLenum mode) {
2627 BEFORE_GL_CALL;
2628 mSymbols.fReadBuffer(mode);
2629 AFTER_GL_CALL;
2632 void raw_fReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels) {
2633 BEFORE_GL_CALL;
2634 mSymbols.fReadPixels(x, FixYValue(y, height), width, height, format, type, pixels);
2635 AFTER_GL_CALL;
2638 void fSampleCoverage(GLclampf value, realGLboolean invert) {
2639 BEFORE_GL_CALL;
2640 mSymbols.fSampleCoverage(value, invert);
2641 AFTER_GL_CALL;
2644 void fStencilFunc(GLenum func, GLint ref, GLuint mask) {
2645 BEFORE_GL_CALL;
2646 mSymbols.fStencilFunc(func, ref, mask);
2647 AFTER_GL_CALL;
2650 void fStencilFuncSeparate(GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask) {
2651 BEFORE_GL_CALL;
2652 mSymbols.fStencilFuncSeparate(frontfunc, backfunc, ref, mask);
2653 AFTER_GL_CALL;
2656 void fStencilMask(GLuint mask) {
2657 BEFORE_GL_CALL;
2658 mSymbols.fStencilMask(mask);
2659 AFTER_GL_CALL;
2662 void fStencilMaskSeparate(GLenum face, GLuint mask) {
2663 BEFORE_GL_CALL;
2664 mSymbols.fStencilMaskSeparate(face, mask);
2665 AFTER_GL_CALL;
2668 void fStencilOp(GLenum fail, GLenum zfail, GLenum zpass) {
2669 BEFORE_GL_CALL;
2670 mSymbols.fStencilOp(fail, zfail, zpass);
2671 AFTER_GL_CALL;
2674 void fStencilOpSeparate(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass) {
2675 BEFORE_GL_CALL;
2676 mSymbols.fStencilOpSeparate(face, sfail, dpfail, dppass);
2677 AFTER_GL_CALL;
2680 void fTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels) {
2681 BEFORE_GL_CALL;
2682 if (IsTextureSizeSafeToPassToDriver(target, width, height)) {
2683 mSymbols.fTexImage2D(target, level, internalformat, width, height, border, format, type, pixels);
2684 } else {
2685 // pass wrong values to cause the GL to generate GL_INVALID_VALUE.
2686 // See bug 737182 and the comment in IsTextureSizeSafeToPassToDriver.
2687 mSymbols.fTexImage2D(target, -1, internalformat, -1, -1, -1, format, type, nullptr);
2689 AFTER_GL_CALL;
2692 void fTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels) {
2693 BEFORE_GL_CALL;
2694 mSymbols.fTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
2695 AFTER_GL_CALL;
2698 void fUniform1f(GLint location, GLfloat v0) {
2699 BEFORE_GL_CALL;
2700 mSymbols.fUniform1f(location, v0);
2701 AFTER_GL_CALL;
2704 void fUniform1fv(GLint location, GLsizei count, const GLfloat* value) {
2705 BEFORE_GL_CALL;
2706 mSymbols.fUniform1fv(location, count, value);
2707 AFTER_GL_CALL;
2710 void fUniform1i(GLint location, GLint v0) {
2711 BEFORE_GL_CALL;
2712 mSymbols.fUniform1i(location, v0);
2713 AFTER_GL_CALL;
2716 void fUniform1iv(GLint location, GLsizei count, const GLint* value) {
2717 BEFORE_GL_CALL;
2718 mSymbols.fUniform1iv(location, count, value);
2719 AFTER_GL_CALL;
2722 void fUniform2f(GLint location, GLfloat v0, GLfloat v1) {
2723 BEFORE_GL_CALL;
2724 mSymbols.fUniform2f(location, v0, v1);
2725 AFTER_GL_CALL;
2728 void fUniform2fv(GLint location, GLsizei count, const GLfloat* value) {
2729 BEFORE_GL_CALL;
2730 mSymbols.fUniform2fv(location, count, value);
2731 AFTER_GL_CALL;
2734 void fUniform2i(GLint location, GLint v0, GLint v1) {
2735 BEFORE_GL_CALL;
2736 mSymbols.fUniform2i(location, v0, v1);
2737 AFTER_GL_CALL;
2740 void fUniform2iv(GLint location, GLsizei count, const GLint* value) {
2741 BEFORE_GL_CALL;
2742 mSymbols.fUniform2iv(location, count, value);
2743 AFTER_GL_CALL;
2746 void fUniform3f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2) {
2747 BEFORE_GL_CALL;
2748 mSymbols.fUniform3f(location, v0, v1, v2);
2749 AFTER_GL_CALL;
2752 void fUniform3fv(GLint location, GLsizei count, const GLfloat* value) {
2753 BEFORE_GL_CALL;
2754 mSymbols.fUniform3fv(location, count, value);
2755 AFTER_GL_CALL;
2758 void fUniform3i(GLint location, GLint v0, GLint v1, GLint v2) {
2759 BEFORE_GL_CALL;
2760 mSymbols.fUniform3i(location, v0, v1, v2);
2761 AFTER_GL_CALL;
2764 void fUniform3iv(GLint location, GLsizei count, const GLint* value) {
2765 BEFORE_GL_CALL;
2766 mSymbols.fUniform3iv(location, count, value);
2767 AFTER_GL_CALL;
2770 void fUniform4f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
2771 BEFORE_GL_CALL;
2772 mSymbols.fUniform4f(location, v0, v1, v2, v3);
2773 AFTER_GL_CALL;
2776 void fUniform4fv(GLint location, GLsizei count, const GLfloat* value) {
2777 BEFORE_GL_CALL;
2778 mSymbols.fUniform4fv(location, count, value);
2779 AFTER_GL_CALL;
2782 void fUniform4i(GLint location, GLint v0, GLint v1, GLint v2, GLint v3) {
2783 BEFORE_GL_CALL;
2784 mSymbols.fUniform4i(location, v0, v1, v2, v3);
2785 AFTER_GL_CALL;
2788 void fUniform4iv(GLint location, GLsizei count, const GLint* value) {
2789 BEFORE_GL_CALL;
2790 mSymbols.fUniform4iv(location, count, value);
2791 AFTER_GL_CALL;
2794 void fUniformMatrix2fv(GLint location, GLsizei count, realGLboolean transpose, const GLfloat* value) {
2795 BEFORE_GL_CALL;
2796 mSymbols.fUniformMatrix2fv(location, count, transpose, value);
2797 AFTER_GL_CALL;
2800 void fUniformMatrix3fv(GLint location, GLsizei count, realGLboolean transpose, const GLfloat* value) {
2801 BEFORE_GL_CALL;
2802 mSymbols.fUniformMatrix3fv(location, count, transpose, value);
2803 AFTER_GL_CALL;
2806 void fUniformMatrix4fv(GLint location, GLsizei count, realGLboolean transpose, const GLfloat* value) {
2807 BEFORE_GL_CALL;
2808 mSymbols.fUniformMatrix4fv(location, count, transpose, value);
2809 AFTER_GL_CALL;
2812 void fUseProgram(GLuint program) {
2813 BEFORE_GL_CALL;
2814 mSymbols.fUseProgram(program);
2815 AFTER_GL_CALL;
2818 void fValidateProgram(GLuint program) {
2819 BEFORE_GL_CALL;
2820 mSymbols.fValidateProgram(program);
2821 AFTER_GL_CALL;
2824 void fVertexAttribPointer(GLuint index, GLint size, GLenum type, realGLboolean normalized, GLsizei stride, const GLvoid* pointer) {
2825 BEFORE_GL_CALL;
2826 mSymbols.fVertexAttribPointer(index, size, type, normalized, stride, pointer);
2827 AFTER_GL_CALL;
2830 void fVertexAttrib1f(GLuint index, GLfloat x) {
2831 BEFORE_GL_CALL;
2832 mSymbols.fVertexAttrib1f(index, x);
2833 AFTER_GL_CALL;
2836 void fVertexAttrib2f(GLuint index, GLfloat x, GLfloat y) {
2837 BEFORE_GL_CALL;
2838 mSymbols.fVertexAttrib2f(index, x, y);
2839 AFTER_GL_CALL;
2842 void fVertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z) {
2843 BEFORE_GL_CALL;
2844 mSymbols.fVertexAttrib3f(index, x, y, z);
2845 AFTER_GL_CALL;
2848 void fVertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) {
2849 BEFORE_GL_CALL;
2850 mSymbols.fVertexAttrib4f(index, x, y, z, w);
2851 AFTER_GL_CALL;
2854 void fVertexAttrib1fv(GLuint index, const GLfloat* v) {
2855 BEFORE_GL_CALL;
2856 mSymbols.fVertexAttrib1fv(index, v);
2857 AFTER_GL_CALL;
2860 void fVertexAttrib2fv(GLuint index, const GLfloat* v) {
2861 BEFORE_GL_CALL;
2862 mSymbols.fVertexAttrib2fv(index, v);
2863 AFTER_GL_CALL;
2866 void fVertexAttrib3fv(GLuint index, const GLfloat* v) {
2867 BEFORE_GL_CALL;
2868 mSymbols.fVertexAttrib3fv(index, v);
2869 AFTER_GL_CALL;
2872 void fVertexAttrib4fv(GLuint index, const GLfloat* v) {
2873 BEFORE_GL_CALL;
2874 mSymbols.fVertexAttrib4fv(index, v);
2875 AFTER_GL_CALL;
2878 void fCompileShader(GLuint shader) {
2879 BEFORE_GL_CALL;
2880 mSymbols.fCompileShader(shader);
2881 AFTER_GL_CALL;
2884 void raw_fCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) {
2885 BEFORE_GL_CALL;
2886 if (IsTextureSizeSafeToPassToDriver(target, width, height)) {
2887 mSymbols.fCopyTexImage2D(target, level, internalformat,
2888 x, FixYValue(y, height),
2889 width, height, border);
2891 } else {
2892 // pass wrong values to cause the GL to generate GL_INVALID_VALUE.
2893 // See bug 737182 and the comment in IsTextureSizeSafeToPassToDriver.
2894 mSymbols.fCopyTexImage2D(target, -1, internalformat,
2895 x, FixYValue(y, height),
2896 -1, -1, -1);
2899 AFTER_GL_CALL;
2902 void raw_fCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) {
2903 BEFORE_GL_CALL;
2904 mSymbols.fCopyTexSubImage2D(target, level, xoffset, yoffset,
2905 x, FixYValue(y, height),
2906 width, height);
2907 AFTER_GL_CALL;
2910 void fGetShaderiv(GLuint shader, GLenum pname, GLint* param) {
2911 BEFORE_GL_CALL;
2912 mSymbols.fGetShaderiv(shader, pname, param);
2913 AFTER_GL_CALL;
2916 void fGetShaderInfoLog(GLuint shader, GLsizei bufSize, GLsizei* length, GLchar* infoLog) {
2917 BEFORE_GL_CALL;
2918 mSymbols.fGetShaderInfoLog(shader, bufSize, length, infoLog);
2919 AFTER_GL_CALL;
2922 void fGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) {
2923 BEFORE_GL_CALL;
2924 if (mIsGLES2) {
2925 mSymbols.fGetShaderPrecisionFormat(shadertype, precisiontype, range, precision);
2926 } else {
2927 // Fall back to automatic values because almost all desktop hardware supports the OpenGL standard precisions.
2928 GetShaderPrecisionFormatNonES2(shadertype, precisiontype, range, precision);
2930 AFTER_GL_CALL;
2933 void fGetShaderSource(GLint obj, GLsizei maxLength, GLsizei* length, GLchar* source) {
2934 BEFORE_GL_CALL;
2935 mSymbols.fGetShaderSource(obj, maxLength, length, source);
2936 AFTER_GL_CALL;
2939 void fShaderSource(GLuint shader, GLsizei count, const GLchar** strings, const GLint* lengths) {
2940 BEFORE_GL_CALL;
2941 mSymbols.fShaderSource(shader, count, strings, lengths);
2942 AFTER_GL_CALL;
2945 private:
2946 void raw_fBindFramebuffer(GLenum target, GLuint framebuffer) {
2947 BEFORE_GL_CALL;
2948 mSymbols.fBindFramebuffer(target, framebuffer);
2949 AFTER_GL_CALL;
2952 public:
2953 void fBindRenderbuffer(GLenum target, GLuint renderbuffer) {
2954 BEFORE_GL_CALL;
2955 mSymbols.fBindRenderbuffer(target, renderbuffer);
2956 AFTER_GL_CALL;
2959 GLenum fCheckFramebufferStatus (GLenum target) {
2960 BEFORE_GL_CALL;
2961 GLenum retval = mSymbols.fCheckFramebufferStatus(target);
2962 AFTER_GL_CALL;
2963 return retval;
2966 void fFramebufferRenderbuffer(GLenum target, GLenum attachmentPoint, GLenum renderbufferTarget, GLuint renderbuffer) {
2967 BEFORE_GL_CALL;
2968 mSymbols.fFramebufferRenderbuffer(target, attachmentPoint, renderbufferTarget, renderbuffer);
2969 AFTER_GL_CALL;
2972 void fFramebufferTexture2D(GLenum target, GLenum attachmentPoint, GLenum textureTarget, GLuint texture, GLint level) {
2973 BEFORE_GL_CALL;
2974 mSymbols.fFramebufferTexture2D(target, attachmentPoint, textureTarget, texture, level);
2975 AFTER_GL_CALL;
2978 void fGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* value) {
2979 BEFORE_GL_CALL;
2980 mSymbols.fGetFramebufferAttachmentParameteriv(target, attachment, pname, value);
2981 AFTER_GL_CALL;
2984 void fGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* value) {
2985 BEFORE_GL_CALL;
2986 mSymbols.fGetRenderbufferParameteriv(target, pname, value);
2987 AFTER_GL_CALL;
2990 realGLboolean fIsFramebuffer (GLuint framebuffer) {
2991 BEFORE_GL_CALL;
2992 realGLboolean retval = mSymbols.fIsFramebuffer(framebuffer);
2993 AFTER_GL_CALL;
2994 return retval;
2997 void raw_fBlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) {
2998 BEFORE_GL_CALL;
2999 mSymbols.fBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
3000 AFTER_GL_CALL;
3003 realGLboolean fIsRenderbuffer (GLuint renderbuffer) {
3004 BEFORE_GL_CALL;
3005 realGLboolean retval = mSymbols.fIsRenderbuffer(renderbuffer);
3006 AFTER_GL_CALL;
3007 return retval;
3010 void fRenderbufferStorage(GLenum target, GLenum internalFormat, GLsizei width, GLsizei height) {
3011 BEFORE_GL_CALL;
3012 mSymbols.fRenderbufferStorage(target, internalFormat, width, height);
3013 AFTER_GL_CALL;
3016 void fRenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height) {
3017 BEFORE_GL_CALL;
3018 mSymbols.fRenderbufferStorageMultisample(target, samples, internalFormat, width, height);
3019 AFTER_GL_CALL;
3022 void fDepthRange(GLclampf a, GLclampf b) {
3023 BEFORE_GL_CALL;
3024 if (mIsGLES2) {
3025 mSymbols.fDepthRangef(a, b);
3026 } else {
3027 mSymbols.fDepthRange(a, b);
3029 AFTER_GL_CALL;
3032 void fClearDepth(GLclampf v) {
3033 BEFORE_GL_CALL;
3034 if (mIsGLES2) {
3035 mSymbols.fClearDepthf(v);
3036 } else {
3037 mSymbols.fClearDepth(v);
3039 AFTER_GL_CALL;
3042 void* fMapBuffer(GLenum target, GLenum access) {
3043 BEFORE_GL_CALL;
3044 void *ret = mSymbols.fMapBuffer(target, access);
3045 AFTER_GL_CALL;
3046 return ret;
3049 realGLboolean fUnmapBuffer(GLenum target) {
3050 BEFORE_GL_CALL;
3051 realGLboolean ret = mSymbols.fUnmapBuffer(target);
3052 AFTER_GL_CALL;
3053 return ret;
3057 #ifdef DEBUG
3058 GLContext *TrackingContext() {
3059 GLContext *tip = this;
3060 while (tip->mSharedContext)
3061 tip = tip->mSharedContext;
3062 return tip;
3065 #define TRACKING_CONTEXT(a) do { TrackingContext()->a; } while (0)
3066 #else
3067 #define TRACKING_CONTEXT(a) do {} while (0)
3068 #endif
3070 GLuint GLAPIENTRY fCreateProgram() {
3071 BEFORE_GL_CALL;
3072 GLuint ret = mSymbols.fCreateProgram();
3073 AFTER_GL_CALL;
3074 TRACKING_CONTEXT(CreatedProgram(this, ret));
3075 return ret;
3078 GLuint GLAPIENTRY fCreateShader(GLenum t) {
3079 BEFORE_GL_CALL;
3080 GLuint ret = mSymbols.fCreateShader(t);
3081 AFTER_GL_CALL;
3082 TRACKING_CONTEXT(CreatedShader(this, ret));
3083 return ret;
3086 void GLAPIENTRY fGenBuffers(GLsizei n, GLuint* names) {
3087 BEFORE_GL_CALL;
3088 mSymbols.fGenBuffers(n, names);
3089 AFTER_GL_CALL;
3090 TRACKING_CONTEXT(CreatedBuffers(this, n, names));
3093 void GLAPIENTRY fGenTextures(GLsizei n, GLuint* names) {
3094 BEFORE_GL_CALL;
3095 mSymbols.fGenTextures(n, names);
3096 AFTER_GL_CALL;
3097 TRACKING_CONTEXT(CreatedTextures(this, n, names));
3100 void GLAPIENTRY fGenFramebuffers(GLsizei n, GLuint* names) {
3101 BEFORE_GL_CALL;
3102 mSymbols.fGenFramebuffers(n, names);
3103 AFTER_GL_CALL;
3104 TRACKING_CONTEXT(CreatedFramebuffers(this, n, names));
3107 void GLAPIENTRY fGenRenderbuffers(GLsizei n, GLuint* names) {
3108 BEFORE_GL_CALL;
3109 mSymbols.fGenRenderbuffers(n, names);
3110 AFTER_GL_CALL;
3111 TRACKING_CONTEXT(CreatedRenderbuffers(this, n, names));
3114 void GLAPIENTRY fDeleteProgram(GLuint program) {
3115 BEFORE_GL_CALL;
3116 mSymbols.fDeleteProgram(program);
3117 AFTER_GL_CALL;
3118 TRACKING_CONTEXT(DeletedProgram(this, program));
3121 void GLAPIENTRY fDeleteShader(GLuint shader) {
3122 BEFORE_GL_CALL;
3123 mSymbols.fDeleteShader(shader);
3124 AFTER_GL_CALL;
3125 TRACKING_CONTEXT(DeletedShader(this, shader));
3128 void GLAPIENTRY fDeleteBuffers(GLsizei n, GLuint *names) {
3129 BEFORE_GL_CALL;
3130 mSymbols.fDeleteBuffers(n, names);
3131 AFTER_GL_CALL;
3132 TRACKING_CONTEXT(DeletedBuffers(this, n, names));
3135 void GLAPIENTRY fDeleteTextures(GLsizei n, GLuint *names) {
3136 BEFORE_GL_CALL;
3137 mSymbols.fDeleteTextures(n, names);
3138 AFTER_GL_CALL;
3139 TRACKING_CONTEXT(DeletedTextures(this, n, names));
3142 void GLAPIENTRY fDeleteFramebuffers(GLsizei n, GLuint *names) {
3143 BEFORE_GL_CALL;
3144 if (n == 1 && *names == 0) {
3145 /* Deleting framebuffer 0 causes hangs on the DROID. See bug 623228 */
3146 } else {
3147 mSymbols.fDeleteFramebuffers(n, names);
3149 AFTER_GL_CALL;
3150 TRACKING_CONTEXT(DeletedFramebuffers(this, n, names));
3153 void GLAPIENTRY fDeleteRenderbuffers(GLsizei n, GLuint *names) {
3154 BEFORE_GL_CALL;
3155 mSymbols.fDeleteRenderbuffers(n, names);
3156 AFTER_GL_CALL;
3157 TRACKING_CONTEXT(DeletedRenderbuffers(this, n, names));
3160 GLenum GLAPIENTRY fGetGraphicsResetStatus() {
3161 BEFORE_GL_CALL;
3162 GLenum ret = mHasRobustness ? mSymbols.fGetGraphicsResetStatus() : 0;
3163 AFTER_GL_CALL;
3164 return ret;
3167 GLsync GLAPIENTRY fFenceSync(GLenum condition, GLbitfield flags) {
3168 BEFORE_GL_CALL;
3169 GLsync ret = mSymbols.fFenceSync(condition, flags);
3170 AFTER_GL_CALL;
3171 return ret;
3174 realGLboolean GLAPIENTRY fIsSync(GLsync sync) {
3175 BEFORE_GL_CALL;
3176 realGLboolean ret = mSymbols.fIsSync(sync);
3177 AFTER_GL_CALL;
3178 return ret;
3181 void GLAPIENTRY fDeleteSync(GLsync sync) {
3182 BEFORE_GL_CALL;
3183 mSymbols.fDeleteSync(sync);
3184 AFTER_GL_CALL;
3187 GLenum GLAPIENTRY fClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout) {
3188 BEFORE_GL_CALL;
3189 GLenum ret = mSymbols.fClientWaitSync(sync, flags, timeout);
3190 AFTER_GL_CALL;
3191 return ret;
3194 void GLAPIENTRY fWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout) {
3195 BEFORE_GL_CALL;
3196 mSymbols.fWaitSync(sync, flags, timeout);
3197 AFTER_GL_CALL;
3200 void GLAPIENTRY fGetInteger64v(GLenum pname, GLint64 *params) {
3201 BEFORE_GL_CALL;
3202 mSymbols.fGetInteger64v(pname, params);
3203 AFTER_GL_CALL;
3206 void GLAPIENTRY fGetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values) {
3207 BEFORE_GL_CALL;
3208 mSymbols.fGetSynciv(sync, pname, bufSize, length, values);
3209 AFTER_GL_CALL;
3212 // OES_EGL_image (GLES)
3213 void fEGLImageTargetTexture2D(GLenum target, GLeglImage image)
3215 BEFORE_GL_CALL;
3216 mSymbols.fEGLImageTargetTexture2D(target, image);
3217 AFTER_GL_CALL;
3220 #ifdef DEBUG
3221 void THEBES_API CreatedProgram(GLContext *aOrigin, GLuint aName);
3222 void THEBES_API CreatedShader(GLContext *aOrigin, GLuint aName);
3223 void THEBES_API CreatedBuffers(GLContext *aOrigin, GLsizei aCount, GLuint *aNames);
3224 void THEBES_API CreatedTextures(GLContext *aOrigin, GLsizei aCount, GLuint *aNames);
3225 void THEBES_API CreatedFramebuffers(GLContext *aOrigin, GLsizei aCount, GLuint *aNames);
3226 void THEBES_API CreatedRenderbuffers(GLContext *aOrigin, GLsizei aCount, GLuint *aNames);
3227 void THEBES_API DeletedProgram(GLContext *aOrigin, GLuint aName);
3228 void THEBES_API DeletedShader(GLContext *aOrigin, GLuint aName);
3229 void THEBES_API DeletedBuffers(GLContext *aOrigin, GLsizei aCount, GLuint *aNames);
3230 void THEBES_API DeletedTextures(GLContext *aOrigin, GLsizei aCount, GLuint *aNames);
3231 void THEBES_API DeletedFramebuffers(GLContext *aOrigin, GLsizei aCount, GLuint *aNames);
3232 void THEBES_API DeletedRenderbuffers(GLContext *aOrigin, GLsizei aCount, GLuint *aNames);
3234 void SharedContextDestroyed(GLContext *aChild);
3235 void ReportOutstandingNames();
3237 struct NamedResource {
3238 NamedResource()
3239 : origin(nullptr), name(0), originDeleted(false)
3242 NamedResource(GLContext *aOrigin, GLuint aName)
3243 : origin(aOrigin), name(aName), originDeleted(false)
3246 GLContext *origin;
3247 GLuint name;
3248 bool originDeleted;
3250 // for sorting
3251 bool operator<(const NamedResource& aOther) const {
3252 if (intptr_t(origin) < intptr_t(aOther.origin))
3253 return true;
3254 if (name < aOther.name)
3255 return true;
3256 return false;
3258 bool operator==(const NamedResource& aOther) const {
3259 return origin == aOther.origin &&
3260 name == aOther.name &&
3261 originDeleted == aOther.originDeleted;
3265 nsTArray<NamedResource> mTrackedPrograms;
3266 nsTArray<NamedResource> mTrackedShaders;
3267 nsTArray<NamedResource> mTrackedTextures;
3268 nsTArray<NamedResource> mTrackedFramebuffers;
3269 nsTArray<NamedResource> mTrackedRenderbuffers;
3270 nsTArray<NamedResource> mTrackedBuffers;
3271 #endif
3275 inline bool
3276 DoesStringMatch(const char* aString, const char *aWantedString)
3278 if (!aString || !aWantedString)
3279 return false;
3281 const char *occurrence = strstr(aString, aWantedString);
3283 // aWanted not found
3284 if (!occurrence)
3285 return false;
3287 // aWantedString preceded by alpha character
3288 if (occurrence != aString && isalpha(*(occurrence-1)))
3289 return false;
3291 // aWantedVendor followed by alpha character
3292 const char *afterOccurrence = occurrence + strlen(aWantedString);
3293 if (isalpha(*afterOccurrence))
3294 return false;
3296 return true;
3299 //RAII via CRTP!
3300 template <class Derived>
3301 struct ScopedGLWrapper
3303 private:
3304 bool mIsUnwrapped;
3306 protected:
3307 GLContext* const mGL;
3309 ScopedGLWrapper(GLContext* gl)
3310 : mIsUnwrapped(false)
3311 , mGL(gl)
3313 MOZ_ASSERT(&ScopedGLWrapper<Derived>::Unwrap == &Derived::Unwrap);
3314 MOZ_ASSERT(&Derived::UnwrapImpl);
3315 MOZ_ASSERT(mGL->IsCurrent());
3318 virtual ~ScopedGLWrapper() {
3319 if (!mIsUnwrapped)
3320 Unwrap();
3323 public:
3324 void Unwrap() {
3325 MOZ_ASSERT(!mIsUnwrapped);
3327 Derived* derived = static_cast<Derived*>(this);
3328 derived->UnwrapImpl();
3330 mIsUnwrapped = true;
3334 struct ScopedFramebufferTexture
3335 : public ScopedGLWrapper<ScopedFramebufferTexture>
3337 friend struct ScopedGLWrapper<ScopedFramebufferTexture>;
3339 protected:
3340 bool mComplete; // True if the framebuffer we create is complete.
3341 GLuint mFB;
3343 public:
3344 ScopedFramebufferTexture(GLContext* gl, GLuint texture)
3345 : ScopedGLWrapper<ScopedFramebufferTexture>(gl)
3346 , mComplete(false)
3347 , mFB(0)
3349 MOZ_ASSERT(mGL->IsCurrent());
3350 GLuint boundFB = mGL->GetUserBoundFBO();
3352 mGL->fGenFramebuffers(1, &mFB);
3353 mGL->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mFB);
3354 mGL->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER,
3355 LOCAL_GL_COLOR_ATTACHMENT0,
3356 LOCAL_GL_TEXTURE_2D,
3357 texture,
3360 GLenum status = mGL->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
3361 if (status == LOCAL_GL_FRAMEBUFFER_COMPLETE) {
3362 mComplete = true;
3363 } else {
3364 mGL->fDeleteFramebuffers(1, &mFB);
3365 mFB = 0;
3368 mGL->BindUserFBO(boundFB);
3371 protected:
3372 void UnwrapImpl() {
3373 if (!mFB)
3374 return;
3376 MOZ_ASSERT(mGL->IsCurrent());
3377 mGL->fDeleteFramebuffers(1, &mFB);
3378 mFB = 0;
3381 public:
3382 GLuint FB() const {
3383 return mFB;
3386 bool IsComplete() const {
3387 return mComplete;
3391 // Wraps glEnable/Disable.
3392 struct ScopedGLState
3393 : public ScopedGLWrapper<ScopedGLState>
3395 friend struct ScopedGLWrapper<ScopedGLState>;
3397 protected:
3398 const GLenum mCapability;
3399 bool mOldState;
3401 public:
3402 // Use |newState = true| to enable, |false| to disable.
3403 ScopedGLState(GLContext* gl, GLenum capability, bool newState)
3404 : ScopedGLWrapper<ScopedGLState>(gl)
3405 , mCapability(capability)
3407 MOZ_ASSERT(mGL->IsCurrent());
3408 mOldState = mGL->fIsEnabled(mCapability);
3410 // Early out if we're already in the right state.
3411 if (newState == mOldState)
3412 return;
3414 if (newState)
3415 mGL->fEnable(mCapability);
3416 else
3417 mGL->fDisable(mCapability);
3420 protected:
3421 void UnwrapImpl() {
3422 MOZ_ASSERT(mGL->IsCurrent());
3424 if (mOldState)
3425 mGL->fEnable(mCapability);
3426 else
3427 mGL->fDisable(mCapability);
3431 // Saves and restores with GetUserBoundFBO and BindUserFBO.
3432 struct ScopedFramebufferBinding
3433 : public ScopedGLWrapper<ScopedFramebufferBinding>
3435 friend struct ScopedGLWrapper<ScopedFramebufferBinding>;
3437 protected:
3438 GLuint mOldState;
3440 private:
3441 void Init() {
3442 MOZ_ASSERT(mGL->IsCurrent());
3443 mOldState = mGL->GetUserBoundFBO();
3446 public:
3447 ScopedFramebufferBinding(GLContext* gl)
3448 : ScopedGLWrapper<ScopedFramebufferBinding>(gl)
3450 Init();
3453 ScopedFramebufferBinding(GLContext* gl, GLuint newFB)
3454 : ScopedGLWrapper<ScopedFramebufferBinding>(gl)
3456 Init();
3457 mGL->BindUserFBO(newFB);
3460 protected:
3461 void UnwrapImpl() {
3462 MOZ_ASSERT(mGL->IsCurrent());
3463 mGL->BindUserFBO(mOldState);
3467 } /* namespace gl */
3468 } /* namespace mozilla */
3470 #endif /* GLCONTEXT_H_ */