GLImages.cpp (4539B)
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 "GLImages.h" 8 #include "GLContext.h" 9 #include "GLContextProvider.h" 10 #include "ScopedGLHelpers.h" 11 #include "GLImages.h" 12 #include "GLBlitHelper.h" 13 #include "GLReadTexImageHelper.h" 14 #include "GLLibraryEGL.h" 15 #include "mozilla/gfx/Logging.h" 16 #include "mozilla/layers/LayersSurfaces.h" 17 18 using namespace mozilla; 19 using namespace mozilla::gl; 20 21 namespace mozilla::layers { 22 23 constinit static RefPtr<GLContext> sSnapshotContext; 24 25 nsresult GLImage::ReadIntoBuffer(uint8_t* aData, int32_t aStride, 26 const gfx::IntSize& aSize, 27 gfx::SurfaceFormat aFormat) { 28 MOZ_ASSERT(NS_IsMainThread(), "Should be on the main thread"); 29 30 if (!sSnapshotContext) { 31 nsCString discardFailureId; 32 sSnapshotContext = GLContextProvider::CreateHeadless({}, &discardFailureId); 33 if (!sSnapshotContext) { 34 NS_WARNING("Failed to create snapshot GLContext"); 35 return NS_ERROR_FAILURE; 36 } 37 } 38 39 sSnapshotContext->MakeCurrent(); 40 ScopedTexture scopedTex(sSnapshotContext); 41 ScopedBindTexture boundTex(sSnapshotContext, scopedTex.Texture()); 42 43 sSnapshotContext->fTexImage2D(LOCAL_GL_TEXTURE_2D, 0, LOCAL_GL_RGBA, 44 aSize.width, aSize.height, 0, LOCAL_GL_RGBA, 45 LOCAL_GL_UNSIGNED_BYTE, nullptr); 46 47 ScopedFramebufferForTexture autoFBForTex(sSnapshotContext, 48 scopedTex.Texture()); 49 if (!autoFBForTex.IsComplete()) { 50 gfxCriticalError() 51 << "GetAsSourceSurface: ScopedFramebufferForTexture failed."; 52 return NS_ERROR_FAILURE; 53 } 54 55 const gl::OriginPos destOrigin = gl::OriginPos::TopLeft; 56 { 57 const ScopedBindFramebuffer bindFB(sSnapshotContext, autoFBForTex.FB()); 58 if (!sSnapshotContext->BlitHelper()->BlitImageToFramebuffer( 59 this, gfx::IntRect(gfx::IntPoint(0, 0), aSize), destOrigin)) { 60 return NS_ERROR_FAILURE; 61 } 62 } 63 64 ScopedBindFramebuffer bind(sSnapshotContext, autoFBForTex.FB()); 65 ReadPixelsIntoBuffer(sSnapshotContext, aData, aStride, aSize, aFormat); 66 return NS_OK; 67 } 68 69 already_AddRefed<gfx::SourceSurface> GLImage::GetAsSourceSurface() { 70 MOZ_ASSERT(NS_IsMainThread(), "Should be on the main thread"); 71 72 gfx::IntSize size = GetSize(); 73 auto format = gfx::SurfaceFormat::B8G8R8A8; 74 RefPtr<gfx::DataSourceSurface> dest = 75 gfx::Factory::CreateDataSourceSurface(size, format); 76 if (NS_WARN_IF(!dest)) { 77 return nullptr; 78 } 79 80 gfx::DataSourceSurface::ScopedMap map(dest, gfx::DataSourceSurface::WRITE); 81 if (NS_WARN_IF(!map.IsMapped())) { 82 return nullptr; 83 } 84 85 nsresult rv = ReadIntoBuffer(map.GetData(), map.GetStride(), size, format); 86 if (NS_WARN_IF(NS_FAILED(rv))) { 87 return nullptr; 88 } 89 90 return dest.forget(); 91 } 92 93 nsresult GLImage::BuildSurfaceDescriptorBuffer( 94 SurfaceDescriptorBuffer& aSdBuffer, BuildSdbFlags aFlags, 95 const std::function<MemoryOrShmem(uint32_t)>& aAllocate) { 96 gfx::IntSize size = GetSize(); 97 auto format = gfx::SurfaceFormat::B8G8R8A8; 98 99 uint8_t* buffer = nullptr; 100 int32_t stride = 0; 101 nsresult rv = AllocateSurfaceDescriptorBufferRgb( 102 size, format, buffer, aSdBuffer, stride, aAllocate); 103 if (NS_WARN_IF(NS_FAILED(rv))) { 104 return rv; 105 } 106 107 return ReadIntoBuffer(buffer, stride, size, format); 108 } 109 110 #ifdef MOZ_WIDGET_ANDROID 111 SurfaceTextureImage::SurfaceTextureImage( 112 AndroidSurfaceTextureHandle aHandle, const gfx::IntSize& aSize, 113 bool aContinuous, gl::OriginPos aOriginPos, bool aHasAlpha, 114 bool aForceBT709ColorSpace, Maybe<gfx::Matrix4x4> aTransformOverride) 115 : GLImage(ImageFormat::SURFACE_TEXTURE), 116 mHandle(aHandle), 117 mSize(aSize), 118 mContinuous(aContinuous), 119 mOriginPos(aOriginPos), 120 mHasAlpha(aHasAlpha), 121 mForceBT709ColorSpace(aForceBT709ColorSpace), 122 mTransformOverride(aTransformOverride) { 123 MOZ_ASSERT(mHandle); 124 } 125 126 Maybe<SurfaceDescriptor> SurfaceTextureImage::GetDesc() { 127 SurfaceDescriptor sd = SurfaceTextureDescriptor( 128 mHandle, mSize, 129 mHasAlpha ? gfx::SurfaceFormat::R8G8B8A8 : gfx::SurfaceFormat::R8G8B8X8, 130 mForceBT709ColorSpace, false /* NOT continuous */, mTransformOverride); 131 return Some(sd); 132 } 133 #endif 134 135 } // namespace mozilla::layers