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/Util.h"
7 // please add new includes below Qt, otherwise it break Qt build due malloc wrapper conflicts
13 // we're using default display for now
14 #define GET_NATIVE_WINDOW(aWidget) (EGLNativeWindowType)GDK_WINDOW_XID((GdkWindow *) aWidget->GetNativeData(NS_NATIVE_WINDOW))
15 #elif defined(MOZ_WIDGET_QT)
16 #include <QtOpenGL/QGLContext>
17 #define GLdouble_defined 1
18 // we're using default display for now
19 #define GET_NATIVE_WINDOW(aWidget) (EGLNativeWindowType)static_cast<QWidget*>(aWidget->GetNativeData(NS_NATIVE_SHELLWIDGET))->winId()
20 #elif defined(MOZ_WIDGET_GONK)
21 #define GET_NATIVE_WINDOW(aWidget) ((EGLNativeWindowType)aWidget->GetNativeData(NS_NATIVE_WINDOW))
22 #include "HWComposer.h"
27 #include <X11/Xutil.h>
28 #include "mozilla/X11Util.h"
29 #include "gfxXlibSurface.h"
34 #if defined(MOZ_WIDGET_ANDROID)
35 #include "AndroidBridge.h"
36 #include "nsSurfaceTexture.h"
38 #include <android/log.h>
39 #define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "Gonk" , ## args)
41 # if defined(MOZ_WIDGET_GONK)
42 # include "cutils/properties.h"
43 # include <ui/GraphicBuffer.h>
45 using namespace android
;
47 # define EGL_NATIVE_BUFFER_ANDROID 0x3140
53 #define GLES2_LIB "libGLESv2.so"
54 #define GLES2_LIB2 "libGLESv2.so.2"
60 #define GLES2_LIB "libGLESv2.dll"
62 #ifndef WIN32_LEAN_AND_MEAN
63 #define WIN32_LEAN_AND_MEAN 1
69 class AutoDestroyHWND
{
71 AutoDestroyHWND(HWND aWnd
= NULL
)
78 ::DestroyWindow(mWnd
);
92 HWND
operator=(HWND aWnd
) {
93 if (mWnd
&& mWnd
!= aWnd
) {
94 ::DestroyWindow(mWnd
);
105 #error "Platform not recognized"
109 #include "mozilla/Preferences.h"
110 #include "gfxUtils.h"
111 #include "gfxFailure.h"
112 #include "gfxASurface.h"
113 #include "gfxImageSurface.h"
114 #include "gfxPlatform.h"
115 #include "GLContextProvider.h"
116 #include "GLLibraryEGL.h"
118 #include "nsThreadUtils.h"
120 #include "nsIWidget.h"
122 #include "gfxCrashReporterUtils.h"
125 #if defined(MOZ_PLATFORM_MAEMO) || defined(MOZ_WIDGET_GONK)
126 static bool gUseBackingSurface
= true;
128 static bool gUseBackingSurface
= false;
131 #ifdef MOZ_WIDGET_GONK
132 extern nsIntRect gScreenBounds
;
138 static GLLibraryEGL sEGLLibrary
;
140 #define ADD_ATTR_2(_array, _k, _v) do { \
141 (_array).AppendElement(_k); \
142 (_array).AppendElement(_v); \
145 #define ADD_ATTR_1(_array, _k) do { \
146 (_array).AppendElement(_k); \
149 #ifndef MOZ_ANDROID_OMTC
151 CreateSurfaceForWindow(nsIWidget
*aWidget
, EGLConfig config
);
155 CreateConfig(EGLConfig
* aConfig
);
158 #ifdef MOZ_EGL_XRENDER_COMPOSITE
160 CreateBasicEGLSurfaceForXSurface(gfxASurface
* aSurface
, EGLConfig
* aConfig
);
164 CreateEGLSurfaceForXSurface(gfxASurface
* aSurface
, EGLConfig
* aConfig
= nullptr);
167 static EGLint gContextAttribs
[] = {
168 LOCAL_EGL_CONTEXT_CLIENT_VERSION
, 2,
172 static EGLint gContextAttribsRobustness
[] = {
173 LOCAL_EGL_CONTEXT_CLIENT_VERSION
, 2,
174 //LOCAL_EGL_CONTEXT_ROBUST_ACCESS_EXT, LOCAL_EGL_TRUE,
175 LOCAL_EGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_EXT
, LOCAL_EGL_LOSE_CONTEXT_ON_RESET_EXT
,
180 next_power_of_two(int v
)
194 is_power_of_two(int v
)
196 NS_ASSERTION(v
>= 0, "bad value");
201 return (v
& (v
-1)) == 0;
204 class GLContextEGL
: public GLContext
206 friend class TextureImageEGL
;
208 static already_AddRefed
<GLContextEGL
>
209 CreateGLContext(const ContextFormat
& format
,
212 GLContextEGL
*shareContext
,
213 bool aIsOffscreen
= false)
217 context
= sEGLLibrary
.fCreateContext(EGL_DISPLAY(),
219 shareContext
? shareContext
->mContext
: EGL_NO_CONTEXT
,
220 sEGLLibrary
.HasRobustness() ? gContextAttribsRobustness
224 shareContext
= nullptr;
225 context
= sEGLLibrary
.fCreateContext(EGL_DISPLAY(),
228 sEGLLibrary
.HasRobustness() ? gContextAttribsRobustness
231 NS_WARNING("Failed to create EGLContext!");
237 nsRefPtr
<GLContextEGL
> glContext
=
238 new GLContextEGL(format
, shareContext
, config
,
239 surface
, context
, aIsOffscreen
);
241 if (!glContext
->Init())
244 return glContext
.forget();
248 GLContextEGL(const ContextFormat
& aFormat
,
249 GLContext
*aShareContext
,
253 bool aIsOffscreen
= false)
254 : GLContext(aFormat
, aIsOffscreen
, aShareContext
)
256 , mSurface(aSurface
), mContext(aContext
)
257 , mPlatformContext(nullptr)
258 , mThebesSurface(nullptr)
261 , mIsDoubleBuffered(false)
262 , mCanBindToTexture(false)
263 , mShareWithEGLImage(false)
264 , mTemporaryEGLImageTexture(0)
266 // any EGL contexts will always be GLESv2
270 printf_stderr("Initializing context %p surface %p on display %p\n", mContext
, mSurface
, EGL_DISPLAY());
272 #ifdef MOZ_WIDGET_GONK
274 mHwc
= new HWComposer();
276 if (mHwc
&& mHwc
->init()) {
277 NS_WARNING("HWComposer initialization failed!");
286 if (mTemporaryEGLImageTexture
!= 0) {
287 fDeleteTextures(1, &mTemporaryEGLImageTexture
);
288 mTemporaryEGLImageTexture
= 0;
294 // If mGLWidget is non-null, then we've been given it by the GL context provider,
295 // and it's managed by the widget implementation. In this case, We can't destroy
297 if (mPlatformContext
)
301 printf_stderr("Destroying context %p surface %p on display %p\n", mContext
, mSurface
, EGL_DISPLAY());
304 sEGLLibrary
.fDestroyContext(EGL_DISPLAY(), mContext
);
305 if (mSurface
&& !mPlatformContext
) {
306 sEGLLibrary
.fDestroySurface(EGL_DISPLAY(), mSurface
);
310 GLContextType
GetContextType() {
311 return ContextTypeEGL
;
317 // We can't use LoadApitraceLibrary here because the GLContext
318 // expects its own handle to the GL library
319 if (!OpenLibrary(APITRACE_LIB
))
321 if (!OpenLibrary(GLES2_LIB
)) {
323 if (!OpenLibrary(GLES2_LIB2
)) {
324 NS_WARNING("Couldn't load GLES2 LIB.");
330 #ifdef MOZ_WIDGET_GONK
331 char propValue
[PROPERTY_VALUE_MAX
];
332 property_get("ro.build.version.sdk", propValue
, "0");
333 if (atoi(propValue
) < 15)
334 gUseBackingSurface
= false;
337 bool current
= MakeCurrent();
339 gfx::LogFailure(NS_LITERAL_CSTRING(
340 "Couldn't get device attachments for device."));
344 SetupLookupFunction();
346 bool ok
= InitWithPrefix("gl", true);
348 PR_STATIC_ASSERT(sizeof(GLint
) >= sizeof(int32_t));
349 mMaxTextureImageSize
= INT32_MAX
;
351 mShareWithEGLImage
= sEGLLibrary
.HasKHRImageBase() &&
352 sEGLLibrary
.HasKHRImageTexture2D() &&
353 IsExtensionSupported(OES_EGL_image
);
361 bool IsDoubleBuffered() {
362 return mIsDoubleBuffered
;
365 void SetIsDoubleBuffered(bool aIsDB
) {
366 mIsDoubleBuffered
= aIsDB
;
369 bool SupportsRobustness()
371 return sEGLLibrary
.HasRobustness();
374 virtual bool IsANGLE()
376 return sEGLLibrary
.IsANGLE();
379 #if defined(MOZ_X11) && defined(MOZ_EGL_XRENDER_COMPOSITE)
380 gfxASurface
* GetOffscreenPixmapSurface()
382 return mThebesSurface
;
385 virtual bool WaitNative() {
386 return sEGLLibrary
.fWaitNative(LOCAL_EGL_CORE_NATIVE_ENGINE
);
395 if (mBound
&& !ReleaseTexImage())
398 EGLBoolean success
= sEGLLibrary
.fBindTexImage(EGL_DISPLAY(),
399 (EGLSurface
)mSurface
, LOCAL_EGL_BACK_BUFFER
);
400 if (success
== LOCAL_EGL_FALSE
)
407 bool ReleaseTexImage()
416 success
= sEGLLibrary
.fReleaseTexImage(EGL_DISPLAY(),
417 (EGLSurface
)mSurface
,
418 LOCAL_EGL_BACK_BUFFER
);
419 if (success
== LOCAL_EGL_FALSE
)
426 bool BindExternalBuffer(GLuint texture
, void* buffer
)
428 #if defined(MOZ_WIDGET_GONK)
430 LOCAL_EGL_IMAGE_PRESERVED
, LOCAL_EGL_TRUE
,
431 LOCAL_EGL_NONE
, LOCAL_EGL_NONE
433 EGLImage image
= sEGLLibrary
.fCreateImage(EGL_DISPLAY(),
435 EGL_NATIVE_BUFFER_ANDROID
,
437 fBindTexture(LOCAL_GL_TEXTURE_EXTERNAL
, texture
);
438 fEGLImageTargetTexture2D(LOCAL_GL_TEXTURE_EXTERNAL
, image
);
439 sEGLLibrary
.fDestroyImage(EGL_DISPLAY(), image
);
446 bool UnbindExternalBuffer(GLuint texture
)
448 #if defined(MOZ_WIDGET_GONK)
449 fActiveTexture(LOCAL_GL_TEXTURE0
);
450 fBindTexture(LOCAL_GL_TEXTURE_2D
, texture
);
451 fTexImage2D(LOCAL_GL_TEXTURE_2D
, 0,
454 LOCAL_GL_RGBA
, LOCAL_GL_UNSIGNED_BYTE
,
462 #ifdef MOZ_WIDGET_GONK
463 virtual already_AddRefed
<TextureImage
>
464 CreateDirectTextureImage(GraphicBuffer
* aBuffer
, GLenum aWrapMode
) MOZ_OVERRIDE
;
467 bool MakeCurrentImpl(bool aForce
= false) {
468 bool succeeded
= true;
470 // Assume that EGL has the same problem as WGL does,
471 // where MakeCurrent with an already-current context is
473 #ifndef MOZ_WIDGET_QT
475 // We need to be able to bind NO_SURFACE when we don't
476 // have access to a surface. We won't be drawing to the screen
477 // but we will be able to do things like resource releases.
478 succeeded
= sEGLLibrary
.fMakeCurrent(EGL_DISPLAY(),
479 EGL_NO_SURFACE
, EGL_NO_SURFACE
,
481 if (!succeeded
&& sEGLLibrary
.fGetError() == LOCAL_EGL_CONTEXT_LOST
) {
483 NS_WARNING("EGL context has been lost.");
485 NS_ASSERTION(succeeded
, "Failed to make GL context current!");
489 if (aForce
|| sEGLLibrary
.fGetCurrentContext() != mContext
) {
491 // Shared Qt GL context need to be informed about context switch
492 if (mSharedContext
) {
493 QGLContext
* qglCtx
= static_cast<QGLContext
*>(static_cast<GLContextEGL
*>(mSharedContext
.get())->mPlatformContext
);
495 qglCtx
->doneCurrent();
499 succeeded
= sEGLLibrary
.fMakeCurrent(EGL_DISPLAY(),
503 int eglError
= sEGLLibrary
.fGetError();
505 if (eglError
== LOCAL_EGL_CONTEXT_LOST
) {
507 NS_WARNING("EGL context has been lost.");
509 NS_WARNING("Failed to make GL context current!");
511 printf_stderr("EGL Error: 0x%04x\n", eglError
);
520 virtual bool IsCurrent() {
521 return sEGLLibrary
.fGetCurrentContext() == mContext
;
527 /* We don't support renewing on QT because we don't create the surface ourselves */
533 sEGLLibrary
.fMakeCurrent(EGL_DISPLAY(), EGL_NO_SURFACE
, EGL_NO_SURFACE
,
536 #ifdef MOZ_ANDROID_OMTC
537 mSurface
= mozilla::AndroidBridge::Bridge()->ProvideEGLSurface();
540 CreateConfig(&config
);
541 mSurface
= CreateSurfaceForWindow(NULL
, config
);
544 return sEGLLibrary
.fMakeCurrent(EGL_DISPLAY(),
552 if (mSurface
&& !mPlatformContext
) {
553 sEGLLibrary
.fMakeCurrent(EGL_DISPLAY(), EGL_NO_SURFACE
, EGL_NO_SURFACE
,
555 sEGLLibrary
.fDestroySurface(EGL_DISPLAY(), mSurface
);
560 bool SetupLookupFunction()
562 mLookupFunc
= (PlatformLookupFunction
)sEGLLibrary
.mSymbols
.fGetProcAddress
;
566 void *GetNativeData(NativeDataType aType
)
569 case NativeGLContext
:
579 if (mSurface
&& !mPlatformContext
) {
580 #ifdef MOZ_WIDGET_GONK
582 return !mHwc
->swapBuffers((hwc_display_t
)EGL_DISPLAY(),
583 (hwc_surface_t
)mSurface
);
586 return sEGLLibrary
.fSwapBuffers(EGL_DISPLAY(), mSurface
);
591 // GLContext interface - returns Tiled Texture Image in our case
592 virtual already_AddRefed
<TextureImage
>
593 CreateTextureImage(const nsIntSize
& aSize
,
594 TextureImage::ContentType aContentType
,
596 TextureImage::Flags aFlags
= TextureImage::NoFlags
);
598 // a function to generate Tiles for Tiled Texture Image
599 virtual already_AddRefed
<TextureImage
>
600 TileGenFunc(const nsIntSize
& aSize
,
601 TextureImage::ContentType aContentType
,
602 TextureImage::Flags aFlags
= TextureImage::NoFlags
);
603 // hold a reference to the given surface
604 // for the lifetime of this context.
605 void HoldSurface(gfxASurface
*aSurf
) {
606 mThebesSurface
= aSurf
;
609 void SetPlatformContext(void *context
) {
610 mPlatformContext
= context
;
613 EGLContext
Context() {
617 bool BindTex2DOffscreen(GLContext
*aOffscreen
);
618 void UnbindTex2DOffscreen(GLContext
*aOffscreen
);
619 bool ResizeOffscreen(const gfxIntSize
& aNewSize
);
620 void BindOffscreenFramebuffer();
622 static already_AddRefed
<GLContextEGL
>
623 CreateEGLPixmapOffscreenContext(const gfxIntSize
& aSize
,
624 const ContextFormat
& aFormat
,
627 #if defined(MOZ_X11) && defined(MOZ_EGL_XRENDER_COMPOSITE)
628 static already_AddRefed
<GLContextEGL
>
629 CreateBasicEGLPixmapOffscreenContext(const gfxIntSize
& aSize
,
630 const ContextFormat
& aFormat
);
632 bool ResizeOffscreenPixmapSurface(const gfxIntSize
& aNewSize
);
635 static already_AddRefed
<GLContextEGL
>
636 CreateEGLPBufferOffscreenContext(const gfxIntSize
& aSize
,
637 const ContextFormat
& aFormat
,
638 bool bufferUnused
= false);
640 void SetOffscreenSize(const gfxIntSize
&aRequestedSize
,
641 const gfxIntSize
&aActualSize
)
643 mOffscreenSize
= aRequestedSize
;
644 mOffscreenActualSize
= aActualSize
;
647 void *GetD3DShareHandle() {
648 if (!sEGLLibrary
.HasANGLESurfaceD3DTexture2DShareHandle()) {
654 #ifndef EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE
655 #define EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE 0x3200
658 if (!sEGLLibrary
.fQuerySurfacePointerANGLE(EGL_DISPLAY(), mSurface
,
659 EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE
, (void**) &h
))
667 virtual bool HasLockSurface() {
668 return sEGLLibrary
.HasKHRLockSurface();
671 virtual SharedTextureHandle
CreateSharedHandle(TextureImage::TextureShareType aType
);
672 virtual SharedTextureHandle
CreateSharedHandle(TextureImage::TextureShareType aType
,
674 SharedTextureBufferType aBufferType
);
675 virtual void UpdateSharedHandle(TextureImage::TextureShareType aType
,
676 SharedTextureHandle aSharedHandle
);
677 virtual void ReleaseSharedHandle(TextureImage::TextureShareType aType
,
678 SharedTextureHandle aSharedHandle
);
679 virtual bool GetSharedHandleDetails(TextureImage::TextureShareType aType
,
680 SharedTextureHandle aSharedHandle
,
681 SharedHandleDetails
& aDetails
);
682 virtual bool AttachSharedHandle(TextureImage::TextureShareType aType
,
683 SharedTextureHandle aSharedHandle
);
685 friend class GLContextProviderEGL
;
690 void *mPlatformContext
;
691 nsRefPtr
<gfxASurface
> mThebesSurface
;
695 bool mIsDoubleBuffered
;
696 bool mCanBindToTexture
;
697 bool mShareWithEGLImage
;
698 #ifdef MOZ_WIDGET_GONK
699 nsAutoPtr
<HWComposer
> mHwc
;
702 // A dummy texture ID that can be used when we need a texture object whose
703 // images we're going to define with EGLImageTargetTexture2D.
704 GLuint mTemporaryEGLImageTexture
;
706 static EGLSurface
CreatePBufferSurfaceTryingPowerOfTwo(EGLConfig config
,
707 EGLenum bindToTextureFormat
,
710 nsTArray
<EGLint
> pbattrs(16);
711 EGLSurface surface
= nullptr;
713 TRY_AGAIN_POWER_OF_TWO
:
715 pbattrs
.AppendElement(LOCAL_EGL_WIDTH
); pbattrs
.AppendElement(pbsize
.width
);
716 pbattrs
.AppendElement(LOCAL_EGL_HEIGHT
); pbattrs
.AppendElement(pbsize
.height
);
718 if (bindToTextureFormat
!= LOCAL_EGL_NONE
) {
719 pbattrs
.AppendElement(LOCAL_EGL_TEXTURE_TARGET
);
720 pbattrs
.AppendElement(LOCAL_EGL_TEXTURE_2D
);
722 pbattrs
.AppendElement(LOCAL_EGL_TEXTURE_FORMAT
);
723 pbattrs
.AppendElement(bindToTextureFormat
);
726 pbattrs
.AppendElement(LOCAL_EGL_NONE
);
728 surface
= sEGLLibrary
.fCreatePbufferSurface(EGL_DISPLAY(), config
, &pbattrs
[0]);
730 if (!is_power_of_two(pbsize
.width
) ||
731 !is_power_of_two(pbsize
.height
))
733 if (!is_power_of_two(pbsize
.width
))
734 pbsize
.width
= next_power_of_two(pbsize
.width
);
735 if (!is_power_of_two(pbsize
.height
))
736 pbsize
.height
= next_power_of_two(pbsize
.height
);
738 NS_WARNING("Failed to create pbuffer, trying power of two dims");
739 goto TRY_AGAIN_POWER_OF_TWO
;
742 NS_WARNING("Failed to create pbuffer surface");
752 #ifdef MOZ_WIDGET_ANDROID
757 class SharedTextureHandleWrapper
760 SharedTextureHandleWrapper(SharedHandleType aHandleType
) : mHandleType(aHandleType
)
764 virtual ~SharedTextureHandleWrapper()
768 SharedHandleType
Type() { return mHandleType
; }
770 SharedHandleType mHandleType
;
773 #ifdef MOZ_WIDGET_ANDROID
775 class SurfaceTextureWrapper
: public SharedTextureHandleWrapper
778 SurfaceTextureWrapper(nsSurfaceTexture
* aSurfaceTexture
) :
779 SharedTextureHandleWrapper(SharedHandleType::SurfaceTexture
)
780 , mSurfaceTexture(aSurfaceTexture
)
784 virtual ~SurfaceTextureWrapper() {
785 mSurfaceTexture
= nullptr;
788 nsSurfaceTexture
* SurfaceTexture() { return mSurfaceTexture
; }
790 nsRefPtr
<nsSurfaceTexture
> mSurfaceTexture
;
793 #endif // MOZ_WIDGET_ANDROID
795 class EGLTextureWrapper
: public SharedTextureHandleWrapper
798 EGLTextureWrapper() :
799 SharedTextureHandleWrapper(SharedHandleType::Image
)
801 , mSyncObject(nullptr)
805 // Args are the active GL context, and a texture in that GL
806 // context for which to create an EGLImage. After the EGLImage
807 // is created, the texture is unused by EGLTextureWrapper.
808 bool CreateEGLImage(GLContextEGL
*ctx
, GLuint texture
) {
809 MOZ_ASSERT(!mEGLImage
&& texture
&& sEGLLibrary
.HasKHRImageBase());
810 static const EGLint eglAttributes
[] = {
813 mEGLImage
= sEGLLibrary
.fCreateImage(EGL_DISPLAY(), ctx
->Context(), LOCAL_EGL_GL_TEXTURE_2D
,
814 (EGLClientBuffer
)texture
, eglAttributes
);
817 printf_stderr("Could not create EGL images: ERROR (0x%04x)\n", sEGLLibrary
.fGetError());
824 virtual ~EGLTextureWrapper() {
826 sEGLLibrary
.fDestroyImage(EGL_DISPLAY(), mEGLImage
);
831 const EGLImage
GetEGLImage() {
835 // Insert a sync point on the given context, which should be the current active
837 bool MakeSync(GLContext
*ctx
) {
838 MOZ_ASSERT(mSyncObject
== nullptr);
840 if (sEGLLibrary
.IsExtensionSupported(GLLibraryEGL::KHR_fence_sync
)) {
841 mSyncObject
= sEGLLibrary
.fCreateSync(EGL_DISPLAY(), LOCAL_EGL_SYNC_FENCE
, nullptr);
842 // We need to flush to make sure the sync object enters the command stream;
843 // we can't use EGL_SYNC_FLUSH_COMMANDS_BIT at wait time, because the wait
844 // happens on a different thread/context.
848 if (mSyncObject
== EGL_NO_SYNC
) {
849 // we failed to create one, so just do a finish
858 // if we have no sync object, then we did a Finish() earlier
862 // wait at most 1 second; this should really be never/rarely hit
863 const uint64_t ns_per_ms
= 1000 * 1000;
864 EGLTime timeout
= 1000 * ns_per_ms
;
866 EGLint result
= sEGLLibrary
.fClientWaitSync(EGL_DISPLAY(), mSyncObject
, 0, timeout
);
867 sEGLLibrary
.fDestroySync(EGL_DISPLAY(), mSyncObject
);
868 mSyncObject
= nullptr;
870 return result
== LOCAL_EGL_CONDITION_SATISFIED
;
879 GLContextEGL::UpdateSharedHandle(TextureImage::TextureShareType aType
,
880 SharedTextureHandle aSharedHandle
)
882 if (aType
!= TextureImage::ThreadShared
) {
883 NS_ERROR("Implementation not available for this sharing type");
887 SharedTextureHandleWrapper
* wrapper
= reinterpret_cast<SharedTextureHandleWrapper
*>(aSharedHandle
);
889 NS_ASSERTION(wrapper
->Type() == SharedHandleType::Image
, "Expected EGLImage shared handle");
890 NS_ASSERTION(mShareWithEGLImage
, "EGLImage not supported or disabled in runtime");
892 EGLTextureWrapper
* wrap
= reinterpret_cast<EGLTextureWrapper
*>(wrapper
);
893 // We need to copy the current GLContext drawing buffer to the texture
894 // exported by the EGLImage. Need to save both the read FBO and the texture
895 // binding, because we're going to munge them to do this.
896 GLuint prevRead
= GetUserBoundReadFBO();
899 fGetIntegerv(LOCAL_GL_TEXTURE_BINDING_2D
, &oldtex
);
900 MOZ_ASSERT(oldtex
!= -1);
901 fBindTexture(LOCAL_GL_TEXTURE_2D
, mTemporaryEGLImageTexture
);
902 fEGLImageTargetTexture2D(LOCAL_GL_TEXTURE_2D
, wrap
->GetEGLImage());
904 // CopyTexSubImage2D, is ~2x slower than simple FBO render to texture with draw quads,
905 // but render with draw quads require complex and hard to maintain context save/restore code
906 fCopyTexSubImage2D(LOCAL_GL_TEXTURE_2D
, 0, 0, 0,
907 0, 0, mOffscreenActualSize
.width
,
908 mOffscreenActualSize
.height
);
910 fBindTexture(LOCAL_GL_TEXTURE_2D
, oldtex
);
911 BindUserReadFBO(prevRead
);
913 // Make sure our copy is finished, so that we can be ready to draw
914 // in different thread GLContext. If we have KHR_fence_sync, then
915 // we insert a sync object, otherwise we have to do a GuaranteeResolve.
916 wrap
->MakeSync(this);
920 GLContextEGL::CreateSharedHandle(TextureImage::TextureShareType aType
)
922 if (aType
!= TextureImage::ThreadShared
)
925 if (!mShareWithEGLImage
)
929 ContextFormat fmt
= ActualFormat();
931 CreateTextureForOffscreen(ChooseGLFormats(fmt
, GLContext::ForceRGBA
), mOffscreenActualSize
,
932 mTemporaryEGLImageTexture
);
934 EGLTextureWrapper
* tex
= new EGLTextureWrapper();
935 bool ok
= tex
->CreateEGLImage(this, mTemporaryEGLImageTexture
);
938 NS_ERROR("EGLImage creation for EGLTextureWrapper failed");
939 ReleaseSharedHandle(aType
, (SharedTextureHandle
)tex
);
943 // Raw pointer shared across threads
944 return (SharedTextureHandle
)tex
;
948 GLContextEGL::CreateSharedHandle(TextureImage::TextureShareType aType
,
950 SharedTextureBufferType aBufferType
)
952 // Both EGLImage and SurfaceTexture only support ThreadShared currently, but
953 // it's possible to make SurfaceTexture work across processes. We should do that.
954 if (aType
!= TextureImage::ThreadShared
)
957 switch (aBufferType
) {
958 #ifdef MOZ_WIDGET_ANDROID
959 case SharedTextureBufferType::SurfaceTexture
:
960 if (!IsExtensionSupported(GLContext::OES_EGL_image_external
)) {
961 NS_WARNING("Missing GL_OES_EGL_image_external");
965 return (SharedTextureHandle
) new SurfaceTextureWrapper(reinterpret_cast<nsSurfaceTexture
*>(aBuffer
));
967 case SharedTextureBufferType::TextureID
: {
968 if (!mShareWithEGLImage
)
971 GLuint texture
= (uintptr_t)aBuffer
;
972 EGLTextureWrapper
* tex
= new EGLTextureWrapper();
973 if (!tex
->CreateEGLImage(this, texture
)) {
974 NS_ERROR("EGLImage creation for EGLTextureWrapper failed");
979 return (SharedTextureHandle
)tex
;
982 NS_ERROR("Unknown shared texture buffer type");
987 void GLContextEGL::ReleaseSharedHandle(TextureImage::TextureShareType aType
,
988 SharedTextureHandle aSharedHandle
)
990 if (aType
!= TextureImage::ThreadShared
) {
991 NS_ERROR("Implementation not available for this sharing type");
995 SharedTextureHandleWrapper
* wrapper
= reinterpret_cast<SharedTextureHandleWrapper
*>(aSharedHandle
);
997 switch (wrapper
->Type()) {
998 #ifdef MOZ_WIDGET_ANDROID
999 case SharedHandleType::SurfaceTexture
:
1004 case SharedHandleType::Image
: {
1005 NS_ASSERTION(mShareWithEGLImage
, "EGLImage not supported or disabled in runtime");
1007 EGLTextureWrapper
* wrap
= (EGLTextureWrapper
*)aSharedHandle
;
1013 NS_ERROR("Unknown shared handle type");
1017 bool GLContextEGL::GetSharedHandleDetails(TextureImage::TextureShareType aType
,
1018 SharedTextureHandle aSharedHandle
,
1019 SharedHandleDetails
& aDetails
)
1021 if (aType
!= TextureImage::ThreadShared
)
1024 SharedTextureHandleWrapper
* wrapper
= reinterpret_cast<SharedTextureHandleWrapper
*>(aSharedHandle
);
1026 switch (wrapper
->Type()) {
1027 #ifdef MOZ_WIDGET_ANDROID
1028 case SharedHandleType::SurfaceTexture
: {
1029 SurfaceTextureWrapper
* surfaceWrapper
= reinterpret_cast<SurfaceTextureWrapper
*>(wrapper
);
1031 aDetails
.mTarget
= LOCAL_GL_TEXTURE_EXTERNAL
;
1032 aDetails
.mProgramType
= RGBALayerExternalProgramType
;
1033 surfaceWrapper
->SurfaceTexture()->GetTransformMatrix(aDetails
.mTextureTransform
);
1038 case SharedHandleType::Image
:
1039 aDetails
.mTarget
= LOCAL_GL_TEXTURE_2D
;
1040 aDetails
.mProgramType
= RGBALayerProgramType
;
1044 NS_ERROR("Unknown shared handle type");
1051 bool GLContextEGL::AttachSharedHandle(TextureImage::TextureShareType aType
,
1052 SharedTextureHandle aSharedHandle
)
1054 if (aType
!= TextureImage::ThreadShared
)
1057 SharedTextureHandleWrapper
* wrapper
= reinterpret_cast<SharedTextureHandleWrapper
*>(aSharedHandle
);
1059 switch (wrapper
->Type()) {
1060 #ifdef MOZ_WIDGET_ANDROID
1061 case SharedHandleType::SurfaceTexture
: {
1064 * NOTE: SurfaceTexture spams us if there are any existing GL errors, so we'll clear
1065 * them here in order to avoid that.
1069 SurfaceTextureWrapper
* surfaceTextureWrapper
= reinterpret_cast<SurfaceTextureWrapper
*>(wrapper
);
1071 // FIXME: SurfaceTexture provides a transform matrix which is supposed to
1072 // be applied to the texture coordinates. We should return that here
1073 // so we can render correctly. Bug 775083
1074 surfaceTextureWrapper
->SurfaceTexture()->UpdateTexImage();
1077 #endif // MOZ_WIDGET_ANDROID
1079 case SharedHandleType::Image
: {
1080 NS_ASSERTION(mShareWithEGLImage
, "EGLImage not supported or disabled in runtime");
1082 EGLTextureWrapper
* wrap
= (EGLTextureWrapper
*)aSharedHandle
;
1084 fEGLImageTargetTexture2D(LOCAL_GL_TEXTURE_2D
, wrap
->GetEGLImage());
1089 NS_ERROR("Unknown shared handle type");
1097 GLContextEGL::BindTex2DOffscreen(GLContext
*aOffscreen
)
1099 if (aOffscreen
->GetContextType() != ContextTypeEGL
) {
1100 NS_WARNING("non-EGL context");
1104 GLContextEGL
*offs
= static_cast<GLContextEGL
*>(aOffscreen
);
1106 if (offs
->mCanBindToTexture
) {
1107 bool ok
= sEGLLibrary
.fBindTexImage(EGL_DISPLAY(),
1109 LOCAL_EGL_BACK_BUFFER
);
1113 if (offs
->mOffscreenTexture
) {
1114 if (offs
->GetSharedContext() != GLContextProviderEGL::GetGlobalContext())
1116 NS_WARNING("offscreen FBO context can only be bound with context sharing!");
1120 fBindTexture(LOCAL_GL_TEXTURE_2D
, offs
->mOffscreenTexture
);
1124 NS_WARNING("don't know how to bind this!");
1130 GLContextEGL::UnbindTex2DOffscreen(GLContext
*aOffscreen
)
1132 NS_ASSERTION(aOffscreen
->GetContextType() == ContextTypeEGL
, "wrong type");
1134 GLContextEGL
*offs
= static_cast<GLContextEGL
*>(aOffscreen
);
1136 if (offs
->mCanBindToTexture
) {
1137 sEGLLibrary
.fReleaseTexImage(EGL_DISPLAY(),
1139 LOCAL_EGL_BACK_BUFFER
);
1144 GLContextEGL::ResizeOffscreen(const gfxIntSize
& aNewSize
)
1146 if (!IsOffscreenSizeAllowed(aNewSize
))
1150 gfxIntSize
pbsize(aNewSize
);
1152 EGLSurface surface
=
1153 CreatePBufferSurfaceTryingPowerOfTwo(mConfig
,
1155 ? (mCreationFormat
.minAlpha
1156 ? LOCAL_EGL_TEXTURE_RGBA
1157 : LOCAL_EGL_TEXTURE_RGB
)
1161 NS_WARNING("Failed to resize pbuffer");
1165 if (!ResizeOffscreenFBOs(pbsize
, false))
1168 SetOffscreenSize(aNewSize
, pbsize
);
1170 if (mSurface
&& !mPlatformContext
) {
1171 sEGLLibrary
.fDestroySurface(EGL_DISPLAY(), mSurface
);
1182 #if defined(MOZ_X11) && defined(MOZ_EGL_XRENDER_COMPOSITE)
1183 if (ResizeOffscreenPixmapSurface(aNewSize
)) {
1184 if (ResizeOffscreenFBOs(aNewSize
, true))
1189 return ResizeOffscreenFBOs(aNewSize
, true);
1193 static GLContextEGL
*
1194 GetGlobalContextEGL()
1196 return static_cast<GLContextEGL
*>(GLContextProviderEGL::GetGlobalContext());
1200 GLFormatForImage(gfxASurface::gfxImageFormat aFormat
)
1203 case gfxASurface::ImageFormatARGB32
:
1204 case gfxASurface::ImageFormatRGB24
:
1205 // Thebes only supports RGBX, not packed RGB.
1206 return LOCAL_GL_RGBA
;
1207 case gfxASurface::ImageFormatRGB16_565
:
1208 return LOCAL_GL_RGB
;
1209 case gfxASurface::ImageFormatA8
:
1210 return LOCAL_GL_LUMINANCE
;
1212 NS_WARNING("Unknown GL format for Image format");
1217 #ifdef MOZ_WIDGET_GONK
1219 PixelFormatForImage(gfxASurface::gfxImageFormat aFormat
)
1222 case gfxASurface::ImageFormatARGB32
:
1223 return PIXEL_FORMAT_RGBA_8888
;
1224 case gfxASurface::ImageFormatRGB24
:
1225 return PIXEL_FORMAT_RGBX_8888
;
1226 case gfxASurface::ImageFormatRGB16_565
:
1227 return PIXEL_FORMAT_RGB_565
;
1228 case gfxASurface::ImageFormatA8
:
1229 return PIXEL_FORMAT_L_8
;
1231 MOZ_NOT_REACHED("Unknown gralloc pixel format for Image format");
1236 static gfxASurface::gfxContentType
1237 ContentTypeForPixelFormat(PixelFormat aFormat
)
1240 case PIXEL_FORMAT_L_8
:
1241 return gfxASurface::CONTENT_ALPHA
;
1242 case PIXEL_FORMAT_RGBA_8888
:
1243 return gfxASurface::CONTENT_COLOR_ALPHA
;
1244 case PIXEL_FORMAT_RGBX_8888
:
1245 case PIXEL_FORMAT_RGB_565
:
1246 return gfxASurface::CONTENT_COLOR
;
1248 MOZ_NOT_REACHED("Unknown content type for gralloc pixel format");
1250 return gfxASurface::CONTENT_COLOR
;
1255 GLTypeForImage(gfxASurface::gfxImageFormat aFormat
)
1258 case gfxASurface::ImageFormatARGB32
:
1259 case gfxASurface::ImageFormatRGB24
:
1260 case gfxASurface::ImageFormatA8
:
1261 return LOCAL_GL_UNSIGNED_BYTE
;
1262 case gfxASurface::ImageFormatRGB16_565
:
1263 return LOCAL_GL_UNSIGNED_SHORT_5_6_5
;
1265 NS_WARNING("Unknown GL format for Image format");
1270 class TextureImageEGL
1271 : public TextureImage
1274 TextureImageEGL(GLuint aTexture
,
1275 const nsIntSize
& aSize
,
1277 ContentType aContentType
,
1278 GLContext
* aContext
,
1279 Flags aFlags
= TextureImage::NoFlags
,
1280 TextureState aTextureState
= Created
)
1281 : TextureImage(aSize
, aWrapMode
, aContentType
, aFlags
)
1282 , mGLContext(aContext
)
1283 , mUpdateFormat(gfxASurface::ImageFormatUnknown
)
1284 , mEGLImage(nullptr)
1285 , mTexture(aTexture
)
1288 , mTextureState(aTextureState
)
1292 mUpdateFormat
= gfxPlatform::GetPlatform()->OptimalFormatForContent(GetContentType());
1294 if (gUseBackingSurface
) {
1295 #ifdef MOZ_WIDGET_GONK
1296 switch (mUpdateFormat
) {
1297 case gfxASurface::ImageFormatARGB32
:
1298 mShaderType
= BGRALayerProgramType
;
1300 case gfxASurface::ImageFormatRGB24
:
1301 mUpdateFormat
= gfxASurface::ImageFormatARGB32
;
1302 mShaderType
= BGRXLayerProgramType
;
1304 case gfxASurface::ImageFormatRGB16_565
:
1305 mShaderType
= RGBXLayerProgramType
;
1307 case gfxASurface::ImageFormatA8
:
1308 mShaderType
= RGBALayerProgramType
;
1311 MOZ_NOT_REACHED("Unknown update format");
1314 if (mUpdateFormat
!= gfxASurface::ImageFormatARGB32
) {
1315 mShaderType
= RGBXLayerProgramType
;
1317 mShaderType
= RGBALayerProgramType
;
1322 if (mUpdateFormat
== gfxASurface::ImageFormatRGB16_565
) {
1323 mShaderType
= RGBXLayerProgramType
;
1324 } else if (mUpdateFormat
== gfxASurface::ImageFormatRGB24
) {
1325 // RGB24 means really RGBX for Thebes, which means we have to
1326 // use the right shader and ignore the uninitialized alpha
1328 mShaderType
= BGRXLayerProgramType
;
1330 mShaderType
= BGRALayerProgramType
;
1335 virtual ~TextureImageEGL()
1337 GLContext
*ctx
= mGLContext
;
1338 if (ctx
->IsDestroyed() || !ctx
->IsOwningThreadCurrent()) {
1339 ctx
= ctx
->GetSharedContext();
1342 // If we have a context, then we need to delete the texture;
1343 // if we don't have a context (either real or shared),
1344 // then they went away when the contex was deleted, because it
1345 // was the only one that had access to it.
1346 if (ctx
&& !ctx
->IsDestroyed()) {
1348 ctx
->fDeleteTextures(1, &mTexture
);
1350 DestroyEGLSurface();
1354 bool UsingDirectTexture()
1356 #ifdef MOZ_WIDGET_GONK
1357 if (mGraphicBuffer
!= nullptr)
1360 return !!mBackingSurface
;
1363 virtual void GetUpdateRegion(nsIntRegion
& aForRegion
)
1365 if (mTextureState
!= Valid
) {
1366 // if the texture hasn't been initialized yet, force the
1367 // client to paint everything
1368 aForRegion
= nsIntRect(nsIntPoint(0, 0), mSize
);
1371 if (UsingDirectTexture()) {
1375 // We can only draw a rectangle, not subregions due to
1376 // the way that our texture upload functions work. If
1377 // needed, we /could/ do multiple texture uploads if we have
1378 // non-overlapping rects, but that's a tradeoff.
1379 aForRegion
= nsIntRegion(aForRegion
.GetBounds());
1382 virtual gfxASurface
* BeginUpdate(nsIntRegion
& aRegion
)
1384 NS_ASSERTION(!mUpdateSurface
, "BeginUpdate() without EndUpdate()?");
1386 // determine the region the client will need to repaint
1387 GetUpdateRegion(aRegion
);
1388 mUpdateRect
= aRegion
.GetBounds();
1390 //printf_stderr("BeginUpdate with updateRect [%d %d %d %d]\n", mUpdateRect.x, mUpdateRect.y, mUpdateRect.width, mUpdateRect.height);
1391 if (!nsIntRect(nsIntPoint(0, 0), mSize
).Contains(mUpdateRect
)) {
1392 NS_ERROR("update outside of image");
1396 #ifdef MOZ_WIDGET_GONK
1397 if (mGraphicBuffer
!= nullptr) {
1398 mUpdateSurface
= GetLockSurface();
1400 return mUpdateSurface
;
1404 if (mBackingSurface
) {
1405 if (sEGLLibrary
.HasKHRLockSurface()) {
1406 mUpdateSurface
= GetLockSurface();
1408 mUpdateSurface
= mBackingSurface
;
1411 return mUpdateSurface
;
1414 //printf_stderr("creating image surface %dx%d format %d\n", mUpdateRect.width, mUpdateRect.height, mUpdateFormat);
1417 new gfxImageSurface(gfxIntSize(mUpdateRect
.width
, mUpdateRect
.height
),
1420 mUpdateSurface
->SetDeviceOffset(gfxPoint(-mUpdateRect
.x
, -mUpdateRect
.y
));
1422 return mUpdateSurface
;
1425 virtual void EndUpdate()
1427 NS_ASSERTION(!!mUpdateSurface
, "EndUpdate() without BeginUpdate()?");
1431 mTextureState
= Valid
;
1432 mUpdateSurface
= nullptr;
1436 if (mBackingSurface
&& mUpdateSurface
== mBackingSurface
) {
1438 if (mBackingSurface
->GetType() == gfxASurface::SurfaceTypeXlib
) {
1439 FinishX(DefaultXDisplay());
1443 mBackingSurface
->SetDeviceOffset(gfxPoint(0, 0));
1444 mTextureState
= Valid
;
1445 mUpdateSurface
= nullptr;
1449 //printf_stderr("EndUpdate: slow path");
1451 // This is the slower path -- we didn't have any way to set up
1452 // a fast mapping between our cairo target surface and the GL
1453 // texture, so we have to upload data.
1455 // Undo the device offset that BeginUpdate set; doesn't much
1456 // matter for us here, but important if we ever do anything
1457 // directly with the surface.
1458 mUpdateSurface
->SetDeviceOffset(gfxPoint(0, 0));
1460 nsRefPtr
<gfxImageSurface
> uploadImage
= nullptr;
1461 gfxIntSize
updateSize(mUpdateRect
.width
, mUpdateRect
.height
);
1463 NS_ASSERTION(mUpdateSurface
->GetType() == gfxASurface::SurfaceTypeImage
&&
1464 mUpdateSurface
->GetSize() == updateSize
,
1465 "Upload image isn't an image surface when one is expected, or is wrong size!");
1467 uploadImage
= static_cast<gfxImageSurface
*>(mUpdateSurface
.get());
1473 mGLContext
->MakeCurrent();
1474 mGLContext
->fBindTexture(LOCAL_GL_TEXTURE_2D
, mTexture
);
1476 if (mTextureState
!= Valid
) {
1477 NS_ASSERTION(mUpdateRect
.x
== 0 && mUpdateRect
.y
== 0 &&
1478 mUpdateRect
.Size() == mSize
,
1479 "Bad initial update on non-created texture!");
1481 mGLContext
->fTexImage2D(LOCAL_GL_TEXTURE_2D
,
1483 GLFormatForImage(mUpdateFormat
),
1487 GLFormatForImage(uploadImage
->Format()),
1488 GLTypeForImage(uploadImage
->Format()),
1489 uploadImage
->Data());
1491 mGLContext
->fTexSubImage2D(LOCAL_GL_TEXTURE_2D
,
1497 GLFormatForImage(uploadImage
->Format()),
1498 GLTypeForImage(uploadImage
->Format()),
1499 uploadImage
->Data());
1502 mUpdateSurface
= nullptr;
1503 mTextureState
= Valid
;
1504 return; // mTexture is bound
1507 virtual bool DirectUpdate(gfxASurface
* aSurf
, const nsIntRegion
& aRegion
, const nsIntPoint
& aFrom
/* = nsIntPoint(0, 0) */)
1509 nsIntRect bounds
= aRegion
.GetBounds();
1512 if (mTextureState
!= Valid
) {
1513 bounds
= nsIntRect(0, 0, mSize
.width
, mSize
.height
);
1514 region
= nsIntRegion(bounds
);
1519 if ((mBackingSurface
&& sEGLLibrary
.HasKHRLockSurface())
1520 #ifdef MOZ_WIDGET_GONK
1521 || (mGraphicBuffer
!= nullptr)
1524 mUpdateSurface
= GetLockSurface();
1525 if (mUpdateSurface
) {
1526 nsRefPtr
<gfxContext
> ctx
= new gfxContext(mUpdateSurface
);
1527 gfxUtils::ClipToRegion(ctx
, aRegion
);
1528 ctx
->SetSource(aSurf
, gfxPoint(-aFrom
.x
, -aFrom
.y
));
1529 ctx
->SetOperator(gfxContext::OPERATOR_SOURCE
);
1531 mUpdateSurface
= nullptr;
1536 mGLContext
->UploadSurfaceToTexture(aSurf
,
1539 mTextureState
== Created
,
1540 bounds
.TopLeft() + aFrom
,
1544 mTextureState
= Valid
;
1548 virtual void BindTexture(GLenum aTextureUnit
)
1550 // Ensure the texture is allocated before it is used.
1551 if (mTextureState
== Created
) {
1555 #ifdef MOZ_WIDGET_GONK
1556 if (UsingDirectTexture()) {
1557 mGLContext
->fActiveTexture(aTextureUnit
);
1558 mGLContext
->fBindTexture(LOCAL_GL_TEXTURE_2D
, mTexture
);
1559 mGLContext
->fEGLImageTargetTexture2D(LOCAL_GL_TEXTURE_2D
, mEGLImage
);
1560 if (sEGLLibrary
.fGetError() != LOCAL_EGL_SUCCESS
) {
1561 LOG("Could not set image target texture. ERROR (0x%04x)", sEGLLibrary
.fGetError());
1566 mGLContext
->fActiveTexture(aTextureUnit
);
1567 mGLContext
->fBindTexture(LOCAL_GL_TEXTURE_2D
, mTexture
);
1568 mGLContext
->fActiveTexture(LOCAL_GL_TEXTURE0
);
1572 virtual GLuint
GetTextureID()
1574 // Ensure the texture is allocated before it is used.
1575 if (mTextureState
== Created
) {
1581 virtual bool InUpdate() const { return !!mUpdateSurface
; }
1583 virtual void Resize(const nsIntSize
& aSize
)
1585 NS_ASSERTION(!mUpdateSurface
, "Resize() while in update?");
1587 if (mSize
== aSize
&& mTextureState
!= Created
)
1590 mGLContext
->fBindTexture(LOCAL_GL_TEXTURE_2D
, mTexture
);
1592 // Try to generate a backin surface first if we have the ability
1593 if (gUseBackingSurface
) {
1594 CreateBackingSurface(gfxIntSize(aSize
.width
, aSize
.height
));
1597 if (!UsingDirectTexture()) {
1598 // If we don't have a backing surface or failed to obtain one,
1599 // use the GL Texture failsafe
1600 mGLContext
->fTexImage2D(LOCAL_GL_TEXTURE_2D
,
1602 GLFormatForImage(mUpdateFormat
),
1606 GLFormatForImage(mUpdateFormat
),
1607 GLTypeForImage(mUpdateFormat
),
1611 mTextureState
= Allocated
;
1617 if (mBound
&& !ReleaseTexImage())
1620 EGLBoolean success
=
1621 sEGLLibrary
.fBindTexImage(EGL_DISPLAY(),
1622 (EGLSurface
)mSurface
,
1623 LOCAL_EGL_BACK_BUFFER
);
1625 if (success
== LOCAL_EGL_FALSE
)
1632 bool ReleaseTexImage()
1637 EGLBoolean success
=
1638 sEGLLibrary
.fReleaseTexImage(EGL_DISPLAY(),
1639 (EGLSurface
)mSurface
,
1640 LOCAL_EGL_BACK_BUFFER
);
1642 if (success
== LOCAL_EGL_FALSE
)
1649 virtual already_AddRefed
<gfxImageSurface
> GetLockSurface()
1652 NS_WARNING("Can't lock surface twice");
1656 #ifdef MOZ_WIDGET_GONK
1657 if (mGraphicBuffer
!= nullptr) {
1658 // Unset the EGLImage target so that we don't get clashing locks
1659 mGLContext
->MakeCurrent(true);
1660 mGLContext
->UnbindExternalBuffer(mTexture
);
1663 if (mGraphicBuffer
->lock(GraphicBuffer::USAGE_SW_READ_OFTEN
|
1664 GraphicBuffer::USAGE_SW_WRITE_OFTEN
,
1666 LOG("Could not lock GraphicBuffer");
1670 nsRefPtr
<gfxImageSurface
> surface
=
1671 new gfxImageSurface(reinterpret_cast<unsigned char *>(vaddr
),
1672 gfxIntSize(mSize
.width
, mSize
.height
),
1673 mGraphicBuffer
->getStride() * gfxUtils::ImageFormatToDepth(mUpdateFormat
) / 8,
1678 return surface
.forget();
1682 if (!sEGLLibrary
.HasKHRLockSurface()) {
1683 NS_WARNING("GetLockSurface called, but no EGL_KHR_lock_surface extension!");
1687 if (!CreateEGLSurface(mBackingSurface
)) {
1688 NS_WARNING("Failed to create EGL surface");
1692 static EGLint lock_attribs
[] = {
1693 LOCAL_EGL_MAP_PRESERVE_PIXELS_KHR
, LOCAL_EGL_TRUE
,
1694 LOCAL_EGL_LOCK_USAGE_HINT_KHR
, LOCAL_EGL_READ_SURFACE_BIT_KHR
| LOCAL_EGL_WRITE_SURFACE_BIT_KHR
,
1698 sEGLLibrary
.fLockSurface(EGL_DISPLAY(), mSurface
, lock_attribs
);
1702 unsigned char *data
= nullptr;
1706 sEGLLibrary
.fQuerySurface(EGL_DISPLAY(), mSurface
, LOCAL_EGL_BITMAP_POINTER_KHR
, (EGLint
*)&data
);
1707 sEGLLibrary
.fQuerySurface(EGL_DISPLAY(), mSurface
, LOCAL_EGL_BITMAP_PITCH_KHR
, &pitch
);
1708 sEGLLibrary
.fQuerySurface(EGL_DISPLAY(), mSurface
, LOCAL_EGL_BITMAP_PIXEL_SIZE_KHR
, &pixsize
);
1710 nsRefPtr
<gfxImageSurface
> sharedImage
=
1711 new gfxImageSurface(data
,
1712 mBackingSurface
->GetSize(),
1716 return sharedImage
.forget();
1719 virtual void UnlockSurface()
1722 NS_WARNING("UnlockSurface called, surface not locked!");
1728 #ifdef MOZ_WIDGET_GONK
1729 if (mGraphicBuffer
!= nullptr) {
1730 mGraphicBuffer
->unlock();
1736 sEGLLibrary
.fUnlockSurface(EGL_DISPLAY(), mSurface
);
1739 virtual already_AddRefed
<gfxASurface
> GetBackingSurface()
1741 nsRefPtr
<gfxASurface
> copy
= mBackingSurface
;
1742 return copy
.forget();
1745 virtual bool CreateEGLSurface(gfxASurface
* aSurface
)
1749 NS_WARNING("no surface");
1753 if (aSurface
->GetType() != gfxASurface::SurfaceTypeXlib
) {
1754 NS_WARNING("wrong surface type, must be xlib");
1762 EGLSurface surface
= CreateEGLSurfaceForXSurface(aSurface
, &mConfig
);
1765 NS_WARNING("couldn't find X config for surface");
1776 virtual void DestroyEGLSurface(void)
1778 #ifdef MOZ_WIDGET_GONK
1779 mGraphicBuffer
.clear();
1782 sEGLLibrary
.fDestroyImage(EGL_DISPLAY(), mEGLImage
);
1783 mEGLImage
= nullptr;
1790 sEGLLibrary
.fDestroySurface(EGL_DISPLAY(), mSurface
);
1794 virtual bool CreateBackingSurface(const gfxIntSize
& aSize
)
1797 DestroyEGLSurface();
1798 mBackingSurface
= nullptr;
1801 Display
* dpy
= DefaultXDisplay();
1802 XRenderPictFormat
* renderFMT
=
1803 gfxXlibSurface::FindRenderFormat(dpy
, mUpdateFormat
);
1805 nsRefPtr
<gfxXlibSurface
> xsurface
=
1806 gfxXlibSurface::Create(DefaultScreenOfDisplay(dpy
),
1808 gfxIntSize(aSize
.width
, aSize
.height
));
1813 if (sEGLLibrary
.HasKHRImagePixmap() &&
1814 mGLContext
->IsExtensionSupported(GLContext::OES_EGL_image
))
1817 sEGLLibrary
.fCreateImage(EGL_DISPLAY(),
1819 LOCAL_EGL_NATIVE_PIXMAP
,
1820 (EGLClientBuffer
)xsurface
->XDrawable(),
1824 printf_stderr("couldn't create EGL image: ERROR (0x%04x)\n", sEGLLibrary
.fGetError());
1827 mGLContext
->fBindTexture(LOCAL_GL_TEXTURE_2D
, mTexture
);
1828 mGLContext
->fEGLImageTargetTexture2D(LOCAL_GL_TEXTURE_2D
, mEGLImage
);
1829 sEGLLibrary
.fDestroyImage(EGL_DISPLAY(), mEGLImage
);
1830 mEGLImage
= nullptr;
1832 if (!CreateEGLSurface(xsurface
)) {
1833 printf_stderr("ProviderEGL Failed create EGL surface: ERROR (0x%04x)\n", sEGLLibrary
.fGetError());
1837 if (!BindTexImage()) {
1838 printf_stderr("ProviderEGL Failed to bind teximage: ERROR (0x%04x)\n", sEGLLibrary
.fGetError());
1843 mBackingSurface
= xsurface
;
1845 return mBackingSurface
!= nullptr;
1848 #ifdef MOZ_WIDGET_GONK
1849 if (gUseBackingSurface
) {
1850 mGLContext
->MakeCurrent(true);
1851 PixelFormat format
= PixelFormatForImage(mUpdateFormat
);
1852 uint32_t usage
= GraphicBuffer::USAGE_HW_TEXTURE
|
1853 GraphicBuffer::USAGE_SW_READ_OFTEN
|
1854 GraphicBuffer::USAGE_SW_WRITE_OFTEN
;
1855 mGraphicBuffer
= new GraphicBuffer(aSize
.width
, aSize
.height
, format
, usage
);
1856 if (mGraphicBuffer
->initCheck() == OK
) {
1857 const int eglImageAttributes
[] = { LOCAL_EGL_IMAGE_PRESERVED
, LOCAL_EGL_TRUE
,
1858 LOCAL_EGL_NONE
, LOCAL_EGL_NONE
};
1859 mEGLImage
= sEGLLibrary
.fCreateImage(EGL_DISPLAY(),
1861 EGL_NATIVE_BUFFER_ANDROID
,
1862 (EGLClientBuffer
) mGraphicBuffer
->getNativeBuffer(),
1863 eglImageAttributes
);
1865 mGraphicBuffer
= nullptr;
1866 LOG("Could not create EGL images: ERROR (0x%04x)", sEGLLibrary
.fGetError());
1873 mGraphicBuffer
= nullptr;
1874 LOG("GraphicBufferAllocator::alloc failed");
1878 return mBackingSurface
!= nullptr;
1882 typedef gfxASurface::gfxImageFormat ImageFormat
;
1884 GLContext
* mGLContext
;
1886 nsIntRect mUpdateRect
;
1887 ImageFormat mUpdateFormat
;
1888 bool mUsingDirectTexture
;
1889 nsRefPtr
<gfxASurface
> mBackingSurface
;
1890 nsRefPtr
<gfxASurface
> mUpdateSurface
;
1891 #ifdef MOZ_WIDGET_GONK
1892 sp
<GraphicBuffer
> mGraphicBuffer
;
1896 EGLSurface mSurface
;
1898 TextureState mTextureState
;
1903 virtual void ApplyFilter()
1905 mGLContext
->ApplyFilterToBoundTexture(mFilter
);
1909 #ifdef MOZ_WIDGET_GONK
1911 class DirectTextureImageEGL
1912 : public TextureImageEGL
1915 DirectTextureImageEGL(GLuint aTexture
,
1916 sp
<GraphicBuffer
> aGraphicBuffer
,
1918 GLContext
* aContext
)
1919 : TextureImageEGL(aTexture
,
1920 nsIntSize(aGraphicBuffer
->getWidth(), aGraphicBuffer
->getHeight()),
1922 ContentTypeForPixelFormat(aGraphicBuffer
->getPixelFormat()),
1927 mGraphicBuffer
= aGraphicBuffer
;
1929 const int eglImageAttributes
[] =
1930 { LOCAL_EGL_IMAGE_PRESERVED
, LOCAL_EGL_TRUE
,
1931 LOCAL_EGL_NONE
, LOCAL_EGL_NONE
};
1933 mEGLImage
= sEGLLibrary
.fCreateImage(EGL_DISPLAY(),
1935 EGL_NATIVE_BUFFER_ANDROID
,
1936 mGraphicBuffer
->getNativeBuffer(),
1937 eglImageAttributes
);
1939 LOG("Could not create EGL images: ERROR (0x%04x)", sEGLLibrary
.fGetError());
1944 #endif // MOZ_WIDGET_GONK
1946 already_AddRefed
<TextureImage
>
1947 GLContextEGL::CreateTextureImage(const nsIntSize
& aSize
,
1948 TextureImage::ContentType aContentType
,
1950 TextureImage::Flags aFlags
)
1952 nsRefPtr
<TextureImage
> t
= new gl::TiledTextureImage(this, aSize
, aContentType
, aFlags
);
1956 #ifdef MOZ_WIDGET_GONK
1957 already_AddRefed
<TextureImage
>
1958 GLContextEGL::CreateDirectTextureImage(GraphicBuffer
* aBuffer
,
1964 fGenTextures(1, &texture
);
1966 nsRefPtr
<TextureImage
> texImage(
1967 new DirectTextureImageEGL(texture
, aBuffer
, aWrapMode
, this));
1968 texImage
->BindTexture(LOCAL_GL_TEXTURE0
);
1970 GLint texfilter
= LOCAL_GL_LINEAR
;
1971 fTexParameteri(LOCAL_GL_TEXTURE_2D
, LOCAL_GL_TEXTURE_MIN_FILTER
, texfilter
);
1972 fTexParameteri(LOCAL_GL_TEXTURE_2D
, LOCAL_GL_TEXTURE_MAG_FILTER
, texfilter
);
1973 fTexParameteri(LOCAL_GL_TEXTURE_2D
, LOCAL_GL_TEXTURE_WRAP_S
, aWrapMode
);
1974 fTexParameteri(LOCAL_GL_TEXTURE_2D
, LOCAL_GL_TEXTURE_WRAP_T
, aWrapMode
);
1976 return texImage
.forget();
1978 #endif // MOZ_WIDGET_GONK
1980 already_AddRefed
<TextureImage
>
1981 GLContextEGL::TileGenFunc(const nsIntSize
& aSize
,
1982 TextureImage::ContentType aContentType
,
1983 TextureImage::Flags aFlags
)
1988 fGenTextures(1, &texture
);
1990 nsRefPtr
<TextureImageEGL
> teximage
=
1991 new TextureImageEGL(texture
, aSize
, LOCAL_GL_CLAMP_TO_EDGE
, aContentType
, this, aFlags
);
1993 teximage
->BindTexture(LOCAL_GL_TEXTURE0
);
1995 GLint texfilter
= aFlags
& TextureImage::UseNearestFilter
? LOCAL_GL_NEAREST
: LOCAL_GL_LINEAR
;
1996 fTexParameteri(LOCAL_GL_TEXTURE_2D
, LOCAL_GL_TEXTURE_MIN_FILTER
, texfilter
);
1997 fTexParameteri(LOCAL_GL_TEXTURE_2D
, LOCAL_GL_TEXTURE_MAG_FILTER
, texfilter
);
1998 fTexParameteri(LOCAL_GL_TEXTURE_2D
, LOCAL_GL_TEXTURE_WRAP_S
, LOCAL_GL_CLAMP_TO_EDGE
);
1999 fTexParameteri(LOCAL_GL_TEXTURE_2D
, LOCAL_GL_TEXTURE_WRAP_T
, LOCAL_GL_CLAMP_TO_EDGE
);
2001 return teximage
.forget();
2004 inline static ContextFormat
2005 DepthToGLFormat(int aDepth
)
2009 return ContextFormat::BasicRGBA32
;
2011 return ContextFormat::BasicRGB24
;
2013 return ContextFormat::BasicRGB16_565
;
2017 return ContextFormat::BasicRGBA32
;
2020 static nsRefPtr
<GLContext
> gGlobalContext
;
2022 static const EGLint kEGLConfigAttribsRGB16
[] = {
2023 LOCAL_EGL_SURFACE_TYPE
, LOCAL_EGL_WINDOW_BIT
,
2024 LOCAL_EGL_RENDERABLE_TYPE
, LOCAL_EGL_OPENGL_ES2_BIT
,
2025 LOCAL_EGL_RED_SIZE
, 5,
2026 LOCAL_EGL_GREEN_SIZE
, 6,
2027 LOCAL_EGL_BLUE_SIZE
, 5,
2028 LOCAL_EGL_ALPHA_SIZE
, 0,
2032 static const EGLint kEGLConfigAttribsRGB24
[] = {
2033 LOCAL_EGL_SURFACE_TYPE
, LOCAL_EGL_WINDOW_BIT
,
2034 LOCAL_EGL_RENDERABLE_TYPE
, LOCAL_EGL_OPENGL_ES2_BIT
,
2035 LOCAL_EGL_RED_SIZE
, 8,
2036 LOCAL_EGL_GREEN_SIZE
, 8,
2037 LOCAL_EGL_BLUE_SIZE
, 8,
2041 static const EGLint kEGLConfigAttribsRGBA32
[] = {
2042 LOCAL_EGL_SURFACE_TYPE
, LOCAL_EGL_WINDOW_BIT
,
2043 LOCAL_EGL_RENDERABLE_TYPE
, LOCAL_EGL_OPENGL_ES2_BIT
,
2044 LOCAL_EGL_RED_SIZE
, 8,
2045 LOCAL_EGL_GREEN_SIZE
, 8,
2046 LOCAL_EGL_BLUE_SIZE
, 8,
2047 LOCAL_EGL_ALPHA_SIZE
, 8,
2052 CreateConfig(EGLConfig
* aConfig
, int32_t depth
)
2054 EGLConfig configs
[64];
2055 const EGLint
* attribs
;
2056 EGLint ncfg
= ArrayLength(configs
);
2060 attribs
= kEGLConfigAttribsRGB16
;
2063 attribs
= kEGLConfigAttribsRGB24
;
2066 attribs
= kEGLConfigAttribsRGBA32
;
2069 NS_ERROR("Unknown pixel depth");
2073 if (!sEGLLibrary
.fChooseConfig(EGL_DISPLAY(), attribs
,
2074 configs
, ncfg
, &ncfg
) ||
2079 for (int j
= 0; j
< ncfg
; ++j
) {
2080 EGLConfig config
= configs
[j
];
2083 if (sEGLLibrary
.fGetConfigAttrib(EGL_DISPLAY(), config
,
2084 LOCAL_EGL_RED_SIZE
, &r
) &&
2085 sEGLLibrary
.fGetConfigAttrib(EGL_DISPLAY(), config
,
2086 LOCAL_EGL_GREEN_SIZE
, &g
) &&
2087 sEGLLibrary
.fGetConfigAttrib(EGL_DISPLAY(), config
,
2088 LOCAL_EGL_BLUE_SIZE
, &b
) &&
2089 sEGLLibrary
.fGetConfigAttrib(EGL_DISPLAY(), config
,
2090 LOCAL_EGL_ALPHA_SIZE
, &a
) &&
2091 ((depth
== 16 && r
== 5 && g
== 6 && b
== 5) ||
2092 (depth
== 24 && r
== 8 && g
== 8 && b
== 8) ||
2093 (depth
== 32 && r
== 8 && g
== 8 && b
== 8 && a
== 8)))
2102 // Return true if a suitable EGLConfig was found and pass it out
2103 // through aConfig. Return false otherwise.
2105 // NB: It's entirely legal for the returned EGLConfig to be valid yet
2106 // have the value null.
2108 CreateConfig(EGLConfig
* aConfig
)
2110 int32_t depth
= gfxPlatform::GetPlatform()->GetScreenDepth();
2111 if (!CreateConfig(aConfig
, depth
)) {
2112 #ifdef MOZ_WIDGET_ANDROID
2114 // Android doesn't always support 16 bit so also try 24 bit
2116 return CreateConfig(aConfig
, 24);
2125 // When MOZ_ANDROID_OMTC is defined,
2126 // use mozilla::AndroidBridge::Bridge()->ProvideEGLSurface() instead.
2127 #ifndef MOZ_ANDROID_OMTC
2129 CreateSurfaceForWindow(nsIWidget
*aWidget
, EGLConfig config
)
2134 sEGLLibrary
.DumpEGLConfig(config
);
2137 #if defined(MOZ_WIDGET_ANDROID)
2139 // On Android, we have to ask Java to make the eglCreateWindowSurface
2140 // call for us. See GLHelpers.java for a description of why.
2142 // We also only have one true "window", so we just use it directly and ignore
2143 // what was passed in.
2144 AndroidGeckoSurfaceView
& sview
= mozilla::AndroidBridge::Bridge()->SurfaceView();
2145 if (sview
.isNull()) {
2146 printf_stderr("got null surface\n");
2150 surface
= mozilla::AndroidBridge::Bridge()->
2151 CallEglCreateWindowSurface(EGL_DISPLAY(), config
, sview
);
2153 surface
= sEGLLibrary
.fCreateWindowSurface(EGL_DISPLAY(), config
, GET_NATIVE_WINDOW(aWidget
), 0);
2156 #ifdef MOZ_WIDGET_GONK
2157 gScreenBounds
.x
= 0;
2158 gScreenBounds
.y
= 0;
2159 sEGLLibrary
.fQuerySurface(EGL_DISPLAY(), surface
, LOCAL_EGL_WIDTH
, &gScreenBounds
.width
);
2160 sEGLLibrary
.fQuerySurface(EGL_DISPLAY(), surface
, LOCAL_EGL_HEIGHT
, &gScreenBounds
.height
);
2167 already_AddRefed
<GLContext
>
2168 GLContextProviderEGL::CreateForWindow(nsIWidget
*aWidget
)
2172 if (!sEGLLibrary
.EnsureInitialized()) {
2176 bool doubleBuffered
= true;
2178 void* currentContext
= sEGLLibrary
.fGetCurrentContext();
2179 if (aWidget
->HasGLContext() && currentContext
) {
2180 int32_t depth
= gfxPlatform::GetPlatform()->GetScreenDepth();
2181 void* platformContext
= currentContext
;
2182 #ifdef MOZ_WIDGET_QT
2183 QGLContext
* context
= const_cast<QGLContext
*>(QGLContext::currentContext());
2184 if (context
&& context
->device()) {
2185 depth
= context
->device()->depth();
2187 doubleBuffered
= context
->format().doubleBuffer();
2188 platformContext
= context
;
2190 nsRefPtr
<GLContextEGL
> glContext
=
2191 new GLContextEGL(ContextFormat(DepthToGLFormat(depth
)),
2194 sEGLLibrary
.fGetCurrentSurface(LOCAL_EGL_DRAW
), // just use same surface for read and draw
2198 if (!glContext
->Init())
2201 glContext
->MakeCurrent();
2202 sEGLLibrary
.LoadConfigSensitiveSymbols();
2204 glContext
->SetIsDoubleBuffered(doubleBuffered
);
2206 glContext
->SetPlatformContext(platformContext
);
2207 if (!gGlobalContext
) {
2208 gGlobalContext
= glContext
;
2211 return glContext
.forget();
2214 if (!CreateConfig(&config
)) {
2215 printf_stderr("Failed to create EGL config!\n");
2219 #ifdef MOZ_ANDROID_OMTC
2220 mozilla::AndroidBridge::Bridge()->RegisterCompositor();
2221 EGLSurface surface
= mozilla::AndroidBridge::Bridge()->ProvideEGLSurface();
2223 EGLSurface surface
= CreateSurfaceForWindow(aWidget
, config
);
2230 if (!sEGLLibrary
.fBindAPI(LOCAL_EGL_OPENGL_ES_API
)) {
2231 sEGLLibrary
.fDestroySurface(EGL_DISPLAY(), surface
);
2235 GLContextEGL
*shareContext
= GetGlobalContextEGL();
2237 nsRefPtr
<GLContextEGL
> glContext
=
2238 GLContextEGL::CreateGLContext(ContextFormat(ContextFormat::BasicRGB24
),
2248 glContext
->MakeCurrent();
2249 sEGLLibrary
.LoadConfigSensitiveSymbols();
2250 glContext
->SetIsDoubleBuffered(doubleBuffered
);
2252 return glContext
.forget();
2256 FillPBufferAttribs_Minimal(nsTArray
<EGLint
>& aAttrs
)
2260 #define A1(_x) do { aAttrs.AppendElement(_x); } while (0)
2261 #define A2(_x,_y) do { A1(_x); A1(_y); } while (0)
2263 A2(LOCAL_EGL_RENDERABLE_TYPE
, LOCAL_EGL_OPENGL_ES2_BIT
);
2265 A2(LOCAL_EGL_SURFACE_TYPE
, LOCAL_EGL_PBUFFER_BIT
);
2273 FillPBufferAttribs(nsTArray
<EGLint
>& aAttrs
,
2274 const ContextFormat
& aFormat
,
2275 bool aCanBindToTexture
,
2276 int aColorBitsOverride
,
2277 int aDepthBitsOverride
)
2281 #define A1(_x) do { aAttrs.AppendElement(_x); } while (0)
2282 #define A2(_x,_y) do { A1(_x); A1(_y); } while (0)
2284 A2(LOCAL_EGL_RENDERABLE_TYPE
, LOCAL_EGL_OPENGL_ES2_BIT
);
2286 A2(LOCAL_EGL_SURFACE_TYPE
, LOCAL_EGL_PBUFFER_BIT
);
2288 if (aColorBitsOverride
== -1) {
2289 A2(LOCAL_EGL_RED_SIZE
, aFormat
.red
);
2290 A2(LOCAL_EGL_GREEN_SIZE
, aFormat
.green
);
2291 A2(LOCAL_EGL_BLUE_SIZE
, aFormat
.blue
);
2293 A2(LOCAL_EGL_RED_SIZE
, aColorBitsOverride
);
2294 A2(LOCAL_EGL_GREEN_SIZE
, aColorBitsOverride
);
2295 A2(LOCAL_EGL_BLUE_SIZE
, aColorBitsOverride
);
2298 A2(LOCAL_EGL_ALPHA_SIZE
, aFormat
.alpha
);
2300 if (aDepthBitsOverride
== -1) {
2301 A2(LOCAL_EGL_DEPTH_SIZE
, aFormat
.minDepth
);
2303 A2(LOCAL_EGL_DEPTH_SIZE
, aDepthBitsOverride
);
2306 A2(LOCAL_EGL_STENCIL_SIZE
, aFormat
.minStencil
);
2308 if (aCanBindToTexture
) {
2309 A2(aFormat
.minAlpha
? LOCAL_EGL_BIND_TO_TEXTURE_RGBA
: LOCAL_EGL_BIND_TO_TEXTURE_RGB
,
2318 already_AddRefed
<GLContextEGL
>
2319 GLContextEGL::CreateEGLPBufferOffscreenContext(const gfxIntSize
& aSize
,
2320 const ContextFormat
& aFormat
,
2327 bool configCanBindToTexture
= true;
2329 EGLConfig configs
[64];
2330 int numConfigs
= sizeof(configs
)/sizeof(EGLConfig
);
2331 int foundConfigs
= 0;
2333 // if we're running under ANGLE, we can't set BIND_TO_TEXTURE --
2334 // it's not supported, and we have dx interop pbuffers anyway
2335 if (sEGLLibrary
.IsANGLE() || bufferUnused
)
2336 configCanBindToTexture
= false;
2338 nsTArray
<EGLint
> attribs(32);
2339 int attribAttempt
= 0;
2341 int tryDepthSize
= (aFormat
.depth
> 0) ? 24 : 0;
2345 FillPBufferAttribs_Minimal(attribs
);
2347 switch (attribAttempt
) {
2349 FillPBufferAttribs(attribs
, aFormat
, configCanBindToTexture
, 8, tryDepthSize
);
2352 FillPBufferAttribs(attribs
, aFormat
, configCanBindToTexture
, -1, tryDepthSize
);
2355 FillPBufferAttribs(attribs
, aFormat
, configCanBindToTexture
, -1, -1);
2360 if (!sEGLLibrary
.fChooseConfig(EGL_DISPLAY(),
2362 configs
, numConfigs
,
2364 || foundConfigs
== 0)
2367 NS_WARNING("No EGL Config for minimal PBuffer!");
2371 if (attribAttempt
< 3) {
2373 goto TRY_ATTRIBS_AGAIN
;
2376 if (configCanBindToTexture
) {
2377 NS_WARNING("No pbuffer EGL configs that can bind to texture, trying without");
2378 configCanBindToTexture
= false;
2380 goto TRY_ATTRIBS_AGAIN
;
2383 // no configs? no pbuffers!
2384 NS_WARNING("Failed to select acceptable config for PBuffer creation!");
2388 // XXX do some smarter matching here, perhaps instead of the more complex
2389 // minimum overrides above
2390 config
= configs
[0];
2392 sEGLLibrary
.DumpEGLConfig(config
);
2395 gfxIntSize
pbsize(aSize
);
2396 surface
= GLContextEGL::CreatePBufferSurfaceTryingPowerOfTwo(config
,
2397 configCanBindToTexture
2399 ? LOCAL_EGL_TEXTURE_RGBA
2400 : LOCAL_EGL_TEXTURE_RGB
)
2404 NS_WARNING("Failed to create PBuffer for context!");
2408 sEGLLibrary
.fBindAPI(LOCAL_EGL_OPENGL_ES_API
);
2410 GLContextEGL
* shareContext
= GetGlobalContextEGL();
2411 context
= sEGLLibrary
.fCreateContext(EGL_DISPLAY(),
2413 shareContext
? shareContext
->mContext
2415 sEGLLibrary
.HasRobustness() ? gContextAttribsRobustness
2418 NS_WARNING("Failed to create GLContext from PBuffer");
2419 sEGLLibrary
.fDestroySurface(EGL_DISPLAY(), surface
);
2423 nsRefPtr
<GLContextEGL
> glContext
= new GLContextEGL(aFormat
, shareContext
,
2424 config
, surface
, context
,
2427 if (!glContext
->Init()) {
2428 NS_WARNING("Failed to initialize GLContext!");
2432 glContext
->mCanBindToTexture
= configCanBindToTexture
;
2434 if (!bufferUnused
) { // We *are* using the buffer
2435 glContext
->SetOffscreenSize(aSize
, pbsize
);
2436 glContext
->mIsPBuffer
= true;
2439 return glContext
.forget();
2444 CreateEGLSurfaceForXSurface(gfxASurface
* aSurface
, EGLConfig
* aConfig
)
2446 gfxXlibSurface
* xsurface
= static_cast<gfxXlibSurface
*>(aSurface
);
2448 aSurface
->GetContentType() == gfxASurface::CONTENT_COLOR
;
2450 static EGLint pixmap_config_rgb
[] = {
2451 LOCAL_EGL_TEXTURE_TARGET
, LOCAL_EGL_TEXTURE_2D
,
2452 LOCAL_EGL_TEXTURE_FORMAT
, LOCAL_EGL_TEXTURE_RGB
,
2456 static EGLint pixmap_config_rgba
[] = {
2457 LOCAL_EGL_TEXTURE_TARGET
, LOCAL_EGL_TEXTURE_2D
,
2458 LOCAL_EGL_TEXTURE_FORMAT
, LOCAL_EGL_TEXTURE_RGBA
,
2462 EGLSurface surface
= nullptr;
2463 if (aConfig
&& *aConfig
) {
2465 surface
= sEGLLibrary
.fCreatePixmapSurface(EGL_DISPLAY(), *aConfig
,
2466 (EGLNativePixmapType
)xsurface
->XDrawable(),
2469 surface
= sEGLLibrary
.fCreatePixmapSurface(EGL_DISPLAY(), *aConfig
,
2470 (EGLNativePixmapType
)xsurface
->XDrawable(),
2471 pixmap_config_rgba
);
2473 if (surface
!= EGL_NO_SURFACE
)
2477 EGLConfig configs
[32];
2478 int numConfigs
= 32;
2480 static EGLint pixmap_config
[] = {
2481 LOCAL_EGL_SURFACE_TYPE
, LOCAL_EGL_PIXMAP_BIT
,
2482 LOCAL_EGL_RENDERABLE_TYPE
, LOCAL_EGL_OPENGL_ES2_BIT
,
2483 LOCAL_EGL_DEPTH_SIZE
, 0,
2484 LOCAL_EGL_BIND_TO_TEXTURE_RGB
, LOCAL_EGL_TRUE
,
2488 static EGLint pixmap_lock_config
[] = {
2489 LOCAL_EGL_SURFACE_TYPE
, LOCAL_EGL_PIXMAP_BIT
| LOCAL_EGL_LOCK_SURFACE_BIT_KHR
,
2490 LOCAL_EGL_RENDERABLE_TYPE
, LOCAL_EGL_OPENGL_ES2_BIT
,
2491 LOCAL_EGL_DEPTH_SIZE
, 0,
2492 LOCAL_EGL_BIND_TO_TEXTURE_RGB
, LOCAL_EGL_TRUE
,
2496 if (!sEGLLibrary
.fChooseConfig(EGL_DISPLAY(),
2497 sEGLLibrary
.HasKHRLockSurface() ?
2498 pixmap_lock_config
: pixmap_config
,
2499 configs
, numConfigs
, &numConfigs
))
2502 if (numConfigs
== 0)
2506 for (i
= 0; i
< numConfigs
; ++i
) {
2508 surface
= sEGLLibrary
.fCreatePixmapSurface(EGL_DISPLAY(), configs
[i
],
2509 (EGLNativePixmapType
)xsurface
->XDrawable(),
2512 surface
= sEGLLibrary
.fCreatePixmapSurface(EGL_DISPLAY(), configs
[i
],
2513 (EGLNativePixmapType
)xsurface
->XDrawable(),
2514 pixmap_config_rgba
);
2516 if (surface
!= EGL_NO_SURFACE
)
2525 *aConfig
= configs
[i
];
2531 already_AddRefed
<GLContextEGL
>
2532 GLContextEGL::CreateEGLPixmapOffscreenContext(const gfxIntSize
& aSize
,
2533 const ContextFormat
& aFormat
,
2536 gfxASurface
*thebesSurface
= nullptr;
2537 EGLNativePixmapType pixmap
= 0;
2540 nsRefPtr
<gfxXlibSurface
> xsurface
=
2541 gfxXlibSurface::Create(DefaultScreenOfDisplay(DefaultXDisplay()),
2542 gfxXlibSurface::FindRenderFormat(DefaultXDisplay(),
2543 gfxASurface::ImageFormatRGB24
),
2546 // XSync required after gfxXlibSurface::Create, otherwise EGL will fail with BadDrawable error
2547 XSync(DefaultXDisplay(), False
);
2548 if (xsurface
->CairoStatus() != 0)
2551 thebesSurface
= xsurface
;
2552 pixmap
= (EGLNativePixmapType
)xsurface
->XDrawable();
2559 EGLSurface surface
= 0;
2560 EGLConfig config
= 0;
2563 surface
= CreateEGLSurfaceForXSurface(thebesSurface
, &config
);
2569 GLContextEGL
*shareContext
= aShare
? GetGlobalContextEGL() : nullptr;
2571 nsRefPtr
<GLContextEGL
> glContext
=
2572 GLContextEGL::CreateGLContext(aFormat
,
2578 glContext
->HoldSurface(thebesSurface
);
2580 return glContext
.forget();
2583 // Under EGL, if we're under X11, then we have to create a Pixmap
2584 // because Maemo's EGL implementation doesn't support pbuffers at all
2585 // for some reason. On Android, pbuffers are supported fine, though
2586 // often without the ability to texture from them directly.
2587 already_AddRefed
<GLContext
>
2588 GLContextProviderEGL::CreateOffscreen(const gfxIntSize
& aSize
,
2589 const ContextFormat
& aFormat
,
2590 const ContextFlags aFlags
)
2592 if (!sEGLLibrary
.EnsureInitialized()) {
2596 #if !defined(MOZ_X11)
2597 bool usePBuffers
= false; // Generally, prefer FBOs to PBuffers
2599 if (sEGLLibrary
.IsANGLE())
2600 usePBuffers
= true; // For d3d share handle, we need an EGL surface
2602 gfxIntSize pbufferSize
= usePBuffers
? aSize
: gfxIntSize(16, 16);
2603 nsRefPtr
<GLContextEGL
> glContext
=
2604 GLContextEGL::CreateEGLPBufferOffscreenContext(pbufferSize
, aFormat
, !usePBuffers
);
2609 gfxIntSize fboSize
= usePBuffers
? glContext
->OffscreenActualSize() : aSize
;
2610 if (!(aFlags
& GLContext::ContextFlagsGlobal
) && !glContext
->ResizeOffscreenFBOs(fboSize
, !usePBuffers
))
2613 return glContext
.forget();
2614 #elif defined(MOZ_X11) && defined(MOZ_EGL_XRENDER_COMPOSITE)
2615 nsRefPtr
<GLContextEGL
> glContext
=
2616 GLContextEGL::CreateBasicEGLPixmapOffscreenContext(aSize
, aFormat
);
2621 if (!(aFlags
& GLContext::ContextFlagsGlobal
) && !glContext
->ResizeOffscreenFBOs(glContext
->OffscreenActualSize(), true))
2624 return glContext
.forget();
2625 #elif defined(MOZ_X11)
2626 nsRefPtr
<GLContextEGL
> glContext
=
2627 GLContextEGL::CreateEGLPixmapOffscreenContext(gfxIntSize(16, 16), aFormat
, true);
2633 if (!(aFlags
& GLContext::ContextFlagsGlobal
) && !glContext
->ResizeOffscreenFBOs(aSize
, true)) {
2634 // we weren't able to create the initial
2635 // offscreen FBO, so this is dead
2638 return glContext
.forget();
2645 GLContextProviderEGL::GetGlobalContext(const ContextFlags
)
2647 // Don't want a global context on Android as 1) share groups across 2 threads fail on many Tegra drivers (bug 759225)
2648 // and 2) some mobile devices have a very strict limit on global number of GL contexts (bug 754257)
2649 #ifdef MOZ_ANDROID_OMTC
2653 // Don't want a global context on Windows as we don't use it for WebGL surface sharing and it makes
2654 // context creation fail after a context loss (bug 764578)
2660 static bool triedToCreateContext
= false;
2661 if (!triedToCreateContext
&& !gGlobalContext
) {
2662 triedToCreateContext
= true;
2663 // Don't assign directly to gGlobalContext here, because
2664 // CreateOffscreen can call us re-entrantly.
2665 nsRefPtr
<GLContext
> ctx
=
2666 GLContextProviderEGL::CreateOffscreen(gfxIntSize(16, 16),
2667 ContextFormat(ContextFormat::BasicRGB24
),
2668 GLContext::ContextFlagsGlobal
);
2669 gGlobalContext
= ctx
;
2671 gGlobalContext
->SetIsGlobalSharedContext(true);
2674 return gGlobalContext
;
2678 GLContextProviderEGL::Shutdown()
2680 gGlobalContext
= nullptr;
2683 //------------------------------------------------------------------------------
2684 // The following methods exist to support an accelerated WebGL XRender composite
2685 // path for BasicLayers. This is a potentially temporary change that can be
2686 // removed when performance of GL layers is superior on mobile linux platforms.
2687 //------------------------------------------------------------------------------
2688 #if defined(MOZ_X11) && defined(MOZ_EGL_XRENDER_COMPOSITE)
2691 CreateBasicEGLSurfaceForXSurface(gfxASurface
* aSurface
, EGLConfig
* aConfig
)
2693 gfxXlibSurface
* xsurface
= static_cast<gfxXlibSurface
*>(aSurface
);
2696 aSurface
->GetContentType() == gfxASurface::CONTENT_COLOR
;
2698 EGLSurface surface
= nullptr;
2699 if (aConfig
&& *aConfig
) {
2700 surface
= sEGLLibrary
.fCreatePixmapSurface(EGL_DISPLAY(), *aConfig
,
2701 xsurface
->XDrawable(),
2704 if (surface
!= EGL_NO_SURFACE
)
2708 EGLConfig configs
[32];
2709 int numConfigs
= 32;
2711 static EGLint pixmap_config
[] = {
2712 LOCAL_EGL_SURFACE_TYPE
, LOCAL_EGL_PIXMAP_BIT
,
2713 LOCAL_EGL_RENDERABLE_TYPE
, LOCAL_EGL_OPENGL_ES2_BIT
,
2715 LOCAL_EGL_DEPTH_SIZE
, 16,
2719 if (!sEGLLibrary
.fChooseConfig(EGL_DISPLAY(),
2721 configs
, numConfigs
, &numConfigs
))
2724 if (numConfigs
== 0)
2728 for (i
= 0; i
< numConfigs
; ++i
) {
2729 surface
= sEGLLibrary
.fCreatePixmapSurface(EGL_DISPLAY(), configs
[i
],
2730 xsurface
->XDrawable(),
2733 if (surface
!= EGL_NO_SURFACE
)
2743 *aConfig
= configs
[i
];
2749 already_AddRefed
<GLContextEGL
>
2750 GLContextEGL::CreateBasicEGLPixmapOffscreenContext(const gfxIntSize
& aSize
,
2751 const ContextFormat
& aFormat
)
2753 gfxASurface
*thebesSurface
= nullptr;
2754 EGLNativePixmapType pixmap
= 0;
2756 XRenderPictFormat
* format
= gfxXlibSurface::FindRenderFormat(DefaultXDisplay(), gfxASurface::ImageFormatARGB32
);
2758 nsRefPtr
<gfxXlibSurface
> xsurface
=
2759 gfxXlibSurface::Create(DefaultScreenOfDisplay(DefaultXDisplay()), format
, aSize
);
2761 // XSync required after gfxXlibSurface::Create, otherwise EGL will fail with BadDrawable error
2762 XSync(DefaultXDisplay(), False
);
2763 if (xsurface
->CairoStatus() != 0)
2768 thebesSurface
= xsurface
;
2770 pixmap
= xsurface
->XDrawable();
2776 EGLSurface surface
= 0;
2777 EGLConfig config
= 0;
2779 surface
= CreateBasicEGLSurfaceForXSurface(xsurface
, &config
);
2785 EGLContext context
= sEGLLibrary
.fCreateContext(EGL_DISPLAY(),
2788 sEGLLibrary
.HasRobustness() ? gContextAttribsRobustness
2791 sEGLLibrary
.fDestroySurface(EGL_DISPLAY(), surface
);
2795 nsRefPtr
<GLContextEGL
> glContext
= new GLContextEGL(aFormat
, nullptr,
2796 config
, surface
, context
,
2799 if (!glContext
->Init())
2804 glContext
->HoldSurface(thebesSurface
);
2806 return glContext
.forget();
2809 bool GLContextEGL::ResizeOffscreenPixmapSurface(const gfxIntSize
& aNewSize
)
2811 gfxASurface
*thebesSurface
= nullptr;
2812 EGLNativePixmapType pixmap
= 0;
2814 XRenderPictFormat
* format
= gfxXlibSurface::FindRenderFormat(DefaultXDisplay(), gfxASurface::ImageFormatARGB32
);
2816 nsRefPtr
<gfxXlibSurface
> xsurface
=
2817 gfxXlibSurface::Create(DefaultScreenOfDisplay(DefaultXDisplay()),
2821 // XSync required after gfxXlibSurface::Create, otherwise EGL will fail with BadDrawable error
2822 XSync(DefaultXDisplay(), False
);
2823 if (xsurface
->CairoStatus() != 0)
2826 thebesSurface
= xsurface
;
2828 pixmap
= xsurface
->XDrawable();
2834 EGLSurface surface
= 0;
2835 EGLConfig config
= 0;
2836 surface
= CreateBasicEGLSurfaceForXSurface(xsurface
, &config
);
2838 NS_WARNING("Failed to resize pbuffer");
2842 sEGLLibrary
.fDestroySurface(EGL_DISPLAY(), mSurface
);
2845 HoldSurface(thebesSurface
);
2846 SetOffscreenSize(aNewSize
, aNewSize
);
2854 } /* namespace gl */
2855 } /* namespace mozilla */