|
1 /* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */ |
|
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 #include "SharedSurfaceEGL.h" |
|
7 #include "GLContextEGL.h" |
|
8 #include "GLBlitHelper.h" |
|
9 #include "ScopedGLHelpers.h" |
|
10 #include "SharedSurfaceGL.h" |
|
11 #include "SurfaceFactory.h" |
|
12 #include "GLLibraryEGL.h" |
|
13 #include "TextureGarbageBin.h" |
|
14 #include "GLReadTexImageHelper.h" |
|
15 |
|
16 using namespace mozilla::gfx; |
|
17 |
|
18 namespace mozilla { |
|
19 namespace gl { |
|
20 |
|
21 SharedSurface_EGLImage* |
|
22 SharedSurface_EGLImage::Create(GLContext* prodGL, |
|
23 const GLFormats& formats, |
|
24 const gfx::IntSize& size, |
|
25 bool hasAlpha, |
|
26 EGLContext context) |
|
27 { |
|
28 GLLibraryEGL* egl = &sEGLLibrary; |
|
29 MOZ_ASSERT(egl); |
|
30 MOZ_ASSERT(context); |
|
31 |
|
32 if (!HasExtensions(egl, prodGL)) { |
|
33 return nullptr; |
|
34 } |
|
35 |
|
36 MOZ_ALWAYS_TRUE(prodGL->MakeCurrent()); |
|
37 GLuint prodTex = CreateTextureForOffscreen(prodGL, formats, size); |
|
38 if (!prodTex) { |
|
39 return nullptr; |
|
40 } |
|
41 |
|
42 EGLClientBuffer buffer = reinterpret_cast<EGLClientBuffer>(prodTex); |
|
43 EGLImage image = egl->fCreateImage(egl->Display(), context, |
|
44 LOCAL_EGL_GL_TEXTURE_2D, buffer, |
|
45 nullptr); |
|
46 if (!image) { |
|
47 prodGL->fDeleteTextures(1, &prodTex); |
|
48 return nullptr; |
|
49 } |
|
50 |
|
51 return new SharedSurface_EGLImage(prodGL, egl, |
|
52 size, hasAlpha, |
|
53 formats, prodTex, image); |
|
54 } |
|
55 |
|
56 |
|
57 bool |
|
58 SharedSurface_EGLImage::HasExtensions(GLLibraryEGL* egl, GLContext* gl) |
|
59 { |
|
60 return egl->HasKHRImageBase() && |
|
61 egl->IsExtensionSupported(GLLibraryEGL::KHR_gl_texture_2D_image) && |
|
62 gl->IsExtensionSupported(GLContext::OES_EGL_image_external); |
|
63 } |
|
64 |
|
65 SharedSurface_EGLImage::SharedSurface_EGLImage(GLContext* gl, |
|
66 GLLibraryEGL* egl, |
|
67 const gfx::IntSize& size, |
|
68 bool hasAlpha, |
|
69 const GLFormats& formats, |
|
70 GLuint prodTex, |
|
71 EGLImage image) |
|
72 : SharedSurface_GL(SharedSurfaceType::EGLImageShare, |
|
73 AttachmentType::GLTexture, |
|
74 gl, |
|
75 size, |
|
76 hasAlpha) |
|
77 , mMutex("SharedSurface_EGLImage mutex") |
|
78 , mEGL(egl) |
|
79 , mFormats(formats) |
|
80 , mProdTex(prodTex) |
|
81 , mImage(image) |
|
82 , mCurConsGL(nullptr) |
|
83 , mConsTex(0) |
|
84 , mSync(0) |
|
85 {} |
|
86 |
|
87 SharedSurface_EGLImage::~SharedSurface_EGLImage() |
|
88 { |
|
89 mEGL->fDestroyImage(Display(), mImage); |
|
90 mImage = 0; |
|
91 |
|
92 mGL->MakeCurrent(); |
|
93 mGL->fDeleteTextures(1, &mProdTex); |
|
94 mProdTex = 0; |
|
95 |
|
96 if (mConsTex) { |
|
97 MOZ_ASSERT(mGarbageBin); |
|
98 mGarbageBin->Trash(mConsTex); |
|
99 mConsTex = 0; |
|
100 } |
|
101 |
|
102 if (mSync) { |
|
103 // We can't call this unless we have the ext, but we will always have |
|
104 // the ext if we have something to destroy. |
|
105 mEGL->fDestroySync(Display(), mSync); |
|
106 mSync = 0; |
|
107 } |
|
108 } |
|
109 |
|
110 void |
|
111 SharedSurface_EGLImage::Fence() |
|
112 { |
|
113 MutexAutoLock lock(mMutex); |
|
114 mGL->MakeCurrent(); |
|
115 |
|
116 if (mEGL->IsExtensionSupported(GLLibraryEGL::KHR_fence_sync) && |
|
117 mGL->IsExtensionSupported(GLContext::OES_EGL_sync)) |
|
118 { |
|
119 if (mSync) { |
|
120 MOZ_ALWAYS_TRUE( mEGL->fDestroySync(Display(), mSync) ); |
|
121 mSync = 0; |
|
122 } |
|
123 |
|
124 mSync = mEGL->fCreateSync(Display(), |
|
125 LOCAL_EGL_SYNC_FENCE, |
|
126 nullptr); |
|
127 if (mSync) { |
|
128 mGL->fFlush(); |
|
129 return; |
|
130 } |
|
131 } |
|
132 |
|
133 MOZ_ASSERT(!mSync); |
|
134 mGL->fFinish(); |
|
135 } |
|
136 |
|
137 bool |
|
138 SharedSurface_EGLImage::WaitSync() |
|
139 { |
|
140 MutexAutoLock lock(mMutex); |
|
141 if (!mSync) { |
|
142 // We must not be needed. |
|
143 return true; |
|
144 } |
|
145 MOZ_ASSERT(mEGL->IsExtensionSupported(GLLibraryEGL::KHR_fence_sync)); |
|
146 |
|
147 // Wait FOREVER, primarily because some NVIDIA (at least Tegra) drivers |
|
148 // have ClientWaitSync returning immediately if the timeout delay is anything |
|
149 // else than FOREVER. |
|
150 // |
|
151 // FIXME: should we try to use a finite timeout delay where possible? |
|
152 EGLint status = mEGL->fClientWaitSync(Display(), |
|
153 mSync, |
|
154 0, |
|
155 LOCAL_EGL_FOREVER); |
|
156 |
|
157 if (status != LOCAL_EGL_CONDITION_SATISFIED) { |
|
158 return false; |
|
159 } |
|
160 |
|
161 MOZ_ALWAYS_TRUE( mEGL->fDestroySync(Display(), mSync) ); |
|
162 mSync = 0; |
|
163 |
|
164 return true; |
|
165 } |
|
166 |
|
167 |
|
168 EGLDisplay |
|
169 SharedSurface_EGLImage::Display() const |
|
170 { |
|
171 return mEGL->Display(); |
|
172 } |
|
173 |
|
174 void |
|
175 SharedSurface_EGLImage::AcquireConsumerTexture(GLContext* consGL, GLuint* out_texture, GLuint* out_target) |
|
176 { |
|
177 MutexAutoLock lock(mMutex); |
|
178 MOZ_ASSERT(!mCurConsGL || consGL == mCurConsGL); |
|
179 |
|
180 if (!mConsTex) { |
|
181 consGL->fGenTextures(1, &mConsTex); |
|
182 MOZ_ASSERT(mConsTex); |
|
183 |
|
184 ScopedBindTexture autoTex(consGL, mConsTex, LOCAL_GL_TEXTURE_EXTERNAL); |
|
185 consGL->fEGLImageTargetTexture2D(LOCAL_GL_TEXTURE_EXTERNAL, mImage); |
|
186 |
|
187 mCurConsGL = consGL; |
|
188 mGarbageBin = consGL->TexGarbageBin(); |
|
189 } |
|
190 |
|
191 MOZ_ASSERT(consGL == mCurConsGL); |
|
192 *out_texture = mConsTex; |
|
193 *out_target = LOCAL_GL_TEXTURE_EXTERNAL; |
|
194 } |
|
195 |
|
196 |
|
197 SurfaceFactory_EGLImage* |
|
198 SurfaceFactory_EGLImage::Create(GLContext* prodGL, |
|
199 const SurfaceCaps& caps) |
|
200 { |
|
201 EGLContext context = GLContextEGL::Cast(prodGL)->GetEGLContext(); |
|
202 |
|
203 GLLibraryEGL* egl = &sEGLLibrary; |
|
204 if (!SharedSurface_EGLImage::HasExtensions(egl, prodGL)) { |
|
205 return nullptr; |
|
206 } |
|
207 |
|
208 return new SurfaceFactory_EGLImage(prodGL, context, caps); |
|
209 } |
|
210 |
|
211 } /* namespace gfx */ |
|
212 } /* namespace mozilla */ |