gfx/layers/opengl/TextureHostOGL.cpp

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:2fa2c486b4f0
1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
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 "TextureHostOGL.h"
7 #include "GLContext.h" // for GLContext, etc
8 #include "GLSharedHandleHelpers.h"
9 #include "GLUploadHelpers.h"
10 #include "GLReadTexImageHelper.h"
11 #include "SharedSurface.h" // for SharedSurface
12 #include "SharedSurfaceEGL.h" // for SharedSurface_EGLImage
13 #include "SharedSurfaceGL.h" // for SharedSurface_GLTexture, etc
14 #include "SurfaceStream.h" // for SurfaceStream
15 #include "SurfaceTypes.h" // for SharedSurfaceType, etc
16 #include "gfx2DGlue.h" // for ContentForFormat, etc
17 #include "gfxReusableSurfaceWrapper.h" // for gfxReusableSurfaceWrapper
18 #include "mozilla/gfx/2D.h" // for DataSourceSurface
19 #include "mozilla/gfx/BaseSize.h" // for BaseSize
20 #include "mozilla/layers/CompositorOGL.h" // for CompositorOGL
21 #ifdef MOZ_WIDGET_GONK
22 # include "GrallocImages.h" // for GrallocImage
23 # include "EGLImageHelpers.h"
24 #endif
25 #include "mozilla/layers/ISurfaceAllocator.h"
26 #include "mozilla/layers/YCbCrImageDataSerializer.h"
27 #include "mozilla/layers/GrallocTextureHost.h"
28 #include "nsPoint.h" // for nsIntPoint
29 #include "nsRegion.h" // for nsIntRegion
30 #include "GfxTexturesReporter.h" // for GfxTexturesReporter
31 #include "GLBlitTextureImageHelper.h"
32 #ifdef XP_MACOSX
33 #include "SharedSurfaceIO.h"
34 #include "mozilla/layers/MacIOSurfaceTextureHostOGL.h"
35 #endif
36 #include "GeckoProfiler.h"
37
38 using namespace mozilla::gl;
39 using namespace mozilla::gfx;
40
41 namespace mozilla {
42 namespace layers {
43
44 class Compositor;
45
46 TemporaryRef<CompositableBackendSpecificData>
47 CreateCompositableBackendSpecificDataOGL()
48 {
49 #ifdef MOZ_WIDGET_GONK
50 return new CompositableDataGonkOGL();
51 #else
52 return nullptr;
53 #endif
54 }
55
56 TemporaryRef<TextureHost>
57 CreateTextureHostOGL(const SurfaceDescriptor& aDesc,
58 ISurfaceAllocator* aDeallocator,
59 TextureFlags aFlags)
60 {
61 RefPtr<TextureHost> result;
62 switch (aDesc.type()) {
63 case SurfaceDescriptor::TSurfaceDescriptorShmem:
64 case SurfaceDescriptor::TSurfaceDescriptorMemory: {
65 result = CreateBackendIndependentTextureHost(aDesc,
66 aDeallocator, aFlags);
67 break;
68 }
69 case SurfaceDescriptor::TSharedTextureDescriptor: {
70 const SharedTextureDescriptor& desc = aDesc.get_SharedTextureDescriptor();
71 result = new SharedTextureHostOGL(aFlags,
72 desc.shareType(),
73 desc.handle(),
74 desc.size(),
75 desc.inverted());
76 break;
77 }
78 case SurfaceDescriptor::TSurfaceStreamDescriptor: {
79 const SurfaceStreamDescriptor& desc = aDesc.get_SurfaceStreamDescriptor();
80 result = new StreamTextureHostOGL(aFlags, desc);
81 break;
82 }
83 #ifdef XP_MACOSX
84 case SurfaceDescriptor::TSurfaceDescriptorMacIOSurface: {
85 const SurfaceDescriptorMacIOSurface& desc =
86 aDesc.get_SurfaceDescriptorMacIOSurface();
87 result = new MacIOSurfaceTextureHostOGL(aFlags, desc);
88 break;
89 }
90 #endif
91 #ifdef MOZ_WIDGET_GONK
92 case SurfaceDescriptor::TNewSurfaceDescriptorGralloc: {
93 const NewSurfaceDescriptorGralloc& desc =
94 aDesc.get_NewSurfaceDescriptorGralloc();
95 result = new GrallocTextureHostOGL(aFlags, desc);
96 break;
97 }
98 #endif
99 default: return nullptr;
100 }
101 return result.forget();
102 }
103
104 static gl::TextureImage::Flags
105 FlagsToGLFlags(TextureFlags aFlags)
106 {
107 uint32_t result = TextureImage::NoFlags;
108
109 if (aFlags & TEXTURE_USE_NEAREST_FILTER)
110 result |= TextureImage::UseNearestFilter;
111 if (aFlags & TEXTURE_NEEDS_Y_FLIP)
112 result |= TextureImage::NeedsYFlip;
113 if (aFlags & TEXTURE_DISALLOW_BIGIMAGE)
114 result |= TextureImage::DisallowBigImage;
115
116 return static_cast<gl::TextureImage::Flags>(result);
117 }
118
119 GLenum
120 WrapMode(gl::GLContext *aGl, bool aAllowRepeat)
121 {
122 if (aAllowRepeat &&
123 (aGl->IsExtensionSupported(GLContext::ARB_texture_non_power_of_two) ||
124 aGl->IsExtensionSupported(GLContext::OES_texture_npot))) {
125 return LOCAL_GL_REPEAT;
126 }
127 return LOCAL_GL_CLAMP_TO_EDGE;
128 }
129
130 CompositableDataGonkOGL::CompositableDataGonkOGL()
131 : mTexture(0)
132 {
133 }
134 CompositableDataGonkOGL::~CompositableDataGonkOGL()
135 {
136 DeleteTextureIfPresent();
137 }
138
139 gl::GLContext*
140 CompositableDataGonkOGL::gl() const
141 {
142 return mCompositor ? mCompositor->gl() : nullptr;
143 }
144
145 void CompositableDataGonkOGL::SetCompositor(Compositor* aCompositor)
146 {
147 mCompositor = static_cast<CompositorOGL*>(aCompositor);
148 }
149
150 void CompositableDataGonkOGL::ClearData()
151 {
152 CompositableBackendSpecificData::ClearData();
153 DeleteTextureIfPresent();
154 }
155
156 GLuint CompositableDataGonkOGL::GetTexture()
157 {
158 if (!mTexture) {
159 if (gl()->MakeCurrent()) {
160 gl()->fGenTextures(1, &mTexture);
161 }
162 }
163 return mTexture;
164 }
165
166 void
167 CompositableDataGonkOGL::DeleteTextureIfPresent()
168 {
169 if (mTexture) {
170 if (gl()->MakeCurrent()) {
171 gl()->fDeleteTextures(1, &mTexture);
172 }
173 mTexture = 0;
174 }
175 }
176
177 #if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
178 bool
179 TextureHostOGL::SetReleaseFence(const android::sp<android::Fence>& aReleaseFence)
180 {
181 if (!aReleaseFence.get() || !aReleaseFence->isValid()) {
182 // HWC might not provide Fence.
183 // In this case, HWC implicitly handles buffer's fence.
184 return false;
185 }
186
187 if (!mReleaseFence.get()) {
188 mReleaseFence = aReleaseFence;
189 } else {
190 android::sp<android::Fence> mergedFence = android::Fence::merge(
191 android::String8::format("TextureHostOGL"),
192 mReleaseFence, aReleaseFence);
193 if (!mergedFence.get()) {
194 // synchronization is broken, the best we can do is hope fences
195 // signal in order so the new fence will act like a union.
196 // This error handling is same as android::ConsumerBase does.
197 mReleaseFence = aReleaseFence;
198 return false;
199 }
200 mReleaseFence = mergedFence;
201 }
202 return true;
203 }
204
205 android::sp<android::Fence>
206 TextureHostOGL::GetAndResetReleaseFence()
207 {
208 // Hold previous ReleaseFence to prevent Fence delivery failure via gecko IPC.
209 mPrevReleaseFence = mReleaseFence;
210 // Reset current ReleaseFence.
211 mReleaseFence = android::Fence::NO_FENCE;
212 return mPrevReleaseFence;
213 }
214 #endif
215
216 bool
217 TextureImageTextureSourceOGL::Update(gfx::DataSourceSurface* aSurface,
218 nsIntRegion* aDestRegion,
219 gfx::IntPoint* aSrcOffset)
220 {
221 MOZ_ASSERT(mGL);
222 if (!mGL) {
223 NS_WARNING("trying to update TextureImageTextureSourceOGL without a GLContext");
224 return false;
225 }
226 MOZ_ASSERT(aSurface);
227
228 IntSize size = aSurface->GetSize();
229 if (!mTexImage ||
230 (mTexImage->GetSize() != size && !aSrcOffset) ||
231 mTexImage->GetContentType() != gfx::ContentForFormat(aSurface->GetFormat())) {
232 if (mFlags & TEXTURE_DISALLOW_BIGIMAGE) {
233 mTexImage = CreateBasicTextureImage(mGL, size,
234 gfx::ContentForFormat(aSurface->GetFormat()),
235 WrapMode(mGL, mFlags & TEXTURE_ALLOW_REPEAT),
236 FlagsToGLFlags(mFlags),
237 SurfaceFormatToImageFormat(aSurface->GetFormat()));
238 } else {
239 // XXX - clarify which size we want to use. IncrementalContentHost will
240 // require the size of the destination surface to be different from
241 // the size of aSurface.
242 // See bug 893300 (tracks the implementation of ContentHost for new textures).
243 mTexImage = CreateTextureImage(mGL,
244 size,
245 gfx::ContentForFormat(aSurface->GetFormat()),
246 WrapMode(mGL, mFlags & TEXTURE_ALLOW_REPEAT),
247 FlagsToGLFlags(mFlags),
248 SurfaceFormatToImageFormat(aSurface->GetFormat()));
249 }
250 ClearCachedFilter();
251 }
252
253 mTexImage->UpdateFromDataSource(aSurface, aDestRegion, aSrcOffset);
254
255 if (mTexImage->InUpdate()) {
256 mTexImage->EndUpdate();
257 }
258 return true;
259 }
260
261 void
262 TextureImageTextureSourceOGL::EnsureBuffer(const nsIntSize& aSize,
263 gfxContentType aContentType)
264 {
265 if (!mTexImage ||
266 mTexImage->GetSize() != aSize.ToIntSize() ||
267 mTexImage->GetContentType() != aContentType) {
268 mTexImage = CreateTextureImage(mGL,
269 aSize.ToIntSize(),
270 aContentType,
271 WrapMode(mGL, mFlags & TEXTURE_ALLOW_REPEAT),
272 FlagsToGLFlags(mFlags));
273 }
274 mTexImage->Resize(aSize.ToIntSize());
275 }
276
277 void
278 TextureImageTextureSourceOGL::CopyTo(const nsIntRect& aSourceRect,
279 DataTextureSource *aDest,
280 const nsIntRect& aDestRect)
281 {
282 MOZ_ASSERT(aDest->AsSourceOGL(), "Incompatible destination type!");
283 TextureImageTextureSourceOGL *dest =
284 aDest->AsSourceOGL()->AsTextureImageTextureSource();
285 MOZ_ASSERT(dest, "Incompatible destination type!");
286
287 mGL->BlitTextureImageHelper()->BlitTextureImage(mTexImage, aSourceRect,
288 dest->mTexImage, aDestRect);
289 dest->mTexImage->MarkValid();
290 }
291
292 void
293 TextureImageTextureSourceOGL::SetCompositor(Compositor* aCompositor)
294 {
295 CompositorOGL* glCompositor = static_cast<CompositorOGL*>(aCompositor);
296
297 if (!glCompositor || (mGL != glCompositor->gl())) {
298 DeallocateDeviceData();
299 mGL = glCompositor ? glCompositor->gl() : nullptr;
300 }
301 }
302
303 gfx::IntSize
304 TextureImageTextureSourceOGL::GetSize() const
305 {
306 if (mTexImage) {
307 if (mIterating) {
308 return mTexImage->GetTileRect().Size();
309 }
310 return mTexImage->GetSize();
311 }
312 NS_WARNING("Trying to query the size of an empty TextureSource.");
313 return gfx::IntSize(0, 0);
314 }
315
316 gfx::SurfaceFormat
317 TextureImageTextureSourceOGL::GetFormat() const
318 {
319 if (mTexImage) {
320 return mTexImage->GetTextureFormat();
321 }
322 NS_WARNING("Trying to query the format of an empty TextureSource.");
323 return gfx::SurfaceFormat::UNKNOWN;
324 }
325
326 nsIntRect TextureImageTextureSourceOGL::GetTileRect()
327 {
328 return ThebesIntRect(mTexImage->GetTileRect());
329 }
330
331 void
332 TextureImageTextureSourceOGL::BindTexture(GLenum aTextureUnit, gfx::Filter aFilter)
333 {
334 MOZ_ASSERT(mTexImage,
335 "Trying to bind a TextureSource that does not have an underlying GL texture.");
336 mTexImage->BindTexture(aTextureUnit);
337 SetFilter(mGL, aFilter);
338 }
339
340 SharedTextureSourceOGL::SharedTextureSourceOGL(CompositorOGL* aCompositor,
341 gl::SharedTextureHandle aHandle,
342 gfx::SurfaceFormat aFormat,
343 GLenum aTarget,
344 GLenum aWrapMode,
345 SharedTextureShareType aShareType,
346 gfx::IntSize aSize)
347 : mSize(aSize)
348 , mCompositor(aCompositor)
349 , mSharedHandle(aHandle)
350 , mFormat(aFormat)
351 , mShareType(aShareType)
352 , mTextureTarget(aTarget)
353 , mWrapMode(aWrapMode)
354 {}
355
356 void
357 SharedTextureSourceOGL::BindTexture(GLenum aTextureUnit, gfx::Filter aFilter)
358 {
359 if (!gl()) {
360 NS_WARNING("Trying to bind a texture without a GLContext");
361 return;
362 }
363 GLuint tex = mCompositor->GetTemporaryTexture(GetTextureTarget(), aTextureUnit);
364
365 gl()->fActiveTexture(aTextureUnit);
366 gl()->fBindTexture(mTextureTarget, tex);
367 if (!AttachSharedHandle(gl(), mShareType, mSharedHandle)) {
368 NS_ERROR("Failed to bind shared texture handle");
369 return;
370 }
371 ApplyFilterToBoundTexture(gl(), aFilter, mTextureTarget);
372 }
373
374 void
375 SharedTextureSourceOGL::DetachSharedHandle()
376 {
377 if (!gl()) {
378 return;
379 }
380 gl::DetachSharedHandle(gl(), mShareType, mSharedHandle);
381 }
382
383 void
384 SharedTextureSourceOGL::SetCompositor(Compositor* aCompositor)
385 {
386 mCompositor = static_cast<CompositorOGL*>(aCompositor);
387 }
388
389 bool
390 SharedTextureSourceOGL::IsValid() const
391 {
392 return !!gl();
393 }
394
395 gl::GLContext*
396 SharedTextureSourceOGL::gl() const
397 {
398 return mCompositor ? mCompositor->gl() : nullptr;
399 }
400
401 gfx::Matrix4x4
402 SharedTextureSourceOGL::GetTextureTransform()
403 {
404 SharedHandleDetails handleDetails;
405 if (!GetSharedHandleDetails(gl(), mShareType, mSharedHandle, handleDetails)) {
406 NS_WARNING("Could not get shared handle details");
407 return gfx::Matrix4x4();
408 }
409
410 return handleDetails.mTextureTransform;
411 }
412
413 SharedTextureHostOGL::SharedTextureHostOGL(TextureFlags aFlags,
414 gl::SharedTextureShareType aShareType,
415 gl::SharedTextureHandle aSharedHandle,
416 gfx::IntSize aSize,
417 bool inverted)
418 : TextureHost(aFlags)
419 , mSize(aSize)
420 , mCompositor(nullptr)
421 , mSharedHandle(aSharedHandle)
422 , mShareType(aShareType)
423 {
424 }
425
426 SharedTextureHostOGL::~SharedTextureHostOGL()
427 {
428 // If need to deallocate textures, call DeallocateSharedData() before
429 // the destructor
430 }
431
432 gl::GLContext*
433 SharedTextureHostOGL::gl() const
434 {
435 return mCompositor ? mCompositor->gl() : nullptr;
436 }
437
438 bool
439 SharedTextureHostOGL::Lock()
440 {
441 if (!mCompositor) {
442 return false;
443 }
444
445 if (!mTextureSource) {
446 // XXX on android GetSharedHandleDetails can call into Java which we'd
447 // rather not do from the compositor
448 SharedHandleDetails handleDetails;
449 if (!GetSharedHandleDetails(gl(), mShareType, mSharedHandle, handleDetails)) {
450 NS_WARNING("Could not get shared handle details");
451 return false;
452 }
453
454 GLenum wrapMode = LOCAL_GL_CLAMP_TO_EDGE;
455 mTextureSource = new SharedTextureSourceOGL(mCompositor,
456 mSharedHandle,
457 handleDetails.mTextureFormat,
458 handleDetails.mTarget,
459 wrapMode,
460 mShareType,
461 mSize);
462 }
463 return true;
464 }
465
466 void
467 SharedTextureHostOGL::Unlock()
468 {
469 if (!mTextureSource) {
470 return;
471 }
472 mTextureSource->DetachSharedHandle();
473 }
474
475 void
476 SharedTextureHostOGL::SetCompositor(Compositor* aCompositor)
477 {
478 CompositorOGL* glCompositor = static_cast<CompositorOGL*>(aCompositor);
479 mCompositor = glCompositor;
480 if (mTextureSource) {
481 mTextureSource->SetCompositor(glCompositor);
482 }
483 }
484
485 gfx::SurfaceFormat
486 SharedTextureHostOGL::GetFormat() const
487 {
488 MOZ_ASSERT(mTextureSource);
489 return mTextureSource->GetFormat();
490 }
491
492 void
493 StreamTextureSourceOGL::BindTexture(GLenum activetex, gfx::Filter aFilter)
494 {
495 MOZ_ASSERT(gl());
496 gl()->fActiveTexture(activetex);
497 gl()->fBindTexture(mTextureTarget, mTextureHandle);
498 SetFilter(gl(), aFilter);
499 }
500
501 bool
502 StreamTextureSourceOGL::RetrieveTextureFromStream()
503 {
504 gl()->MakeCurrent();
505
506 SharedSurface* sharedSurf = mStream->SwapConsumer();
507 if (!sharedSurf) {
508 // We don't have a valid surf to show yet.
509 return false;
510 }
511
512 gl()->MakeCurrent();
513
514 mSize = IntSize(sharedSurf->Size().width, sharedSurf->Size().height);
515
516 DataSourceSurface* toUpload = nullptr;
517 switch (sharedSurf->Type()) {
518 case SharedSurfaceType::GLTextureShare: {
519 SharedSurface_GLTexture* glTexSurf = SharedSurface_GLTexture::Cast(sharedSurf);
520 mTextureHandle = glTexSurf->ConsTexture(gl());
521 mTextureTarget = glTexSurf->ConsTextureTarget();
522 MOZ_ASSERT(mTextureHandle);
523 mFormat = sharedSurf->HasAlpha() ? SurfaceFormat::R8G8B8A8
524 : SurfaceFormat::R8G8B8X8;
525 break;
526 }
527 case SharedSurfaceType::EGLImageShare: {
528 SharedSurface_EGLImage* eglImageSurf =
529 SharedSurface_EGLImage::Cast(sharedSurf);
530
531 eglImageSurf->AcquireConsumerTexture(gl(), &mTextureHandle, &mTextureTarget);
532 MOZ_ASSERT(mTextureHandle);
533 mFormat = sharedSurf->HasAlpha() ? SurfaceFormat::R8G8B8A8
534 : SurfaceFormat::R8G8B8X8;
535 break;
536 }
537 #ifdef XP_MACOSX
538 case SharedSurfaceType::IOSurface: {
539 SharedSurface_IOSurface* glTexSurf = SharedSurface_IOSurface::Cast(sharedSurf);
540 mTextureHandle = glTexSurf->ConsTexture(gl());
541 mTextureTarget = glTexSurf->ConsTextureTarget();
542 MOZ_ASSERT(mTextureHandle);
543 mFormat = sharedSurf->HasAlpha() ? SurfaceFormat::R8G8B8A8
544 : SurfaceFormat::R8G8B8X8;
545 break;
546 }
547 #endif
548 case SharedSurfaceType::Basic: {
549 toUpload = SharedSurface_Basic::Cast(sharedSurf)->GetData();
550 MOZ_ASSERT(toUpload);
551 break;
552 }
553 default:
554 MOZ_CRASH("Invalid SharedSurface type.");
555 }
556
557 if (toUpload) {
558 // mBounds seems to end up as (0,0,0,0) a lot, so don't use it?
559 nsIntSize size(ThebesIntSize(toUpload->GetSize()));
560 nsIntRect rect(nsIntPoint(0,0), size);
561 nsIntRegion bounds(rect);
562 mFormat = UploadSurfaceToTexture(gl(),
563 toUpload,
564 bounds,
565 mUploadTexture,
566 true);
567 mTextureHandle = mUploadTexture;
568 mTextureTarget = LOCAL_GL_TEXTURE_2D;
569 }
570
571 MOZ_ASSERT(mTextureHandle);
572 gl()->fBindTexture(mTextureTarget, mTextureHandle);
573 gl()->fTexParameteri(mTextureTarget,
574 LOCAL_GL_TEXTURE_WRAP_S,
575 LOCAL_GL_CLAMP_TO_EDGE);
576 gl()->fTexParameteri(mTextureTarget,
577 LOCAL_GL_TEXTURE_WRAP_T,
578 LOCAL_GL_CLAMP_TO_EDGE);
579
580 ClearCachedFilter();
581
582 return true;
583 }
584
585 void
586 StreamTextureSourceOGL::DeallocateDeviceData()
587 {
588 if (mUploadTexture) {
589 MOZ_ASSERT(gl());
590 gl()->MakeCurrent();
591 gl()->fDeleteTextures(1, &mUploadTexture);
592 mUploadTexture = 0;
593 mTextureHandle = 0;
594 }
595 }
596
597 gl::GLContext*
598 StreamTextureSourceOGL::gl() const
599 {
600 return mCompositor ? mCompositor->gl() : nullptr;
601 }
602
603 void
604 StreamTextureSourceOGL::SetCompositor(Compositor* aCompositor)
605 {
606 mCompositor = static_cast<CompositorOGL*>(aCompositor);
607 }
608
609 StreamTextureHostOGL::StreamTextureHostOGL(TextureFlags aFlags,
610 const SurfaceStreamDescriptor& aDesc)
611 : TextureHost(aFlags)
612 {
613 mStream = SurfaceStream::FromHandle(aDesc.handle());
614 MOZ_ASSERT(mStream);
615 }
616
617 StreamTextureHostOGL::~StreamTextureHostOGL()
618 {
619 // If need to deallocate textures, call DeallocateSharedData() before
620 // the destructor
621 }
622
623 bool
624 StreamTextureHostOGL::Lock()
625 {
626 if (!mCompositor) {
627 return false;
628 }
629
630 if (!mTextureSource) {
631 mTextureSource = new StreamTextureSourceOGL(mCompositor,
632 mStream);
633 }
634
635 return mTextureSource->RetrieveTextureFromStream();
636 }
637
638 void
639 StreamTextureHostOGL::Unlock()
640 {
641 }
642
643 void
644 StreamTextureHostOGL::SetCompositor(Compositor* aCompositor)
645 {
646 CompositorOGL* glCompositor = static_cast<CompositorOGL*>(aCompositor);
647 mCompositor = glCompositor;
648 if (mTextureSource) {
649 mTextureSource->SetCompositor(glCompositor);
650 }
651 }
652
653 gfx::SurfaceFormat
654 StreamTextureHostOGL::GetFormat() const
655 {
656 MOZ_ASSERT(mTextureSource);
657 return mTextureSource->GetFormat();
658 }
659
660 gfx::IntSize
661 StreamTextureHostOGL::GetSize() const
662 {
663 MOZ_ASSERT(mTextureSource);
664 return mTextureSource->GetSize();
665 }
666
667 } // namespace
668 } // namespace

mercurial