Coverage Report

Created: 2018-09-25 14:53

/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