Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/gfx/layers/opengl/TextureHostOGL.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#include "TextureHostOGL.h"
8
9
#include "EGLUtils.h"
10
#include "GLContext.h"                  // for GLContext, etc
11
#include "GLLibraryEGL.h"               // for GLLibraryEGL
12
#include "GLUploadHelpers.h"
13
#include "GLReadTexImageHelper.h"
14
#include "gfx2DGlue.h"                  // for ContentForFormat, etc
15
#include "mozilla/gfx/2D.h"             // for DataSourceSurface
16
#include "mozilla/gfx/BaseSize.h"       // for BaseSize
17
#include "mozilla/gfx/Logging.h"        // for gfxCriticalError
18
#include "mozilla/layers/ISurfaceAllocator.h"
19
#include "nsRegion.h"                   // for nsIntRegion
20
#include "AndroidSurfaceTexture.h"
21
#include "GfxTexturesReporter.h"        // for GfxTexturesReporter
22
#include "GLBlitTextureImageHelper.h"
23
#include "GeckoProfiler.h"
24
25
#ifdef XP_MACOSX
26
#include "mozilla/layers/MacIOSurfaceTextureHostOGL.h"
27
#endif
28
29
using namespace mozilla::gl;
30
using namespace mozilla::gfx;
31
32
namespace mozilla {
33
namespace layers {
34
35
class Compositor;
36
37
already_AddRefed<TextureHost>
38
CreateTextureHostOGL(const SurfaceDescriptor& aDesc,
39
                     ISurfaceAllocator* aDeallocator,
40
                     LayersBackend aBackend,
41
                     TextureFlags aFlags)
42
0
{
43
0
  RefPtr<TextureHost> result;
44
0
  switch (aDesc.type()) {
45
#ifdef MOZ_WIDGET_ANDROID
46
    case SurfaceDescriptor::TSurfaceTextureDescriptor: {
47
      const SurfaceTextureDescriptor& desc = aDesc.get_SurfaceTextureDescriptor();
48
      java::GeckoSurfaceTexture::LocalRef surfaceTexture = java::GeckoSurfaceTexture::Lookup(desc.handle());
49
50
      result = new SurfaceTextureHost(aFlags,
51
                                      surfaceTexture,
52
                                      desc.size(),
53
                                      desc.format(),
54
                                      desc.continuous(),
55
                                      desc.ignoreTransform());
56
      break;
57
    }
58
#endif
59
60
0
    case SurfaceDescriptor::TEGLImageDescriptor: {
61
0
      const EGLImageDescriptor& desc = aDesc.get_EGLImageDescriptor();
62
0
      result = new EGLImageTextureHost(aFlags,
63
0
                                       (EGLImage)desc.image(),
64
0
                                       (EGLSync)desc.fence(),
65
0
                                       desc.size(),
66
0
                                       desc.hasAlpha());
67
0
      break;
68
0
    }
69
0
70
#ifdef XP_MACOSX
71
    case SurfaceDescriptor::TSurfaceDescriptorMacIOSurface: {
72
      const SurfaceDescriptorMacIOSurface& desc =
73
        aDesc.get_SurfaceDescriptorMacIOSurface();
74
      result = new MacIOSurfaceTextureHostOGL(aFlags, desc);
75
      break;
76
    }
77
#endif
78
79
0
    case SurfaceDescriptor::TSurfaceDescriptorSharedGLTexture: {
80
0
      const auto& desc = aDesc.get_SurfaceDescriptorSharedGLTexture();
81
0
      result = new GLTextureHost(aFlags, desc.texture(),
82
0
                                 desc.target(),
83
0
                                 (GLsync)desc.fence(),
84
0
                                 desc.size(),
85
0
                                 desc.hasAlpha());
86
0
      break;
87
0
    }
88
0
    default: {
89
0
      MOZ_ASSERT_UNREACHABLE("Unsupported SurfaceDescriptor type");
90
0
      break;
91
0
    }
92
0
  }
93
0
  return result.forget();
94
0
}
95
96
static gl::TextureImage::Flags
97
FlagsToGLFlags(TextureFlags aFlags)
98
0
{
99
0
  uint32_t result = TextureImage::NoFlags;
100
0
101
0
  if (aFlags & TextureFlags::USE_NEAREST_FILTER)
102
0
    result |= TextureImage::UseNearestFilter;
103
0
  if (aFlags & TextureFlags::ORIGIN_BOTTOM_LEFT)
104
0
    result |= TextureImage::OriginBottomLeft;
105
0
  if (aFlags & TextureFlags::DISALLOW_BIGIMAGE)
106
0
    result |= TextureImage::DisallowBigImage;
107
0
108
0
  return static_cast<gl::TextureImage::Flags>(result);
109
0
}
110
111
bool
112
TextureImageTextureSourceOGL::Update(gfx::DataSourceSurface* aSurface,
113
                                     nsIntRegion* aDestRegion,
114
                                     gfx::IntPoint* aSrcOffset)
115
0
{
116
0
  GLContext *gl = mGL;
117
0
  MOZ_ASSERT(gl);
118
0
  if (!gl || !gl->MakeCurrent()) {
119
0
    NS_WARNING("trying to update TextureImageTextureSourceOGL without a GLContext");
120
0
    return false;
121
0
  }
122
0
  if (!aSurface) {
123
0
    gfxCriticalError() << "Invalid surface for OGL update";
124
0
    return false;
125
0
  }
126
0
  MOZ_ASSERT(aSurface);
127
0
128
0
  IntSize size = aSurface->GetSize();
129
0
  if (!mTexImage ||
130
0
      (mTexImage->GetSize() != size && !aSrcOffset) ||
131
0
      mTexImage->GetContentType() != gfx::ContentForFormat(aSurface->GetFormat())) {
132
0
    if (mFlags & TextureFlags::DISALLOW_BIGIMAGE) {
133
0
      GLint maxTextureSize;
134
0
      gl->fGetIntegerv(LOCAL_GL_MAX_TEXTURE_SIZE, &maxTextureSize);
135
0
      if (size.width > maxTextureSize || size.height > maxTextureSize) {
136
0
        NS_WARNING("Texture exceeds maximum texture size, refusing upload");
137
0
        return false;
138
0
      }
139
0
      // Explicitly use CreateBasicTextureImage instead of CreateTextureImage,
140
0
      // because CreateTextureImage might still choose to create a tiled
141
0
      // texture image.
142
0
      mTexImage = CreateBasicTextureImage(gl, size,
143
0
                                          gfx::ContentForFormat(aSurface->GetFormat()),
144
0
                                          LOCAL_GL_CLAMP_TO_EDGE,
145
0
                                          FlagsToGLFlags(mFlags));
146
0
    } else {
147
0
      // XXX - clarify which size we want to use. IncrementalContentHost will
148
0
      // require the size of the destination surface to be different from
149
0
      // the size of aSurface.
150
0
      // See bug 893300 (tracks the implementation of ContentHost for new textures).
151
0
      mTexImage = CreateTextureImage(gl,
152
0
                                     size,
153
0
                                     gfx::ContentForFormat(aSurface->GetFormat()),
154
0
                                     LOCAL_GL_CLAMP_TO_EDGE,
155
0
                                     FlagsToGLFlags(mFlags),
156
0
                                     SurfaceFormatToImageFormat(aSurface->GetFormat()));
157
0
    }
158
0
    ClearCachedFilter();
159
0
160
0
    if (aDestRegion &&
161
0
        !aSrcOffset &&
162
0
        !aDestRegion->IsEqual(gfx::IntRect(0, 0, size.width, size.height))) {
163
0
      // UpdateFromDataSource will ignore our specified aDestRegion since the texture
164
0
      // hasn't been allocated with glTexImage2D yet. Call Resize() to force the
165
0
      // allocation (full size, but no upload), and then we'll only upload the pixels
166
0
      // we care about below.
167
0
      mTexImage->Resize(size);
168
0
    }
169
0
  }
170
0
171
0
  return mTexImage->UpdateFromDataSource(aSurface, aDestRegion, aSrcOffset);
172
0
}
173
174
void
175
TextureImageTextureSourceOGL::EnsureBuffer(const IntSize& aSize,
176
                                           gfxContentType aContentType)
177
0
{
178
0
  if (!mTexImage ||
179
0
      mTexImage->GetSize() != aSize ||
180
0
      mTexImage->GetContentType() != aContentType) {
181
0
    mTexImage = CreateTextureImage(mGL,
182
0
                                   aSize,
183
0
                                   aContentType,
184
0
                                   LOCAL_GL_CLAMP_TO_EDGE,
185
0
                                   FlagsToGLFlags(mFlags));
186
0
  }
187
0
  mTexImage->Resize(aSize);
188
0
}
189
190
void
191
TextureImageTextureSourceOGL::SetTextureSourceProvider(TextureSourceProvider* aProvider)
192
0
{
193
0
  GLContext* newGL = aProvider ? aProvider->GetGLContext() : nullptr;
194
0
  if (!newGL || mGL != newGL) {
195
0
    DeallocateDeviceData();
196
0
  }
197
0
  mGL = newGL;
198
0
}
199
200
gfx::IntSize
201
TextureImageTextureSourceOGL::GetSize() const
202
0
{
203
0
  if (mTexImage) {
204
0
    if (mIterating) {
205
0
      return mTexImage->GetTileRect().Size();
206
0
    }
207
0
    return mTexImage->GetSize();
208
0
  }
209
0
  NS_WARNING("Trying to query the size of an empty TextureSource.");
210
0
  return gfx::IntSize(0, 0);
211
0
}
212
213
gfx::SurfaceFormat
214
TextureImageTextureSourceOGL::GetFormat() const
215
0
{
216
0
  if (mTexImage) {
217
0
    return mTexImage->GetTextureFormat();
218
0
  }
219
0
  NS_WARNING("Trying to query the format of an empty TextureSource.");
220
0
  return gfx::SurfaceFormat::UNKNOWN;
221
0
}
222
223
gfx::IntRect TextureImageTextureSourceOGL::GetTileRect()
224
0
{
225
0
  return mTexImage->GetTileRect();
226
0
}
227
228
void
229
TextureImageTextureSourceOGL::BindTexture(GLenum aTextureUnit,
230
                                          gfx::SamplingFilter aSamplingFilter)
231
0
{
232
0
  MOZ_ASSERT(mTexImage,
233
0
    "Trying to bind a TextureSource that does not have an underlying GL texture.");
234
0
  mTexImage->BindTexture(aTextureUnit);
235
0
  SetSamplingFilter(mGL, aSamplingFilter);
236
0
}
237
238
////////////////////////////////////////////////////////////////////////
239
// GLTextureSource
240
241
GLTextureSource::GLTextureSource(TextureSourceProvider* aProvider,
242
                                 GLuint aTextureHandle,
243
                                 GLenum aTarget,
244
                                 gfx::IntSize aSize,
245
                                 gfx::SurfaceFormat aFormat)
246
  : mGL(aProvider->GetGLContext())
247
  , mTextureHandle(aTextureHandle)
248
  , mTextureTarget(aTarget)
249
  , mSize(aSize)
250
  , mFormat(aFormat)
251
0
{
252
0
  MOZ_COUNT_CTOR(GLTextureSource);
253
0
}
254
255
GLTextureSource::~GLTextureSource()
256
0
{
257
0
  MOZ_COUNT_DTOR(GLTextureSource);
258
0
  DeleteTextureHandle();
259
0
}
260
261
void
262
GLTextureSource::DeallocateDeviceData()
263
0
{
264
0
  DeleteTextureHandle();
265
0
}
266
267
void
268
GLTextureSource::DeleteTextureHandle()
269
0
{
270
0
  GLContext* gl = this->gl();
271
0
  if (mTextureHandle != 0 && gl && gl->MakeCurrent()) {
272
0
    gl->fDeleteTextures(1, &mTextureHandle);
273
0
  }
274
0
  mTextureHandle = 0;
275
0
}
276
277
void
278
GLTextureSource::BindTexture(GLenum aTextureUnit,
279
                             gfx::SamplingFilter aSamplingFilter)
280
0
{
281
0
  MOZ_ASSERT(mTextureHandle != 0);
282
0
  GLContext* gl = this->gl();
283
0
  if (!gl || !gl->MakeCurrent()) {
284
0
    return;
285
0
  }
286
0
  gl->fActiveTexture(aTextureUnit);
287
0
  gl->fBindTexture(mTextureTarget, mTextureHandle);
288
0
  ApplySamplingFilterToBoundTexture(gl, aSamplingFilter, mTextureTarget);
289
0
}
290
291
void
292
GLTextureSource::SetTextureSourceProvider(TextureSourceProvider* aProvider)
293
0
{
294
0
  GLContext* newGL = aProvider ? aProvider->GetGLContext() : nullptr;
295
0
  if (!newGL) {
296
0
    mGL = newGL;
297
0
  } else if (mGL != newGL) {
298
0
    gfxCriticalError() << "GLTextureSource does not support changing compositors";
299
0
  }
300
0
301
0
  if (mNextSibling) {
302
0
    mNextSibling->SetTextureSourceProvider(aProvider);
303
0
  }
304
0
}
305
306
bool
307
GLTextureSource::IsValid() const
308
0
{
309
0
  return !!gl() && mTextureHandle != 0;
310
0
}
311
312
////////////////////////////////////////////////////////////////////////
313
// DirectMapTextureSource
314
315
DirectMapTextureSource::DirectMapTextureSource(TextureSourceProvider* aProvider,
316
                                               gfx::DataSourceSurface* aSurface)
317
  : GLTextureSource(aProvider,
318
                    0,
319
                    LOCAL_GL_TEXTURE_RECTANGLE_ARB,
320
                    aSurface->GetSize(),
321
                    aSurface->GetFormat())
322
0
{
323
0
  MOZ_ASSERT(aSurface);
324
0
325
0
  UpdateInternal(aSurface, nullptr, nullptr, true);
326
0
}
327
328
bool
329
DirectMapTextureSource::Update(gfx::DataSourceSurface* aSurface,
330
                               nsIntRegion* aDestRegion,
331
                               gfx::IntPoint* aSrcOffset)
332
0
{
333
0
  if (!aSurface) {
334
0
    return false;
335
0
  }
336
0
337
0
  return UpdateInternal(aSurface, aDestRegion, aSrcOffset, false);
338
0
}
339
340
bool
341
DirectMapTextureSource::Sync(bool aBlocking)
342
0
{
343
0
  if (!gl() || !gl()->MakeCurrent()) {
344
0
    // We use this function to decide whether we can unlock the texture
345
0
    // and clean it up. If we return false here and for whatever reason
346
0
    // the context is absent or invalid, the compositor will keep a
347
0
    // reference to this texture forever.
348
0
    return true;
349
0
  }
350
0
351
0
  if (!gl()->IsDestroyed()) {
352
0
    if (aBlocking) {
353
0
      gl()->fFinishObjectAPPLE(LOCAL_GL_TEXTURE, mTextureHandle);
354
0
    } else {
355
0
      return gl()->fTestObjectAPPLE(LOCAL_GL_TEXTURE, mTextureHandle);
356
0
    }
357
0
  }
358
0
  return true;
359
0
}
360
361
bool
362
DirectMapTextureSource::UpdateInternal(gfx::DataSourceSurface* aSurface,
363
                                       nsIntRegion* aDestRegion,
364
                                       gfx::IntPoint* aSrcOffset,
365
                                       bool aInit)
366
0
{
367
0
  if (!gl() || !gl()->MakeCurrent()) {
368
0
    return false;
369
0
  }
370
0
371
0
  if (aInit) {
372
0
    gl()->fGenTextures(1, &mTextureHandle);
373
0
    gl()->fBindTexture(LOCAL_GL_TEXTURE_RECTANGLE_ARB, mTextureHandle);
374
0
375
0
    gl()->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB,
376
0
                         LOCAL_GL_TEXTURE_STORAGE_HINT_APPLE,
377
0
                         LOCAL_GL_STORAGE_CACHED_APPLE);
378
0
    gl()->fTextureRangeAPPLE(LOCAL_GL_TEXTURE_RECTANGLE_ARB,
379
0
                             aSurface->Stride() * aSurface->GetSize().height,
380
0
                             aSurface->GetData());
381
0
382
0
    gl()->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB,
383
0
                         LOCAL_GL_TEXTURE_WRAP_S,
384
0
                         LOCAL_GL_CLAMP_TO_EDGE);
385
0
    gl()->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB,
386
0
                         LOCAL_GL_TEXTURE_WRAP_T,
387
0
                         LOCAL_GL_CLAMP_TO_EDGE);
388
0
  }
389
0
390
0
  MOZ_ASSERT(mTextureHandle);
391
0
392
0
  // APPLE_client_storage
393
0
  gl()->fPixelStorei(LOCAL_GL_UNPACK_CLIENT_STORAGE_APPLE, LOCAL_GL_TRUE);
394
0
395
0
  nsIntRegion destRegion = aDestRegion ? *aDestRegion
396
0
                                       : IntRect(0, 0,
397
0
                                                 aSurface->GetSize().width,
398
0
                                                 aSurface->GetSize().height);
399
0
  gfx::IntPoint srcPoint = aSrcOffset ? *aSrcOffset
400
0
                                      : gfx::IntPoint(0, 0);
401
0
  mFormat = gl::UploadSurfaceToTexture(gl(),
402
0
                                       aSurface,
403
0
                                       destRegion,
404
0
                                       mTextureHandle,
405
0
                                       aSurface->GetSize(),
406
0
                                       nullptr,
407
0
                                       aInit,
408
0
                                       srcPoint,
409
0
                                       LOCAL_GL_TEXTURE0,
410
0
                                       LOCAL_GL_TEXTURE_RECTANGLE_ARB);
411
0
412
0
  gl()->fPixelStorei(LOCAL_GL_UNPACK_CLIENT_STORAGE_APPLE, LOCAL_GL_FALSE);
413
0
  return true;
414
0
}
415
416
////////////////////////////////////////////////////////////////////////
417
////////////////////////////////////////////////////////////////////////
418
// SurfaceTextureHost
419
420
#ifdef MOZ_WIDGET_ANDROID
421
422
SurfaceTextureSource::SurfaceTextureSource(TextureSourceProvider* aProvider,
423
                                           mozilla::java::GeckoSurfaceTexture::Ref& aSurfTex,
424
                                           gfx::SurfaceFormat aFormat,
425
                                           GLenum aTarget,
426
                                           GLenum aWrapMode,
427
                                           gfx::IntSize aSize,
428
                                           bool aIgnoreTransform)
429
  : mGL(aProvider->GetGLContext())
430
  , mSurfTex(aSurfTex)
431
  , mFormat(aFormat)
432
  , mTextureTarget(aTarget)
433
  , mWrapMode(aWrapMode)
434
  , mSize(aSize)
435
  , mIgnoreTransform(aIgnoreTransform)
436
{
437
}
438
439
void
440
SurfaceTextureSource::BindTexture(GLenum aTextureUnit,
441
                                  gfx::SamplingFilter aSamplingFilter)
442
{
443
  MOZ_ASSERT(mSurfTex);
444
  GLContext* gl = this->gl();
445
  if (!gl || !gl->MakeCurrent()) {
446
    NS_WARNING("Trying to bind a texture without a GLContext");
447
    return;
448
  }
449
450
  gl->fActiveTexture(aTextureUnit);
451
  gl->fBindTexture(mTextureTarget, mSurfTex->GetTexName());
452
453
  ApplySamplingFilterToBoundTexture(gl, aSamplingFilter, mTextureTarget);
454
}
455
456
void
457
SurfaceTextureSource::SetTextureSourceProvider(TextureSourceProvider* aProvider)
458
{
459
  GLContext* newGL = aProvider->GetGLContext();
460
  if (!newGL || mGL != newGL) {
461
    DeallocateDeviceData();
462
    return;
463
  }
464
465
  mGL = newGL;
466
}
467
468
bool
469
SurfaceTextureSource::IsValid() const
470
{
471
  return !!gl();
472
}
473
474
gfx::Matrix4x4
475
SurfaceTextureSource::GetTextureTransform()
476
{
477
  MOZ_ASSERT(mSurfTex);
478
479
  gfx::Matrix4x4 ret;
480
481
  // GetTransformMatrix() returns the transform set by the producer side of
482
  // the SurfaceTexture. We should ignore this if we know the transform should
483
  // be identity but the producer couldn't set it correctly, like is the
484
  // case for AndroidNativeWindowTextureData.
485
  if (!mIgnoreTransform) {
486
    const auto& surf = java::sdk::SurfaceTexture::LocalRef(java::sdk::SurfaceTexture::Ref::From(mSurfTex));
487
    AndroidSurfaceTexture::GetTransformMatrix(surf, &ret);
488
  }
489
490
  return ret;
491
}
492
493
void
494
SurfaceTextureSource::DeallocateDeviceData()
495
{
496
  mSurfTex = nullptr;
497
}
498
499
////////////////////////////////////////////////////////////////////////
500
501
SurfaceTextureHost::SurfaceTextureHost(TextureFlags aFlags,
502
                                       mozilla::java::GeckoSurfaceTexture::Ref& aSurfTex,
503
                                       gfx::IntSize aSize,
504
                                       gfx::SurfaceFormat aFormat,
505
                                       bool aContinuousUpdate,
506
                                       bool aIgnoreTransform)
507
  : TextureHost(aFlags)
508
  , mSurfTex(aSurfTex)
509
  , mSize(aSize)
510
  , mFormat(aFormat)
511
  , mContinuousUpdate(aContinuousUpdate)
512
  , mIgnoreTransform(aIgnoreTransform)
513
{
514
  if (!mSurfTex) {
515
    return;
516
  }
517
518
  // Continuous update makes no sense with single buffer mode
519
  MOZ_ASSERT(!mSurfTex->IsSingleBuffer() || !mContinuousUpdate);
520
521
  mSurfTex->IncrementUse();
522
}
523
524
SurfaceTextureHost::~SurfaceTextureHost()
525
{
526
  if (mSurfTex) {
527
    mSurfTex->DecrementUse();
528
    mSurfTex = nullptr;
529
  }
530
}
531
532
void
533
SurfaceTextureHost::PrepareTextureSource(CompositableTextureSourceRef& aTexture)
534
{
535
  if (!mContinuousUpdate && mSurfTex) {
536
    if (!EnsureAttached()) {
537
      return;
538
    }
539
540
    // UpdateTexImage() advances the internal buffer queue, so we only want to call this
541
    // once per transactionwhen we are not in continuous mode (as we are here). Otherwise,
542
    // the SurfaceTexture content will be de-synced from the rest of the page in subsequent
543
    // compositor passes.
544
    mSurfTex->UpdateTexImage();
545
  }
546
}
547
548
gl::GLContext*
549
SurfaceTextureHost::gl() const
550
{
551
  return mProvider ? mProvider->GetGLContext() : nullptr;
552
}
553
554
bool
555
SurfaceTextureHost::EnsureAttached()
556
{
557
  GLContext* gl = this->gl();
558
  if (!gl || !gl->MakeCurrent()) {
559
    return false;
560
  }
561
562
  if (!mSurfTex) {
563
    return false;
564
  }
565
566
  if (!mSurfTex->IsAttachedToGLContext((int64_t)gl)) {
567
    GLuint texName;
568
    gl->fGenTextures(1, &texName);
569
    if (NS_FAILED(mSurfTex->AttachToGLContext((int64_t)gl, texName))) {
570
      return false;
571
    }
572
  }
573
574
  return true;
575
}
576
577
bool
578
SurfaceTextureHost::Lock()
579
{
580
  if (!EnsureAttached()) {
581
    return false;
582
  }
583
584
  if (mContinuousUpdate) {
585
    mSurfTex->UpdateTexImage();
586
  }
587
588
  if (!mTextureSource) {
589
    GLenum target = LOCAL_GL_TEXTURE_EXTERNAL; // This is required by SurfaceTexture
590
    GLenum wrapMode = LOCAL_GL_CLAMP_TO_EDGE;
591
    mTextureSource = new SurfaceTextureSource(mProvider,
592
                                              mSurfTex,
593
                                              mFormat,
594
                                              target,
595
                                              wrapMode,
596
                                              mSize,
597
                                              mIgnoreTransform);
598
  }
599
600
  return true;
601
}
602
603
void
604
SurfaceTextureHost::SetTextureSourceProvider(TextureSourceProvider* aProvider)
605
{
606
  if (mProvider != aProvider) {
607
    if (!aProvider || !aProvider->GetGLContext()) {
608
      DeallocateDeviceData();
609
      return;
610
    }
611
    mProvider = aProvider;
612
  }
613
614
  if (mTextureSource) {
615
    mTextureSource->SetTextureSourceProvider(aProvider);
616
  }
617
}
618
619
void
620
SurfaceTextureHost::NotifyNotUsed()
621
{
622
  if (mSurfTex && mSurfTex->IsSingleBuffer()) {
623
    mSurfTex->ReleaseTexImage();
624
  }
625
626
  TextureHost::NotifyNotUsed();
627
}
628
629
gfx::SurfaceFormat
630
SurfaceTextureHost::GetFormat() const
631
{
632
  return mFormat;
633
}
634
635
void
636
SurfaceTextureHost::DeallocateDeviceData()
637
{
638
  if (mTextureSource) {
639
    mTextureSource->DeallocateDeviceData();
640
  }
641
642
  if (mSurfTex) {
643
    mSurfTex->DecrementUse();
644
    mSurfTex = nullptr;
645
  }
646
}
647
648
#endif // MOZ_WIDGET_ANDROID
649
650
////////////////////////////////////////////////////////////////////////
651
////////////////////////////////////////////////////////////////////////
652
// EGLImage
653
654
EGLImageTextureSource::EGLImageTextureSource(TextureSourceProvider* aProvider,
655
                                             EGLImage aImage,
656
                                             gfx::SurfaceFormat aFormat,
657
                                             GLenum aTarget,
658
                                             GLenum aWrapMode,
659
                                             gfx::IntSize aSize)
660
  : mImage(aImage)
661
  , mFormat(aFormat)
662
  , mTextureTarget(aTarget)
663
  , mWrapMode(aWrapMode)
664
  , mSize(aSize)
665
0
{
666
0
  MOZ_ASSERT(mTextureTarget == LOCAL_GL_TEXTURE_2D ||
667
0
             mTextureTarget == LOCAL_GL_TEXTURE_EXTERNAL);
668
0
  SetTextureSourceProvider(aProvider);
669
0
}
670
671
void
672
EGLImageTextureSource::BindTexture(GLenum aTextureUnit,
673
                                   gfx::SamplingFilter aSamplingFilter)
674
0
{
675
0
  GLContext* gl = this->gl();
676
0
  if (!gl || !gl->MakeCurrent()) {
677
0
    NS_WARNING("Trying to bind a texture without a GLContext");
678
0
    return;
679
0
  }
680
0
681
0
  MOZ_ASSERT(DoesEGLContextSupportSharingWithEGLImage(gl),
682
0
             "EGLImage not supported or disabled in runtime");
683
0
684
0
  GLuint tex = mCompositor->GetTemporaryTexture(mTextureTarget, aTextureUnit);
685
0
686
0
  gl->fActiveTexture(aTextureUnit);
687
0
  gl->fBindTexture(mTextureTarget, tex);
688
0
689
0
  gl->fEGLImageTargetTexture2D(mTextureTarget, mImage);
690
0
691
0
  ApplySamplingFilterToBoundTexture(gl, aSamplingFilter, mTextureTarget);
692
0
}
693
694
void
695
EGLImageTextureSource::SetTextureSourceProvider(TextureSourceProvider* aProvider)
696
0
{
697
0
  if (mCompositor == aProvider) {
698
0
    return;
699
0
  }
700
0
701
0
  if (!aProvider) {
702
0
    mGL = nullptr;
703
0
    mCompositor = nullptr;
704
0
    return;
705
0
  }
706
0
707
0
  mGL = aProvider->GetGLContext();
708
0
  if (Compositor* compositor = aProvider->AsCompositor()) {
709
0
    mCompositor = compositor->AsCompositorOGL();
710
0
  }
711
0
}
712
713
bool
714
EGLImageTextureSource::IsValid() const
715
0
{
716
0
  return !!gl();
717
0
}
718
719
gfx::Matrix4x4
720
EGLImageTextureSource::GetTextureTransform()
721
0
{
722
0
  gfx::Matrix4x4 ret;
723
0
  return ret;
724
0
}
725
726
////////////////////////////////////////////////////////////////////////
727
728
EGLImageTextureHost::EGLImageTextureHost(TextureFlags aFlags,
729
                                         EGLImage aImage,
730
                                         EGLSync aSync,
731
                                         gfx::IntSize aSize,
732
                                         bool hasAlpha)
733
  : TextureHost(aFlags)
734
  , mImage(aImage)
735
  , mSync(aSync)
736
  , mSize(aSize)
737
  , mHasAlpha(hasAlpha)
738
0
{}
739
740
EGLImageTextureHost::~EGLImageTextureHost()
741
0
{}
742
743
gl::GLContext*
744
EGLImageTextureHost::gl() const
745
0
{
746
0
  return mProvider ? mProvider ->GetGLContext() : nullptr;
747
0
}
748
749
bool
750
EGLImageTextureHost::Lock()
751
0
{
752
0
  GLContext* gl = this->gl();
753
0
  if (!gl || !gl->MakeCurrent()) {
754
0
    return false;
755
0
  }
756
0
757
0
  auto* egl = gl::GLLibraryEGL::Get();
758
0
  EGLint status = LOCAL_EGL_CONDITION_SATISFIED;
759
0
760
0
  if (mSync) {
761
0
    MOZ_ASSERT(egl->IsExtensionSupported(GLLibraryEGL::KHR_fence_sync));
762
0
    status = egl->fClientWaitSync(EGL_DISPLAY(), mSync, 0, LOCAL_EGL_FOREVER);
763
0
  }
764
0
765
0
  if (status != LOCAL_EGL_CONDITION_SATISFIED) {
766
0
    MOZ_ASSERT(status != 0,
767
0
               "ClientWaitSync generated an error. Has mSync already been destroyed?");
768
0
    return false;
769
0
  }
770
0
771
0
  if (!mTextureSource) {
772
0
    gfx::SurfaceFormat format = mHasAlpha ? gfx::SurfaceFormat::R8G8B8A8
773
0
                                          : gfx::SurfaceFormat::R8G8B8X8;
774
0
    GLenum target = gl->GetPreferredEGLImageTextureTarget();
775
0
    GLenum wrapMode = LOCAL_GL_CLAMP_TO_EDGE;
776
0
    mTextureSource = new EGLImageTextureSource(mProvider,
777
0
                                               mImage,
778
0
                                               format,
779
0
                                               target,
780
0
                                               wrapMode,
781
0
                                               mSize);
782
0
  }
783
0
784
0
  return true;
785
0
}
786
787
void
788
EGLImageTextureHost::Unlock()
789
0
{
790
0
}
791
792
void
793
EGLImageTextureHost::SetTextureSourceProvider(TextureSourceProvider* aProvider)
794
0
{
795
0
  if (mProvider != aProvider) {
796
0
    if (!aProvider || !aProvider->GetGLContext()) {
797
0
      mProvider = nullptr;
798
0
      mTextureSource = nullptr;
799
0
      return;
800
0
    }
801
0
    mProvider = aProvider;
802
0
  }
803
0
804
0
  if (mTextureSource) {
805
0
    mTextureSource->SetTextureSourceProvider(aProvider);
806
0
  }
807
0
}
808
809
gfx::SurfaceFormat
810
EGLImageTextureHost::GetFormat() const
811
0
{
812
0
  MOZ_ASSERT(mTextureSource);
813
0
  return mTextureSource ? mTextureSource->GetFormat() : gfx::SurfaceFormat::UNKNOWN;
814
0
}
815
816
//
817
818
GLTextureHost::GLTextureHost(TextureFlags aFlags,
819
                             GLuint aTextureHandle,
820
                             GLenum aTarget,
821
                             GLsync aSync,
822
                             gfx::IntSize aSize,
823
                             bool aHasAlpha)
824
  : TextureHost(aFlags)
825
  , mTexture(aTextureHandle)
826
  , mTarget(aTarget)
827
  , mSync(aSync)
828
  , mSize(aSize)
829
  , mHasAlpha(aHasAlpha)
830
0
{}
831
832
GLTextureHost::~GLTextureHost()
833
0
{}
834
835
gl::GLContext*
836
GLTextureHost::gl() const
837
0
{
838
0
  return mProvider ? mProvider->GetGLContext() : nullptr;
839
0
}
840
841
bool
842
GLTextureHost::Lock()
843
0
{
844
0
  GLContext* gl = this->gl();
845
0
  if (!gl || !gl->MakeCurrent()) {
846
0
    return false;
847
0
  }
848
0
849
0
  if (mSync) {
850
0
    if (!gl->MakeCurrent()) {
851
0
      return false;
852
0
    }
853
0
    gl->fWaitSync(mSync, 0, LOCAL_GL_TIMEOUT_IGNORED);
854
0
    gl->fDeleteSync(mSync);
855
0
    mSync = 0;
856
0
  }
857
0
858
0
  if (!mTextureSource) {
859
0
    gfx::SurfaceFormat format = mHasAlpha ? gfx::SurfaceFormat::R8G8B8A8
860
0
                                          : gfx::SurfaceFormat::R8G8B8X8;
861
0
    mTextureSource = new GLTextureSource(mProvider,
862
0
                                         mTexture,
863
0
                                         mTarget,
864
0
                                         mSize,
865
0
                                         format);
866
0
  }
867
0
868
0
  return true;
869
0
}
870
871
void
872
GLTextureHost::SetTextureSourceProvider(TextureSourceProvider* aProvider)
873
0
{
874
0
  if (mProvider != aProvider) {
875
0
    if (!aProvider || !aProvider->GetGLContext()) {
876
0
      mProvider = nullptr;
877
0
      mTextureSource = nullptr;
878
0
      return;
879
0
    }
880
0
    mProvider = aProvider;
881
0
  }
882
0
883
0
  if (mTextureSource) {
884
0
    mTextureSource->SetTextureSourceProvider(aProvider);
885
0
  }
886
0
}
887
888
gfx::SurfaceFormat
889
GLTextureHost::GetFormat() const
890
0
{
891
0
  MOZ_ASSERT(mTextureSource);
892
0
  return mTextureSource ? mTextureSource->GetFormat() : gfx::SurfaceFormat::UNKNOWN;
893
0
}
894
895
} // namespace layers
896
} // namespace mozilla