1 : /* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is mozilla.org code.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Mozilla Corporation.
19 : * Portions created by the Initial Developer are Copyright (C) 2010
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : * Vladimir Vukicevic <vladimir@pobox.com>
24 : * Mark Steele <mwsteele@gmail.com>
25 : * Bas Schouten <bschouten@mozilla.com>
26 : * Jeff Gilbert <jgilbert@mozilla.com>
27 : *
28 : * Alternatively, the contents of this file may be used under the terms of
29 : * either the GNU General Public License Version 2 or later (the "GPL"), or
30 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
31 : * in which case the provisions of the GPL or the LGPL are applicable instead
32 : * of those above. If you wish to allow use of your version of this file only
33 : * under the terms of either the GPL or the LGPL, and not to allow others to
34 : * use your version of this file under the terms of the MPL, indicate your
35 : * decision by deleting the provisions above and replace them with the notice
36 : * and other provisions required by the GPL or the LGPL. If you do not delete
37 : * the provisions above, a recipient may use your version of this file under
38 : * the terms of any one of the MPL, the GPL or the LGPL.
39 : *
40 : * ***** END LICENSE BLOCK ***** */
41 :
42 : #ifndef GLCONTEXT_H_
43 : #define GLCONTEXT_H_
44 :
45 : #include <stdio.h>
46 : #if defined(XP_UNIX)
47 : #include <stdint.h>
48 : #endif
49 : #include <string.h>
50 : #include <ctype.h>
51 :
52 : #ifdef WIN32
53 : #include <windows.h>
54 : #endif
55 :
56 : #include "GLDefs.h"
57 : #include "gfxASurface.h"
58 : #include "gfxImageSurface.h"
59 : #include "gfxContext.h"
60 : #include "gfxRect.h"
61 : #include "nsISupportsImpl.h"
62 : #include "prlink.h"
63 :
64 : #include "nsDataHashtable.h"
65 : #include "nsHashKeys.h"
66 : #include "nsRegion.h"
67 : #include "nsAutoPtr.h"
68 : #include "nsThreadUtils.h"
69 :
70 : #if defined(MOZ_PLATFORM_MAEMO) || defined(ANDROID) || defined(MOZ_EGL_XRENDER_COMPOSITE)
71 : #define USE_GLES2 1
72 : #endif
73 :
74 : typedef char realGLboolean;
75 :
76 : #include "GLContextSymbols.h"
77 :
78 : namespace mozilla {
79 : namespace layers {
80 : class LayerManagerOGL;
81 : class ColorTextureLayerProgram;
82 : }
83 :
84 : namespace gl {
85 : class GLContext;
86 :
87 : class LibrarySymbolLoader
88 : {
89 : public:
90 : bool OpenLibrary(const char *library);
91 :
92 : typedef PRFuncPtr (GLAPIENTRY * PlatformLookupFunction) (const char *);
93 :
94 : enum {
95 : MAX_SYMBOL_NAMES = 5,
96 : MAX_SYMBOL_LENGTH = 128
97 : };
98 :
99 : typedef struct {
100 : PRFuncPtr *symPointer;
101 : const char *symNames[MAX_SYMBOL_NAMES];
102 : } SymLoadStruct;
103 :
104 : bool LoadSymbols(SymLoadStruct *firstStruct,
105 : bool tryplatform = false,
106 : const char *prefix = nsnull);
107 :
108 : /*
109 : * Static version of the functions in this class
110 : */
111 : static PRFuncPtr LookupSymbol(PRLibrary *lib,
112 : const char *symname,
113 : PlatformLookupFunction lookupFunction = nsnull);
114 : static bool LoadSymbols(PRLibrary *lib,
115 : SymLoadStruct *firstStruct,
116 : PlatformLookupFunction lookupFunction = nsnull,
117 : const char *prefix = nsnull);
118 : protected:
119 0 : LibrarySymbolLoader() {
120 0 : mLibrary = nsnull;
121 0 : mLookupFunc = nsnull;
122 0 : }
123 :
124 : PRLibrary *mLibrary;
125 : PlatformLookupFunction mLookupFunc;
126 : };
127 :
128 : enum ShaderProgramType {
129 : RGBALayerProgramType,
130 : BGRALayerProgramType,
131 : RGBXLayerProgramType,
132 : BGRXLayerProgramType,
133 : RGBARectLayerProgramType,
134 : ColorLayerProgramType,
135 : YCbCrLayerProgramType,
136 : ComponentAlphaPass1ProgramType,
137 : ComponentAlphaPass2ProgramType,
138 : Copy2DProgramType,
139 : Copy2DRectProgramType,
140 : NumProgramTypes
141 : };
142 :
143 :
144 : /**
145 : * A TextureImage encapsulates a surface that can be drawn to by a
146 : * Thebes gfxContext and (hopefully efficiently!) synchronized to a
147 : * texture in the server. TextureImages are associated with one and
148 : * only one GLContext.
149 : *
150 : * Implementation note: TextureImages attempt to unify two categories
151 : * of backends
152 : *
153 : * (1) proxy to server-side object that can be bound to a texture;
154 : * e.g. Pixmap on X11.
155 : *
156 : * (2) efficient manager of texture memory; e.g. by having clients draw
157 : * into a scratch buffer which is then uploaded with
158 : * glTexSubImage2D().
159 : */
160 : class TextureImage
161 : {
162 0 : NS_INLINE_DECL_REFCOUNTING(TextureImage)
163 : public:
164 : enum TextureState
165 : {
166 : Created, // Texture created, but has not had glTexImage called to initialize it.
167 : Allocated, // Texture memory exists, but contents are invalid.
168 : Valid // Texture fully ready to use.
169 : };
170 :
171 : typedef gfxASurface::gfxContentType ContentType;
172 :
173 0 : virtual ~TextureImage() {}
174 :
175 : /**
176 : * Returns a gfxASurface for updating |aRegion| of the client's
177 : * image if successul, NULL if not. |aRegion|'s bounds must fit
178 : * within Size(); its coordinate space (if any) is ignored. If
179 : * the update begins successfully, the returned gfxASurface is
180 : * owned by this. Otherwise, NULL is returned.
181 : *
182 : * |aRegion| is an inout param: the returned region is what the
183 : * client must repaint. Category (1) regions above can
184 : * efficiently handle repaints to "scattered" regions, while (2)
185 : * can only efficiently handle repaints to rects.
186 : *
187 : * Painting the returned surface outside of |aRegion| results
188 : * in undefined behavior.
189 : *
190 : * BeginUpdate() calls cannot be "nested", and each successful
191 : * BeginUpdate() must be followed by exactly one EndUpdate() (see
192 : * below). Failure to do so can leave this in a possibly
193 : * inconsistent state. Unsuccessful BeginUpdate()s must not be
194 : * followed by EndUpdate().
195 : */
196 : virtual gfxASurface* BeginUpdate(nsIntRegion& aRegion) = 0;
197 : /**
198 : * Retrieves the region that will require updating, given a
199 : * region that needs to be updated. This can be used for
200 : * making decisions about updating before calling BeginUpdate().
201 : *
202 : * |aRegion| is an inout param.
203 : */
204 0 : virtual void GetUpdateRegion(nsIntRegion& aForRegion) {
205 0 : };
206 : /**
207 : * Finish the active update and synchronize with the server, if
208 : * necessary.
209 : *
210 : * BeginUpdate() must have been called exactly once before
211 : * EndUpdate().
212 : */
213 : virtual void EndUpdate() = 0;
214 :
215 : /**
216 : * The Image may contain several textures for different regions (tiles).
217 : * These functions iterate over each sub texture image tile.
218 : */
219 0 : virtual void BeginTileIteration() {
220 0 : };
221 :
222 0 : virtual bool NextTile() {
223 0 : return false;
224 : };
225 :
226 0 : virtual nsIntRect GetTileRect() {
227 0 : return nsIntRect(nsIntPoint(0,0), mSize);
228 : };
229 :
230 : virtual GLuint GetTextureID() = 0;
231 :
232 0 : virtual PRUint32 GetTileCount() {
233 0 : return 1;
234 : };
235 :
236 : /**
237 : * Set this TextureImage's size, and ensure a texture has been
238 : * allocated. Must not be called between BeginUpdate and EndUpdate.
239 : * After a resize, the contents are undefined.
240 : *
241 : * If this isn't implemented by a subclass, it will just perform
242 : * a dummy BeginUpdate/EndUpdate pair.
243 : */
244 0 : virtual void Resize(const nsIntSize& aSize) {
245 0 : mSize = aSize;
246 0 : nsIntRegion r(nsIntRect(0, 0, aSize.width, aSize.height));
247 0 : BeginUpdate(r);
248 0 : EndUpdate();
249 0 : }
250 :
251 : /**
252 : * Mark this texture as having valid contents. Call this after modifying
253 : * the texture contents externally.
254 : */
255 0 : virtual void MarkValid() {}
256 :
257 : /**
258 : * aSurf - the source surface to update from
259 : * aRegion - the region in this image to update
260 : * aFrom - offset in the source to update from
261 : */
262 : virtual bool DirectUpdate(gfxASurface *aSurf, const nsIntRegion& aRegion, const nsIntPoint& aFrom = nsIntPoint(0,0)) = 0;
263 :
264 : virtual void BindTexture(GLenum aTextureUnit) = 0;
265 0 : virtual void ReleaseTexture() {};
266 :
267 : void BindTextureAndApplyFilter(GLenum aTextureUnit) {
268 : BindTexture(aTextureUnit);
269 : ApplyFilter();
270 : }
271 :
272 : class ScopedBindTexture
273 : {
274 : public:
275 0 : ScopedBindTexture(TextureImage *aTexture, GLenum aTextureUnit) :
276 0 : mTexture(aTexture)
277 : {
278 0 : if (mTexture) {
279 0 : mTexture->BindTexture(aTextureUnit);
280 : }
281 0 : }
282 :
283 0 : ~ScopedBindTexture()
284 : {
285 0 : if (mTexture) {
286 0 : mTexture->ReleaseTexture();
287 : }
288 0 : }
289 :
290 : protected:
291 : TextureImage *mTexture;
292 : };
293 :
294 : class ScopedBindTextureAndApplyFilter
295 : : public ScopedBindTexture
296 : {
297 : public:
298 : ScopedBindTextureAndApplyFilter(TextureImage *aTexture, GLenum aTextureUnit) :
299 : ScopedBindTexture(aTexture, aTextureUnit)
300 : {
301 : if (mTexture) {
302 : mTexture->ApplyFilter();
303 : }
304 : }
305 : };
306 :
307 : /**
308 : * Returns the shader program type that should be used to render
309 : * this texture. Only valid after a matching BeginUpdate/EndUpdate
310 : * pair have been called.
311 : */
312 0 : virtual ShaderProgramType GetShaderProgramType()
313 : {
314 0 : return mShaderType;
315 : }
316 :
317 : /** Can be called safely at any time. */
318 :
319 : /**
320 : * If this TextureImage has a permanent gfxASurface backing,
321 : * return it. Otherwise return NULL.
322 : */
323 0 : virtual already_AddRefed<gfxASurface> GetBackingSurface()
324 0 : { return NULL; }
325 :
326 0 : const nsIntSize& GetSize() const { return mSize; }
327 0 : ContentType GetContentType() const { return mContentType; }
328 : virtual bool InUpdate() const = 0;
329 0 : GLenum GetWrapMode() const { return mWrapMode; }
330 :
331 : void SetFilter(gfxPattern::GraphicsFilter aFilter) { mFilter = aFilter; }
332 :
333 : /**
334 : * Applies this TextureImage's filter, assuming that its texture is
335 : * the currently bound texture.
336 : */
337 : virtual void ApplyFilter() = 0;
338 :
339 : protected:
340 : friend class GLContext;
341 :
342 : /**
343 : * After the ctor, the TextureImage is invalid. Implementations
344 : * must allocate resources successfully before returning the new
345 : * TextureImage from GLContext::CreateTextureImage(). That is,
346 : * clients must not be given partially-constructed TextureImages.
347 : */
348 0 : TextureImage(const nsIntSize& aSize,
349 : GLenum aWrapMode, ContentType aContentType,
350 : bool aIsRGB = false)
351 : : mSize(aSize)
352 : , mWrapMode(aWrapMode)
353 0 : , mContentType(aContentType)
354 0 : {}
355 :
356 : nsIntSize mSize;
357 : GLenum mWrapMode;
358 : ContentType mContentType;
359 : ShaderProgramType mShaderType;
360 : gfxPattern::GraphicsFilter mFilter;
361 : };
362 :
363 : /**
364 : * BasicTextureImage is the baseline TextureImage implementation ---
365 : * it updates its texture by allocating a scratch buffer for the
366 : * client to draw into, then using glTexSubImage2D() to upload the new
367 : * pixels. Platforms must provide the code to create a new surface
368 : * into which the updated pixels will be drawn, and the code to
369 : * convert the update surface's pixels into an image on which we can
370 : * glTexSubImage2D().
371 : */
372 : class BasicTextureImage
373 : : public TextureImage
374 : {
375 : public:
376 : typedef gfxASurface::gfxImageFormat ImageFormat;
377 : virtual ~BasicTextureImage();
378 :
379 0 : BasicTextureImage(GLuint aTexture,
380 : const nsIntSize& aSize,
381 : GLenum aWrapMode,
382 : ContentType aContentType,
383 : GLContext* aContext)
384 : : TextureImage(aSize, aWrapMode, aContentType)
385 : , mTexture(aTexture)
386 : , mTextureState(Created)
387 : , mGLContext(aContext)
388 0 : , mUpdateOffset(0, 0)
389 0 : {}
390 :
391 : virtual void BindTexture(GLenum aTextureUnit);
392 :
393 : virtual gfxASurface* BeginUpdate(nsIntRegion& aRegion);
394 : virtual void GetUpdateRegion(nsIntRegion& aForRegion);
395 : virtual void EndUpdate();
396 : virtual bool DirectUpdate(gfxASurface* aSurf, const nsIntRegion& aRegion, const nsIntPoint& aFrom = nsIntPoint(0,0));
397 0 : virtual GLuint GetTextureID() { return mTexture; };
398 : // Returns a surface to draw into
399 : virtual already_AddRefed<gfxASurface>
400 : GetSurfaceForUpdate(const gfxIntSize& aSize, ImageFormat aFmt);
401 :
402 0 : virtual void MarkValid() { mTextureState = Valid; }
403 :
404 : // Call when drawing into the update surface is complete.
405 : // Returns true if textures should be upload with a relative
406 : // offset - See UploadSurfaceToTexture.
407 : virtual bool FinishedSurfaceUpdate();
408 :
409 : // Call after surface data has been uploaded to a texture.
410 : virtual void FinishedSurfaceUpload();
411 :
412 0 : virtual bool InUpdate() const { return !!mUpdateSurface; }
413 :
414 : virtual void Resize(const nsIntSize& aSize);
415 :
416 : virtual void ApplyFilter();
417 : protected:
418 :
419 : GLuint mTexture;
420 : TextureState mTextureState;
421 : GLContext* mGLContext;
422 : nsRefPtr<gfxASurface> mUpdateSurface;
423 : nsIntRegion mUpdateRegion;
424 :
425 : // The offset into the update surface at which the update rect is located.
426 : nsIntPoint mUpdateOffset;
427 : };
428 :
429 : /**
430 : * A container class that complements many sub TextureImages into a big TextureImage.
431 : * Aims to behave just like the real thing.
432 : */
433 :
434 : class TiledTextureImage
435 : : public TextureImage
436 : {
437 : public:
438 : TiledTextureImage(GLContext* aGL, nsIntSize aSize,
439 : TextureImage::ContentType, bool aUseNearestFilter = false);
440 : ~TiledTextureImage();
441 : void DumpDiv();
442 : virtual gfxASurface* BeginUpdate(nsIntRegion& aRegion);
443 : virtual void GetUpdateRegion(nsIntRegion& aForRegion);
444 : virtual void EndUpdate();
445 : virtual void Resize(const nsIntSize& aSize);
446 : virtual PRUint32 GetTileCount();
447 : virtual void BeginTileIteration();
448 : virtual bool NextTile();
449 : virtual nsIntRect GetTileRect();
450 0 : virtual GLuint GetTextureID() {
451 0 : return mImages[mCurrentImage]->GetTextureID();
452 : };
453 : virtual bool DirectUpdate(gfxASurface* aSurf, const nsIntRegion& aRegion, const nsIntPoint& aFrom = nsIntPoint(0,0));
454 0 : virtual bool InUpdate() const { return mInUpdate; };
455 : virtual void BindTexture(GLenum);
456 : virtual void ApplyFilter();
457 : protected:
458 : unsigned int mCurrentImage;
459 : nsTArray< nsRefPtr<TextureImage> > mImages;
460 : bool mInUpdate;
461 : nsIntSize mSize;
462 : unsigned int mTileSize;
463 : unsigned int mRows, mColumns;
464 : GLContext* mGL;
465 : bool mUseNearestFilter;
466 : // A temporary surface to faciliate cross-tile updates.
467 : nsRefPtr<gfxASurface> mUpdateSurface;
468 : // The region of update requested
469 : nsIntRegion mUpdateRegion;
470 : TextureState mTextureState;
471 : };
472 :
473 : struct THEBES_API ContextFormat
474 : {
475 : static const ContextFormat BasicRGBA32Format;
476 :
477 : enum StandardContextFormat {
478 : Empty,
479 : BasicRGBA32,
480 : StrictBasicRGBA32,
481 : BasicRGB24,
482 : StrictBasicRGB24,
483 : BasicRGB16_565,
484 : StrictBasicRGB16_565
485 : };
486 :
487 0 : ContextFormat() {
488 0 : memset(this, 0, sizeof(ContextFormat));
489 0 : }
490 :
491 0 : ContextFormat(const StandardContextFormat cf) {
492 0 : memset(this, 0, sizeof(ContextFormat));
493 0 : switch (cf) {
494 : case BasicRGBA32:
495 0 : red = green = blue = alpha = 8;
496 0 : minRed = minGreen = minBlue = minAlpha = 1;
497 0 : break;
498 :
499 : case StrictBasicRGBA32:
500 0 : red = green = blue = alpha = 8;
501 0 : minRed = minGreen = minBlue = minAlpha = 8;
502 0 : break;
503 :
504 : case BasicRGB24:
505 0 : red = green = blue = 8;
506 0 : minRed = minGreen = minBlue = 1;
507 0 : break;
508 :
509 : case StrictBasicRGB24:
510 0 : red = green = blue = 8;
511 0 : minRed = minGreen = minBlue = 8;
512 0 : break;
513 :
514 : case StrictBasicRGB16_565:
515 0 : red = minRed = 5;
516 0 : green = minGreen = 6;
517 0 : blue = minBlue = 5;
518 0 : break;
519 :
520 : default:
521 0 : break;
522 : }
523 0 : }
524 :
525 : int depth, minDepth;
526 : int stencil, minStencil;
527 : int red, minRed;
528 : int green, minGreen;
529 : int blue, minBlue;
530 : int alpha, minAlpha;
531 : int samples;
532 :
533 : int colorBits() const { return red + green + blue; }
534 : };
535 :
536 : class GLContext
537 : : public LibrarySymbolLoader
538 : {
539 0 : NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GLContext)
540 : public:
541 0 : GLContext(const ContextFormat& aFormat,
542 : bool aIsOffscreen = false,
543 : GLContext *aSharedContext = nsnull)
544 : : mFlushGuaranteesResolve(false),
545 : mUserBoundDrawFBO(0),
546 : mUserBoundReadFBO(0),
547 : mInternalBoundDrawFBO(0),
548 : mInternalBoundReadFBO(0),
549 : #ifdef DEBUG
550 : mInInternalBindingMode_DrawFBO(true),
551 : mInInternalBindingMode_ReadFBO(true),
552 : #endif
553 : mOffscreenFBOsDirty(false),
554 : mInitialized(false),
555 : mIsOffscreen(aIsOffscreen),
556 : #ifdef USE_GLES2
557 : mIsGLES2(true),
558 : #else
559 : mIsGLES2(false),
560 : #endif
561 : mIsGlobalSharedContext(false),
562 : mHasRobustness(false),
563 : mContextLost(false),
564 : mVendor(-1),
565 : mRenderer(-1),
566 : mCreationFormat(aFormat),
567 : mSharedContext(aSharedContext),
568 : mOffscreenTexture(0),
569 : mFlipped(false),
570 : mBlitProgram(0),
571 : mBlitFramebuffer(0),
572 : mOffscreenDrawFBO(0),
573 : mOffscreenReadFBO(0),
574 : mOffscreenColorRB(0),
575 : mOffscreenDepthRB(0),
576 : mOffscreenStencilRB(0),
577 : mMaxTextureSize(0),
578 : mMaxCubeMapTextureSize(0),
579 : mMaxTextureImageSize(0),
580 : mMaxRenderbufferSize(0)
581 : #ifdef DEBUG
582 0 : , mGLError(LOCAL_GL_NO_ERROR)
583 : #endif
584 : {
585 0 : mUserData.Init();
586 0 : }
587 :
588 0 : virtual ~GLContext() {
589 0 : NS_ASSERTION(IsDestroyed(), "GLContext implementation must call MarkDestroyed in destructor!");
590 : #ifdef DEBUG
591 0 : if (mSharedContext) {
592 0 : GLContext *tip = mSharedContext;
593 0 : while (tip->mSharedContext)
594 0 : tip = tip->mSharedContext;
595 0 : tip->SharedContextDestroyed(this);
596 0 : tip->ReportOutstandingNames();
597 : }
598 : #endif
599 0 : }
600 :
601 : enum GLContextType {
602 : ContextTypeUnknown,
603 : ContextTypeWGL,
604 : ContextTypeCGL,
605 : ContextTypeGLX,
606 : ContextTypeEGL,
607 : ContextTypeOSMesa
608 : };
609 :
610 0 : virtual GLContextType GetContextType() { return ContextTypeUnknown; }
611 :
612 : virtual bool MakeCurrentImpl(bool aForce = false) = 0;
613 :
614 : #ifdef DEBUG
615 : static void StaticInit() {
616 : PR_NewThreadPrivateIndex(&sCurrentGLContextTLS, NULL);
617 : }
618 : #endif
619 :
620 0 : bool MakeCurrent(bool aForce = false) {
621 : #ifdef DEBUG
622 0 : PR_SetThreadPrivate(sCurrentGLContextTLS, this);
623 : #endif
624 0 : return MakeCurrentImpl(aForce);
625 : }
626 :
627 : bool IsContextLost() { return mContextLost; }
628 :
629 : virtual bool SetupLookupFunction() = 0;
630 :
631 0 : virtual void WindowDestroyed() {}
632 :
633 0 : virtual void ReleaseSurface() {}
634 :
635 : void *GetUserData(void *aKey) {
636 : void *result = nsnull;
637 : mUserData.Get(aKey, &result);
638 : return result;
639 : }
640 :
641 : void SetUserData(void *aKey, void *aValue) {
642 : mUserData.Put(aKey, aValue);
643 : }
644 :
645 : // Mark this context as destroyed. This will NULL out all
646 : // the GL function pointers!
647 : void THEBES_API MarkDestroyed();
648 :
649 0 : bool IsDestroyed() {
650 : // MarkDestroyed will mark all these as null.
651 0 : return mSymbols.fUseProgram == nsnull;
652 : }
653 :
654 : enum NativeDataType {
655 : NativeGLContext,
656 : NativeImageSurface,
657 : NativeThebesSurface,
658 : NativeDataTypeMax
659 : };
660 :
661 0 : virtual void *GetNativeData(NativeDataType aType) { return NULL; }
662 0 : GLContext *GetSharedContext() { return mSharedContext; }
663 :
664 : bool IsGlobalSharedContext() { return mIsGlobalSharedContext; }
665 0 : void SetIsGlobalSharedContext(bool aIsOne) { mIsGlobalSharedContext = aIsOne; }
666 :
667 : const ContextFormat& CreationFormat() { return mCreationFormat; }
668 : const ContextFormat& ActualFormat() { return mActualFormat; }
669 :
670 : /**
671 : * If this GL context has a D3D texture share handle, returns non-null.
672 : */
673 0 : virtual void *GetD3DShareHandle() { return nsnull; }
674 :
675 : /**
676 : * If this context is double-buffered, returns TRUE.
677 : */
678 0 : virtual bool IsDoubleBuffered() { return false; }
679 :
680 : /**
681 : * If this context is the GLES2 API, returns TRUE.
682 : * This means that various GLES2 restrictions might be in effect (modulo
683 : * extensions).
684 : */
685 0 : bool IsGLES2() const {
686 0 : return mIsGLES2;
687 : }
688 :
689 : /**
690 : * Returns true if either this is the GLES2 API, or had the GL_ARB_ES2_compatibility extension
691 : */
692 : bool HasES2Compatibility() {
693 : return mIsGLES2 || IsExtensionSupported(ARB_ES2_compatibility);
694 : }
695 :
696 : /**
697 : * Returns true if the context is using ANGLE. This should only be overridden for an ANGLE
698 : * implementation.
699 : */
700 0 : virtual bool IsANGLE() {
701 0 : return false;
702 : }
703 :
704 : /**
705 : * The derived class is expected to provide information on whether or not it
706 : * supports robustness.
707 : */
708 : virtual bool SupportsRobustness() = 0;
709 :
710 : enum {
711 : VendorIntel,
712 : VendorNVIDIA,
713 : VendorATI,
714 : VendorQualcomm,
715 : VendorOther
716 : };
717 :
718 : enum {
719 : RendererAdreno200,
720 : RendererOther
721 : };
722 :
723 : int Vendor() const {
724 : return mVendor;
725 : }
726 :
727 0 : int Renderer() const {
728 0 : return mRenderer;
729 : }
730 :
731 : bool CanUploadSubTextures();
732 :
733 : /**
734 : * If this context wraps a double-buffered target, swap the back
735 : * and front buffers. It should be assumed that after a swap, the
736 : * contents of the new back buffer are undefined.
737 : */
738 0 : virtual bool SwapBuffers() { return false; }
739 :
740 : /**
741 : * Defines a two-dimensional texture image for context target surface
742 : */
743 0 : virtual bool BindTexImage() { return false; }
744 : /*
745 : * Releases a color buffer that is being used as a texture
746 : */
747 0 : virtual bool ReleaseTexImage() { return false; }
748 :
749 : /**
750 : * Applies aFilter to the texture currently bound to GL_TEXTURE_2D.
751 : */
752 : void ApplyFilterToBoundTexture(gfxPattern::GraphicsFilter aFilter);
753 :
754 :
755 : /*
756 : * Offscreen support API
757 : */
758 :
759 : /*
760 : * Bind aOffscreen's color buffer as a texture to the TEXTURE_2D
761 : * target. Returns TRUE on success, otherwise FALSE. If
762 : * aOffscreen is not an offscreen context, returns FALSE. If
763 : * BindOffscreenNeedsTexture() returns TRUE, then you should have
764 : * a 2D texture name bound whose image will be replaced by the
765 : * contents of the offscreen context. If it returns FALSE,
766 : * the current 2D texture binding will be replaced.
767 : *
768 : * After a successul call to BindTex2DOffscreen, UnbindTex2DOffscreen
769 : * *must* be called once rendering is complete.
770 : *
771 : * The same texture unit must be active for Bind/Unbind of a given
772 : * context.
773 : */
774 0 : virtual bool BindOffscreenNeedsTexture(GLContext *aOffscreen) {
775 0 : return aOffscreen->mOffscreenTexture == 0;
776 : }
777 :
778 0 : virtual bool BindTex2DOffscreen(GLContext *aOffscreen) {
779 0 : if (aOffscreen->GetContextType() != GetContextType()) {
780 0 : return false;
781 : }
782 :
783 0 : if (!aOffscreen->mSharedContext ||
784 0 : aOffscreen->mSharedContext != mSharedContext)
785 : {
786 0 : return false;
787 : }
788 :
789 0 : if (!aOffscreen->mOffscreenTexture) {
790 0 : return false;
791 : }
792 :
793 0 : fBindTexture(LOCAL_GL_TEXTURE_2D, aOffscreen->mOffscreenTexture);
794 :
795 0 : return true;
796 : }
797 :
798 0 : virtual void UnbindTex2DOffscreen(GLContext *aOffscreen) { }
799 :
800 : bool IsOffscreen() {
801 : return mIsOffscreen;
802 : }
803 :
804 : private:
805 : bool mFlushGuaranteesResolve;
806 :
807 : public:
808 : void SetFlushGuaranteesResolve(bool aFlushGuaranteesResolve) {
809 : mFlushGuaranteesResolve = aFlushGuaranteesResolve;
810 : }
811 :
812 : // Before reads from offscreen texture
813 : void GuaranteeResolve() {
814 : if (mFlushGuaranteesResolve) {
815 : BlitDirtyFBOs();
816 : fFlush();
817 : } else {
818 : fFinish();
819 : }
820 : }
821 :
822 : /*
823 : * Resize the current offscreen buffer. Returns true on success.
824 : * If it returns false, the context should be treated as unusable
825 : * and should be recreated. After the resize, the viewport is not
826 : * changed; glViewport should be called as appropriate.
827 : *
828 : * Only valid if IsOffscreen() returns true.
829 : */
830 0 : virtual bool ResizeOffscreen(const gfxIntSize& aNewSize) {
831 0 : if (mOffscreenDrawFBO || mOffscreenReadFBO)
832 0 : return ResizeOffscreenFBO(aNewSize, mOffscreenReadFBO != 0);
833 0 : return false;
834 : }
835 :
836 : /*
837 : * Return size of this offscreen context.
838 : *
839 : * Only valid if IsOffscreen() returns true.
840 : */
841 : gfxIntSize OffscreenSize() {
842 : return mOffscreenSize;
843 : }
844 :
845 : /*
846 : * In some cases, we have to allocate a bigger offscreen buffer
847 : * than what's requested. This is the bigger size.
848 : *
849 : * Only valid if IsOffscreen() returns true.
850 : */
851 : gfxIntSize OffscreenActualSize() {
852 : return mOffscreenActualSize;
853 : }
854 :
855 : /*
856 : * If this context is FBO-backed, return the FBO or the color
857 : * buffer texture. If the context is not FBO-backed, 0 is
858 : * returned (which is also a valid FBO binding).
859 : *
860 : * Only valid if IsOffscreen() returns true.
861 : */
862 : GLuint GetOffscreenFBO() {
863 : // 0 is interpreted as (off)screen, whether for read or draw operations
864 : return 0;
865 : }
866 :
867 : GLuint GetOffscreenTexture() {
868 : return mOffscreenTexture;
869 : }
870 :
871 0 : virtual bool SupportsFramebufferMultisample() {
872 0 : return IsExtensionSupported(EXT_framebuffer_multisample) || IsExtensionSupported(ANGLE_framebuffer_multisample);
873 : }
874 :
875 0 : virtual bool SupportsOffscreenSplit() {
876 0 : return IsExtensionSupported(EXT_framebuffer_blit) || IsExtensionSupported(ANGLE_framebuffer_blit);
877 : }
878 :
879 :
880 :
881 : private:
882 : GLuint mUserBoundDrawFBO;
883 : GLuint mUserBoundReadFBO;
884 : GLuint mInternalBoundDrawFBO;
885 : GLuint mInternalBoundReadFBO;
886 :
887 : public:
888 0 : void fBindFramebuffer(GLenum target, GLuint framebuffer) {
889 0 : switch (target) {
890 : case LOCAL_GL_DRAW_FRAMEBUFFER_EXT:
891 0 : mUserBoundDrawFBO = framebuffer;
892 :
893 0 : if (framebuffer == 0) {
894 0 : mInternalBoundDrawFBO = mOffscreenDrawFBO;
895 : } else {
896 0 : mInternalBoundDrawFBO = mUserBoundDrawFBO;
897 : }
898 :
899 : raw_fBindFramebuffer(LOCAL_GL_DRAW_FRAMEBUFFER_EXT,
900 0 : mInternalBoundDrawFBO);
901 0 : break;
902 :
903 : case LOCAL_GL_READ_FRAMEBUFFER_EXT:
904 0 : mUserBoundReadFBO = framebuffer;
905 :
906 0 : if (framebuffer == 0) {
907 0 : mInternalBoundReadFBO = mOffscreenReadFBO;
908 : } else {
909 0 : mInternalBoundReadFBO = mUserBoundReadFBO;
910 : }
911 :
912 : raw_fBindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER_EXT,
913 0 : mInternalBoundReadFBO);
914 0 : break;
915 :
916 : case LOCAL_GL_FRAMEBUFFER:
917 0 : mUserBoundDrawFBO = mUserBoundReadFBO = framebuffer;
918 :
919 0 : if (framebuffer == 0) {
920 0 : mInternalBoundDrawFBO = mOffscreenDrawFBO;
921 0 : mInternalBoundReadFBO = mOffscreenReadFBO;
922 : } else {
923 0 : mInternalBoundDrawFBO = mUserBoundDrawFBO;
924 0 : mInternalBoundReadFBO = mUserBoundReadFBO;
925 : }
926 :
927 0 : if (SupportsOffscreenSplit()) {
928 : raw_fBindFramebuffer(LOCAL_GL_DRAW_FRAMEBUFFER_EXT,
929 0 : mInternalBoundDrawFBO);
930 : raw_fBindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER_EXT,
931 0 : mInternalBoundReadFBO);
932 : } else {
933 : raw_fBindFramebuffer(LOCAL_GL_FRAMEBUFFER,
934 0 : mInternalBoundDrawFBO);
935 : }
936 :
937 0 : break;
938 :
939 : default:
940 0 : raw_fBindFramebuffer(target, framebuffer);
941 0 : break;
942 : }
943 0 : }
944 :
945 : #ifdef DEBUG
946 : // See comment near BindInternalDrawFBO()
947 : bool mInInternalBindingMode_DrawFBO;
948 : bool mInInternalBindingMode_ReadFBO;
949 : #endif
950 :
951 0 : GLuint GetUserBoundDrawFBO() {
952 : #ifdef DEBUG
953 0 : GLint ret = 0;
954 : // Don't need a branch here, because:
955 : // LOCAL_GL_DRAW_FRAMEBUFFER_BINDING_EXT == LOCAL_GL_FRAMEBUFFER_BINDING == 0x8CA6
956 : // We use raw_ here because this is debug code and we need to see what
957 : // the driver thinks.
958 0 : raw_fGetIntegerv(LOCAL_GL_DRAW_FRAMEBUFFER_BINDING_EXT, &ret);
959 :
960 0 : bool abort = false;
961 :
962 0 : if (mInInternalBindingMode_DrawFBO) {
963 0 : NS_ERROR("Draw FBO still bound internally!");
964 0 : printf_stderr("Current internal draw FBO: %d, user: %d)\n", ret, mUserBoundDrawFBO);
965 0 : abort = true;
966 : }
967 :
968 0 : if (mInternalBoundDrawFBO != (GLuint)ret) {
969 0 : NS_ERROR("Draw FBO binding misprediction!");
970 0 : printf_stderr("Bound draw FBO was: %d, Expected: %d\n", ret, mInternalBoundDrawFBO);
971 0 : abort = true;
972 : }
973 :
974 0 : if (abort)
975 0 : NS_ABORT();
976 : #endif
977 :
978 : // We only ever expose the user's bound FBOs
979 0 : return mUserBoundDrawFBO;
980 : }
981 :
982 0 : GLuint GetUserBoundReadFBO() {
983 : #ifdef DEBUG
984 0 : GLint ret = 0;
985 : // We use raw_ here because this is debug code and we need to see what
986 : // the driver thinks.
987 0 : if (SupportsOffscreenSplit())
988 0 : raw_fGetIntegerv(LOCAL_GL_READ_FRAMEBUFFER_BINDING_EXT, &ret);
989 : else
990 0 : raw_fGetIntegerv(LOCAL_GL_FRAMEBUFFER_BINDING, &ret);
991 :
992 0 : bool abort = false;
993 :
994 0 : if (mInInternalBindingMode_ReadFBO) {
995 0 : NS_ERROR("Read FBO still bound internally!");
996 0 : printf_stderr("Current internal read FBO: %d, user: %d)\n", ret, mUserBoundReadFBO);
997 0 : abort = true;
998 : }
999 :
1000 0 : if (mInternalBoundReadFBO != (GLuint)ret) {
1001 0 : NS_ERROR("Read FBO binding misprediction!");
1002 0 : printf_stderr("Bound read FBO was: %d, Expected: %d\n", ret, mInternalBoundReadFBO);
1003 0 : abort = true;
1004 : }
1005 :
1006 0 : if (abort)
1007 0 : NS_ABORT();
1008 : #endif
1009 :
1010 : // We only ever expose the user's bound FBOs
1011 0 : return mUserBoundReadFBO;
1012 : }
1013 :
1014 0 : void BindUserDrawFBO(GLuint name) {
1015 0 : if (SupportsOffscreenSplit())
1016 0 : fBindFramebuffer(LOCAL_GL_DRAW_FRAMEBUFFER_EXT, name);
1017 : else
1018 0 : fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, name);
1019 : #ifdef DEBUG
1020 0 : mInInternalBindingMode_DrawFBO = false;
1021 : #endif
1022 0 : }
1023 :
1024 0 : void BindUserReadFBO(GLuint name) {
1025 0 : if (SupportsOffscreenSplit())
1026 0 : fBindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER_EXT, name);
1027 : else
1028 0 : fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, name);
1029 : #ifdef DEBUG
1030 0 : mInInternalBindingMode_ReadFBO = false;
1031 : #endif
1032 0 : }
1033 :
1034 : // BindInternalDraw/ReadFBO() switch us over into 'internal binding mode'
1035 : // for the corresponding Draw or Read binding.
1036 : // To exit internal binding mode, use BindUserDraw/ReadFBO().
1037 : // While in internal binding mode for Draw/Read, the corresponding
1038 : // GetBoundUserDraw/ReadFBO() is undefined, and will trigger ABORT in DEBUG builds.
1039 0 : void BindInternalDrawFBO(GLuint name) {
1040 : #ifdef DEBUG
1041 0 : mInInternalBindingMode_DrawFBO = true;
1042 : #endif
1043 0 : if (SupportsOffscreenSplit())
1044 0 : raw_fBindFramebuffer(LOCAL_GL_DRAW_FRAMEBUFFER_EXT, name);
1045 : else
1046 0 : raw_fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, name);
1047 :
1048 0 : mInternalBoundDrawFBO = name;
1049 0 : }
1050 :
1051 0 : void BindInternalReadFBO(GLuint name) {
1052 : #ifdef DEBUG
1053 0 : mInInternalBindingMode_ReadFBO = true;
1054 : #endif
1055 0 : if (SupportsOffscreenSplit())
1056 0 : raw_fBindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER_EXT, name);
1057 : else
1058 0 : raw_fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, name);
1059 :
1060 0 : mInternalBoundReadFBO = name;
1061 0 : }
1062 :
1063 0 : void BindInternalFBO(GLuint name) {
1064 0 : BindInternalDrawFBO(name);
1065 0 : BindInternalReadFBO(name);
1066 0 : }
1067 :
1068 0 : void InitFramebuffers() {
1069 0 : MakeCurrent();
1070 0 : BindUserDrawFBO(0);
1071 0 : BindUserReadFBO(0);
1072 0 : }
1073 :
1074 0 : GLuint SwapUserDrawFBO(GLuint name) {
1075 0 : GLuint prev = GetUserBoundDrawFBO();
1076 0 : BindUserDrawFBO(name);
1077 0 : return prev;
1078 : }
1079 :
1080 : GLuint SwapUserReadFBO(GLuint name) {
1081 : GLuint prev = GetUserBoundReadFBO();
1082 : BindUserReadFBO(name);
1083 : return prev;
1084 : }
1085 :
1086 : private:
1087 : bool mOffscreenFBOsDirty;
1088 :
1089 : void GetShaderPrecisionFormatNonES2(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) {
1090 : switch (precisiontype) {
1091 : case LOCAL_GL_LOW_FLOAT:
1092 : case LOCAL_GL_MEDIUM_FLOAT:
1093 : case LOCAL_GL_HIGH_FLOAT:
1094 : // Assume IEEE 754 precision
1095 : range[0] = 127;
1096 : range[1] = 127;
1097 : *precision = 0;
1098 : break;
1099 : case LOCAL_GL_LOW_INT:
1100 : case LOCAL_GL_MEDIUM_INT:
1101 : case LOCAL_GL_HIGH_INT:
1102 : // Some (most) hardware only supports single-precision floating-point numbers,
1103 : // which can accurately represent integers up to +/-16777216
1104 : range[0] = 24;
1105 : range[1] = 24;
1106 : *precision = 0;
1107 : break;
1108 : }
1109 : }
1110 :
1111 : // Do whatever setup is necessary to draw to our offscreen FBO, if it's
1112 : // bound.
1113 0 : void BeforeGLDrawCall() {
1114 0 : if (mInternalBoundDrawFBO != mOffscreenDrawFBO)
1115 0 : return;
1116 :
1117 0 : if (mOffscreenDrawFBO == mOffscreenReadFBO)
1118 0 : return;
1119 :
1120 0 : mOffscreenFBOsDirty = true;
1121 : }
1122 :
1123 : // Do whatever tear-down is necessary after drawing to our offscreen FBO,
1124 : // if it's bound.
1125 0 : void AfterGLDrawCall() {
1126 0 : }
1127 :
1128 : // Do whatever setup is necessary to read from our offscreen FBO, if it's
1129 : // bound.
1130 0 : void BeforeGLReadCall() {
1131 0 : if (mInternalBoundReadFBO != mOffscreenReadFBO)
1132 0 : return;
1133 :
1134 0 : if (mOffscreenDrawFBO == mOffscreenReadFBO)
1135 0 : return;
1136 :
1137 : // If we're not dirty, there's no need to blit
1138 0 : if (!mOffscreenFBOsDirty)
1139 0 : return;
1140 :
1141 0 : const bool scissor = fIsEnabled(LOCAL_GL_SCISSOR_TEST);
1142 0 : if (scissor)
1143 0 : fDisable(LOCAL_GL_SCISSOR_TEST);
1144 :
1145 : // Store current bindings for restoring later
1146 0 : GLuint prevDraw = GetUserBoundDrawFBO();
1147 0 : GLuint prevRead = GetUserBoundReadFBO();
1148 :
1149 0 : NS_ABORT_IF_FALSE(SupportsOffscreenSplit(), "Doesn't support offscreen split?");
1150 :
1151 : // Manually setting internal bindings, entering internal mode
1152 : // Flip read/draw for blitting
1153 0 : BindInternalDrawFBO(mOffscreenReadFBO);
1154 0 : BindInternalReadFBO(mOffscreenDrawFBO);
1155 :
1156 0 : GLint width = mOffscreenActualSize.width;
1157 0 : GLint height = mOffscreenActualSize.height;
1158 : raw_fBlitFramebuffer(0, 0, width, height,
1159 : 0, 0, width, height,
1160 : LOCAL_GL_COLOR_BUFFER_BIT,
1161 0 : LOCAL_GL_NEAREST);
1162 :
1163 : // Reset to emulated user binding, exiting internal mode
1164 0 : BindUserDrawFBO(prevDraw);
1165 0 : BindUserReadFBO(prevRead);
1166 :
1167 0 : if (scissor)
1168 0 : fEnable(LOCAL_GL_SCISSOR_TEST);
1169 :
1170 0 : mOffscreenFBOsDirty = false;
1171 : }
1172 :
1173 : // Do whatever tear-down is necessary after reading from our offscreen FBO,
1174 : // if it's bound.
1175 0 : void AfterGLReadCall() {
1176 0 : }
1177 :
1178 : public:
1179 : // Draw call hooks:
1180 0 : void fClear(GLbitfield mask) {
1181 0 : BeforeGLDrawCall();
1182 0 : raw_fClear(mask);
1183 0 : AfterGLDrawCall();
1184 0 : }
1185 :
1186 0 : void fDrawArrays(GLenum mode, GLint first, GLsizei count) {
1187 0 : BeforeGLDrawCall();
1188 0 : raw_fDrawArrays(mode, first, count);
1189 0 : AfterGLDrawCall();
1190 0 : }
1191 :
1192 : void fDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices) {
1193 : BeforeGLDrawCall();
1194 : raw_fDrawElements(mode, count, type, indices);
1195 : AfterGLDrawCall();
1196 : }
1197 :
1198 : // Read call hooks:
1199 0 : void fReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels) {
1200 0 : BeforeGLReadCall();
1201 0 : raw_fReadPixels(x, y, width, height, format, type, pixels);
1202 0 : AfterGLReadCall();
1203 0 : }
1204 :
1205 : void fCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) {
1206 : BeforeGLReadCall();
1207 : raw_fCopyTexImage2D(target, level, internalformat,
1208 : x, y, width, height, border);
1209 : AfterGLReadCall();
1210 : }
1211 :
1212 : void fCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) {
1213 : BeforeGLReadCall();
1214 : raw_fCopyTexSubImage2D(target, level, xoffset, yoffset,
1215 : x, y, width, height);
1216 : AfterGLReadCall();
1217 : }
1218 :
1219 0 : void ForceDirtyFBOs() {
1220 0 : GLuint draw = SwapUserDrawFBO(0);
1221 :
1222 0 : BeforeGLDrawCall();
1223 : // no-op; just pretend we did something
1224 0 : AfterGLDrawCall();
1225 :
1226 0 : BindUserDrawFBO(draw);
1227 0 : }
1228 :
1229 : void BlitDirtyFBOs() {
1230 : GLuint read = SwapUserReadFBO(0);
1231 :
1232 : BeforeGLReadCall();
1233 : // no-op; we just want to make sure the Read FBO is updated if it needs to be
1234 : AfterGLReadCall();
1235 :
1236 : BindUserReadFBO(read);
1237 : }
1238 :
1239 0 : void fFinish() {
1240 0 : BeforeGLReadCall();
1241 0 : raw_fFinish();
1242 0 : AfterGLReadCall();
1243 0 : }
1244 :
1245 : // Draw/Read
1246 : void fBlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) {
1247 : BeforeGLDrawCall();
1248 : BeforeGLReadCall();
1249 : raw_fBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
1250 : AfterGLReadCall();
1251 : AfterGLDrawCall();
1252 : }
1253 :
1254 : #if defined(MOZ_X11) && defined(MOZ_EGL_XRENDER_COMPOSITE)
1255 : virtual gfxASurface* GetOffscreenPixmapSurface()
1256 : {
1257 : return 0;
1258 : };
1259 :
1260 : virtual bool WaitNative() { return false; }
1261 : #endif
1262 :
1263 0 : virtual bool TextureImageSupportsGetBackingSurface() {
1264 0 : return false;
1265 : }
1266 :
1267 0 : virtual bool RenewSurface() { return false; }
1268 :
1269 : /**`
1270 : * Return a valid, allocated TextureImage of |aSize| with
1271 : * |aContentType|. The TextureImage's texture is configured to
1272 : * use |aWrapMode| (usually GL_CLAMP_TO_EDGE or GL_REPEAT) and by
1273 : * default, GL_LINEAR filtering. Specify
1274 : * |aUseNearestFilter=true| for GL_NEAREST filtering. Return
1275 : * NULL if creating the TextureImage fails.
1276 : *
1277 : * The returned TextureImage may only be used with this GLContext.
1278 : * Attempting to use the returned TextureImage after this
1279 : * GLContext is destroyed will result in undefined (and likely
1280 : * crashy) behavior.
1281 : */
1282 : virtual already_AddRefed<TextureImage>
1283 : CreateTextureImage(const nsIntSize& aSize,
1284 : TextureImage::ContentType aContentType,
1285 : GLenum aWrapMode,
1286 : bool aUseNearestFilter=false);
1287 :
1288 : /**
1289 : * In EGL we want to use Tiled Texture Images, which we return
1290 : * from CreateTextureImage above.
1291 : * Inside TiledTextureImage we need to create actual images and to
1292 : * prevent infinite recursion we need to differentiate the two
1293 : * functions.
1294 : **/
1295 : virtual already_AddRefed<TextureImage>
1296 0 : TileGenFunc(const nsIntSize& aSize,
1297 : TextureImage::ContentType aContentType,
1298 : bool aUseNearestFilter = false)
1299 : {
1300 0 : return nsnull;
1301 : };
1302 :
1303 : /**
1304 : * Read the image data contained in aTexture, and return it as an ImageSurface.
1305 : * If GL_RGBA is given as the format, a ImageFormatARGB32 surface is returned.
1306 : * Not implemented yet:
1307 : * If GL_RGB is given as the format, a ImageFormatRGB24 surface is returned.
1308 : * If GL_LUMINANCE is given as the format, a ImageFormatA8 surface is returned.
1309 : *
1310 : * THIS IS EXPENSIVE. It is ridiculously expensive. Only do this
1311 : * if you absolutely positively must, and never in any performance
1312 : * critical path.
1313 : */
1314 : already_AddRefed<gfxImageSurface> ReadTextureImage(GLuint aTexture,
1315 : const gfxIntSize& aSize,
1316 : GLenum aTextureFormat,
1317 : bool aYInvert = false);
1318 :
1319 : already_AddRefed<gfxImageSurface> GetTexImage(GLuint aTexture, bool aYInvert, ShaderProgramType aShader);
1320 :
1321 : /**
1322 : * Call ReadPixels into an existing gfxImageSurface for the given bounds.
1323 : * The image surface must be using image format RGBA32 or RGB24.
1324 : */
1325 : void THEBES_API ReadPixelsIntoImageSurface(GLint aX, GLint aY,
1326 : GLsizei aWidth, GLsizei aHeight,
1327 : gfxImageSurface *aDest);
1328 :
1329 : /**
1330 : * Copy a rectangle from one TextureImage into another. The
1331 : * source and destination are given in integer coordinates, and
1332 : * will be converted to texture coordinates.
1333 : *
1334 : * For the source texture, the wrap modes DO apply -- it's valid
1335 : * to use REPEAT or PAD and expect appropriate behaviour if the source
1336 : * rectangle extends beyond its bounds.
1337 : *
1338 : * For the destination texture, the wrap modes DO NOT apply -- the
1339 : * destination will be clipped by the bounds of the texture.
1340 : *
1341 : * Note: calling this function will cause the following OpenGL state
1342 : * to be changed:
1343 : *
1344 : * - current program
1345 : * - framebuffer binding
1346 : * - viewport
1347 : * - blend state (will be enabled at end)
1348 : * - scissor state (will be enabled at end)
1349 : * - vertex attrib 0 and 1 (pointer and enable state [enable state will be disabled at exit])
1350 : * - array buffer binding (will be 0)
1351 : * - active texture (will be 0)
1352 : * - texture 0 binding
1353 : */
1354 : void BlitTextureImage(TextureImage *aSrc, const nsIntRect& aSrcRect,
1355 : TextureImage *aDst, const nsIntRect& aDstRect);
1356 :
1357 : /**
1358 : * Creates a RGB/RGBA texture (or uses one provided) and uploads the surface
1359 : * contents to it within aSrcRect.
1360 : *
1361 : * aSrcRect.x/y will be uploaded to 0/0 in the texture, and the size
1362 : * of the texture with be aSrcRect.width/height.
1363 : *
1364 : * If an existing texture is passed through aTexture, it is assumed it
1365 : * has already been initialised with glTexImage2D (or this function),
1366 : * and that its size is equal to or greater than aSrcRect + aDstPoint.
1367 : * You can alternatively set the overwrite flag to true and have a new
1368 : * texture memory block allocated.
1369 : *
1370 : * The aDstPoint parameter is ignored if no texture was provided
1371 : * or aOverwrite is true.
1372 : *
1373 : * \param aSurface Surface to upload.
1374 : * \param aDstRegion Region of texture to upload to.
1375 : * \param aTexture Texture to use, or 0 to have one created for you.
1376 : * \param aOverwrite Over an existing texture with a new one.
1377 : * \param aSrcPoint Offset into aSrc where the region's bound's
1378 : * TopLeft() sits.
1379 : * \param aPixelBuffer Pass true to upload texture data with an
1380 : * offset from the base data (generally for pixel buffer objects),
1381 : * otherwise textures are upload with an absolute pointer to the data.
1382 : * \return Shader program needed to render this texture.
1383 : */
1384 : ShaderProgramType UploadSurfaceToTexture(gfxASurface *aSurface,
1385 : const nsIntRegion& aDstRegion,
1386 : GLuint& aTexture,
1387 : bool aOverwrite = false,
1388 : const nsIntPoint& aSrcPoint = nsIntPoint(0, 0),
1389 : bool aPixelBuffer = false);
1390 :
1391 :
1392 : void TexImage2D(GLenum target, GLint level, GLint internalformat,
1393 : GLsizei width, GLsizei height, GLsizei stride,
1394 : GLint pixelsize, GLint border, GLenum format,
1395 : GLenum type, const GLvoid *pixels);
1396 :
1397 : void TexSubImage2D(GLenum target, GLint level,
1398 : GLint xoffset, GLint yoffset,
1399 : GLsizei width, GLsizei height, GLsizei stride,
1400 : GLint pixelsize, GLenum format,
1401 : GLenum type, const GLvoid* pixels);
1402 :
1403 : /**
1404 : * Uses the Khronos GL_EXT_unpack_subimage extension, working around
1405 : * quirks in the Tegra implementation of this extension.
1406 : */
1407 : void TexSubImage2DWithUnpackSubimageGLES(GLenum target, GLint level,
1408 : GLint xoffset, GLint yoffset,
1409 : GLsizei width, GLsizei height,
1410 : GLsizei stride, GLint pixelsize,
1411 : GLenum format, GLenum type,
1412 : const GLvoid* pixels);
1413 :
1414 : void TexSubImage2DWithoutUnpackSubimage(GLenum target, GLint level,
1415 : GLint xoffset, GLint yoffset,
1416 : GLsizei width, GLsizei height,
1417 : GLsizei stride, GLint pixelsize,
1418 : GLenum format, GLenum type,
1419 : const GLvoid* pixels);
1420 :
1421 : /** Helper for DecomposeIntoNoRepeatTriangles
1422 : */
1423 0 : struct RectTriangles {
1424 0 : RectTriangles() { }
1425 :
1426 : void addRect(GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1,
1427 : GLfloat tx0, GLfloat ty0, GLfloat tx1, GLfloat ty1);
1428 :
1429 : /**
1430 : * these return a float pointer to the start of each array respectively.
1431 : * Use it for glVertexAttribPointer calls.
1432 : * We can return NULL if we choose to use Vertex Buffer Objects here.
1433 : */
1434 0 : float* vertexPointer() {
1435 0 : return &vertexCoords[0].x;
1436 : };
1437 :
1438 0 : float* texCoordPointer() {
1439 0 : return &texCoords[0].u;
1440 : };
1441 :
1442 0 : unsigned int elements() {
1443 0 : return vertexCoords.Length();
1444 : };
1445 :
1446 0 : typedef struct { GLfloat x,y; } vert_coord;
1447 0 : typedef struct { GLfloat u,v; } tex_coord;
1448 : private:
1449 : // default is 4 rectangles, each made up of 2 triangles (3 coord vertices each)
1450 : nsAutoTArray<vert_coord, 6> vertexCoords;
1451 : nsAutoTArray<tex_coord, 6> texCoords;
1452 : };
1453 :
1454 : /**
1455 : * Decompose drawing the possibly-wrapped aTexCoordRect rectangle
1456 : * of a texture of aTexSize into one or more rectangles (represented
1457 : * as 2 triangles) and associated tex coordinates, such that
1458 : * we don't have to use the REPEAT wrap mode.
1459 : *
1460 : * The resulting triangle vertex coordinates will be in the space of
1461 : * (0.0, 0.0) to (1.0, 1.0) -- transform the coordinates appropriately
1462 : * if you need a different space.
1463 : *
1464 : * The resulting vertex coordinates should be drawn using GL_TRIANGLES,
1465 : * and rects.numRects * 3 * 6
1466 : */
1467 : static void DecomposeIntoNoRepeatTriangles(const nsIntRect& aTexCoordRect,
1468 : const nsIntSize& aTexSize,
1469 : RectTriangles& aRects);
1470 :
1471 : /**
1472 : * Known GL extensions that can be queried by
1473 : * IsExtensionSupported. The results of this are cached, and as
1474 : * such it's safe to use this even in performance critical code.
1475 : * If you add to this array, remember to add to the string names
1476 : * in GLContext.cpp.
1477 : */
1478 : enum GLExtensions {
1479 : EXT_framebuffer_object,
1480 : ARB_framebuffer_object,
1481 : ARB_texture_rectangle,
1482 : EXT_bgra,
1483 : EXT_texture_format_BGRA8888,
1484 : OES_depth24,
1485 : OES_depth32,
1486 : OES_stencil8,
1487 : OES_texture_npot,
1488 : OES_depth_texture,
1489 : OES_packed_depth_stencil,
1490 : IMG_read_format,
1491 : EXT_read_format_bgra,
1492 : APPLE_client_storage,
1493 : ARB_texture_non_power_of_two,
1494 : ARB_pixel_buffer_object,
1495 : ARB_ES2_compatibility,
1496 : OES_texture_float,
1497 : ARB_texture_float,
1498 : EXT_unpack_subimage,
1499 : OES_standard_derivatives,
1500 : EXT_texture_filter_anisotropic,
1501 : EXT_framebuffer_blit,
1502 : ANGLE_framebuffer_blit,
1503 : EXT_framebuffer_multisample,
1504 : ANGLE_framebuffer_multisample,
1505 : OES_rgb8_rgba8,
1506 : ARB_robustness,
1507 : EXT_robustness,
1508 : Extensions_Max
1509 : };
1510 :
1511 0 : bool IsExtensionSupported(GLExtensions aKnownExtension) {
1512 0 : return mAvailableExtensions[aKnownExtension];
1513 : }
1514 :
1515 : // for unknown extensions
1516 : bool IsExtensionSupported(const char *extension);
1517 :
1518 : // Shared code for GL extensions and GLX extensions.
1519 : static bool ListHasExtension(const GLubyte *extensions,
1520 : const char *extension);
1521 :
1522 0 : GLint GetMaxTextureSize() { return mMaxTextureSize; }
1523 : GLint GetMaxTextureImageSize() { return mMaxTextureImageSize; }
1524 : void SetFlipped(bool aFlipped) { mFlipped = aFlipped; }
1525 :
1526 : // this should just be a std::bitset, but that ended up breaking
1527 : // MacOS X builds; see bug 584919. We can replace this with one
1528 : // later on. This is handy to use in WebGL contexts as well,
1529 : // so making it public.
1530 : template<size_t setlen>
1531 : struct ExtensionBitset {
1532 0 : ExtensionBitset() {
1533 0 : for (size_t i = 0; i < setlen; ++i)
1534 0 : values[i] = false;
1535 0 : }
1536 :
1537 0 : bool& operator[](size_t index) {
1538 0 : NS_ASSERTION(index < setlen, "out of range");
1539 0 : return values[index];
1540 : }
1541 :
1542 : bool values[setlen];
1543 : };
1544 :
1545 : /**
1546 : * Context reset constants.
1547 : * These are used to determine who is guilty when a context reset
1548 : * happens.
1549 : */
1550 : enum ContextResetARB {
1551 : CONTEXT_NO_ERROR = 0,
1552 : CONTEXT_GUILTY_CONTEXT_RESET_ARB = 0x8253,
1553 : CONTEXT_INNOCENT_CONTEXT_RESET_ARB = 0x8254,
1554 : CONTEXT_UNKNOWN_CONTEXT_RESET_ARB = 0x8255
1555 : };
1556 :
1557 : bool HasRobustness() {
1558 : return mHasRobustness;
1559 : }
1560 :
1561 : protected:
1562 : bool mInitialized;
1563 : bool mIsOffscreen;
1564 : bool mIsGLES2;
1565 : bool mIsGlobalSharedContext;
1566 : bool mHasRobustness;
1567 : bool mContextLost;
1568 :
1569 : PRInt32 mVendor;
1570 : PRInt32 mRenderer;
1571 :
1572 : public:
1573 : enum {
1574 : DebugEnabled = 1 << 0,
1575 : DebugTrace = 1 << 1,
1576 : DebugAbortOnError = 1 << 2
1577 : };
1578 :
1579 : static PRUint32 sDebugMode;
1580 :
1581 0 : static PRUint32 DebugMode() {
1582 : #ifdef DEBUG
1583 0 : return sDebugMode;
1584 : #else
1585 : return 0;
1586 : #endif
1587 : }
1588 :
1589 : protected:
1590 :
1591 : ContextFormat mCreationFormat;
1592 : nsRefPtr<GLContext> mSharedContext;
1593 :
1594 : GLContextSymbols mSymbols;
1595 :
1596 : #ifdef DEBUG
1597 : // GLDebugMode will check that we don't send call
1598 : // to a GLContext that isn't current on the current
1599 : // thread.
1600 : // Store the current context when binding to thread local
1601 : // storage to support DebugMode on an arbitrary thread.
1602 : static PRUintn sCurrentGLContextTLS;
1603 : #endif
1604 :
1605 : void UpdateActualFormat();
1606 : ContextFormat mActualFormat;
1607 :
1608 : gfxIntSize mOffscreenSize;
1609 : gfxIntSize mOffscreenActualSize;
1610 : GLuint mOffscreenTexture;
1611 : bool mFlipped;
1612 :
1613 : // lazy-initialized things
1614 : GLuint mBlitProgram, mBlitFramebuffer;
1615 : void UseBlitProgram();
1616 : void SetBlitFramebufferForDestTexture(GLuint aTexture);
1617 :
1618 : // Helper to create/resize an offscreen FBO,
1619 : // for offscreen implementations that use FBOs.
1620 : // Note that it does -not- clear the resized buffers.
1621 : bool ResizeOffscreenFBO(const gfxIntSize& aSize, const bool aUseReadFBO, const bool aDisableAA);
1622 0 : bool ResizeOffscreenFBO(const gfxIntSize& aSize, const bool aUseReadFBO) {
1623 0 : if (ResizeOffscreenFBO(aSize, aUseReadFBO, false))
1624 0 : return true;
1625 :
1626 0 : if (!mCreationFormat.samples) {
1627 0 : NS_WARNING("ResizeOffscreenFBO failed to resize non-AA context!");
1628 0 : return false;
1629 : } else {
1630 0 : NS_WARNING("ResizeOffscreenFBO failed to resize AA context! Falling back to no AA...");
1631 : }
1632 :
1633 0 : if (DebugMode()) {
1634 0 : printf_stderr("Requested level of multisampling is unavailable, continuing without multisampling\n");
1635 : }
1636 :
1637 0 : if (ResizeOffscreenFBO(aSize, aUseReadFBO, true))
1638 0 : return true;
1639 :
1640 0 : NS_WARNING("ResizeOffscreenFBO failed to resize AA context even without AA!");
1641 0 : return false;
1642 : }
1643 :
1644 : void DeleteOffscreenFBO();
1645 :
1646 : GLuint mOffscreenDrawFBO;
1647 : GLuint mOffscreenReadFBO;
1648 : GLuint mOffscreenColorRB;
1649 : GLuint mOffscreenDepthRB;
1650 : GLuint mOffscreenStencilRB;
1651 :
1652 : ExtensionBitset<Extensions_Max> mAvailableExtensions;
1653 :
1654 : // Clear to transparent black, with 0 depth and stencil,
1655 : // while preserving current ClearColor etc. values.
1656 : // Useful for resizing offscreen buffers.
1657 : public:
1658 : void ClearSafely();
1659 :
1660 : protected:
1661 :
1662 : nsDataHashtable<nsVoidPtrHashKey, void*> mUserData;
1663 :
1664 : void SetIsGLES2(bool aIsGLES2) {
1665 : NS_ASSERTION(!mInitialized, "SetIsGLES2 can only be called before initialization!");
1666 : mIsGLES2 = aIsGLES2;
1667 : }
1668 :
1669 : bool InitWithPrefix(const char *prefix, bool trygl);
1670 :
1671 : void InitExtensions();
1672 :
1673 : virtual already_AddRefed<TextureImage>
1674 0 : CreateBasicTextureImage(GLuint aTexture,
1675 : const nsIntSize& aSize,
1676 : GLenum aWrapMode,
1677 : TextureImage::ContentType aContentType,
1678 : GLContext* aContext)
1679 : {
1680 : nsRefPtr<BasicTextureImage> teximage(
1681 0 : new BasicTextureImage(aTexture, aSize, aWrapMode, aContentType, aContext));
1682 0 : return teximage.forget();
1683 : }
1684 :
1685 0 : bool IsOffscreenSizeAllowed(const gfxIntSize& aSize) const {
1686 0 : PRInt32 biggerDimension = NS_MAX(aSize.width, aSize.height);
1687 0 : PRInt32 maxAllowed = NS_MIN(mMaxRenderbufferSize, mMaxTextureSize);
1688 0 : return biggerDimension <= maxAllowed;
1689 : }
1690 :
1691 : protected:
1692 : nsTArray<nsIntRect> mViewportStack;
1693 : nsTArray<nsIntRect> mScissorStack;
1694 :
1695 : GLint mMaxTextureSize;
1696 : GLint mMaxCubeMapTextureSize;
1697 : GLint mMaxTextureImageSize;
1698 : GLint mMaxRenderbufferSize;
1699 :
1700 0 : bool IsTextureSizeSafeToPassToDriver(GLenum target, GLsizei width, GLsizei height) const {
1701 : #ifdef XP_MACOSX
1702 : if (mVendor == VendorIntel) {
1703 : // see bug 737182 for 2D textures, bug 684822 for cube map textures.
1704 : // some drivers handle incorrectly some large texture sizes that are below the
1705 : // max texture size that they report. So we check ourselves against our own values
1706 : // (mMax[CubeMap]TextureSize).
1707 : GLsizei maxSize = target == LOCAL_GL_TEXTURE_CUBE_MAP ||
1708 : (target >= LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X &&
1709 : target <= LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
1710 : ? mMaxCubeMapTextureSize
1711 : : mMaxTextureSize;
1712 : return width <= maxSize && height <= maxSize;
1713 : }
1714 : #endif
1715 0 : return true;
1716 : }
1717 :
1718 : public:
1719 :
1720 : /** \returns the first GL error, and guarantees that all GL error flags are cleared,
1721 : * i.e. that a subsequent GetError call will return NO_ERROR
1722 : */
1723 : GLenum GetAndClearError() {
1724 : // the first error is what we want to return
1725 : GLenum error = fGetError();
1726 :
1727 : if (error) {
1728 : // clear all pending errors
1729 : while(fGetError()) {}
1730 : }
1731 :
1732 : return error;
1733 : }
1734 :
1735 : #ifdef DEBUG
1736 :
1737 : #ifndef MOZ_FUNCTION_NAME
1738 : # ifdef __GNUC__
1739 : # define MOZ_FUNCTION_NAME __PRETTY_FUNCTION__
1740 : # elif defined(_MSC_VER)
1741 : # define MOZ_FUNCTION_NAME __FUNCTION__
1742 : # else
1743 : # define MOZ_FUNCTION_NAME __func__ // defined in C99, supported in various C++ compilers. Just raw function name.
1744 : # endif
1745 : #endif
1746 :
1747 : protected:
1748 : GLenum mGLError;
1749 :
1750 : public:
1751 :
1752 0 : void BeforeGLCall(const char* glFunction) {
1753 0 : if (DebugMode()) {
1754 0 : GLContext *currentGLContext = NULL;
1755 :
1756 0 : currentGLContext = (GLContext*)PR_GetThreadPrivate(sCurrentGLContextTLS);
1757 :
1758 0 : if (DebugMode() & DebugTrace)
1759 0 : printf_stderr("[gl:%p] > %s\n", this, glFunction);
1760 0 : if (this != currentGLContext) {
1761 : printf_stderr("Fatal: %s called on non-current context %p. "
1762 : "The current context for this thread is %p.\n",
1763 0 : glFunction, this, currentGLContext);
1764 0 : NS_ABORT();
1765 : }
1766 : }
1767 0 : }
1768 :
1769 0 : void AfterGLCall(const char* glFunction) {
1770 0 : if (DebugMode()) {
1771 : // calling fFinish() immediately after every GL call makes sure that if this GL command crashes,
1772 : // the stack trace will actually point to it. Otherwise, OpenGL being an asynchronous API, stack traces
1773 : // tend to be meaningless
1774 0 : mSymbols.fFinish();
1775 0 : mGLError = mSymbols.fGetError();
1776 0 : if (DebugMode() & DebugTrace)
1777 0 : printf_stderr("[gl:%p] < %s [0x%04x]\n", this, glFunction, mGLError);
1778 0 : if (mGLError != LOCAL_GL_NO_ERROR) {
1779 : printf_stderr("GL ERROR: %s generated GL error %s(0x%04x)\n",
1780 : glFunction,
1781 : GLErrorToString(mGLError),
1782 0 : mGLError);
1783 0 : if (DebugMode() & DebugAbortOnError)
1784 0 : NS_ABORT();
1785 : }
1786 : }
1787 0 : }
1788 :
1789 0 : const char* GLErrorToString(GLenum aError)
1790 : {
1791 0 : switch (aError) {
1792 : case LOCAL_GL_INVALID_ENUM:
1793 0 : return "GL_INVALID_ENUM";
1794 : case LOCAL_GL_INVALID_VALUE:
1795 0 : return "GL_INVALID_VALUE";
1796 : case LOCAL_GL_INVALID_OPERATION:
1797 0 : return "GL_INVALID_OPERATION";
1798 : case LOCAL_GL_STACK_OVERFLOW:
1799 0 : return "GL_STACK_OVERFLOW";
1800 : case LOCAL_GL_STACK_UNDERFLOW:
1801 0 : return "GL_STACK_UNDERFLOW";
1802 : case LOCAL_GL_OUT_OF_MEMORY:
1803 0 : return "GL_OUT_OF_MEMORY";
1804 : case LOCAL_GL_TABLE_TOO_LARGE:
1805 0 : return "GL_TABLE_TOO_LARGE";
1806 : case LOCAL_GL_INVALID_FRAMEBUFFER_OPERATION:
1807 0 : return "GL_INVALID_FRAMEBUFFER_OPERATION";
1808 : default:
1809 0 : return "";
1810 : }
1811 : }
1812 :
1813 : #define BEFORE_GL_CALL do { \
1814 : BeforeGLCall(MOZ_FUNCTION_NAME); \
1815 : } while (0)
1816 :
1817 : #define AFTER_GL_CALL do { \
1818 : AfterGLCall(MOZ_FUNCTION_NAME); \
1819 : } while (0)
1820 :
1821 : #else
1822 :
1823 : #define BEFORE_GL_CALL do { } while (0)
1824 : #define AFTER_GL_CALL do { } while (0)
1825 :
1826 : #endif
1827 :
1828 : /*** In GL debug mode, we completely override glGetError ***/
1829 :
1830 : GLenum fGetError() {
1831 : #ifdef DEBUG
1832 : // debug mode ends up eating the error in AFTER_GL_CALL
1833 : if (DebugMode()) {
1834 : GLenum err = mGLError;
1835 : mGLError = LOCAL_GL_NO_ERROR;
1836 : return err;
1837 : }
1838 : #endif
1839 :
1840 : return mSymbols.fGetError();
1841 : }
1842 :
1843 :
1844 : /*** Scissor functions ***/
1845 :
1846 : protected:
1847 :
1848 : GLint FixYValue(GLint y, GLint height)
1849 : {
1850 : return mFlipped ? ViewportRect().height - (height + y) : y;
1851 : }
1852 :
1853 : // only does the glScissor call, no ScissorRect business
1854 : void raw_fScissor(GLint x, GLint y, GLsizei width, GLsizei height) {
1855 : BEFORE_GL_CALL;
1856 : // GL's coordinate system is flipped compared to ours (in the Y axis),
1857 : // so we may need to flip our rectangle.
1858 : mSymbols.fScissor(x,
1859 : FixYValue(y, height),
1860 : width,
1861 : height);
1862 : AFTER_GL_CALL;
1863 : }
1864 :
1865 : public:
1866 :
1867 : // but let GL-using code use that instead, updating the ScissorRect
1868 : void fScissor(GLint x, GLint y, GLsizei width, GLsizei height) {
1869 : ScissorRect().SetRect(x, y, width, height);
1870 : raw_fScissor(x, y, width, height);
1871 : }
1872 :
1873 : nsIntRect& ScissorRect() {
1874 : return mScissorStack[mScissorStack.Length()-1];
1875 : }
1876 :
1877 : void PushScissorRect() {
1878 : nsIntRect copy(ScissorRect());
1879 : mScissorStack.AppendElement(copy);
1880 : }
1881 :
1882 : void PushScissorRect(const nsIntRect& aRect) {
1883 : mScissorStack.AppendElement(aRect);
1884 : raw_fScissor(aRect.x, aRect.y, aRect.width, aRect.height);
1885 : }
1886 :
1887 : void PopScissorRect() {
1888 : if (mScissorStack.Length() < 2) {
1889 : NS_WARNING("PopScissorRect with Length < 2!");
1890 : return;
1891 : }
1892 :
1893 : nsIntRect thisRect = ScissorRect();
1894 : mScissorStack.TruncateLength(mScissorStack.Length() - 1);
1895 : if (!thisRect.IsEqualInterior(ScissorRect())) {
1896 : raw_fScissor(ScissorRect().x, ScissorRect().y,
1897 : ScissorRect().width, ScissorRect().height);
1898 : }
1899 : }
1900 :
1901 : /*** Viewport functions ***/
1902 :
1903 : protected:
1904 :
1905 : // only does the glViewport call, no ViewportRect business
1906 0 : void raw_fViewport(GLint x, GLint y, GLsizei width, GLsizei height) {
1907 0 : BEFORE_GL_CALL;
1908 : // XXX: Flipping should really happen using the destination height, but
1909 : // we use viewport instead and assume viewport size matches the
1910 : // destination. If we ever try use partial viewports for layers we need
1911 : // to fix this, and remove the assertion.
1912 0 : NS_ASSERTION(!mFlipped || (x == 0 && y == 0), "TODO: Need to flip the viewport rect");
1913 0 : mSymbols.fViewport(x, y, width, height);
1914 0 : AFTER_GL_CALL;
1915 0 : }
1916 :
1917 : public:
1918 :
1919 0 : void fViewport(GLint x, GLint y, GLsizei width, GLsizei height) {
1920 0 : ViewportRect().SetRect(x, y, width, height);
1921 0 : raw_fViewport(x, y, width, height);
1922 0 : }
1923 :
1924 0 : nsIntRect& ViewportRect() {
1925 0 : return mViewportStack[mViewportStack.Length()-1];
1926 : }
1927 :
1928 : void PushViewportRect() {
1929 : nsIntRect copy(ViewportRect());
1930 : mViewportStack.AppendElement(copy);
1931 : }
1932 :
1933 0 : void PushViewportRect(const nsIntRect& aRect) {
1934 0 : mViewportStack.AppendElement(aRect);
1935 0 : raw_fViewport(aRect.x, aRect.y, aRect.width, aRect.height);
1936 0 : }
1937 :
1938 0 : void PopViewportRect() {
1939 0 : if (mViewportStack.Length() < 2) {
1940 0 : NS_WARNING("PopViewportRect with Length < 2!");
1941 0 : return;
1942 : }
1943 :
1944 0 : nsIntRect thisRect = ViewportRect();
1945 0 : mViewportStack.TruncateLength(mViewportStack.Length() - 1);
1946 0 : if (!thisRect.IsEqualInterior(ViewportRect())) {
1947 0 : raw_fViewport(ViewportRect().x, ViewportRect().y,
1948 0 : ViewportRect().width, ViewportRect().height);
1949 : }
1950 : }
1951 :
1952 : /*** other GL functions ***/
1953 :
1954 0 : void fActiveTexture(GLenum texture) {
1955 0 : BEFORE_GL_CALL;
1956 0 : mSymbols.fActiveTexture(texture);
1957 0 : AFTER_GL_CALL;
1958 0 : }
1959 :
1960 0 : void fAttachShader(GLuint program, GLuint shader) {
1961 0 : BEFORE_GL_CALL;
1962 0 : mSymbols.fAttachShader(program, shader);
1963 0 : AFTER_GL_CALL;
1964 0 : }
1965 :
1966 0 : void fBindAttribLocation(GLuint program, GLuint index, const GLchar* name) {
1967 0 : BEFORE_GL_CALL;
1968 0 : mSymbols.fBindAttribLocation(program, index, name);
1969 0 : AFTER_GL_CALL;
1970 0 : }
1971 :
1972 0 : void fBindBuffer(GLenum target, GLuint buffer) {
1973 0 : BEFORE_GL_CALL;
1974 0 : mSymbols.fBindBuffer(target, buffer);
1975 0 : AFTER_GL_CALL;
1976 0 : }
1977 :
1978 0 : void fBindTexture(GLenum target, GLuint texture) {
1979 0 : BEFORE_GL_CALL;
1980 0 : mSymbols.fBindTexture(target, texture);
1981 0 : AFTER_GL_CALL;
1982 0 : }
1983 :
1984 : void fBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {
1985 : BEFORE_GL_CALL;
1986 : mSymbols.fBlendColor(red, green, blue, alpha);
1987 : AFTER_GL_CALL;
1988 : }
1989 :
1990 : void fBlendEquation(GLenum mode) {
1991 : BEFORE_GL_CALL;
1992 : mSymbols.fBlendEquation(mode);
1993 : AFTER_GL_CALL;
1994 : }
1995 :
1996 : void fBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha) {
1997 : BEFORE_GL_CALL;
1998 : mSymbols.fBlendEquationSeparate(modeRGB, modeAlpha);
1999 : AFTER_GL_CALL;
2000 : }
2001 :
2002 : void fBlendFunc(GLenum sfactor, GLenum dfactor) {
2003 : BEFORE_GL_CALL;
2004 : mSymbols.fBlendFunc(sfactor, dfactor);
2005 : AFTER_GL_CALL;
2006 : }
2007 :
2008 : void fBlendFuncSeparate(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha) {
2009 : BEFORE_GL_CALL;
2010 : mSymbols.fBlendFuncSeparate(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha);
2011 : AFTER_GL_CALL;
2012 : }
2013 :
2014 : void fBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage) {
2015 : BEFORE_GL_CALL;
2016 : mSymbols.fBufferData(target, size, data, usage);
2017 :
2018 : // bug 744888
2019 : if (!data &&
2020 : Vendor() == VendorNVIDIA)
2021 : {
2022 : char c = 0;
2023 : mSymbols.fBufferSubData(target, size-1, 1, &c);
2024 : }
2025 :
2026 : AFTER_GL_CALL;
2027 : }
2028 :
2029 : void fBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data) {
2030 : BEFORE_GL_CALL;
2031 : mSymbols.fBufferSubData(target, offset, size, data);
2032 : AFTER_GL_CALL;
2033 : }
2034 :
2035 0 : void raw_fClear(GLbitfield mask) {
2036 0 : BEFORE_GL_CALL;
2037 0 : mSymbols.fClear(mask);
2038 0 : AFTER_GL_CALL;
2039 0 : }
2040 :
2041 0 : void fClearColor(GLclampf r, GLclampf g, GLclampf b, GLclampf a) {
2042 0 : BEFORE_GL_CALL;
2043 0 : mSymbols.fClearColor(r, g, b, a);
2044 0 : AFTER_GL_CALL;
2045 0 : }
2046 :
2047 0 : void fClearStencil(GLint s) {
2048 0 : BEFORE_GL_CALL;
2049 0 : mSymbols.fClearStencil(s);
2050 0 : AFTER_GL_CALL;
2051 0 : }
2052 :
2053 0 : void fColorMask(realGLboolean red, realGLboolean green, realGLboolean blue, realGLboolean alpha) {
2054 0 : BEFORE_GL_CALL;
2055 0 : mSymbols.fColorMask(red, green, blue, alpha);
2056 0 : AFTER_GL_CALL;
2057 0 : }
2058 :
2059 : void fCullFace(GLenum mode) {
2060 : BEFORE_GL_CALL;
2061 : mSymbols.fCullFace(mode);
2062 : AFTER_GL_CALL;
2063 : }
2064 :
2065 : void fDetachShader(GLuint program, GLuint shader) {
2066 : BEFORE_GL_CALL;
2067 : mSymbols.fDetachShader(program, shader);
2068 : AFTER_GL_CALL;
2069 : }
2070 :
2071 : void fDepthFunc(GLenum func) {
2072 : BEFORE_GL_CALL;
2073 : mSymbols.fDepthFunc(func);
2074 : AFTER_GL_CALL;
2075 : }
2076 :
2077 0 : void fDepthMask(realGLboolean flag) {
2078 0 : BEFORE_GL_CALL;
2079 0 : mSymbols.fDepthMask(flag);
2080 0 : AFTER_GL_CALL;
2081 0 : }
2082 :
2083 0 : void fDisable(GLenum capability) {
2084 0 : BEFORE_GL_CALL;
2085 0 : mSymbols.fDisable(capability);
2086 0 : AFTER_GL_CALL;
2087 0 : }
2088 :
2089 0 : void fDisableVertexAttribArray(GLuint index) {
2090 0 : BEFORE_GL_CALL;
2091 0 : mSymbols.fDisableVertexAttribArray(index);
2092 0 : AFTER_GL_CALL;
2093 0 : }
2094 :
2095 0 : void raw_fDrawArrays(GLenum mode, GLint first, GLsizei count) {
2096 0 : BEFORE_GL_CALL;
2097 0 : mSymbols.fDrawArrays(mode, first, count);
2098 0 : AFTER_GL_CALL;
2099 0 : }
2100 :
2101 : void raw_fDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices) {
2102 : BEFORE_GL_CALL;
2103 : mSymbols.fDrawElements(mode, count, type, indices);
2104 : AFTER_GL_CALL;
2105 : }
2106 :
2107 0 : void fEnable(GLenum capability) {
2108 0 : BEFORE_GL_CALL;
2109 0 : mSymbols.fEnable(capability);
2110 0 : AFTER_GL_CALL;
2111 0 : }
2112 :
2113 0 : void fEnableVertexAttribArray(GLuint index) {
2114 0 : BEFORE_GL_CALL;
2115 0 : mSymbols.fEnableVertexAttribArray(index);
2116 0 : AFTER_GL_CALL;
2117 0 : }
2118 :
2119 0 : void raw_fFinish() {
2120 0 : BEFORE_GL_CALL;
2121 0 : mSymbols.fFinish();
2122 0 : AFTER_GL_CALL;
2123 0 : }
2124 :
2125 : void fFlush() {
2126 : BEFORE_GL_CALL;
2127 : mSymbols.fFlush();
2128 : AFTER_GL_CALL;
2129 : }
2130 :
2131 : void fFrontFace(GLenum face) {
2132 : BEFORE_GL_CALL;
2133 : mSymbols.fFrontFace(face);
2134 : AFTER_GL_CALL;
2135 : }
2136 :
2137 : void fGetActiveAttrib(GLuint program, GLuint index, GLsizei maxLength, GLsizei* length, GLint* size, GLenum* type, GLchar* name) {
2138 : BEFORE_GL_CALL;
2139 : mSymbols.fGetActiveAttrib(program, index, maxLength, length, size, type, name);
2140 : AFTER_GL_CALL;
2141 : }
2142 :
2143 : void fGetActiveUniform(GLuint program, GLuint index, GLsizei maxLength, GLsizei* length, GLint* size, GLenum* type, GLchar* name) {
2144 : BEFORE_GL_CALL;
2145 : mSymbols.fGetActiveUniform(program, index, maxLength, length, size, type, name);
2146 : AFTER_GL_CALL;
2147 : }
2148 :
2149 : void fGetAttachedShaders(GLuint program, GLsizei maxCount, GLsizei* count, GLuint* shaders) {
2150 : BEFORE_GL_CALL;
2151 : mSymbols.fGetAttachedShaders(program, maxCount, count, shaders);
2152 : AFTER_GL_CALL;
2153 : }
2154 :
2155 : GLint fGetAttribLocation (GLuint program, const GLchar* name) {
2156 : BEFORE_GL_CALL;
2157 : GLint retval = mSymbols.fGetAttribLocation(program, name);
2158 : AFTER_GL_CALL;
2159 : return retval;
2160 : }
2161 :
2162 : private:
2163 0 : void raw_fGetIntegerv(GLenum pname, GLint *params) {
2164 0 : BEFORE_GL_CALL;
2165 0 : mSymbols.fGetIntegerv(pname, params);
2166 0 : AFTER_GL_CALL;
2167 0 : }
2168 :
2169 : public:
2170 0 : void fGetIntegerv(GLenum pname, GLint *params) {
2171 0 : switch (pname)
2172 : {
2173 : // LOCAL_GL_FRAMEBUFFER_BINDING is equal to
2174 : // LOCAL_GL_DRAW_FRAMEBUFFER_BINDING_EXT, so we don't need two
2175 : // cases.
2176 : case LOCAL_GL_FRAMEBUFFER_BINDING:
2177 0 : *params = GetUserBoundDrawFBO();
2178 0 : break;
2179 :
2180 : case LOCAL_GL_READ_FRAMEBUFFER_BINDING_EXT:
2181 0 : *params = GetUserBoundReadFBO();
2182 0 : break;
2183 :
2184 : default:
2185 0 : raw_fGetIntegerv(pname, params);
2186 0 : break;
2187 : }
2188 0 : }
2189 :
2190 0 : void fGetFloatv(GLenum pname, GLfloat *params) {
2191 0 : BEFORE_GL_CALL;
2192 0 : mSymbols.fGetFloatv(pname, params);
2193 0 : AFTER_GL_CALL;
2194 0 : }
2195 :
2196 0 : void fGetBooleanv(GLenum pname, realGLboolean *params) {
2197 0 : BEFORE_GL_CALL;
2198 0 : mSymbols.fGetBooleanv(pname, params);
2199 0 : AFTER_GL_CALL;
2200 0 : }
2201 :
2202 : void fGetBufferParameteriv(GLenum target, GLenum pname, GLint* params) {
2203 : BEFORE_GL_CALL;
2204 : mSymbols.fGetBufferParameteriv(target, pname, params);
2205 : AFTER_GL_CALL;
2206 : }
2207 :
2208 : void fGenerateMipmap(GLenum target) {
2209 : BEFORE_GL_CALL;
2210 : mSymbols.fGenerateMipmap(target);
2211 : AFTER_GL_CALL;
2212 : }
2213 :
2214 0 : void fGetProgramiv(GLuint program, GLenum pname, GLint* param) {
2215 0 : BEFORE_GL_CALL;
2216 0 : mSymbols.fGetProgramiv(program, pname, param);
2217 0 : AFTER_GL_CALL;
2218 0 : }
2219 :
2220 0 : void fGetProgramInfoLog(GLuint program, GLsizei bufSize, GLsizei* length, GLchar* infoLog) {
2221 0 : BEFORE_GL_CALL;
2222 0 : mSymbols.fGetProgramInfoLog(program, bufSize, length, infoLog);
2223 0 : AFTER_GL_CALL;
2224 0 : }
2225 :
2226 0 : void fTexParameteri(GLenum target, GLenum pname, GLint param) {
2227 0 : BEFORE_GL_CALL;
2228 0 : mSymbols.fTexParameteri(target, pname, param);
2229 0 : AFTER_GL_CALL;
2230 0 : }
2231 :
2232 : void fTexParameterf(GLenum target, GLenum pname, GLfloat param) {
2233 : BEFORE_GL_CALL;
2234 : mSymbols.fTexParameterf(target, pname, param);
2235 : AFTER_GL_CALL;
2236 : }
2237 :
2238 0 : const GLubyte* fGetString(GLenum name) {
2239 0 : BEFORE_GL_CALL;
2240 0 : const GLubyte *result = mSymbols.fGetString(name);
2241 0 : AFTER_GL_CALL;
2242 0 : return result;
2243 : }
2244 :
2245 0 : void fGetTexImage(GLenum target, GLint level, GLenum format, GLenum type, GLvoid *img) {
2246 0 : if (!mSymbols.fGetTexImage) {
2247 0 : return;
2248 : }
2249 0 : BEFORE_GL_CALL;
2250 0 : mSymbols.fGetTexImage(target, level, format, type, img);
2251 0 : AFTER_GL_CALL;
2252 : };
2253 :
2254 0 : void fGetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint *params)
2255 : {
2256 0 : if (!mSymbols.fGetTexLevelParameteriv) {
2257 0 : *params = 0;
2258 0 : return;
2259 : }
2260 0 : BEFORE_GL_CALL;
2261 0 : mSymbols.fGetTexLevelParameteriv(target, level, pname, params);
2262 0 : AFTER_GL_CALL;
2263 : }
2264 :
2265 : void fGetTexParameterfv(GLenum target, GLenum pname, const GLfloat *params) {
2266 : BEFORE_GL_CALL;
2267 : mSymbols.fGetTexParameterfv(target, pname, params);
2268 : AFTER_GL_CALL;
2269 : }
2270 :
2271 : void fGetTexParameteriv(GLenum target, GLenum pname, const GLint *params) {
2272 : BEFORE_GL_CALL;
2273 : mSymbols.fGetTexParameteriv(target, pname, params);
2274 : AFTER_GL_CALL;
2275 : }
2276 :
2277 : void fGetUniformfv(GLuint program, GLint location, GLfloat* params) {
2278 : BEFORE_GL_CALL;
2279 : mSymbols.fGetUniformfv(program, location, params);
2280 : AFTER_GL_CALL;
2281 : }
2282 :
2283 : void fGetUniformiv(GLuint program, GLint location, GLint* params) {
2284 : BEFORE_GL_CALL;
2285 : mSymbols.fGetUniformiv(program, location, params);
2286 : AFTER_GL_CALL;
2287 : }
2288 :
2289 0 : GLint fGetUniformLocation (GLint programObj, const GLchar* name) {
2290 0 : BEFORE_GL_CALL;
2291 0 : GLint retval = mSymbols.fGetUniformLocation(programObj, name);
2292 0 : AFTER_GL_CALL;
2293 0 : return retval;
2294 : }
2295 :
2296 : void fGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* retval) {
2297 : BEFORE_GL_CALL;
2298 : mSymbols.fGetVertexAttribfv(index, pname, retval);
2299 : AFTER_GL_CALL;
2300 : }
2301 :
2302 : void fGetVertexAttribiv(GLuint index, GLenum pname, GLint* retval) {
2303 : BEFORE_GL_CALL;
2304 : mSymbols.fGetVertexAttribiv(index, pname, retval);
2305 : AFTER_GL_CALL;
2306 : }
2307 :
2308 : void fHint(GLenum target, GLenum mode) {
2309 : BEFORE_GL_CALL;
2310 : mSymbols.fHint(target, mode);
2311 : AFTER_GL_CALL;
2312 : }
2313 :
2314 : realGLboolean fIsBuffer(GLuint buffer) {
2315 : BEFORE_GL_CALL;
2316 : realGLboolean retval = mSymbols.fIsBuffer(buffer);
2317 : AFTER_GL_CALL;
2318 : return retval;
2319 : }
2320 :
2321 0 : realGLboolean fIsEnabled (GLenum capability) {
2322 0 : BEFORE_GL_CALL;
2323 0 : realGLboolean retval = mSymbols.fIsEnabled(capability);
2324 0 : AFTER_GL_CALL;
2325 0 : return retval;
2326 : }
2327 :
2328 : realGLboolean fIsProgram (GLuint program) {
2329 : BEFORE_GL_CALL;
2330 : realGLboolean retval = mSymbols.fIsProgram(program);
2331 : AFTER_GL_CALL;
2332 : return retval;
2333 : }
2334 :
2335 : realGLboolean fIsShader (GLuint shader) {
2336 : BEFORE_GL_CALL;
2337 : realGLboolean retval = mSymbols.fIsShader(shader);
2338 : AFTER_GL_CALL;
2339 : return retval;
2340 : }
2341 :
2342 : realGLboolean fIsTexture (GLuint texture) {
2343 : BEFORE_GL_CALL;
2344 : realGLboolean retval = mSymbols.fIsTexture(texture);
2345 : AFTER_GL_CALL;
2346 : return retval;
2347 : }
2348 :
2349 : void fLineWidth(GLfloat width) {
2350 : BEFORE_GL_CALL;
2351 : mSymbols.fLineWidth(width);
2352 : AFTER_GL_CALL;
2353 : }
2354 :
2355 0 : void fLinkProgram(GLuint program) {
2356 0 : BEFORE_GL_CALL;
2357 0 : mSymbols.fLinkProgram(program);
2358 0 : AFTER_GL_CALL;
2359 0 : }
2360 :
2361 0 : void fPixelStorei(GLenum pname, GLint param) {
2362 0 : BEFORE_GL_CALL;
2363 0 : mSymbols.fPixelStorei(pname, param);
2364 0 : AFTER_GL_CALL;
2365 0 : }
2366 :
2367 : void fPolygonOffset(GLfloat factor, GLfloat bias) {
2368 : BEFORE_GL_CALL;
2369 : mSymbols.fPolygonOffset(factor, bias);
2370 : AFTER_GL_CALL;
2371 : }
2372 :
2373 : void fReadBuffer(GLenum mode) {
2374 : BEFORE_GL_CALL;
2375 : mSymbols.fReadBuffer(mode);
2376 : AFTER_GL_CALL;
2377 : }
2378 :
2379 0 : void raw_fReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels) {
2380 0 : BEFORE_GL_CALL;
2381 0 : mSymbols.fReadPixels(x, y, width, height, format, type, pixels);
2382 0 : AFTER_GL_CALL;
2383 0 : }
2384 :
2385 : void fSampleCoverage(GLclampf value, realGLboolean invert) {
2386 : BEFORE_GL_CALL;
2387 : mSymbols.fSampleCoverage(value, invert);
2388 : AFTER_GL_CALL;
2389 : }
2390 :
2391 : void fStencilFunc(GLenum func, GLint ref, GLuint mask) {
2392 : BEFORE_GL_CALL;
2393 : mSymbols.fStencilFunc(func, ref, mask);
2394 : AFTER_GL_CALL;
2395 : }
2396 :
2397 : void fStencilFuncSeparate(GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask) {
2398 : BEFORE_GL_CALL;
2399 : mSymbols.fStencilFuncSeparate(frontfunc, backfunc, ref, mask);
2400 : AFTER_GL_CALL;
2401 : }
2402 :
2403 0 : void fStencilMask(GLuint mask) {
2404 0 : BEFORE_GL_CALL;
2405 0 : mSymbols.fStencilMask(mask);
2406 0 : AFTER_GL_CALL;
2407 0 : }
2408 :
2409 0 : void fStencilMaskSeparate(GLenum face, GLuint mask) {
2410 0 : BEFORE_GL_CALL;
2411 0 : mSymbols.fStencilMaskSeparate(face, mask);
2412 0 : AFTER_GL_CALL;
2413 0 : }
2414 :
2415 : void fStencilOp(GLenum fail, GLenum zfail, GLenum zpass) {
2416 : BEFORE_GL_CALL;
2417 : mSymbols.fStencilOp(fail, zfail, zpass);
2418 : AFTER_GL_CALL;
2419 : }
2420 :
2421 : void fStencilOpSeparate(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass) {
2422 : BEFORE_GL_CALL;
2423 : mSymbols.fStencilOpSeparate(face, sfail, dpfail, dppass);
2424 : AFTER_GL_CALL;
2425 : }
2426 :
2427 0 : void fTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels) {
2428 0 : BEFORE_GL_CALL;
2429 0 : if (IsTextureSizeSafeToPassToDriver(target, width, height)) {
2430 0 : mSymbols.fTexImage2D(target, level, internalformat, width, height, border, format, type, pixels);
2431 : } else {
2432 : // pass wrong values to cause the GL to generate GL_INVALID_VALUE.
2433 : // See bug 737182 and the comment in IsTextureSizeSafeToPassToDriver.
2434 0 : mSymbols.fTexImage2D(target, -1, internalformat, -1, -1, -1, format, type, nsnull);
2435 : }
2436 0 : AFTER_GL_CALL;
2437 0 : }
2438 :
2439 0 : void fTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels) {
2440 0 : BEFORE_GL_CALL;
2441 0 : mSymbols.fTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
2442 0 : AFTER_GL_CALL;
2443 0 : }
2444 :
2445 : void fUniform1f(GLint location, GLfloat v0) {
2446 : BEFORE_GL_CALL;
2447 : mSymbols.fUniform1f(location, v0);
2448 : AFTER_GL_CALL;
2449 : }
2450 :
2451 : void fUniform1fv(GLint location, GLsizei count, const GLfloat* value) {
2452 : BEFORE_GL_CALL;
2453 : mSymbols.fUniform1fv(location, count, value);
2454 : AFTER_GL_CALL;
2455 : }
2456 :
2457 0 : void fUniform1i(GLint location, GLint v0) {
2458 0 : BEFORE_GL_CALL;
2459 0 : mSymbols.fUniform1i(location, v0);
2460 0 : AFTER_GL_CALL;
2461 0 : }
2462 :
2463 : void fUniform1iv(GLint location, GLsizei count, const GLint* value) {
2464 : BEFORE_GL_CALL;
2465 : mSymbols.fUniform1iv(location, count, value);
2466 : AFTER_GL_CALL;
2467 : }
2468 :
2469 : void fUniform2f(GLint location, GLfloat v0, GLfloat v1) {
2470 : BEFORE_GL_CALL;
2471 : mSymbols.fUniform2f(location, v0, v1);
2472 : AFTER_GL_CALL;
2473 : }
2474 :
2475 : void fUniform2fv(GLint location, GLsizei count, const GLfloat* value) {
2476 : BEFORE_GL_CALL;
2477 : mSymbols.fUniform2fv(location, count, value);
2478 : AFTER_GL_CALL;
2479 : }
2480 :
2481 : void fUniform2i(GLint location, GLint v0, GLint v1) {
2482 : BEFORE_GL_CALL;
2483 : mSymbols.fUniform2i(location, v0, v1);
2484 : AFTER_GL_CALL;
2485 : }
2486 :
2487 : void fUniform2iv(GLint location, GLsizei count, const GLint* value) {
2488 : BEFORE_GL_CALL;
2489 : mSymbols.fUniform2iv(location, count, value);
2490 : AFTER_GL_CALL;
2491 : }
2492 :
2493 : void fUniform3f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2) {
2494 : BEFORE_GL_CALL;
2495 : mSymbols.fUniform3f(location, v0, v1, v2);
2496 : AFTER_GL_CALL;
2497 : }
2498 :
2499 : void fUniform3fv(GLint location, GLsizei count, const GLfloat* value) {
2500 : BEFORE_GL_CALL;
2501 : mSymbols.fUniform3fv(location, count, value);
2502 : AFTER_GL_CALL;
2503 : }
2504 :
2505 : void fUniform3i(GLint location, GLint v0, GLint v1, GLint v2) {
2506 : BEFORE_GL_CALL;
2507 : mSymbols.fUniform3i(location, v0, v1, v2);
2508 : AFTER_GL_CALL;
2509 : }
2510 :
2511 : void fUniform3iv(GLint location, GLsizei count, const GLint* value) {
2512 : BEFORE_GL_CALL;
2513 : mSymbols.fUniform3iv(location, count, value);
2514 : AFTER_GL_CALL;
2515 : }
2516 :
2517 : void fUniform4f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
2518 : BEFORE_GL_CALL;
2519 : mSymbols.fUniform4f(location, v0, v1, v2, v3);
2520 : AFTER_GL_CALL;
2521 : }
2522 :
2523 : void fUniform4fv(GLint location, GLsizei count, const GLfloat* value) {
2524 : BEFORE_GL_CALL;
2525 : mSymbols.fUniform4fv(location, count, value);
2526 : AFTER_GL_CALL;
2527 : }
2528 :
2529 : void fUniform4i(GLint location, GLint v0, GLint v1, GLint v2, GLint v3) {
2530 : BEFORE_GL_CALL;
2531 : mSymbols.fUniform4i(location, v0, v1, v2, v3);
2532 : AFTER_GL_CALL;
2533 : }
2534 :
2535 : void fUniform4iv(GLint location, GLsizei count, const GLint* value) {
2536 : BEFORE_GL_CALL;
2537 : mSymbols.fUniform4iv(location, count, value);
2538 : AFTER_GL_CALL;
2539 : }
2540 :
2541 : void fUniformMatrix2fv(GLint location, GLsizei count, realGLboolean transpose, const GLfloat* value) {
2542 : BEFORE_GL_CALL;
2543 : mSymbols.fUniformMatrix2fv(location, count, transpose, value);
2544 : AFTER_GL_CALL;
2545 : }
2546 :
2547 : void fUniformMatrix3fv(GLint location, GLsizei count, realGLboolean transpose, const GLfloat* value) {
2548 : BEFORE_GL_CALL;
2549 : mSymbols.fUniformMatrix3fv(location, count, transpose, value);
2550 : AFTER_GL_CALL;
2551 : }
2552 :
2553 : void fUniformMatrix4fv(GLint location, GLsizei count, realGLboolean transpose, const GLfloat* value) {
2554 : BEFORE_GL_CALL;
2555 : mSymbols.fUniformMatrix4fv(location, count, transpose, value);
2556 : AFTER_GL_CALL;
2557 : }
2558 :
2559 0 : void fUseProgram(GLuint program) {
2560 0 : BEFORE_GL_CALL;
2561 0 : mSymbols.fUseProgram(program);
2562 0 : AFTER_GL_CALL;
2563 0 : }
2564 :
2565 : void fValidateProgram(GLuint program) {
2566 : BEFORE_GL_CALL;
2567 : mSymbols.fValidateProgram(program);
2568 : AFTER_GL_CALL;
2569 : }
2570 :
2571 0 : void fVertexAttribPointer(GLuint index, GLint size, GLenum type, realGLboolean normalized, GLsizei stride, const GLvoid* pointer) {
2572 0 : BEFORE_GL_CALL;
2573 0 : mSymbols.fVertexAttribPointer(index, size, type, normalized, stride, pointer);
2574 0 : AFTER_GL_CALL;
2575 0 : }
2576 :
2577 : void fVertexAttrib1f(GLuint index, GLfloat x) {
2578 : BEFORE_GL_CALL;
2579 : mSymbols.fVertexAttrib1f(index, x);
2580 : AFTER_GL_CALL;
2581 : }
2582 :
2583 : void fVertexAttrib2f(GLuint index, GLfloat x, GLfloat y) {
2584 : BEFORE_GL_CALL;
2585 : mSymbols.fVertexAttrib2f(index, x, y);
2586 : AFTER_GL_CALL;
2587 : }
2588 :
2589 : void fVertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z) {
2590 : BEFORE_GL_CALL;
2591 : mSymbols.fVertexAttrib3f(index, x, y, z);
2592 : AFTER_GL_CALL;
2593 : }
2594 :
2595 : void fVertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) {
2596 : BEFORE_GL_CALL;
2597 : mSymbols.fVertexAttrib4f(index, x, y, z, w);
2598 : AFTER_GL_CALL;
2599 : }
2600 :
2601 : void fVertexAttrib1fv(GLuint index, const GLfloat* v) {
2602 : BEFORE_GL_CALL;
2603 : mSymbols.fVertexAttrib1fv(index, v);
2604 : AFTER_GL_CALL;
2605 : }
2606 :
2607 : void fVertexAttrib2fv(GLuint index, const GLfloat* v) {
2608 : BEFORE_GL_CALL;
2609 : mSymbols.fVertexAttrib2fv(index, v);
2610 : AFTER_GL_CALL;
2611 : }
2612 :
2613 : void fVertexAttrib3fv(GLuint index, const GLfloat* v) {
2614 : BEFORE_GL_CALL;
2615 : mSymbols.fVertexAttrib3fv(index, v);
2616 : AFTER_GL_CALL;
2617 : }
2618 :
2619 : void fVertexAttrib4fv(GLuint index, const GLfloat* v) {
2620 : BEFORE_GL_CALL;
2621 : mSymbols.fVertexAttrib4fv(index, v);
2622 : AFTER_GL_CALL;
2623 : }
2624 :
2625 0 : void fCompileShader(GLuint shader) {
2626 0 : BEFORE_GL_CALL;
2627 0 : mSymbols.fCompileShader(shader);
2628 0 : AFTER_GL_CALL;
2629 0 : }
2630 :
2631 : void raw_fCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) {
2632 : BEFORE_GL_CALL;
2633 : if (IsTextureSizeSafeToPassToDriver(target, width, height)) {
2634 : mSymbols.fCopyTexImage2D(target, level, internalformat,
2635 : x, FixYValue(y, height),
2636 : width, height, border);
2637 :
2638 : } else {
2639 : // pass wrong values to cause the GL to generate GL_INVALID_VALUE.
2640 : // See bug 737182 and the comment in IsTextureSizeSafeToPassToDriver.
2641 : mSymbols.fCopyTexImage2D(target, -1, internalformat,
2642 : x, FixYValue(y, height),
2643 : -1, -1, -1);
2644 :
2645 : }
2646 : AFTER_GL_CALL;
2647 : }
2648 :
2649 : void raw_fCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) {
2650 : BEFORE_GL_CALL;
2651 : mSymbols.fCopyTexSubImage2D(target, level, xoffset, yoffset,
2652 : x, FixYValue(y, height),
2653 : width, height);
2654 : AFTER_GL_CALL;
2655 : }
2656 :
2657 0 : void fGetShaderiv(GLuint shader, GLenum pname, GLint* param) {
2658 0 : BEFORE_GL_CALL;
2659 0 : mSymbols.fGetShaderiv(shader, pname, param);
2660 0 : AFTER_GL_CALL;
2661 0 : }
2662 :
2663 0 : void fGetShaderInfoLog(GLuint shader, GLsizei bufSize, GLsizei* length, GLchar* infoLog) {
2664 0 : BEFORE_GL_CALL;
2665 0 : mSymbols.fGetShaderInfoLog(shader, bufSize, length, infoLog);
2666 0 : AFTER_GL_CALL;
2667 0 : }
2668 :
2669 : void fGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) {
2670 : BEFORE_GL_CALL;
2671 : if (mIsGLES2) {
2672 : mSymbols.fGetShaderPrecisionFormat(shadertype, precisiontype, range, precision);
2673 : } else {
2674 : // Fall back to automatic values because almost all desktop hardware supports the OpenGL standard precisions.
2675 : GetShaderPrecisionFormatNonES2(shadertype, precisiontype, range, precision);
2676 : }
2677 : AFTER_GL_CALL;
2678 : }
2679 :
2680 : void fGetShaderSource(GLint obj, GLsizei maxLength, GLsizei* length, GLchar* source) {
2681 : BEFORE_GL_CALL;
2682 : mSymbols.fGetShaderSource(obj, maxLength, length, source);
2683 : AFTER_GL_CALL;
2684 : }
2685 :
2686 0 : void fShaderSource(GLuint shader, GLsizei count, const GLchar** strings, const GLint* lengths) {
2687 0 : BEFORE_GL_CALL;
2688 0 : mSymbols.fShaderSource(shader, count, strings, lengths);
2689 0 : AFTER_GL_CALL;
2690 0 : }
2691 :
2692 : private:
2693 0 : void raw_fBindFramebuffer(GLenum target, GLuint framebuffer) {
2694 0 : BEFORE_GL_CALL;
2695 0 : mSymbols.fBindFramebuffer(target, framebuffer);
2696 0 : AFTER_GL_CALL;
2697 0 : }
2698 :
2699 : public:
2700 0 : void fBindRenderbuffer(GLenum target, GLuint renderbuffer) {
2701 0 : BEFORE_GL_CALL;
2702 0 : mSymbols.fBindRenderbuffer(target, renderbuffer);
2703 0 : AFTER_GL_CALL;
2704 0 : }
2705 :
2706 0 : GLenum fCheckFramebufferStatus (GLenum target) {
2707 0 : BEFORE_GL_CALL;
2708 0 : GLenum retval = mSymbols.fCheckFramebufferStatus(target);
2709 0 : AFTER_GL_CALL;
2710 0 : return retval;
2711 : }
2712 :
2713 0 : void fFramebufferRenderbuffer(GLenum target, GLenum attachmentPoint, GLenum renderbufferTarget, GLuint renderbuffer) {
2714 0 : BEFORE_GL_CALL;
2715 0 : mSymbols.fFramebufferRenderbuffer(target, attachmentPoint, renderbufferTarget, renderbuffer);
2716 0 : AFTER_GL_CALL;
2717 0 : }
2718 :
2719 0 : void fFramebufferTexture2D(GLenum target, GLenum attachmentPoint, GLenum textureTarget, GLuint texture, GLint level) {
2720 0 : BEFORE_GL_CALL;
2721 0 : mSymbols.fFramebufferTexture2D(target, attachmentPoint, textureTarget, texture, level);
2722 0 : AFTER_GL_CALL;
2723 0 : }
2724 :
2725 : void fGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* value) {
2726 : BEFORE_GL_CALL;
2727 : mSymbols.fGetFramebufferAttachmentParameteriv(target, attachment, pname, value);
2728 : AFTER_GL_CALL;
2729 : }
2730 :
2731 : void fGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* value) {
2732 : BEFORE_GL_CALL;
2733 : mSymbols.fGetRenderbufferParameteriv(target, pname, value);
2734 : AFTER_GL_CALL;
2735 : }
2736 :
2737 : realGLboolean fIsFramebuffer (GLuint framebuffer) {
2738 : BEFORE_GL_CALL;
2739 : realGLboolean retval = mSymbols.fIsFramebuffer(framebuffer);
2740 : AFTER_GL_CALL;
2741 : return retval;
2742 : }
2743 :
2744 0 : void raw_fBlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) {
2745 0 : BEFORE_GL_CALL;
2746 0 : mSymbols.fBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
2747 0 : AFTER_GL_CALL;
2748 0 : }
2749 :
2750 : realGLboolean fIsRenderbuffer (GLuint renderbuffer) {
2751 : BEFORE_GL_CALL;
2752 : realGLboolean retval = mSymbols.fIsRenderbuffer(renderbuffer);
2753 : AFTER_GL_CALL;
2754 : return retval;
2755 : }
2756 :
2757 0 : void fRenderbufferStorage(GLenum target, GLenum internalFormat, GLsizei width, GLsizei height) {
2758 0 : BEFORE_GL_CALL;
2759 0 : mSymbols.fRenderbufferStorage(target, internalFormat, width, height);
2760 0 : AFTER_GL_CALL;
2761 0 : }
2762 :
2763 0 : void fRenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height) {
2764 0 : BEFORE_GL_CALL;
2765 0 : mSymbols.fRenderbufferStorageMultisample(target, samples, internalFormat, width, height);
2766 0 : AFTER_GL_CALL;
2767 0 : }
2768 :
2769 : void fDepthRange(GLclampf a, GLclampf b) {
2770 : BEFORE_GL_CALL;
2771 : if (mIsGLES2) {
2772 : mSymbols.fDepthRangef(a, b);
2773 : } else {
2774 : mSymbols.fDepthRange(a, b);
2775 : }
2776 : AFTER_GL_CALL;
2777 : }
2778 :
2779 0 : void fClearDepth(GLclampf v) {
2780 0 : BEFORE_GL_CALL;
2781 0 : if (mIsGLES2) {
2782 0 : mSymbols.fClearDepthf(v);
2783 : } else {
2784 0 : mSymbols.fClearDepth(v);
2785 : }
2786 0 : AFTER_GL_CALL;
2787 0 : }
2788 :
2789 : void* fMapBuffer(GLenum target, GLenum access) {
2790 : BEFORE_GL_CALL;
2791 : void *ret = mSymbols.fMapBuffer(target, access);
2792 : AFTER_GL_CALL;
2793 : return ret;
2794 : }
2795 :
2796 : realGLboolean fUnmapBuffer(GLenum target) {
2797 : BEFORE_GL_CALL;
2798 : realGLboolean ret = mSymbols.fUnmapBuffer(target);
2799 : AFTER_GL_CALL;
2800 : return ret;
2801 : }
2802 :
2803 :
2804 : #ifdef DEBUG
2805 0 : GLContext *TrackingContext() {
2806 0 : GLContext *tip = this;
2807 0 : while (tip->mSharedContext)
2808 0 : tip = tip->mSharedContext;
2809 0 : return tip;
2810 : }
2811 :
2812 : #define TRACKING_CONTEXT(a) do { TrackingContext()->a; } while (0)
2813 : #else
2814 : #define TRACKING_CONTEXT(a) do {} while (0)
2815 : #endif
2816 :
2817 0 : GLuint GLAPIENTRY fCreateProgram() {
2818 0 : BEFORE_GL_CALL;
2819 0 : GLuint ret = mSymbols.fCreateProgram();
2820 0 : AFTER_GL_CALL;
2821 0 : TRACKING_CONTEXT(CreatedProgram(this, ret));
2822 0 : return ret;
2823 : }
2824 :
2825 0 : GLuint GLAPIENTRY fCreateShader(GLenum t) {
2826 0 : BEFORE_GL_CALL;
2827 0 : GLuint ret = mSymbols.fCreateShader(t);
2828 0 : AFTER_GL_CALL;
2829 0 : TRACKING_CONTEXT(CreatedShader(this, ret));
2830 0 : return ret;
2831 : }
2832 :
2833 : void GLAPIENTRY fGenBuffers(GLsizei n, GLuint* names) {
2834 : BEFORE_GL_CALL;
2835 : mSymbols.fGenBuffers(n, names);
2836 : AFTER_GL_CALL;
2837 : TRACKING_CONTEXT(CreatedBuffers(this, n, names));
2838 : }
2839 :
2840 0 : void GLAPIENTRY fGenTextures(GLsizei n, GLuint* names) {
2841 0 : BEFORE_GL_CALL;
2842 0 : mSymbols.fGenTextures(n, names);
2843 0 : AFTER_GL_CALL;
2844 0 : TRACKING_CONTEXT(CreatedTextures(this, n, names));
2845 0 : }
2846 :
2847 0 : void GLAPIENTRY fGenFramebuffers(GLsizei n, GLuint* names) {
2848 0 : BEFORE_GL_CALL;
2849 0 : mSymbols.fGenFramebuffers(n, names);
2850 0 : AFTER_GL_CALL;
2851 0 : TRACKING_CONTEXT(CreatedFramebuffers(this, n, names));
2852 0 : }
2853 :
2854 0 : void GLAPIENTRY fGenRenderbuffers(GLsizei n, GLuint* names) {
2855 0 : BEFORE_GL_CALL;
2856 0 : mSymbols.fGenRenderbuffers(n, names);
2857 0 : AFTER_GL_CALL;
2858 0 : TRACKING_CONTEXT(CreatedRenderbuffers(this, n, names));
2859 0 : }
2860 :
2861 0 : void GLAPIENTRY fDeleteProgram(GLuint program) {
2862 0 : BEFORE_GL_CALL;
2863 0 : mSymbols.fDeleteProgram(program);
2864 0 : AFTER_GL_CALL;
2865 0 : TRACKING_CONTEXT(DeletedProgram(this, program));
2866 0 : }
2867 :
2868 0 : void GLAPIENTRY fDeleteShader(GLuint shader) {
2869 0 : BEFORE_GL_CALL;
2870 0 : mSymbols.fDeleteShader(shader);
2871 0 : AFTER_GL_CALL;
2872 0 : TRACKING_CONTEXT(DeletedShader(this, shader));
2873 0 : }
2874 :
2875 : void GLAPIENTRY fDeleteBuffers(GLsizei n, GLuint *names) {
2876 : BEFORE_GL_CALL;
2877 : mSymbols.fDeleteBuffers(n, names);
2878 : AFTER_GL_CALL;
2879 : TRACKING_CONTEXT(DeletedBuffers(this, n, names));
2880 : }
2881 :
2882 0 : void GLAPIENTRY fDeleteTextures(GLsizei n, GLuint *names) {
2883 0 : BEFORE_GL_CALL;
2884 0 : mSymbols.fDeleteTextures(n, names);
2885 0 : AFTER_GL_CALL;
2886 0 : TRACKING_CONTEXT(DeletedTextures(this, n, names));
2887 0 : }
2888 :
2889 0 : void GLAPIENTRY fDeleteFramebuffers(GLsizei n, GLuint *names) {
2890 0 : BEFORE_GL_CALL;
2891 0 : if (n == 1 && *names == 0) {
2892 : /* Deleting framebuffer 0 causes hangs on the DROID. See bug 623228 */
2893 : } else {
2894 0 : mSymbols.fDeleteFramebuffers(n, names);
2895 : }
2896 0 : AFTER_GL_CALL;
2897 0 : TRACKING_CONTEXT(DeletedFramebuffers(this, n, names));
2898 0 : }
2899 :
2900 0 : void GLAPIENTRY fDeleteRenderbuffers(GLsizei n, GLuint *names) {
2901 0 : BEFORE_GL_CALL;
2902 0 : mSymbols.fDeleteRenderbuffers(n, names);
2903 0 : AFTER_GL_CALL;
2904 0 : TRACKING_CONTEXT(DeletedRenderbuffers(this, n, names));
2905 0 : }
2906 :
2907 : GLenum GLAPIENTRY fGetGraphicsResetStatus() {
2908 : BEFORE_GL_CALL;
2909 : GLenum ret = mHasRobustness ? mSymbols.fGetGraphicsResetStatus() : 0;
2910 : AFTER_GL_CALL;
2911 : return ret;
2912 : }
2913 :
2914 : #ifdef DEBUG
2915 : void THEBES_API CreatedProgram(GLContext *aOrigin, GLuint aName);
2916 : void THEBES_API CreatedShader(GLContext *aOrigin, GLuint aName);
2917 : void THEBES_API CreatedBuffers(GLContext *aOrigin, GLsizei aCount, GLuint *aNames);
2918 : void THEBES_API CreatedTextures(GLContext *aOrigin, GLsizei aCount, GLuint *aNames);
2919 : void THEBES_API CreatedFramebuffers(GLContext *aOrigin, GLsizei aCount, GLuint *aNames);
2920 : void THEBES_API CreatedRenderbuffers(GLContext *aOrigin, GLsizei aCount, GLuint *aNames);
2921 : void THEBES_API DeletedProgram(GLContext *aOrigin, GLuint aName);
2922 : void THEBES_API DeletedShader(GLContext *aOrigin, GLuint aName);
2923 : void THEBES_API DeletedBuffers(GLContext *aOrigin, GLsizei aCount, GLuint *aNames);
2924 : void THEBES_API DeletedTextures(GLContext *aOrigin, GLsizei aCount, GLuint *aNames);
2925 : void THEBES_API DeletedFramebuffers(GLContext *aOrigin, GLsizei aCount, GLuint *aNames);
2926 : void THEBES_API DeletedRenderbuffers(GLContext *aOrigin, GLsizei aCount, GLuint *aNames);
2927 :
2928 : void SharedContextDestroyed(GLContext *aChild);
2929 : void ReportOutstandingNames();
2930 :
2931 0 : struct NamedResource {
2932 : NamedResource()
2933 : : origin(nsnull), name(0), originDeleted(false)
2934 : { }
2935 :
2936 0 : NamedResource(GLContext *aOrigin, GLuint aName)
2937 0 : : origin(aOrigin), name(aName), originDeleted(false)
2938 0 : { }
2939 :
2940 : GLContext *origin;
2941 : GLuint name;
2942 : bool originDeleted;
2943 :
2944 : // for sorting
2945 0 : bool operator<(const NamedResource& aOther) const {
2946 0 : if (intptr_t(origin) < intptr_t(aOther.origin))
2947 0 : return true;
2948 0 : if (name < aOther.name)
2949 0 : return true;
2950 0 : return false;
2951 : }
2952 0 : bool operator==(const NamedResource& aOther) const {
2953 : return origin == aOther.origin &&
2954 : name == aOther.name &&
2955 0 : originDeleted == aOther.originDeleted;
2956 : }
2957 : };
2958 :
2959 : nsTArray<NamedResource> mTrackedPrograms;
2960 : nsTArray<NamedResource> mTrackedShaders;
2961 : nsTArray<NamedResource> mTrackedTextures;
2962 : nsTArray<NamedResource> mTrackedFramebuffers;
2963 : nsTArray<NamedResource> mTrackedRenderbuffers;
2964 : nsTArray<NamedResource> mTrackedBuffers;
2965 : #endif
2966 :
2967 : };
2968 :
2969 : inline bool
2970 0 : DoesStringMatch(const char* aString, const char *aWantedString)
2971 : {
2972 0 : if (!aString || !aWantedString)
2973 0 : return false;
2974 :
2975 0 : const char *occurrence = strstr(aString, aWantedString);
2976 :
2977 : // aWanted not found
2978 0 : if (!occurrence)
2979 0 : return false;
2980 :
2981 : // aWantedString preceded by alpha character
2982 0 : if (occurrence != aString && isalpha(*(occurrence-1)))
2983 0 : return false;
2984 :
2985 : // aWantedVendor followed by alpha character
2986 0 : const char *afterOccurrence = occurrence + strlen(aWantedString);
2987 0 : if (isalpha(*afterOccurrence))
2988 0 : return false;
2989 :
2990 0 : return true;
2991 : }
2992 :
2993 : } /* namespace gl */
2994 : } /* namespace mozilla */
2995 :
2996 : #endif /* GLCONTEXT_H_ */
|