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