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/. */
21 #include "GLLibraryLoader.h"
22 #include "gfxASurface.h"
23 #include "gfxImageSurface.h"
24 #include "gfxContext.h"
26 #include "gfx3DMatrix.h"
27 #include "nsISupportsImpl.h"
30 #include "nsDataHashtable.h"
31 #include "nsHashKeys.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"
49 class LayerManagerOGL
;
50 class ColorTextureLayerProgram
;
56 typedef uintptr_t SharedTextureHandle
;
58 enum ShaderProgramType
{
60 RGBALayerExternalProgramType
,
64 RGBARectLayerProgramType
,
65 RGBAExternalLayerProgramType
,
66 ColorLayerProgramType
,
67 YCbCrLayerProgramType
,
68 ComponentAlphaPass1ProgramType
,
69 ComponentAlphaPass2ProgramType
,
71 Copy2DRectProgramType
,
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
82 * Implementation note: TextureImages attempt to unify two categories
85 * (1) proxy to server-side object that can be bound to a texture;
88 * (2) efficient manager of texture memory; e.g. by having clients draw
89 * into a scratch buffer which is then uploaded with
94 NS_INLINE_DECL_REFCOUNTING(TextureImage
)
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.
105 UseNearestFilter
= 0x1,
107 ForceSingleTile
= 0x4
110 enum TextureShareType
{
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
154 * BeginUpdate() must have been called exactly once before
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() {
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
,
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() {
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
) {
202 nsIntRegion
r(nsIntRect(0, 0, aSize
.width
, aSize
.height
));
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
);
228 class ScopedBindTexture
231 ScopedBindTexture(TextureImage
*aTexture
, GLenum aTextureUnit
) :
235 mTexture
->BindTexture(aTextureUnit
);
242 mTexture
->ReleaseTexture();
247 TextureImage
*mTexture
;
250 class ScopedBindTextureAndApplyFilter
251 : public ScopedBindTexture
254 ScopedBindTextureAndApplyFilter(TextureImage
*aTexture
, GLenum aTextureUnit
) :
255 ScopedBindTexture(aTexture
, aTextureUnit
)
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()
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()
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;
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
)
308 , mWrapMode(aWrapMode
)
309 , mContentType(aContentType
)
310 , mFilter(gfxPattern::FILTER_GOOD
)
314 virtual nsIntRect
GetSrcTileRect() {
315 return nsIntRect(nsIntPoint(0,0), mSize
);
320 ContentType mContentType
;
321 ShaderProgramType mShaderType
;
322 gfxPattern::GraphicsFilter mFilter
;
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
335 class BasicTextureImage
336 : public TextureImage
339 typedef gfxASurface::gfxImageFormat ImageFormat
;
340 virtual ~BasicTextureImage();
342 BasicTextureImage(GLuint aTexture
,
343 const nsIntSize
& aSize
,
345 ContentType aContentType
,
347 TextureImage::Flags aFlags
= TextureImage::NoFlags
)
348 : TextureImage(aSize
, aWrapMode
, aContentType
, aFlags
)
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();
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
402 TiledTextureImage(GLContext
* aGL
, nsIntSize aSize
,
403 TextureImage::ContentType
, TextureImage::Flags aFlags
= TextureImage::NoFlags
);
404 ~TiledTextureImage();
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();
425 virtual nsIntRect
GetSrcTileRect();
427 unsigned int mCurrentImage
;
428 TileIterationCallback mIterationCallback
;
429 void* mIterationCallbackData
;
430 nsTArray
< nsRefPtr
<TextureImage
> > mImages
;
433 unsigned int mTileSize
;
434 unsigned int mRows
, mColumns
;
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
{
458 memset(this, 0, sizeof(ContextFormat
));
461 ContextFormat(const StandardContextFormat cf
) {
462 memset(this, 0, sizeof(ContextFormat
));
465 red
= green
= blue
= alpha
= 8;
466 minRed
= minGreen
= minBlue
= minAlpha
= 1;
469 case StrictBasicRGBA32
:
470 red
= green
= blue
= alpha
= 8;
471 minRed
= minGreen
= minBlue
= minAlpha
= 8;
475 red
= green
= blue
= 8;
476 minRed
= minGreen
= minBlue
= 1;
479 case StrictBasicRGB24
:
480 red
= green
= blue
= 8;
481 minRed
= minGreen
= minBlue
= 8;
484 case StrictBasicRGB16_565
:
486 green
= minGreen
= 6;
496 int stencil
, minStencil
;
503 int colorBits() const { return red
+ green
+ blue
; }
507 : public GLLibraryLoader
509 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GLContext
)
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),
518 mTexBlit_UseDrawNotCopy(false),
519 mUserBoundDrawFBO(0),
520 mUserBoundReadFBO(0),
521 mInternalBoundDrawFBO(0),
522 mInternalBoundReadFBO(0),
524 mInInternalBindingMode_DrawFBO(true),
525 mInInternalBindingMode_ReadFBO(true),
527 mOffscreenFBOsDirty(false),
529 mIsOffscreen(aIsOffscreen
),
531 mIsGlobalSharedContext(false),
532 mHasRobustness(false),
536 mCreationFormat(aFormat
),
537 mSharedContext(aSharedContext
),
538 mOffscreenTexture(0),
542 mOffscreenDrawFBO(0),
543 mOffscreenReadFBO(0),
544 mOffscreenColorRB(0),
545 mOffscreenDepthRB(0),
546 mOffscreenStencilRB(0),
548 mMaxCubeMapTextureSize(0),
549 mMaxTextureImageSize(0),
550 mMaxRenderbufferSize(0),
551 mWorkAroundDriverBugs(true)
553 , mGLError(LOCAL_GL_NO_ERROR
)
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!");
565 if (mSharedContext
) {
566 GLContext
*tip
= mSharedContext
;
567 while (tip
->mSharedContext
)
568 tip
= tip
->mSharedContext
;
569 tip
->SharedContextDestroyed(this);
570 tip
->ReportOutstandingNames();
572 ReportOutstandingNames();
578 ContextFlagsNone
= 0x0,
579 ContextFlagsGlobal
= 0x1,
580 ContextFlagsMesaLLVMPipe
= 0x2
591 virtual GLContextType
GetContextType() { return ContextTypeUnknown
; }
593 virtual bool MakeCurrentImpl(bool aForce
= false) = 0;
596 static void StaticInit() {
597 PR_NewThreadPrivateIndex(&sCurrentGLContextTLS
, NULL
);
601 bool MakeCurrent(bool aForce
= false) {
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.
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!");
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
);
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();
644 // MarkDestroyed will mark all these as null.
645 return mSymbols
.fUseProgram
== nullptr;
648 enum NativeDataType
{
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
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
696 bool IsGLES2() const {
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
711 virtual bool IsANGLE() {
716 * The derived class is expected to provide information on whether or not it
717 * supports robustness.
719 virtual bool SupportsRobustness() = 0;
742 int Renderer() const {
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
)
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
804 virtual bool BindOffscreenNeedsTexture(GLContext
*aOffscreen
) {
805 return aOffscreen
->mOffscreenTexture
== 0;
808 virtual bool BindTex2DOffscreen(GLContext
*aOffscreen
) {
809 if (aOffscreen
->GetContextType() != GetContextType()) {
813 if (!aOffscreen
->mSharedContext
||
814 aOffscreen
->mSharedContext
!= mSharedContext
)
819 if (!aOffscreen
->mOffscreenTexture
) {
823 fBindTexture(LOCAL_GL_TEXTURE_2D
, aOffscreen
->mOffscreenTexture
);
828 virtual void UnbindTex2DOffscreen(GLContext
*aOffscreen
) { }
834 // Before reads from offscreen texture
835 void GuaranteeResolve() {
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();
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);
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
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
{
924 #ifdef MOZ_WIDGET_ANDROID
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
,
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
) { }
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; }
993 GLuint mUserBoundDrawFBO
;
994 GLuint mUserBoundReadFBO
;
995 GLuint mInternalBoundDrawFBO
;
996 GLuint mInternalBoundReadFBO
;
999 void fBindFramebuffer(GLenum target
, GLuint framebuffer
) {
1001 case LOCAL_GL_DRAW_FRAMEBUFFER_EXT
:
1002 mUserBoundDrawFBO
= framebuffer
;
1004 if (framebuffer
== 0) {
1005 mInternalBoundDrawFBO
= mOffscreenDrawFBO
;
1007 mInternalBoundDrawFBO
= mUserBoundDrawFBO
;
1010 raw_fBindFramebuffer(LOCAL_GL_DRAW_FRAMEBUFFER_EXT
,
1011 mInternalBoundDrawFBO
);
1014 case LOCAL_GL_READ_FRAMEBUFFER_EXT
:
1015 mUserBoundReadFBO
= framebuffer
;
1017 if (framebuffer
== 0) {
1018 mInternalBoundReadFBO
= mOffscreenReadFBO
;
1020 mInternalBoundReadFBO
= mUserBoundReadFBO
;
1023 raw_fBindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER_EXT
,
1024 mInternalBoundReadFBO
);
1027 case LOCAL_GL_FRAMEBUFFER
:
1028 mUserBoundDrawFBO
= mUserBoundReadFBO
= framebuffer
;
1030 if (framebuffer
== 0) {
1031 mInternalBoundDrawFBO
= mOffscreenDrawFBO
;
1032 mInternalBoundReadFBO
= mOffscreenReadFBO
;
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
);
1044 raw_fBindFramebuffer(LOCAL_GL_FRAMEBUFFER
,
1045 mInternalBoundDrawFBO
);
1051 raw_fBindFramebuffer(target
, framebuffer
);
1056 void fGetIntegerv(GLenum pname
, GLint
*params
) {
1059 // LOCAL_GL_FRAMEBUFFER_BINDING is equal to
1060 // LOCAL_GL_DRAW_FRAMEBUFFER_BINDING_EXT, so we don't need two
1062 case LOCAL_GL_FRAMEBUFFER_BINDING
:
1063 *params
= GetUserBoundDrawFBO();
1066 case LOCAL_GL_READ_FRAMEBUFFER_BINDING_EXT
:
1067 *params
= GetUserBoundReadFBO();
1071 raw_fGetIntegerv(pname
, params
);
1077 // See comment near BindInternalDrawFBO()
1078 bool mInInternalBindingMode_DrawFBO
;
1079 bool mInInternalBindingMode_ReadFBO
;
1082 GLuint
GetUserBoundDrawFBO() {
1084 MOZ_ASSERT(IsCurrent());
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
);
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
);
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
);
1111 // We only ever expose the user's bound FBOs
1112 return mUserBoundDrawFBO
;
1115 GLuint
GetUserBoundReadFBO() {
1117 MOZ_ASSERT(IsCurrent());
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
);
1125 raw_fGetIntegerv(LOCAL_GL_FRAMEBUFFER_BINDING
, &ret
);
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
);
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
);
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
);
1153 fBindFramebuffer(LOCAL_GL_FRAMEBUFFER
, name
);
1155 mInInternalBindingMode_DrawFBO
= false;
1159 void BindUserReadFBO(GLuint name
) {
1160 if (SupportsOffscreenSplit())
1161 fBindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER_EXT
, name
);
1163 fBindFramebuffer(LOCAL_GL_FRAMEBUFFER
, name
);
1165 mInInternalBindingMode_ReadFBO
= false;
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
) {
1185 mInInternalBindingMode_DrawFBO
= true;
1187 if (SupportsOffscreenSplit())
1188 raw_fBindFramebuffer(LOCAL_GL_DRAW_FRAMEBUFFER_EXT
, name
);
1190 raw_fBindFramebuffer(LOCAL_GL_FRAMEBUFFER
, name
);
1192 mInternalBoundDrawFBO
= name
;
1195 void BindInternalReadFBO(GLuint name
) {
1197 mInInternalBindingMode_ReadFBO
= true;
1199 if (SupportsOffscreenSplit())
1200 raw_fBindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER_EXT
, name
);
1202 raw_fBindFramebuffer(LOCAL_GL_FRAMEBUFFER
, name
);
1204 mInternalBoundReadFBO
= name
;
1207 void BindInternalFBO(GLuint name
) {
1208 BindInternalDrawFBO(name
);
1209 BindInternalReadFBO(name
);
1212 void InitFramebuffers() {
1218 GLuint
SwapUserDrawFBO(GLuint name
) {
1219 GLuint prev
= GetUserBoundDrawFBO();
1220 BindUserDrawFBO(name
);
1224 GLuint
SwapUserReadFBO(GLuint name
) {
1225 GLuint prev
= GetUserBoundReadFBO();
1226 BindUserReadFBO(name
);
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
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
1255 // Do whatever setup is necessary to draw to our offscreen FBO, if it's
1257 void BeforeGLDrawCall() {
1258 if (mInternalBoundDrawFBO
!= mOffscreenDrawFBO
)
1261 if (mOffscreenDrawFBO
== mOffscreenReadFBO
)
1264 mOffscreenFBOsDirty
= true;
1267 // Do whatever tear-down is necessary after drawing to our offscreen FBO,
1269 void AfterGLDrawCall() {
1272 // Do whatever setup is necessary to read from our offscreen FBO, if it's
1274 void BeforeGLReadCall() {
1275 if (mInternalBoundReadFBO
!= mOffscreenReadFBO
)
1278 if (mOffscreenDrawFBO
== mOffscreenReadFBO
)
1281 // If we're not dirty, there's no need to blit
1282 if (!mOffscreenFBOsDirty
)
1285 const bool scissor
= fIsEnabled(LOCAL_GL_SCISSOR_TEST
);
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
,
1307 // Reset to emulated user binding, exiting internal mode
1308 BindUserDrawFBO(prevDraw
);
1309 BindUserReadFBO(prevRead
);
1312 fEnable(LOCAL_GL_SCISSOR_TEST
);
1314 mOffscreenFBOsDirty
= false;
1317 // Do whatever tear-down is necessary after reading from our offscreen FBO,
1319 void AfterGLReadCall() {
1324 void fClear(GLbitfield mask
) {
1330 void fDrawArrays(GLenum mode
, GLint first
, GLsizei count
) {
1332 raw_fDrawArrays(mode
, first
, count
);
1336 void fDrawElements(GLenum mode
, GLsizei count
, GLenum type
, const GLvoid
*indices
) {
1338 raw_fDrawElements(mode
, count
, type
, indices
);
1343 void fReadPixels(GLint x
, GLint y
, GLsizei width
, GLsizei height
, GLenum format
, GLenum type
, GLvoid
*pixels
) {
1345 raw_fReadPixels(x
, y
, width
, height
, format
, type
, pixels
);
1349 void fCopyTexImage2D(GLenum target
, GLint level
, GLenum internalformat
, GLint x
, GLint y
, GLsizei width
, GLsizei height
, GLint border
) {
1351 raw_fCopyTexImage2D(target
, level
, internalformat
,
1352 x
, y
, width
, height
, border
);
1356 void fCopyTexSubImage2D(GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLint x
, GLint y
, GLsizei width
, GLsizei height
) {
1358 raw_fCopyTexSubImage2D(target
, level
, xoffset
, yoffset
,
1359 x
, y
, width
, height
);
1363 void ForceDirtyFBOs() {
1364 GLuint draw
= SwapUserDrawFBO(0);
1367 // no-op; just pretend we did something
1370 BindUserDrawFBO(draw
);
1373 void BlitDirtyFBOs() {
1374 GLuint read
= SwapUserReadFBO(0);
1377 // no-op; we just want to make sure the Read FBO is updated if it needs to be
1380 BindUserReadFBO(read
);
1384 void fBlitFramebuffer(GLint srcX0
, GLint srcY0
, GLint srcX1
, GLint srcY1
, GLint dstX0
, GLint dstY0
, GLint dstX1
, GLint dstY1
, GLbitfield mask
, GLenum filter
) {
1387 raw_fBlitFramebuffer(srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
1392 #if defined(MOZ_X11) && defined(MOZ_EGL_XRENDER_COMPOSITE)
1393 virtual gfxASurface
* GetOffscreenPixmapSurface()
1398 virtual bool WaitNative() { return false; }
1401 virtual bool TextureImageSupportsGetBackingSurface() {
1405 virtual bool RenewSurface() { return false; }
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
1421 virtual already_AddRefed
<TextureImage
>
1422 CreateTextureImage(const nsIntSize
& aSize
,
1423 TextureImage::ContentType aContentType
,
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
1434 virtual already_AddRefed
<TextureImage
>
1435 TileGenFunc(const nsIntSize
& aSize
,
1436 TextureImage::ContentType aContentType
,
1437 TextureImage::Flags aFlags
= TextureImage::NoFlags
)
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
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
1489 * - framebuffer binding
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
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
,
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
{
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
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
;
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
1635 EXT_framebuffer_object
,
1636 ARB_framebuffer_object
,
1637 ARB_texture_rectangle
,
1639 EXT_texture_format_BGRA8888
,
1645 OES_packed_depth_stencil
,
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
,
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
,
1673 OES_EGL_image_external
,
1674 EXT_packed_depth_stencil
,
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
{
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
);
1709 printf_stderr("Extensions: %s\n", exts
);
1714 char* space
= strchr(cur
, ' ');
1721 for (int i
= 0; extList
[i
]; ++i
) {
1722 if (strcmp(cur
, extList
[i
]) == 0) {
1724 printf_stderr("Found extension %s\n", cur
);
1735 bool& operator[](size_t index
) {
1736 MOZ_ASSERT(index
< Size
, "out of range");
1737 return extensions
[index
];
1740 bool extensions
[Size
];
1744 ExtensionBitset
<Extensions_Max
> mAvailableExtensions
;
1748 * Context reset constants.
1749 * These are used to determine who is guilty when a context reset
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
;
1767 bool mIsGlobalSharedContext
;
1768 bool mHasRobustness
;
1776 DebugEnabled
= 1 << 0,
1777 DebugTrace
= 1 << 1,
1778 DebugAbortOnError
= 1 << 2
1781 static uint32_t sDebugMode
;
1783 static uint32_t DebugMode() {
1793 ContextFormat mCreationFormat
;
1794 nsRefPtr
<GLContext
> mSharedContext
;
1796 // The thread on which this context was created.
1797 nsCOMPtr
<nsIThread
> mOwningThread
;
1799 GLContextSymbols mSymbols
;
1802 // GLDebugMode will check that we don't send call
1803 // to a GLContext that isn't current on the current
1805 // Store the current context when binding to thread local
1806 // storage to support DebugMode on an arbitrary thread.
1807 static unsigned sCurrentGLContextTLS
;
1810 void UpdateActualFormat();
1811 ContextFormat mActualFormat
;
1813 gfxIntSize mOffscreenSize
;
1814 gfxIntSize mOffscreenActualSize
;
1815 GLuint mOffscreenTexture
;
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
))
1831 ContextFormat
format(mCreationFormat
);
1833 if (format
.samples
) {
1835 if (ResizeOffscreenFBOs(format
, aSize
, aNeedsReadBuffer
))
1838 NS_WARNING("ResizeOffscreenFBOs failed to resize an AA context! Falling back to no AA...");
1842 if (ResizeOffscreenFBOs(format
, aSize
, aNeedsReadBuffer
))
1845 NS_WARNING("ResizeOffscreenFBOs failed to resize non-AA context!");
1861 GLenum texColorType
;
1863 GLenum depthStencil
;
1869 enum ColorByteOrder
{
1874 GLFormats
ChooseGLFormats(ContextFormat
& aCF
, GLContext::ColorByteOrder aByteOrder
= GLContext::DefaultByteOrder
);
1875 void CreateTextureForOffscreen(const GLFormats
& aFormats
, const gfxIntSize
& aSize
,
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
,
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.
1900 bool WorkAroundDriverBugs() const { return mWorkAroundDriverBugs
; }
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
,
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 {
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
1956 return width
<= maxSize
&& height
<= maxSize
;
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();
1972 // clear all pending errors
1973 while(fGetError()) {}
1981 #ifndef MOZ_FUNCTION_NAME
1983 # define MOZ_FUNCTION_NAME __PRETTY_FUNCTION__
1984 # elif defined(_MSC_VER)
1985 # define MOZ_FUNCTION_NAME __FUNCTION__
1987 # define MOZ_FUNCTION_NAME __func__ // defined in C99, supported in various C++ compilers. Just raw function name.
1996 void BeforeGLCall(const char* glFunction
) {
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
);
2013 void AfterGLCall(const char* glFunction
) {
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
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",
2025 GLErrorToString(mGLError
),
2027 if (DebugMode() & DebugAbortOnError
)
2033 const char* GLErrorToString(GLenum 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";
2057 #define BEFORE_GL_CALL do { \
2058 BeforeGLCall(MOZ_FUNCTION_NAME); \
2061 #define AFTER_GL_CALL do { \
2062 AfterGLCall(MOZ_FUNCTION_NAME); \
2067 #define BEFORE_GL_CALL do { } while (0)
2068 #define AFTER_GL_CALL do { } while (0)
2072 /*** In GL debug mode, we completely override glGetError ***/
2074 GLenum
fGetError() {
2076 // debug mode ends up eating the error in AFTER_GL_CALL
2078 GLenum err
= mGLError
;
2079 mGLError
= LOCAL_GL_NO_ERROR
;
2084 return mSymbols
.fGetError();
2088 /*** Scissor functions ***/
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
) {
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
),
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!");
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 ***/
2149 // only does the glViewport call, no ViewportRect business
2150 void raw_fViewport(GLint x
, GLint y
, GLsizei width
, GLsizei height
) {
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
);
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!");
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
) {
2200 mSymbols
.fActiveTexture(texture
);
2204 void fAttachShader(GLuint program
, GLuint shader
) {
2206 mSymbols
.fAttachShader(program
, shader
);
2210 void fBindAttribLocation(GLuint program
, GLuint index
, const GLchar
* name
) {
2212 mSymbols
.fBindAttribLocation(program
, index
, name
);
2216 void fBindBuffer(GLenum target
, GLuint buffer
) {
2218 mSymbols
.fBindBuffer(target
, buffer
);
2222 void fBindTexture(GLenum target
, GLuint texture
) {
2224 mSymbols
.fBindTexture(target
, texture
);
2228 void fBlendColor(GLclampf red
, GLclampf green
, GLclampf blue
, GLclampf alpha
) {
2230 mSymbols
.fBlendColor(red
, green
, blue
, alpha
);
2234 void fBlendEquation(GLenum mode
) {
2236 mSymbols
.fBlendEquation(mode
);
2240 void fBlendEquationSeparate(GLenum modeRGB
, GLenum modeAlpha
) {
2242 mSymbols
.fBlendEquationSeparate(modeRGB
, modeAlpha
);
2246 void fBlendFunc(GLenum sfactor
, GLenum dfactor
) {
2248 mSymbols
.fBlendFunc(sfactor
, dfactor
);
2252 void fBlendFuncSeparate(GLenum sfactorRGB
, GLenum dfactorRGB
, GLenum sfactorAlpha
, GLenum dfactorAlpha
) {
2254 mSymbols
.fBlendFuncSeparate(sfactorRGB
, dfactorRGB
, sfactorAlpha
, dfactorAlpha
);
2258 void fBufferData(GLenum target
, GLsizeiptr size
, const GLvoid
* data
, GLenum usage
) {
2260 mSymbols
.fBufferData(target
, size
, data
, usage
);
2263 if (WorkAroundDriverBugs() &&
2265 Vendor() == VendorNVIDIA
)
2268 mSymbols
.fBufferSubData(target
, size
-1, 1, &c
);
2274 void fBufferSubData(GLenum target
, GLintptr offset
, GLsizeiptr size
, const GLvoid
* data
) {
2276 mSymbols
.fBufferSubData(target
, offset
, size
, data
);
2280 void raw_fClear(GLbitfield mask
) {
2282 mSymbols
.fClear(mask
);
2286 void fClearColor(GLclampf r
, GLclampf g
, GLclampf b
, GLclampf a
) {
2288 mSymbols
.fClearColor(r
, g
, b
, a
);
2292 void fClearStencil(GLint s
) {
2294 mSymbols
.fClearStencil(s
);
2298 void fColorMask(realGLboolean red
, realGLboolean green
, realGLboolean blue
, realGLboolean alpha
) {
2300 mSymbols
.fColorMask(red
, green
, blue
, alpha
);
2304 void fCompressedTexImage2D(GLenum target
, GLint level
, GLenum internalformat
, GLsizei width
, GLsizei height
, GLint border
, GLsizei imageSize
, const GLvoid
*pixels
) {
2306 mSymbols
.fCompressedTexImage2D(target
, level
, internalformat
, width
, height
, border
, imageSize
, pixels
);
2310 void fCompressedTexSubImage2D(GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLsizei width
, GLsizei height
, GLenum format
, GLsizei imageSize
, const GLvoid
*pixels
) {
2312 mSymbols
.fCompressedTexSubImage2D(target
, level
, xoffset
, yoffset
, width
, height
, format
, imageSize
, pixels
);
2316 void fCullFace(GLenum mode
) {
2318 mSymbols
.fCullFace(mode
);
2322 void fDetachShader(GLuint program
, GLuint shader
) {
2324 mSymbols
.fDetachShader(program
, shader
);
2328 void fDepthFunc(GLenum func
) {
2330 mSymbols
.fDepthFunc(func
);
2334 void fDepthMask(realGLboolean flag
) {
2336 mSymbols
.fDepthMask(flag
);
2340 void fDisable(GLenum capability
) {
2342 mSymbols
.fDisable(capability
);
2346 void fDisableVertexAttribArray(GLuint index
) {
2348 mSymbols
.fDisableVertexAttribArray(index
);
2352 void raw_fDrawArrays(GLenum mode
, GLint first
, GLsizei count
) {
2354 mSymbols
.fDrawArrays(mode
, first
, count
);
2358 void raw_fDrawElements(GLenum mode
, GLsizei count
, GLenum type
, const GLvoid
*indices
) {
2360 mSymbols
.fDrawElements(mode
, count
, type
, indices
);
2364 void fEnable(GLenum capability
) {
2366 mSymbols
.fEnable(capability
);
2370 void fEnableVertexAttribArray(GLuint index
) {
2372 mSymbols
.fEnableVertexAttribArray(index
);
2388 void fFrontFace(GLenum face
) {
2390 mSymbols
.fFrontFace(face
);
2394 void fGetActiveAttrib(GLuint program
, GLuint index
, GLsizei maxLength
, GLsizei
* length
, GLint
* size
, GLenum
* type
, GLchar
* name
) {
2396 mSymbols
.fGetActiveAttrib(program
, index
, maxLength
, length
, size
, type
, name
);
2400 void fGetActiveUniform(GLuint program
, GLuint index
, GLsizei maxLength
, GLsizei
* length
, GLint
* size
, GLenum
* type
, GLchar
* name
) {
2402 mSymbols
.fGetActiveUniform(program
, index
, maxLength
, length
, size
, type
, name
);
2406 void fGetAttachedShaders(GLuint program
, GLsizei maxCount
, GLsizei
* count
, GLuint
* shaders
) {
2408 mSymbols
.fGetAttachedShaders(program
, maxCount
, count
, shaders
);
2412 GLint
fGetAttribLocation (GLuint program
, const GLchar
* name
) {
2414 GLint retval
= mSymbols
.fGetAttribLocation(program
, name
);
2420 void raw_fGetIntegerv(GLenum pname
, GLint
*params
) {
2422 mSymbols
.fGetIntegerv(pname
, params
);
2427 void GetUIntegerv(GLenum pname
, GLuint
*params
) {
2428 fGetIntegerv(pname
, reinterpret_cast<GLint
*>(params
));
2431 void fGetFloatv(GLenum pname
, GLfloat
*params
) {
2433 mSymbols
.fGetFloatv(pname
, params
);
2437 void fGetBooleanv(GLenum pname
, realGLboolean
*params
) {
2439 mSymbols
.fGetBooleanv(pname
, params
);
2443 void fGetBufferParameteriv(GLenum target
, GLenum pname
, GLint
* params
) {
2445 mSymbols
.fGetBufferParameteriv(target
, pname
, params
);
2449 void fGenerateMipmap(GLenum target
) {
2451 mSymbols
.fGenerateMipmap(target
);
2455 void fGetProgramiv(GLuint program
, GLenum pname
, GLint
* param
) {
2457 mSymbols
.fGetProgramiv(program
, pname
, param
);
2461 void fGetProgramInfoLog(GLuint program
, GLsizei bufSize
, GLsizei
* length
, GLchar
* infoLog
) {
2463 mSymbols
.fGetProgramInfoLog(program
, bufSize
, length
, infoLog
);
2467 void fTexParameteri(GLenum target
, GLenum pname
, GLint param
) {
2469 mSymbols
.fTexParameteri(target
, pname
, param
);
2473 void fTexParameterf(GLenum target
, GLenum pname
, GLfloat param
) {
2475 mSymbols
.fTexParameterf(target
, pname
, param
);
2479 const GLubyte
* fGetString(GLenum name
) {
2481 const GLubyte
*result
= mSymbols
.fGetString(name
);
2486 void fGetTexImage(GLenum target
, GLint level
, GLenum format
, GLenum type
, GLvoid
*img
) {
2487 if (!mSymbols
.fGetTexImage
) {
2491 mSymbols
.fGetTexImage(target
, level
, format
, type
, img
);
2495 void fGetTexLevelParameteriv(GLenum target
, GLint level
, GLenum pname
, GLint
*params
)
2497 if (!mSymbols
.fGetTexLevelParameteriv
) {
2502 mSymbols
.fGetTexLevelParameteriv(target
, level
, pname
, params
);
2506 void fGetTexParameterfv(GLenum target
, GLenum pname
, const GLfloat
*params
) {
2508 mSymbols
.fGetTexParameterfv(target
, pname
, params
);
2512 void fGetTexParameteriv(GLenum target
, GLenum pname
, const GLint
*params
) {
2514 mSymbols
.fGetTexParameteriv(target
, pname
, params
);
2518 void fGetUniformfv(GLuint program
, GLint location
, GLfloat
* params
) {
2520 mSymbols
.fGetUniformfv(program
, location
, params
);
2524 void fGetUniformiv(GLuint program
, GLint location
, GLint
* params
) {
2526 mSymbols
.fGetUniformiv(program
, location
, params
);
2530 GLint
fGetUniformLocation (GLint programObj
, const GLchar
* name
) {
2532 GLint retval
= mSymbols
.fGetUniformLocation(programObj
, name
);
2537 void fGetVertexAttribfv(GLuint index
, GLenum pname
, GLfloat
* retval
) {
2539 mSymbols
.fGetVertexAttribfv(index
, pname
, retval
);
2543 void fGetVertexAttribiv(GLuint index
, GLenum pname
, GLint
* retval
) {
2545 mSymbols
.fGetVertexAttribiv(index
, pname
, retval
);
2549 void fGetVertexAttribPointerv(GLuint index
, GLenum pname
, GLvoid
** retval
) {
2551 mSymbols
.fGetVertexAttribPointerv(index
, pname
, retval
);
2555 void fHint(GLenum target
, GLenum mode
) {
2557 mSymbols
.fHint(target
, mode
);
2561 realGLboolean
fIsBuffer(GLuint buffer
) {
2563 realGLboolean retval
= mSymbols
.fIsBuffer(buffer
);
2568 realGLboolean
fIsEnabled (GLenum capability
) {
2570 realGLboolean retval
= mSymbols
.fIsEnabled(capability
);
2575 realGLboolean
fIsProgram (GLuint program
) {
2577 realGLboolean retval
= mSymbols
.fIsProgram(program
);
2582 realGLboolean
fIsShader (GLuint shader
) {
2584 realGLboolean retval
= mSymbols
.fIsShader(shader
);
2589 realGLboolean
fIsTexture (GLuint texture
) {
2591 realGLboolean retval
= mSymbols
.fIsTexture(texture
);
2596 void fLineWidth(GLfloat width
) {
2598 mSymbols
.fLineWidth(width
);
2602 void fLinkProgram(GLuint program
) {
2604 mSymbols
.fLinkProgram(program
);
2608 void fPixelStorei(GLenum pname
, GLint param
) {
2610 mSymbols
.fPixelStorei(pname
, param
);
2614 void fPointParameterf(GLenum pname
, GLfloat param
) {
2616 mSymbols
.fPointParameterf(pname
, param
);
2620 void fPolygonOffset(GLfloat factor
, GLfloat bias
) {
2622 mSymbols
.fPolygonOffset(factor
, bias
);
2626 void fReadBuffer(GLenum mode
) {
2628 mSymbols
.fReadBuffer(mode
);
2632 void raw_fReadPixels(GLint x
, GLint y
, GLsizei width
, GLsizei height
, GLenum format
, GLenum type
, GLvoid
*pixels
) {
2634 mSymbols
.fReadPixels(x
, FixYValue(y
, height
), width
, height
, format
, type
, pixels
);
2638 void fSampleCoverage(GLclampf value
, realGLboolean invert
) {
2640 mSymbols
.fSampleCoverage(value
, invert
);
2644 void fStencilFunc(GLenum func
, GLint ref
, GLuint mask
) {
2646 mSymbols
.fStencilFunc(func
, ref
, mask
);
2650 void fStencilFuncSeparate(GLenum frontfunc
, GLenum backfunc
, GLint ref
, GLuint mask
) {
2652 mSymbols
.fStencilFuncSeparate(frontfunc
, backfunc
, ref
, mask
);
2656 void fStencilMask(GLuint mask
) {
2658 mSymbols
.fStencilMask(mask
);
2662 void fStencilMaskSeparate(GLenum face
, GLuint mask
) {
2664 mSymbols
.fStencilMaskSeparate(face
, mask
);
2668 void fStencilOp(GLenum fail
, GLenum zfail
, GLenum zpass
) {
2670 mSymbols
.fStencilOp(fail
, zfail
, zpass
);
2674 void fStencilOpSeparate(GLenum face
, GLenum sfail
, GLenum dpfail
, GLenum dppass
) {
2676 mSymbols
.fStencilOpSeparate(face
, sfail
, dpfail
, dppass
);
2680 void fTexImage2D(GLenum target
, GLint level
, GLint internalformat
, GLsizei width
, GLsizei height
, GLint border
, GLenum format
, GLenum type
, const GLvoid
*pixels
) {
2682 if (IsTextureSizeSafeToPassToDriver(target
, width
, height
)) {
2683 mSymbols
.fTexImage2D(target
, level
, internalformat
, width
, height
, border
, format
, type
, pixels
);
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);
2692 void fTexSubImage2D(GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLsizei width
, GLsizei height
, GLenum format
, GLenum type
, const GLvoid
* pixels
) {
2694 mSymbols
.fTexSubImage2D(target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, pixels
);
2698 void fUniform1f(GLint location
, GLfloat v0
) {
2700 mSymbols
.fUniform1f(location
, v0
);
2704 void fUniform1fv(GLint location
, GLsizei count
, const GLfloat
* value
) {
2706 mSymbols
.fUniform1fv(location
, count
, value
);
2710 void fUniform1i(GLint location
, GLint v0
) {
2712 mSymbols
.fUniform1i(location
, v0
);
2716 void fUniform1iv(GLint location
, GLsizei count
, const GLint
* value
) {
2718 mSymbols
.fUniform1iv(location
, count
, value
);
2722 void fUniform2f(GLint location
, GLfloat v0
, GLfloat v1
) {
2724 mSymbols
.fUniform2f(location
, v0
, v1
);
2728 void fUniform2fv(GLint location
, GLsizei count
, const GLfloat
* value
) {
2730 mSymbols
.fUniform2fv(location
, count
, value
);
2734 void fUniform2i(GLint location
, GLint v0
, GLint v1
) {
2736 mSymbols
.fUniform2i(location
, v0
, v1
);
2740 void fUniform2iv(GLint location
, GLsizei count
, const GLint
* value
) {
2742 mSymbols
.fUniform2iv(location
, count
, value
);
2746 void fUniform3f(GLint location
, GLfloat v0
, GLfloat v1
, GLfloat v2
) {
2748 mSymbols
.fUniform3f(location
, v0
, v1
, v2
);
2752 void fUniform3fv(GLint location
, GLsizei count
, const GLfloat
* value
) {
2754 mSymbols
.fUniform3fv(location
, count
, value
);
2758 void fUniform3i(GLint location
, GLint v0
, GLint v1
, GLint v2
) {
2760 mSymbols
.fUniform3i(location
, v0
, v1
, v2
);
2764 void fUniform3iv(GLint location
, GLsizei count
, const GLint
* value
) {
2766 mSymbols
.fUniform3iv(location
, count
, value
);
2770 void fUniform4f(GLint location
, GLfloat v0
, GLfloat v1
, GLfloat v2
, GLfloat v3
) {
2772 mSymbols
.fUniform4f(location
, v0
, v1
, v2
, v3
);
2776 void fUniform4fv(GLint location
, GLsizei count
, const GLfloat
* value
) {
2778 mSymbols
.fUniform4fv(location
, count
, value
);
2782 void fUniform4i(GLint location
, GLint v0
, GLint v1
, GLint v2
, GLint v3
) {
2784 mSymbols
.fUniform4i(location
, v0
, v1
, v2
, v3
);
2788 void fUniform4iv(GLint location
, GLsizei count
, const GLint
* value
) {
2790 mSymbols
.fUniform4iv(location
, count
, value
);
2794 void fUniformMatrix2fv(GLint location
, GLsizei count
, realGLboolean transpose
, const GLfloat
* value
) {
2796 mSymbols
.fUniformMatrix2fv(location
, count
, transpose
, value
);
2800 void fUniformMatrix3fv(GLint location
, GLsizei count
, realGLboolean transpose
, const GLfloat
* value
) {
2802 mSymbols
.fUniformMatrix3fv(location
, count
, transpose
, value
);
2806 void fUniformMatrix4fv(GLint location
, GLsizei count
, realGLboolean transpose
, const GLfloat
* value
) {
2808 mSymbols
.fUniformMatrix4fv(location
, count
, transpose
, value
);
2812 void fUseProgram(GLuint program
) {
2814 mSymbols
.fUseProgram(program
);
2818 void fValidateProgram(GLuint program
) {
2820 mSymbols
.fValidateProgram(program
);
2824 void fVertexAttribPointer(GLuint index
, GLint size
, GLenum type
, realGLboolean normalized
, GLsizei stride
, const GLvoid
* pointer
) {
2826 mSymbols
.fVertexAttribPointer(index
, size
, type
, normalized
, stride
, pointer
);
2830 void fVertexAttrib1f(GLuint index
, GLfloat x
) {
2832 mSymbols
.fVertexAttrib1f(index
, x
);
2836 void fVertexAttrib2f(GLuint index
, GLfloat x
, GLfloat y
) {
2838 mSymbols
.fVertexAttrib2f(index
, x
, y
);
2842 void fVertexAttrib3f(GLuint index
, GLfloat x
, GLfloat y
, GLfloat z
) {
2844 mSymbols
.fVertexAttrib3f(index
, x
, y
, z
);
2848 void fVertexAttrib4f(GLuint index
, GLfloat x
, GLfloat y
, GLfloat z
, GLfloat w
) {
2850 mSymbols
.fVertexAttrib4f(index
, x
, y
, z
, w
);
2854 void fVertexAttrib1fv(GLuint index
, const GLfloat
* v
) {
2856 mSymbols
.fVertexAttrib1fv(index
, v
);
2860 void fVertexAttrib2fv(GLuint index
, const GLfloat
* v
) {
2862 mSymbols
.fVertexAttrib2fv(index
, v
);
2866 void fVertexAttrib3fv(GLuint index
, const GLfloat
* v
) {
2868 mSymbols
.fVertexAttrib3fv(index
, v
);
2872 void fVertexAttrib4fv(GLuint index
, const GLfloat
* v
) {
2874 mSymbols
.fVertexAttrib4fv(index
, v
);
2878 void fCompileShader(GLuint shader
) {
2880 mSymbols
.fCompileShader(shader
);
2884 void raw_fCopyTexImage2D(GLenum target
, GLint level
, GLenum internalformat
, GLint x
, GLint y
, GLsizei width
, GLsizei height
, GLint border
) {
2886 if (IsTextureSizeSafeToPassToDriver(target
, width
, height
)) {
2887 mSymbols
.fCopyTexImage2D(target
, level
, internalformat
,
2888 x
, FixYValue(y
, height
),
2889 width
, height
, border
);
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
),
2902 void raw_fCopyTexSubImage2D(GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLint x
, GLint y
, GLsizei width
, GLsizei height
) {
2904 mSymbols
.fCopyTexSubImage2D(target
, level
, xoffset
, yoffset
,
2905 x
, FixYValue(y
, height
),
2910 void fGetShaderiv(GLuint shader
, GLenum pname
, GLint
* param
) {
2912 mSymbols
.fGetShaderiv(shader
, pname
, param
);
2916 void fGetShaderInfoLog(GLuint shader
, GLsizei bufSize
, GLsizei
* length
, GLchar
* infoLog
) {
2918 mSymbols
.fGetShaderInfoLog(shader
, bufSize
, length
, infoLog
);
2922 void fGetShaderPrecisionFormat(GLenum shadertype
, GLenum precisiontype
, GLint
* range
, GLint
* precision
) {
2925 mSymbols
.fGetShaderPrecisionFormat(shadertype
, precisiontype
, range
, precision
);
2927 // Fall back to automatic values because almost all desktop hardware supports the OpenGL standard precisions.
2928 GetShaderPrecisionFormatNonES2(shadertype
, precisiontype
, range
, precision
);
2933 void fGetShaderSource(GLint obj
, GLsizei maxLength
, GLsizei
* length
, GLchar
* source
) {
2935 mSymbols
.fGetShaderSource(obj
, maxLength
, length
, source
);
2939 void fShaderSource(GLuint shader
, GLsizei count
, const GLchar
** strings
, const GLint
* lengths
) {
2941 mSymbols
.fShaderSource(shader
, count
, strings
, lengths
);
2946 void raw_fBindFramebuffer(GLenum target
, GLuint framebuffer
) {
2948 mSymbols
.fBindFramebuffer(target
, framebuffer
);
2953 void fBindRenderbuffer(GLenum target
, GLuint renderbuffer
) {
2955 mSymbols
.fBindRenderbuffer(target
, renderbuffer
);
2959 GLenum
fCheckFramebufferStatus (GLenum target
) {
2961 GLenum retval
= mSymbols
.fCheckFramebufferStatus(target
);
2966 void fFramebufferRenderbuffer(GLenum target
, GLenum attachmentPoint
, GLenum renderbufferTarget
, GLuint renderbuffer
) {
2968 mSymbols
.fFramebufferRenderbuffer(target
, attachmentPoint
, renderbufferTarget
, renderbuffer
);
2972 void fFramebufferTexture2D(GLenum target
, GLenum attachmentPoint
, GLenum textureTarget
, GLuint texture
, GLint level
) {
2974 mSymbols
.fFramebufferTexture2D(target
, attachmentPoint
, textureTarget
, texture
, level
);
2978 void fGetFramebufferAttachmentParameteriv(GLenum target
, GLenum attachment
, GLenum pname
, GLint
* value
) {
2980 mSymbols
.fGetFramebufferAttachmentParameteriv(target
, attachment
, pname
, value
);
2984 void fGetRenderbufferParameteriv(GLenum target
, GLenum pname
, GLint
* value
) {
2986 mSymbols
.fGetRenderbufferParameteriv(target
, pname
, value
);
2990 realGLboolean
fIsFramebuffer (GLuint framebuffer
) {
2992 realGLboolean retval
= mSymbols
.fIsFramebuffer(framebuffer
);
2997 void raw_fBlitFramebuffer(GLint srcX0
, GLint srcY0
, GLint srcX1
, GLint srcY1
, GLint dstX0
, GLint dstY0
, GLint dstX1
, GLint dstY1
, GLbitfield mask
, GLenum filter
) {
2999 mSymbols
.fBlitFramebuffer(srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
3003 realGLboolean
fIsRenderbuffer (GLuint renderbuffer
) {
3005 realGLboolean retval
= mSymbols
.fIsRenderbuffer(renderbuffer
);
3010 void fRenderbufferStorage(GLenum target
, GLenum internalFormat
, GLsizei width
, GLsizei height
) {
3012 mSymbols
.fRenderbufferStorage(target
, internalFormat
, width
, height
);
3016 void fRenderbufferStorageMultisample(GLenum target
, GLsizei samples
, GLenum internalFormat
, GLsizei width
, GLsizei height
) {
3018 mSymbols
.fRenderbufferStorageMultisample(target
, samples
, internalFormat
, width
, height
);
3022 void fDepthRange(GLclampf a
, GLclampf b
) {
3025 mSymbols
.fDepthRangef(a
, b
);
3027 mSymbols
.fDepthRange(a
, b
);
3032 void fClearDepth(GLclampf v
) {
3035 mSymbols
.fClearDepthf(v
);
3037 mSymbols
.fClearDepth(v
);
3042 void* fMapBuffer(GLenum target
, GLenum access
) {
3044 void *ret
= mSymbols
.fMapBuffer(target
, access
);
3049 realGLboolean
fUnmapBuffer(GLenum target
) {
3051 realGLboolean ret
= mSymbols
.fUnmapBuffer(target
);
3058 GLContext
*TrackingContext() {
3059 GLContext
*tip
= this;
3060 while (tip
->mSharedContext
)
3061 tip
= tip
->mSharedContext
;
3065 #define TRACKING_CONTEXT(a) do { TrackingContext()->a; } while (0)
3067 #define TRACKING_CONTEXT(a) do {} while (0)
3070 GLuint GLAPIENTRY
fCreateProgram() {
3072 GLuint ret
= mSymbols
.fCreateProgram();
3074 TRACKING_CONTEXT(CreatedProgram(this, ret
));
3078 GLuint GLAPIENTRY
fCreateShader(GLenum t
) {
3080 GLuint ret
= mSymbols
.fCreateShader(t
);
3082 TRACKING_CONTEXT(CreatedShader(this, ret
));
3086 void GLAPIENTRY
fGenBuffers(GLsizei n
, GLuint
* names
) {
3088 mSymbols
.fGenBuffers(n
, names
);
3090 TRACKING_CONTEXT(CreatedBuffers(this, n
, names
));
3093 void GLAPIENTRY
fGenTextures(GLsizei n
, GLuint
* names
) {
3095 mSymbols
.fGenTextures(n
, names
);
3097 TRACKING_CONTEXT(CreatedTextures(this, n
, names
));
3100 void GLAPIENTRY
fGenFramebuffers(GLsizei n
, GLuint
* names
) {
3102 mSymbols
.fGenFramebuffers(n
, names
);
3104 TRACKING_CONTEXT(CreatedFramebuffers(this, n
, names
));
3107 void GLAPIENTRY
fGenRenderbuffers(GLsizei n
, GLuint
* names
) {
3109 mSymbols
.fGenRenderbuffers(n
, names
);
3111 TRACKING_CONTEXT(CreatedRenderbuffers(this, n
, names
));
3114 void GLAPIENTRY
fDeleteProgram(GLuint program
) {
3116 mSymbols
.fDeleteProgram(program
);
3118 TRACKING_CONTEXT(DeletedProgram(this, program
));
3121 void GLAPIENTRY
fDeleteShader(GLuint shader
) {
3123 mSymbols
.fDeleteShader(shader
);
3125 TRACKING_CONTEXT(DeletedShader(this, shader
));
3128 void GLAPIENTRY
fDeleteBuffers(GLsizei n
, GLuint
*names
) {
3130 mSymbols
.fDeleteBuffers(n
, names
);
3132 TRACKING_CONTEXT(DeletedBuffers(this, n
, names
));
3135 void GLAPIENTRY
fDeleteTextures(GLsizei n
, GLuint
*names
) {
3137 mSymbols
.fDeleteTextures(n
, names
);
3139 TRACKING_CONTEXT(DeletedTextures(this, n
, names
));
3142 void GLAPIENTRY
fDeleteFramebuffers(GLsizei n
, GLuint
*names
) {
3144 if (n
== 1 && *names
== 0) {
3145 /* Deleting framebuffer 0 causes hangs on the DROID. See bug 623228 */
3147 mSymbols
.fDeleteFramebuffers(n
, names
);
3150 TRACKING_CONTEXT(DeletedFramebuffers(this, n
, names
));
3153 void GLAPIENTRY
fDeleteRenderbuffers(GLsizei n
, GLuint
*names
) {
3155 mSymbols
.fDeleteRenderbuffers(n
, names
);
3157 TRACKING_CONTEXT(DeletedRenderbuffers(this, n
, names
));
3160 GLenum GLAPIENTRY
fGetGraphicsResetStatus() {
3162 GLenum ret
= mHasRobustness
? mSymbols
.fGetGraphicsResetStatus() : 0;
3167 GLsync GLAPIENTRY
fFenceSync(GLenum condition
, GLbitfield flags
) {
3169 GLsync ret
= mSymbols
.fFenceSync(condition
, flags
);
3174 realGLboolean GLAPIENTRY
fIsSync(GLsync sync
) {
3176 realGLboolean ret
= mSymbols
.fIsSync(sync
);
3181 void GLAPIENTRY
fDeleteSync(GLsync sync
) {
3183 mSymbols
.fDeleteSync(sync
);
3187 GLenum GLAPIENTRY
fClientWaitSync(GLsync sync
, GLbitfield flags
, GLuint64 timeout
) {
3189 GLenum ret
= mSymbols
.fClientWaitSync(sync
, flags
, timeout
);
3194 void GLAPIENTRY
fWaitSync(GLsync sync
, GLbitfield flags
, GLuint64 timeout
) {
3196 mSymbols
.fWaitSync(sync
, flags
, timeout
);
3200 void GLAPIENTRY
fGetInteger64v(GLenum pname
, GLint64
*params
) {
3202 mSymbols
.fGetInteger64v(pname
, params
);
3206 void GLAPIENTRY
fGetSynciv(GLsync sync
, GLenum pname
, GLsizei bufSize
, GLsizei
*length
, GLint
*values
) {
3208 mSymbols
.fGetSynciv(sync
, pname
, bufSize
, length
, values
);
3212 // OES_EGL_image (GLES)
3213 void fEGLImageTargetTexture2D(GLenum target
, GLeglImage image
)
3216 mSymbols
.fEGLImageTargetTexture2D(target
, image
);
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
{
3239 : origin(nullptr), name(0), originDeleted(false)
3242 NamedResource(GLContext
*aOrigin
, GLuint aName
)
3243 : origin(aOrigin
), name(aName
), originDeleted(false)
3251 bool operator<(const NamedResource
& aOther
) const {
3252 if (intptr_t(origin
) < intptr_t(aOther
.origin
))
3254 if (name
< aOther
.name
)
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
;
3276 DoesStringMatch(const char* aString
, const char *aWantedString
)
3278 if (!aString
|| !aWantedString
)
3281 const char *occurrence
= strstr(aString
, aWantedString
);
3283 // aWanted not found
3287 // aWantedString preceded by alpha character
3288 if (occurrence
!= aString
&& isalpha(*(occurrence
-1)))
3291 // aWantedVendor followed by alpha character
3292 const char *afterOccurrence
= occurrence
+ strlen(aWantedString
);
3293 if (isalpha(*afterOccurrence
))
3300 template <class Derived
>
3301 struct ScopedGLWrapper
3307 GLContext
* const mGL
;
3309 ScopedGLWrapper(GLContext
* gl
)
3310 : mIsUnwrapped(false)
3313 MOZ_ASSERT(&ScopedGLWrapper
<Derived
>::Unwrap
== &Derived::Unwrap
);
3314 MOZ_ASSERT(&Derived::UnwrapImpl
);
3315 MOZ_ASSERT(mGL
->IsCurrent());
3318 virtual ~ScopedGLWrapper() {
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
>;
3340 bool mComplete
; // True if the framebuffer we create is complete.
3344 ScopedFramebufferTexture(GLContext
* gl
, GLuint texture
)
3345 : ScopedGLWrapper
<ScopedFramebufferTexture
>(gl
)
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
,
3360 GLenum status
= mGL
->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER
);
3361 if (status
== LOCAL_GL_FRAMEBUFFER_COMPLETE
) {
3364 mGL
->fDeleteFramebuffers(1, &mFB
);
3368 mGL
->BindUserFBO(boundFB
);
3376 MOZ_ASSERT(mGL
->IsCurrent());
3377 mGL
->fDeleteFramebuffers(1, &mFB
);
3386 bool IsComplete() const {
3391 // Wraps glEnable/Disable.
3392 struct ScopedGLState
3393 : public ScopedGLWrapper
<ScopedGLState
>
3395 friend struct ScopedGLWrapper
<ScopedGLState
>;
3398 const GLenum mCapability
;
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
)
3415 mGL
->fEnable(mCapability
);
3417 mGL
->fDisable(mCapability
);
3422 MOZ_ASSERT(mGL
->IsCurrent());
3425 mGL
->fEnable(mCapability
);
3427 mGL
->fDisable(mCapability
);
3431 // Saves and restores with GetUserBoundFBO and BindUserFBO.
3432 struct ScopedFramebufferBinding
3433 : public ScopedGLWrapper
<ScopedFramebufferBinding
>
3435 friend struct ScopedGLWrapper
<ScopedFramebufferBinding
>;
3442 MOZ_ASSERT(mGL
->IsCurrent());
3443 mOldState
= mGL
->GetUserBoundFBO();
3447 ScopedFramebufferBinding(GLContext
* gl
)
3448 : ScopedGLWrapper
<ScopedFramebufferBinding
>(gl
)
3453 ScopedFramebufferBinding(GLContext
* gl
, GLuint newFB
)
3454 : ScopedGLWrapper
<ScopedFramebufferBinding
>(gl
)
3457 mGL
->BindUserFBO(newFB
);
3462 MOZ_ASSERT(mGL
->IsCurrent());
3463 mGL
->BindUserFBO(mOldState
);
3467 } /* namespace gl */
3468 } /* namespace mozilla */
3470 #endif /* GLCONTEXT_H_ */