gfx/gl/SharedSurfaceEGL.cpp

branch
TOR_BUG_9701
changeset 15
b8a032363ba2
equal deleted inserted replaced
-1:000000000000 0:0faec9bf5a6f
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 */

mercurial