/src/mozilla-central/gfx/gl/TextureImageEGL.cpp
Line | Count | Source (jump to first uncovered line) |
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/. */ |
5 | | |
6 | | #include "TextureImageEGL.h" |
7 | | #include "GLLibraryEGL.h" |
8 | | #include "GLContext.h" |
9 | | #include "GLUploadHelpers.h" |
10 | | #include "gfxPlatform.h" |
11 | | #include "mozilla/gfx/Types.h" |
12 | | |
13 | | namespace mozilla { |
14 | | namespace gl { |
15 | | |
16 | | static GLenum |
17 | | GLFormatForImage(gfx::SurfaceFormat aFormat) |
18 | 0 | { |
19 | 0 | switch (aFormat) { |
20 | 0 | case gfx::SurfaceFormat::B8G8R8A8: |
21 | 0 | case gfx::SurfaceFormat::B8G8R8X8: |
22 | 0 | return LOCAL_GL_RGBA; |
23 | 0 | case gfx::SurfaceFormat::R5G6B5_UINT16: |
24 | 0 | return LOCAL_GL_RGB; |
25 | 0 | case gfx::SurfaceFormat::A8: |
26 | 0 | return LOCAL_GL_LUMINANCE; |
27 | 0 | default: |
28 | 0 | NS_WARNING("Unknown GL format for Surface format"); |
29 | 0 | } |
30 | 0 | return 0; |
31 | 0 | } |
32 | | |
33 | | static GLenum |
34 | | GLTypeForImage(gfx::SurfaceFormat aFormat) |
35 | 0 | { |
36 | 0 | switch (aFormat) { |
37 | 0 | case gfx::SurfaceFormat::B8G8R8A8: |
38 | 0 | case gfx::SurfaceFormat::B8G8R8X8: |
39 | 0 | case gfx::SurfaceFormat::A8: |
40 | 0 | return LOCAL_GL_UNSIGNED_BYTE; |
41 | 0 | case gfx::SurfaceFormat::R5G6B5_UINT16: |
42 | 0 | return LOCAL_GL_UNSIGNED_SHORT_5_6_5; |
43 | 0 | default: |
44 | 0 | NS_WARNING("Unknown GL format for Surface format"); |
45 | 0 | } |
46 | 0 | return 0; |
47 | 0 | } |
48 | | |
49 | | TextureImageEGL::TextureImageEGL(GLuint aTexture, |
50 | | const gfx::IntSize& aSize, |
51 | | GLenum aWrapMode, |
52 | | ContentType aContentType, |
53 | | GLContext* aContext, |
54 | | Flags aFlags, |
55 | | TextureState aTextureState, |
56 | | TextureImage::ImageFormat aImageFormat) |
57 | | : TextureImage(aSize, aWrapMode, aContentType, aFlags) |
58 | | , mGLContext(aContext) |
59 | | , mUpdateFormat(gfx::ImageFormatToSurfaceFormat(aImageFormat)) |
60 | | , mEGLImage(nullptr) |
61 | | , mTexture(aTexture) |
62 | | , mSurface(nullptr) |
63 | | , mConfig(nullptr) |
64 | | , mTextureState(aTextureState) |
65 | | , mBound(false) |
66 | 0 | { |
67 | 0 | if (mUpdateFormat == gfx::SurfaceFormat::UNKNOWN) { |
68 | 0 | mUpdateFormat = |
69 | 0 | gfxPlatform::GetPlatform()->Optimal2DFormatForContent(GetContentType()); |
70 | 0 | } |
71 | 0 |
|
72 | 0 | if (mUpdateFormat == gfx::SurfaceFormat::R5G6B5_UINT16) { |
73 | 0 | mTextureFormat = gfx::SurfaceFormat::R8G8B8X8; |
74 | 0 | } else if (mUpdateFormat == gfx::SurfaceFormat::B8G8R8X8) { |
75 | 0 | mTextureFormat = gfx::SurfaceFormat::B8G8R8X8; |
76 | 0 | } else { |
77 | 0 | mTextureFormat = gfx::SurfaceFormat::B8G8R8A8; |
78 | 0 | } |
79 | 0 | } |
80 | | |
81 | | TextureImageEGL::~TextureImageEGL() |
82 | 0 | { |
83 | 0 | if (mGLContext->IsDestroyed() || !mGLContext->IsOwningThreadCurrent()) { |
84 | 0 | return; |
85 | 0 | } |
86 | 0 | |
87 | 0 | // If we have a context, then we need to delete the texture; |
88 | 0 | // if we don't have a context (either real or shared), |
89 | 0 | // then they went away when the contex was deleted, because it |
90 | 0 | // was the only one that had access to it. |
91 | 0 | if (mGLContext->MakeCurrent()) { |
92 | 0 | mGLContext->fDeleteTextures(1, &mTexture); |
93 | 0 | } |
94 | 0 | ReleaseTexImage(); |
95 | 0 | DestroyEGLSurface(); |
96 | 0 | } |
97 | | |
98 | | bool |
99 | | TextureImageEGL::DirectUpdate(gfx::DataSourceSurface* aSurf, const nsIntRegion& aRegion, const gfx::IntPoint& aFrom /* = gfx::IntPoint(0,0) */) |
100 | 0 | { |
101 | 0 | gfx::IntRect bounds = aRegion.GetBounds(); |
102 | 0 |
|
103 | 0 | nsIntRegion region; |
104 | 0 | if (mTextureState != Valid) { |
105 | 0 | bounds = gfx::IntRect(0, 0, mSize.width, mSize.height); |
106 | 0 | region = nsIntRegion(bounds); |
107 | 0 | } else { |
108 | 0 | region = aRegion; |
109 | 0 | } |
110 | 0 |
|
111 | 0 | bool needInit = mTextureState == Created; |
112 | 0 | size_t uploadSize = 0; |
113 | 0 | mTextureFormat = |
114 | 0 | UploadSurfaceToTexture(mGLContext, |
115 | 0 | aSurf, |
116 | 0 | region, |
117 | 0 | mTexture, |
118 | 0 | mSize, |
119 | 0 | &uploadSize, |
120 | 0 | needInit, |
121 | 0 | aFrom); |
122 | 0 | if (mTextureFormat == SurfaceFormat::UNKNOWN) { |
123 | 0 | return false; |
124 | 0 | } |
125 | 0 | |
126 | 0 | if (uploadSize > 0) { |
127 | 0 | UpdateUploadSize(uploadSize); |
128 | 0 | } |
129 | 0 |
|
130 | 0 | mTextureState = Valid; |
131 | 0 | return true; |
132 | 0 | } |
133 | | |
134 | | void |
135 | | TextureImageEGL::BindTexture(GLenum aTextureUnit) |
136 | 0 | { |
137 | 0 | // Ensure the texture is allocated before it is used. |
138 | 0 | if (mTextureState == Created) { |
139 | 0 | Resize(mSize); |
140 | 0 | } |
141 | 0 |
|
142 | 0 | mGLContext->fActiveTexture(aTextureUnit); |
143 | 0 | mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture); |
144 | 0 | mGLContext->fActiveTexture(LOCAL_GL_TEXTURE0); |
145 | 0 | } |
146 | | |
147 | | void |
148 | | TextureImageEGL::Resize(const gfx::IntSize& aSize) |
149 | 0 | { |
150 | 0 | if (mSize == aSize && mTextureState != Created) |
151 | 0 | return; |
152 | 0 | |
153 | 0 | mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture); |
154 | 0 |
|
155 | 0 | mGLContext->fTexImage2D(LOCAL_GL_TEXTURE_2D, |
156 | 0 | 0, |
157 | 0 | GLFormatForImage(mUpdateFormat), |
158 | 0 | aSize.width, |
159 | 0 | aSize.height, |
160 | 0 | 0, |
161 | 0 | GLFormatForImage(mUpdateFormat), |
162 | 0 | GLTypeForImage(mUpdateFormat), |
163 | 0 | nullptr); |
164 | 0 |
|
165 | 0 | mTextureState = Allocated; |
166 | 0 | mSize = aSize; |
167 | 0 | } |
168 | | |
169 | | bool |
170 | | TextureImageEGL::BindTexImage() |
171 | 0 | { |
172 | 0 | if (mBound && !ReleaseTexImage()) |
173 | 0 | return false; |
174 | 0 | |
175 | 0 | auto* egl = gl::GLLibraryEGL::Get(); |
176 | 0 | EGLBoolean success = |
177 | 0 | egl->fBindTexImage(EGL_DISPLAY(), |
178 | 0 | (EGLSurface)mSurface, |
179 | 0 | LOCAL_EGL_BACK_BUFFER); |
180 | 0 |
|
181 | 0 | if (success == LOCAL_EGL_FALSE) |
182 | 0 | return false; |
183 | 0 | |
184 | 0 | mBound = true; |
185 | 0 | return true; |
186 | 0 | } |
187 | | |
188 | | bool |
189 | | TextureImageEGL::ReleaseTexImage() |
190 | 0 | { |
191 | 0 | if (!mBound) |
192 | 0 | return true; |
193 | 0 | |
194 | 0 | auto* egl = gl::GLLibraryEGL::Get(); |
195 | 0 | EGLBoolean success = |
196 | 0 | egl->fReleaseTexImage(EGL_DISPLAY(), |
197 | 0 | (EGLSurface)mSurface, |
198 | 0 | LOCAL_EGL_BACK_BUFFER); |
199 | 0 |
|
200 | 0 | if (success == LOCAL_EGL_FALSE) |
201 | 0 | return false; |
202 | 0 | |
203 | 0 | mBound = false; |
204 | 0 | return true; |
205 | 0 | } |
206 | | |
207 | | void |
208 | | TextureImageEGL::DestroyEGLSurface(void) |
209 | 0 | { |
210 | 0 | if (!mSurface) |
211 | 0 | return; |
212 | 0 | |
213 | 0 | auto* egl = gl::GLLibraryEGL::Get(); |
214 | 0 | egl->fDestroySurface(EGL_DISPLAY(), mSurface); |
215 | 0 | mSurface = nullptr; |
216 | 0 | } |
217 | | |
218 | | already_AddRefed<TextureImage> |
219 | | CreateTextureImageEGL(GLContext* gl, |
220 | | const gfx::IntSize& aSize, |
221 | | TextureImage::ContentType aContentType, |
222 | | GLenum aWrapMode, |
223 | | TextureImage::Flags aFlags, |
224 | | TextureImage::ImageFormat aImageFormat) |
225 | 0 | { |
226 | 0 | RefPtr<TextureImage> t = new gl::TiledTextureImage(gl, aSize, aContentType, aFlags, aImageFormat); |
227 | 0 | return t.forget(); |
228 | 0 | } |
229 | | |
230 | | already_AddRefed<TextureImage> |
231 | | TileGenFuncEGL(GLContext* gl, |
232 | | const gfx::IntSize& aSize, |
233 | | TextureImage::ContentType aContentType, |
234 | | TextureImage::Flags aFlags, |
235 | | TextureImage::ImageFormat aImageFormat) |
236 | 0 | { |
237 | 0 | gl->MakeCurrent(); |
238 | 0 |
|
239 | 0 | GLuint texture; |
240 | 0 | gl->fGenTextures(1, &texture); |
241 | 0 |
|
242 | 0 | RefPtr<TextureImageEGL> teximage = |
243 | 0 | new TextureImageEGL(texture, aSize, LOCAL_GL_CLAMP_TO_EDGE, aContentType, |
244 | 0 | gl, aFlags, TextureImage::Created, aImageFormat); |
245 | 0 |
|
246 | 0 | teximage->BindTexture(LOCAL_GL_TEXTURE0); |
247 | 0 |
|
248 | 0 | GLint texfilter = aFlags & TextureImage::UseNearestFilter ? LOCAL_GL_NEAREST : LOCAL_GL_LINEAR; |
249 | 0 | gl->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, texfilter); |
250 | 0 | gl->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, texfilter); |
251 | 0 | gl->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE); |
252 | 0 | gl->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE); |
253 | 0 |
|
254 | 0 | return teximage.forget(); |
255 | 0 | } |
256 | | |
257 | | } // namespace gl |
258 | | } // namespace mozilla |