1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "mozilla/ArrayUtils.h"
8 #include "GLContextEGL.h"
14 // we're using default display for now
15 #define GET_NATIVE_WINDOW(aWidget) (EGLNativeWindowType)GDK_WINDOW_XID((GdkWindow *) aWidget->GetNativeData(NS_NATIVE_WINDOW))
16 #elif defined(MOZ_WIDGET_QT)
17 #define GET_NATIVE_WINDOW(aWidget) (EGLNativeWindowType)(aWidget->GetNativeData(NS_NATIVE_SHAREABLE_WINDOW))
18 #elif defined(MOZ_WIDGET_GONK)
19 #define GET_NATIVE_WINDOW(aWidget) ((EGLNativeWindowType)aWidget->GetNativeData(NS_NATIVE_WINDOW))
20 #include "HwcComposer2D.h"
21 #include "libdisplay/GonkDisplay.h"
26 #if defined(MOZ_WIDGET_ANDROID)
27 #include "AndroidBridge.h"
30 #include <android/log.h>
31 #define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "Gonk" , ## args)
33 # if defined(MOZ_WIDGET_GONK)
34 # include "cutils/properties.h"
35 # include <ui/GraphicBuffer.h>
37 using namespace android
;
42 #define GLES2_LIB "libGLESv2.so"
43 #define GLES2_LIB2 "libGLESv2.so.2"
49 #define GLES2_LIB "libGLESv2.dll"
51 #ifndef WIN32_LEAN_AND_MEAN
52 #define WIN32_LEAN_AND_MEAN 1
58 class AutoDestroyHWND
{
60 AutoDestroyHWND(HWND aWnd
= nullptr)
67 ::DestroyWindow(mWnd
);
81 HWND
operator=(HWND aWnd
) {
82 if (mWnd
&& mWnd
!= aWnd
) {
83 ::DestroyWindow(mWnd
);
94 #error "Platform not recognized"
98 #include "mozilla/Preferences.h"
100 #include "gfxFailure.h"
101 #include "gfxASurface.h"
102 #include "gfxPlatform.h"
103 #include "GLContextProvider.h"
104 #include "GLLibraryEGL.h"
105 #include "TextureImageEGL.h"
107 #include "nsThreadUtils.h"
109 #include "nsIWidget.h"
111 #include "gfxCrashReporterUtils.h"
113 #include "ScopedGLHelpers.h"
114 #include "GLBlitHelper.h"
116 using namespace mozilla::gfx
;
121 #define ADD_ATTR_2(_array, _k, _v) do { \
122 (_array).AppendElement(_k); \
123 (_array).AppendElement(_v); \
126 #define ADD_ATTR_1(_array, _k) do { \
127 (_array).AppendElement(_k); \
131 CreateConfig(EGLConfig
* aConfig
);
133 // append three zeros at the end of attribs list to work around
134 // EGL implementation bugs that iterate until they find 0, instead of
135 // EGL_NONE. See bug 948406.
136 #define EGL_ATTRIBS_LIST_SAFE_TERMINATION_WORKING_AROUND_BUGS \
137 LOCAL_EGL_NONE, 0, 0, 0
139 static EGLint gTerminationAttribs
[] = {
140 EGL_ATTRIBS_LIST_SAFE_TERMINATION_WORKING_AROUND_BUGS
143 static EGLint gContextAttribs
[] = {
144 LOCAL_EGL_CONTEXT_CLIENT_VERSION
, 2,
145 EGL_ATTRIBS_LIST_SAFE_TERMINATION_WORKING_AROUND_BUGS
148 static EGLint gContextAttribsRobustness
[] = {
149 LOCAL_EGL_CONTEXT_CLIENT_VERSION
, 2,
150 //LOCAL_EGL_CONTEXT_ROBUST_ACCESS_EXT, LOCAL_EGL_TRUE,
151 LOCAL_EGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_EXT
, LOCAL_EGL_LOSE_CONTEXT_ON_RESET_EXT
,
152 EGL_ATTRIBS_LIST_SAFE_TERMINATION_WORKING_AROUND_BUGS
156 next_power_of_two(int v
)
170 is_power_of_two(int v
)
172 NS_ASSERTION(v
>= 0, "bad value");
177 return (v
& (v
-1)) == 0;
181 DestroySurface(EGLSurface oldSurface
) {
182 if (oldSurface
!= EGL_NO_SURFACE
) {
183 sEGLLibrary
.fMakeCurrent(EGL_DISPLAY(),
184 EGL_NO_SURFACE
, EGL_NO_SURFACE
,
186 sEGLLibrary
.fDestroySurface(EGL_DISPLAY(), oldSurface
);
191 CreateSurfaceForWindow(nsIWidget
* widget
, const EGLConfig
& config
) {
192 EGLSurface newSurface
= EGL_NO_SURFACE
;
194 #ifdef MOZ_WIDGET_ANDROID
195 mozilla::AndroidBridge::Bridge()->RegisterCompositor();
196 newSurface
= mozilla::AndroidBridge::Bridge()->CreateEGLSurfaceForCompositor();
197 if (newSurface
== EGL_NO_SURFACE
) {
198 return EGL_NO_SURFACE
;
201 MOZ_ASSERT(widget
!= nullptr);
202 newSurface
= sEGLLibrary
.fCreateWindowSurface(EGL_DISPLAY(), config
, GET_NATIVE_WINDOW(widget
), 0);
207 GLContextEGL::GLContextEGL(
208 const SurfaceCaps
& caps
,
209 GLContext
* shareContext
,
214 : GLContext(caps
, shareContext
, isOffscreen
)
217 , mSurfaceOverride(EGL_NO_SURFACE
)
219 , mThebesSurface(nullptr)
222 , mIsDoubleBuffered(false)
223 , mCanBindToTexture(false)
224 , mShareWithEGLImage(false)
227 // any EGL contexts will always be GLESv2
228 SetProfileVersion(ContextProfile::OpenGLES
, 200);
231 printf_stderr("Initializing context %p surface %p on display %p\n", mContext
, mSurface
, EGL_DISPLAY());
233 #if defined(MOZ_WIDGET_GONK)
235 mHwc
= HwcComposer2D::GetInstance();
236 MOZ_ASSERT(!mHwc
->Initialized());
238 if (mHwc
->Init(EGL_DISPLAY(), mSurface
, this)) {
239 NS_WARNING("HWComposer initialization failed!");
246 GLContextEGL::~GLContextEGL()
250 // Wrapped context should not destroy eglContext/Surface
256 printf_stderr("Destroying context %p surface %p on display %p\n", mContext
, mSurface
, EGL_DISPLAY());
259 sEGLLibrary
.fDestroyContext(EGL_DISPLAY(), mContext
);
260 sEGLLibrary
.UnsetCachedCurrentContext();
262 #if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION < 17
264 // In ICS, SurfaceFlinger's DisplayHardware::fini() does not destroy the EGLSurface associated with the
265 // native framebuffer. Destroying it causes crashes in the ICS emulator
266 // EGL implementation, specifically because the egl_window_surface_t dtor
267 // calls nativeWindow->cancelBuffer and FramebufferNativeWindow does not initialize
268 // the cancelBuffer function pointer, see bug 986836
273 mozilla::gl::DestroySurface(mSurface
);
280 // We can't use LoadApitraceLibrary here because the GLContext
281 // expects its own handle to the GL library
282 if (!OpenLibrary(APITRACE_LIB
))
284 if (!OpenLibrary(GLES2_LIB
)) {
286 if (!OpenLibrary(GLES2_LIB2
)) {
287 NS_WARNING("Couldn't load GLES2 LIB.");
293 SetupLookupFunction();
294 if (!InitWithPrefix("gl", true))
297 bool current
= MakeCurrent();
299 gfx::LogFailure(NS_LITERAL_CSTRING(
300 "Couldn't get device attachments for device."));
304 PR_STATIC_ASSERT(sizeof(GLint
) >= sizeof(int32_t));
305 mMaxTextureImageSize
= INT32_MAX
;
307 mShareWithEGLImage
= sEGLLibrary
.HasKHRImageBase() &&
308 sEGLLibrary
.HasKHRImageTexture2D() &&
309 IsExtensionSupported(OES_EGL_image
);
315 GLContextEGL::BindTexImage()
320 if (mBound
&& !ReleaseTexImage())
323 EGLBoolean success
= sEGLLibrary
.fBindTexImage(EGL_DISPLAY(),
324 (EGLSurface
)mSurface
, LOCAL_EGL_BACK_BUFFER
);
325 if (success
== LOCAL_EGL_FALSE
)
333 GLContextEGL::ReleaseTexImage()
342 success
= sEGLLibrary
.fReleaseTexImage(EGL_DISPLAY(),
343 (EGLSurface
)mSurface
,
344 LOCAL_EGL_BACK_BUFFER
);
345 if (success
== LOCAL_EGL_FALSE
)
353 GLContextEGL::SetEGLSurfaceOverride(EGLSurface surf
) {
355 /* Blit `draw` to `read` if we need to, before we potentially juggle
356 * `read` around. If we don't, we might attach a different `read`,
357 * and *then* hit AssureBlitted, which will blit a dirty `draw` onto
360 Screen()->AssureBlitted();
363 mSurfaceOverride
= surf
? (EGLSurface
) surf
: mSurface
;
368 GLContextEGL::MakeCurrentImpl(bool aForce
) {
369 bool succeeded
= true;
371 // Assume that EGL has the same problem as WGL does,
372 // where MakeCurrent with an already-current context is
374 bool hasDifferentContext
= false;
375 if (sEGLLibrary
.CachedCurrentContext() != mContext
) {
376 // even if the cached context doesn't match the current one
378 if (sEGLLibrary
.fGetCurrentContext() != mContext
) {
379 hasDifferentContext
= true;
381 sEGLLibrary
.SetCachedCurrentContext(mContext
);
385 if (aForce
|| hasDifferentContext
) {
386 EGLSurface surface
= mSurfaceOverride
!= EGL_NO_SURFACE
389 if (surface
== EGL_NO_SURFACE
) {
392 succeeded
= sEGLLibrary
.fMakeCurrent(EGL_DISPLAY(),
396 int eglError
= sEGLLibrary
.fGetError();
397 if (eglError
== LOCAL_EGL_CONTEXT_LOST
) {
399 NS_WARNING("EGL context has been lost.");
401 NS_WARNING("Failed to make GL context current!");
403 printf_stderr("EGL Error: 0x%04x\n", eglError
);
407 sEGLLibrary
.SetCachedCurrentContext(mContext
);
410 MOZ_ASSERT(sEGLLibrary
.CachedCurrentContextMatches());
417 GLContextEGL::IsCurrent() {
418 return sEGLLibrary
.fGetCurrentContext() == mContext
;
422 GLContextEGL::RenewSurface() {
426 #ifndef MOZ_WIDGET_ANDROID
427 MOZ_CRASH("unimplemented");
428 // to support this on non-Android platforms, need to keep track of the nsIWidget that
429 // this GLContext was created for (with CreateForWindow) so that we know what to
430 // pass again to CreateSurfaceForWindow below.
431 // The reason why Android doesn't need this is that it delegates EGLSurface creation to
432 // Java code which is the only thing that knows about our actual widget.
434 // unconditionally release the surface and create a new one. Don't try to optimize this away.
435 // If we get here, then by definition we know that we want to get a new surface.
437 mSurface
= mozilla::gl::CreateSurfaceForWindow(nullptr, mConfig
); // the nullptr here is where we assume Android.
438 if (mSurface
== EGL_NO_SURFACE
) {
441 return MakeCurrent(true);
445 GLContextEGL::ReleaseSurface() {
447 DestroySurface(mSurface
);
449 mSurface
= EGL_NO_SURFACE
;
453 GLContextEGL::SetupLookupFunction()
455 mLookupFunc
= (PlatformLookupFunction
)sEGLLibrary
.mSymbols
.fGetProcAddress
;
460 GLContextEGL::SwapBuffers()
463 #ifdef MOZ_WIDGET_GONK
466 return mHwc
->Render(EGL_DISPLAY(), mSurface
);
468 return GetGonkDisplay()->SwapBuffers(EGL_DISPLAY(), mSurface
);
472 return sEGLLibrary
.fSwapBuffers(EGL_DISPLAY(), mSurface
);
478 // hold a reference to the given surface
479 // for the lifetime of this context.
481 GLContextEGL::HoldSurface(gfxASurface
*aSurf
) {
482 mThebesSurface
= aSurf
;
485 already_AddRefed
<GLContextEGL
>
486 GLContextEGL::CreateGLContext(const SurfaceCaps
& caps
,
487 GLContextEGL
*shareContext
,
492 if (sEGLLibrary
.fBindAPI(LOCAL_EGL_OPENGL_ES_API
) == LOCAL_EGL_FALSE
) {
493 NS_WARNING("Failed to bind API to GLES!");
497 EGLContext eglShareContext
= shareContext
? shareContext
->mContext
499 EGLint
* attribs
= sEGLLibrary
.HasRobustness() ? gContextAttribsRobustness
502 EGLContext context
= sEGLLibrary
.fCreateContext(EGL_DISPLAY(),
506 if (!context
&& shareContext
) {
507 shareContext
= nullptr;
508 context
= sEGLLibrary
.fCreateContext(EGL_DISPLAY(),
514 NS_WARNING("Failed to create EGLContext!");
518 nsRefPtr
<GLContextEGL
> glContext
= new GLContextEGL(caps
,
525 if (!glContext
->Init())
528 return glContext
.forget();
532 GLContextEGL::CreatePBufferSurfaceTryingPowerOfTwo(EGLConfig config
,
533 EGLenum bindToTextureFormat
,
536 nsTArray
<EGLint
> pbattrs(16);
537 EGLSurface surface
= nullptr;
539 TRY_AGAIN_POWER_OF_TWO
:
541 pbattrs
.AppendElement(LOCAL_EGL_WIDTH
); pbattrs
.AppendElement(pbsize
.width
);
542 pbattrs
.AppendElement(LOCAL_EGL_HEIGHT
); pbattrs
.AppendElement(pbsize
.height
);
544 if (bindToTextureFormat
!= LOCAL_EGL_NONE
) {
545 pbattrs
.AppendElement(LOCAL_EGL_TEXTURE_TARGET
);
546 pbattrs
.AppendElement(LOCAL_EGL_TEXTURE_2D
);
548 pbattrs
.AppendElement(LOCAL_EGL_TEXTURE_FORMAT
);
549 pbattrs
.AppendElement(bindToTextureFormat
);
552 for (size_t i
= 0; i
< MOZ_ARRAY_LENGTH(gTerminationAttribs
); i
++) {
553 pbattrs
.AppendElement(gTerminationAttribs
[i
]);
556 surface
= sEGLLibrary
.fCreatePbufferSurface(EGL_DISPLAY(), config
, &pbattrs
[0]);
558 if (!is_power_of_two(pbsize
.width
) ||
559 !is_power_of_two(pbsize
.height
))
561 if (!is_power_of_two(pbsize
.width
))
562 pbsize
.width
= next_power_of_two(pbsize
.width
);
563 if (!is_power_of_two(pbsize
.height
))
564 pbsize
.height
= next_power_of_two(pbsize
.height
);
566 NS_WARNING("Failed to create pbuffer, trying power of two dims");
567 goto TRY_AGAIN_POWER_OF_TWO
;
570 NS_WARNING("Failed to create pbuffer surface");
577 static const EGLint kEGLConfigAttribsOffscreenPBuffer
[] = {
578 LOCAL_EGL_SURFACE_TYPE
, LOCAL_EGL_PBUFFER_BIT
,
579 LOCAL_EGL_RENDERABLE_TYPE
, LOCAL_EGL_OPENGL_ES2_BIT
,
580 // Old versions of llvmpipe seem to need this to properly create the pbuffer (bug 981856)
581 LOCAL_EGL_RED_SIZE
, 8,
582 LOCAL_EGL_GREEN_SIZE
, 8,
583 LOCAL_EGL_BLUE_SIZE
, 8,
584 LOCAL_EGL_ALPHA_SIZE
, 0,
585 EGL_ATTRIBS_LIST_SAFE_TERMINATION_WORKING_AROUND_BUGS
588 static const EGLint kEGLConfigAttribsRGB16
[] = {
589 LOCAL_EGL_SURFACE_TYPE
, LOCAL_EGL_WINDOW_BIT
,
590 LOCAL_EGL_RENDERABLE_TYPE
, LOCAL_EGL_OPENGL_ES2_BIT
,
591 LOCAL_EGL_RED_SIZE
, 5,
592 LOCAL_EGL_GREEN_SIZE
, 6,
593 LOCAL_EGL_BLUE_SIZE
, 5,
594 LOCAL_EGL_ALPHA_SIZE
, 0,
595 EGL_ATTRIBS_LIST_SAFE_TERMINATION_WORKING_AROUND_BUGS
598 static const EGLint kEGLConfigAttribsRGB24
[] = {
599 LOCAL_EGL_SURFACE_TYPE
, LOCAL_EGL_WINDOW_BIT
,
600 LOCAL_EGL_RENDERABLE_TYPE
, LOCAL_EGL_OPENGL_ES2_BIT
,
601 LOCAL_EGL_RED_SIZE
, 8,
602 LOCAL_EGL_GREEN_SIZE
, 8,
603 LOCAL_EGL_BLUE_SIZE
, 8,
604 LOCAL_EGL_ALPHA_SIZE
, 0,
605 EGL_ATTRIBS_LIST_SAFE_TERMINATION_WORKING_AROUND_BUGS
608 static const EGLint kEGLConfigAttribsRGBA32
[] = {
609 LOCAL_EGL_SURFACE_TYPE
, LOCAL_EGL_WINDOW_BIT
,
610 LOCAL_EGL_RENDERABLE_TYPE
, LOCAL_EGL_OPENGL_ES2_BIT
,
611 LOCAL_EGL_RED_SIZE
, 8,
612 LOCAL_EGL_GREEN_SIZE
, 8,
613 LOCAL_EGL_BLUE_SIZE
, 8,
614 LOCAL_EGL_ALPHA_SIZE
, 8,
615 #if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
616 LOCAL_EGL_FRAMEBUFFER_TARGET_ANDROID
, LOCAL_EGL_TRUE
,
618 EGL_ATTRIBS_LIST_SAFE_TERMINATION_WORKING_AROUND_BUGS
622 CreateConfig(EGLConfig
* aConfig
, int32_t depth
)
624 EGLConfig configs
[64];
625 const EGLint
* attribs
;
626 EGLint ncfg
= ArrayLength(configs
);
630 attribs
= kEGLConfigAttribsRGB16
;
633 attribs
= kEGLConfigAttribsRGB24
;
636 attribs
= kEGLConfigAttribsRGBA32
;
639 NS_ERROR("Unknown pixel depth");
643 if (!sEGLLibrary
.fChooseConfig(EGL_DISPLAY(), attribs
,
644 configs
, ncfg
, &ncfg
) ||
649 #ifdef MOZ_WIDGET_GONK
650 // On gonk, it's important to select a configuration with the
651 // the correct order as well as bits per channel.
652 // EGL_NATIVE_VISUAL_ID gives us the Android pixel format which
653 // is an enum that tells us both order and bits per channel.
655 // HAL_PIXEL_FORMAT_RGBX_8888
656 // HAL_PIXEL_FORMAT_BGRA_8888
657 // HAL_PIXEL_FORMAT_RGB_565
658 for (int j
= 0; j
< ncfg
; ++j
) {
659 EGLConfig config
= configs
[j
];
661 if (sEGLLibrary
.fGetConfigAttrib(EGL_DISPLAY(), config
,
662 LOCAL_EGL_NATIVE_VISUAL_ID
, &format
) &&
663 format
== GetGonkDisplay()->surfaceformat
)
671 for (int j
= 0; j
< ncfg
; ++j
) {
672 EGLConfig config
= configs
[j
];
674 if (sEGLLibrary
.fGetConfigAttrib(EGL_DISPLAY(), config
,
675 LOCAL_EGL_RED_SIZE
, &r
) &&
676 sEGLLibrary
.fGetConfigAttrib(EGL_DISPLAY(), config
,
677 LOCAL_EGL_GREEN_SIZE
, &g
) &&
678 sEGLLibrary
.fGetConfigAttrib(EGL_DISPLAY(), config
,
679 LOCAL_EGL_BLUE_SIZE
, &b
) &&
680 sEGLLibrary
.fGetConfigAttrib(EGL_DISPLAY(), config
,
681 LOCAL_EGL_ALPHA_SIZE
, &a
) &&
682 ((depth
== 16 && r
== 5 && g
== 6 && b
== 5) ||
683 (depth
== 24 && r
== 8 && g
== 8 && b
== 8) ||
684 (depth
== 32 && r
== 8 && g
== 8 && b
== 8 && a
== 8)))
693 // Return true if a suitable EGLConfig was found and pass it out
694 // through aConfig. Return false otherwise.
696 // NB: It's entirely legal for the returned EGLConfig to be valid yet
697 // have the value null.
699 CreateConfig(EGLConfig
* aConfig
)
701 int32_t depth
= gfxPlatform::GetPlatform()->GetScreenDepth();
702 if (!CreateConfig(aConfig
, depth
)) {
703 #ifdef MOZ_WIDGET_ANDROID
705 // Android doesn't always support 16 bit so also try 24 bit
707 return CreateConfig(aConfig
, 24);
710 // Some devices that have 24 bit screens only support 16 bit OpenGL?
712 return CreateConfig(aConfig
, 16);
721 already_AddRefed
<GLContext
>
722 GLContextProviderEGL::CreateWrappingExisting(void* aContext
, void* aSurface
)
724 if (!sEGLLibrary
.EnsureInitialized()) {
725 MOZ_CRASH("Failed to load EGL library!\n");
729 if (aContext
&& aSurface
) {
730 SurfaceCaps caps
= SurfaceCaps::Any();
731 EGLConfig config
= EGL_NO_CONFIG
;
732 nsRefPtr
<GLContextEGL
> glContext
=
733 new GLContextEGL(caps
,
735 config
, (EGLSurface
)aSurface
, (EGLContext
)aContext
);
737 glContext
->SetIsDoubleBuffered(true);
738 glContext
->mOwnsContext
= false;
740 return glContext
.forget();
746 already_AddRefed
<GLContext
>
747 GLContextProviderEGL::CreateForWindow(nsIWidget
*aWidget
)
749 if (!sEGLLibrary
.EnsureInitialized()) {
750 MOZ_CRASH("Failed to load EGL library!\n");
754 bool doubleBuffered
= true;
757 if (!CreateConfig(&config
)) {
758 MOZ_CRASH("Failed to create EGLConfig!\n");
762 EGLSurface surface
= mozilla::gl::CreateSurfaceForWindow(aWidget
, config
);
764 if (surface
== EGL_NO_SURFACE
) {
765 MOZ_CRASH("Failed to create EGLSurface!\n");
769 SurfaceCaps caps
= SurfaceCaps::Any();
770 nsRefPtr
<GLContextEGL
> glContext
=
771 GLContextEGL::CreateGLContext(caps
,
776 MOZ_CRASH("Failed to create EGLContext!\n");
777 DestroySurface(surface
);
781 glContext
->MakeCurrent();
782 glContext
->SetIsDoubleBuffered(doubleBuffered
);
784 return glContext
.forget();
787 already_AddRefed
<GLContextEGL
>
788 GLContextEGL::CreateEGLPBufferOffscreenContext(const gfxIntSize
& size
)
793 const EGLint numConfigs
= 1; // We only need one.
794 EGLConfig configs
[numConfigs
];
795 EGLint foundConfigs
= 0;
796 if (!sEGLLibrary
.fChooseConfig(EGL_DISPLAY(),
797 kEGLConfigAttribsOffscreenPBuffer
,
800 || foundConfigs
== 0)
802 NS_WARNING("No EGL Config for minimal PBuffer!");
806 // We absolutely don't care, so just pick the first one.
808 if (GLContext::ShouldSpew())
809 sEGLLibrary
.DumpEGLConfig(config
);
811 gfxIntSize
pbSize(size
);
812 surface
= GLContextEGL::CreatePBufferSurfaceTryingPowerOfTwo(config
,
816 NS_WARNING("Failed to create PBuffer for context!");
820 SurfaceCaps dummyCaps
= SurfaceCaps::Any();
821 nsRefPtr
<GLContextEGL
> glContext
=
822 GLContextEGL::CreateGLContext(dummyCaps
,
826 NS_WARNING("Failed to create GLContext from PBuffer");
827 sEGLLibrary
.fDestroySurface(EGL_DISPLAY(), surface
);
831 if (!glContext
->Init()) {
832 NS_WARNING("Failed to initialize GLContext!");
833 // GLContextEGL::dtor will destroy |surface| for us.
837 return glContext
.forget();
840 already_AddRefed
<GLContextEGL
>
841 GLContextEGL::CreateEGLPixmapOffscreenContext(const gfxIntSize
& size
)
843 gfxASurface
*thebesSurface
= nullptr;
844 EGLNativePixmapType pixmap
= 0;
850 EGLSurface surface
= 0;
851 EGLConfig config
= 0;
858 SurfaceCaps dummyCaps
= SurfaceCaps::Any();
859 nsRefPtr
<GLContextEGL
> glContext
=
860 GLContextEGL::CreateGLContext(dummyCaps
,
864 NS_WARNING("Failed to create GLContext from XSurface");
865 sEGLLibrary
.fDestroySurface(EGL_DISPLAY(), surface
);
869 if (!glContext
->Init()) {
870 NS_WARNING("Failed to initialize GLContext!");
871 // GLContextEGL::dtor will destroy |surface| for us.
875 glContext
->HoldSurface(thebesSurface
);
877 return glContext
.forget();
880 already_AddRefed
<GLContext
>
881 GLContextProviderEGL::CreateHeadless()
883 if (!sEGLLibrary
.EnsureInitialized()) {
887 gfxIntSize dummySize
= gfxIntSize(16, 16);
888 nsRefPtr
<GLContext
> glContext
;
889 glContext
= GLContextEGL::CreateEGLPBufferOffscreenContext(dummySize
);
893 return glContext
.forget();
896 // Under EGL, on Android, pbuffers are supported fine, though
897 // often without the ability to texture from them directly.
898 already_AddRefed
<GLContext
>
899 GLContextProviderEGL::CreateOffscreen(const gfxIntSize
& size
,
900 const SurfaceCaps
& caps
)
902 nsRefPtr
<GLContext
> glContext
= CreateHeadless();
906 if (!glContext
->InitOffscreen(ToIntSize(size
), caps
))
909 return glContext
.forget();
912 // Don't want a global context on Android as 1) share groups across 2 threads fail on many Tegra drivers (bug 759225)
913 // and 2) some mobile devices have a very strict limit on global number of GL contexts (bug 754257)
914 // and 3) each EGL context eats 750k on B2G (bug 813783)
916 GLContextProviderEGL::GetGlobalContext()
922 GLContextProviderEGL::Shutdown()
927 } /* namespace mozilla */
929 #undef EGL_ATTRIBS_LIST_SAFE_TERMINATION_WORKING_AROUND_BUGS