Bug 1322746 - Support PLANAR_YCBCR, GPU_VIDEO, and D3D11_YCBCR_IMAGE in GLBlitHelper. - r=jerry

MozReview-Commit-ID: FNsmq0RPvYB
This commit is contained in:
Jeff Gilbert 2017-07-17 19:17:41 -07:00
Родитель 816740fb9e
Коммит 8a890b29aa
26 изменённых файлов: 1427 добавлений и 1143 удалений

Просмотреть файл

@ -5249,9 +5249,17 @@ CanvasRenderingContext2D::DrawImage(const CanvasImageSource& aImage,
gl->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR);
const gl::OriginPos destOrigin = gl::OriginPos::TopLeft;
bool ok = gl->BlitHelper()->BlitImageToTexture(srcImage, srcImage->GetSize(),
videoTexture, LOCAL_GL_TEXTURE_2D,
destOrigin);
bool ok = false;
do {
const gl::ScopedFramebufferForTexture autoFBForTex(gl, videoTexture);
if (!autoFBForTex.IsComplete()) {
MOZ_ASSERT(false, "ScopedFramebufferForTexture not complete.");
break;
}
const gl::ScopedBindFramebuffer bindFB(gl, autoFBForTex.FB());
ok = gl->BlitHelper()->BlitImageToFramebuffer(srcImage, srcImage->GetSize(),
destOrigin);
} while (false);
if (ok) {
NativeSurface texSurf;
texSurf.mType = NativeSurfaceType::OPENGL_TEXTURE;

Просмотреть файл

@ -701,9 +701,7 @@ TexUnpackImage::TexOrSubImage(bool isSubImage, bool needsRespec, const char* fun
const gfx::IntSize destSize(mWidth, mHeight);
const auto dstOrigin = (webgl->mPixelStore_FlipY ? gl::OriginPos::TopLeft
: gl::OriginPos::BottomLeft);
if (!gl->BlitHelper()->BlitImageToFramebuffer(mImage, destSize, scopedFB.FB(),
dstOrigin))
{
if (!gl->BlitHelper()->BlitImageToFramebuffer(mImage, destSize, dstOrigin)) {
fallbackReason = "likely bug: failed to blit";
break;
}

Просмотреть файл

@ -721,6 +721,12 @@ WebGLContext::InitAndValidateGL(FailureReason* const out_failReason)
return false;
}
if (!gl->IsSupported(GLFeature::vertex_array_object)) {
*out_failReason = { "FEATURE_FAILURE_WEBGL_VAOS",
"Requires vertex_array_object." };
return false;
}
mDefaultVertexArray = WebGLVertexArray::Create(this);
mDefaultVertexArray->mAttribs.SetLength(mGLMaxVertexAttribs);
mBoundVertexArray = mDefaultVertexArray;

Просмотреть файл

@ -1833,8 +1833,11 @@ ScopedCopyTexImageSource::ScopedCopyTexImageSource(WebGLContext* webgl,
// Draw-blit rgbaTex into rgbaFB.
const gfx::IntSize srcSize(srcWidth, srcHeight);
gl->BlitHelper()->DrawBlitTextureToFramebuffer(scopedTex.Texture(), rgbaFB,
srcSize, srcSize);
{
const gl::ScopedBindFramebuffer bindFB(gl, rgbaFB);
gl->BlitHelper()->DrawBlitTextureToFramebuffer(scopedTex.Texture(), srcSize,
srcSize);
}
// Restore Tex2D binding and destroy the temp tex.
scopedBindTex.Unwrap();

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -10,152 +10,178 @@
#include "GLContextTypes.h"
#include "GLConsts.h"
#include "nsSize.h"
#include "ipc/IPCMessageUtils.h"
#include "mozilla/Attributes.h"
#include "mozilla/gfx/Point.h"
#ifdef XP_WIN
#include <windows.h>
#endif
namespace mozilla {
namespace layers {
class D3D11YCbCrImage;
class Image;
class GPUVideoImage;
class PlanarYCbCrImage;
class SurfaceTextureImage;
class MacIOSurfaceImage;
class EGLImageImage;
class SurfaceDescriptorD3D10;
class SurfaceDescriptorDXGIYCbCr;
} // namespace layers
namespace gl {
class BindAnglePlanes;
class GLContext;
bool
GuessDivisors(const gfx::IntSize& ySize, const gfx::IntSize& uvSize,
gfx::IntSize* const out_divisors);
class DrawBlitProg final
{
GLBlitHelper& mParent;
const GLuint mProg;
const GLint mLoc_u1ForYFlip;
const GLint mLoc_uClipRect;
const GLint mLoc_uTexSize0;
const GLint mLoc_uTexSize1;
const GLint mLoc_uDivisors;
const GLint mLoc_uColorMatrix;
public:
DrawBlitProg(GLBlitHelper* parent, GLuint prog);
~DrawBlitProg();
struct BaseArgs final {
gfx::IntSize destSize;
bool yFlip;
gfx::IntRect clipRect;
gfx::IntSize texSize0;
};
struct YUVArgs final {
gfx::IntSize texSize1;
gfx::IntSize divisors;
YUVColorSpace colorSpace;
};
void Draw(const BaseArgs& args, const YUVArgs* argsYUV = nullptr) const;
};
class ScopedSaveMultiTex final
{
GLContext& mGL;
const uint8_t mTexCount;
const GLenum mTexTarget;
const GLuint mOldTexUnit;
GLuint mOldTexSampler[3];
GLuint mOldTex[3];
public:
ScopedSaveMultiTex(GLContext* gl, uint8_t texCount, GLenum texTarget);
~ScopedSaveMultiTex();
};
/** Buffer blitting helper */
class GLBlitHelper final
{
enum Channel
friend class BindAnglePlanes;
friend class DrawBlitProg;
friend class GLContext;
enum class DrawBlitType : uint8_t
{
Channel_Y = 0,
Channel_Cb,
Channel_Cr,
Channel_Max,
Tex2DRGBA,
Tex2DPlanarYUV,
TexRectRGBA,
//TexExtYUV,
TexExtNV12,
TexExtPlanarYUV,
};
/**
* BlitTex2D is used to copy blit the content of a GL_TEXTURE_2D object,
* BlitTexRect is used to copy blit the content of a GL_TEXTURE_RECT object,
* The difference between BlitTex2D and BlitTexRect is the texture type, which affect
* the fragment shader a bit.
*
* ConvertPlnarYcbCr is used to color convert copy blit the PlanarYCbCrImage
* into a normal RGB texture by create textures of each color channel, and
* convert it in GPU.
* Convert type is created for canvas.
*/
enum BlitType
{
BlitTex2D,
BlitTexRect,
ConvertPlanarYCbCr,
ConvertSurfaceTexture,
ConvertEGLImage,
ConvertMacIOSurfaceImage
};
// The GLContext is the sole owner of the GLBlitHelper.
GLContext* mGL;
GLContext* const mGL;
std::map<uint8_t, UniquePtr<DrawBlitProg>> mDrawBlitProgs;
GLuint mTexBlit_Buffer;
GLuint mTexBlit_VertShader;
GLuint mTex2DBlit_FragShader;
GLuint mTex2DRectBlit_FragShader;
GLuint mTex2DBlit_Program;
GLuint mTex2DRectBlit_Program;
GLuint mQuadVAO;
GLint mYFlipLoc;
GLuint mYuvUploads[3];
gfx::IntSize mYuvUploads_YSize;
gfx::IntSize mYuvUploads_UVSize;
GLint mTextureTransformLoc;
#ifdef XP_WIN
mutable RefPtr<ID3D11Device> mD3D11;
// Data for image blit path
GLuint mTexExternalBlit_FragShader;
GLuint mTexYUVPlanarBlit_FragShader;
GLuint mTexNV12PlanarBlit_FragShader;
GLuint mTexExternalBlit_Program;
GLuint mTexYUVPlanarBlit_Program;
GLuint mTexNV12PlanarBlit_Program;
GLuint mFBO;
GLuint mSrcTexY;
GLuint mSrcTexCb;
GLuint mSrcTexCr;
GLuint mSrcTexEGL;
GLint mYTexScaleLoc;
GLint mCbCrTexScaleLoc;
GLint mYuvColorMatrixLoc;
int mTexWidth;
int mTexHeight;
ID3D11Device* GetD3D11() const;
#endif
// Cache some uniform values
float mCurYScale;
float mCurCbCrScale;
void UseBlitProgram();
void SetBlitFramebufferForDestTexture(GLuint aTexture);
bool UseTexQuadProgram(BlitType target, const gfx::IntSize& srcSize);
bool InitTexQuadProgram(BlitType target = BlitTex2D);
void DeleteTexBlitProgram();
void BindAndUploadYUVTexture(Channel which, uint32_t width, uint32_t height, void* data, bool allocation);
void BindAndUploadEGLImage(EGLImage image, GLuint target);
const DrawBlitProg* GetDrawBlitProg(DrawBlitType type) const;
bool BlitPlanarYCbCrImage(layers::PlanarYCbCrImage* yuvImage);
bool BlitImage(layers::PlanarYCbCrImage* yuvImage, const gfx::IntSize& destSize,
OriginPos destOrigin);
#ifdef MOZ_WIDGET_ANDROID
// Blit onto the current FB.
bool BlitSurfaceTextureImage(layers::SurfaceTextureImage* stImage);
bool BlitEGLImageImage(layers::EGLImageImage* eglImage);
bool BlitImage(layers::SurfaceTextureImage* stImage);
bool BlitImage(layers::EGLImageImage* eglImage);
#endif
#ifdef XP_MACOSX
bool BlitMacIOSurfaceImage(layers::MacIOSurfaceImage* ioImage);
bool BlitImage(layers::MacIOSurfaceImage* ioImage);
#endif
explicit GLBlitHelper(GLContext* gl);
friend class GLContext;
public:
~GLBlitHelper();
// If you don't have |srcFormats| for the 2nd definition,
// then you'll need the framebuffer_blit extensions to use
// the first BlitFramebufferToFramebuffer.
void BlitFramebuffer(const gfx::IntSize& srcSize,
const gfx::IntSize& destSize) const;
void BlitFramebufferToFramebuffer(GLuint srcFB, GLuint destFB,
const gfx::IntSize& srcSize,
const gfx::IntSize& destSize,
bool internalFBs = false);
void BlitFramebufferToFramebuffer(GLuint srcFB, GLuint destFB,
const gfx::IntSize& srcSize,
const gfx::IntSize& destSize,
const GLFormats& srcFormats,
bool internalFBs = false);
void BlitTextureToFramebuffer(GLuint srcTex, GLuint destFB,
const gfx::IntSize& srcSize,
const gfx::IntSize& destSize) const;
void BlitFramebufferToTexture(GLuint destTex, const gfx::IntSize& srcSize,
const gfx::IntSize& destSize,
GLenum srcTarget = LOCAL_GL_TEXTURE_2D,
bool internalFBs = false);
void DrawBlitTextureToFramebuffer(GLuint srcTex, GLuint destFB,
const gfx::IntSize& srcSize,
const gfx::IntSize& destSize,
GLenum srcTarget = LOCAL_GL_TEXTURE_2D,
bool internalFBs = false);
void BlitFramebufferToTexture(GLuint srcFB, GLuint destTex,
const gfx::IntSize& srcSize,
GLenum destTarget = LOCAL_GL_TEXTURE_2D) const;
void BlitTextureToFramebuffer(GLuint srcTex, const gfx::IntSize& srcSize,
const gfx::IntSize& destSize,
GLenum destTarget = LOCAL_GL_TEXTURE_2D,
bool internalFBs = false);
GLenum srcTarget = LOCAL_GL_TEXTURE_2D) const;
void BlitTextureToTexture(GLuint srcTex, GLuint destTex,
const gfx::IntSize& srcSize,
const gfx::IntSize& destSize,
GLenum srcTarget = LOCAL_GL_TEXTURE_2D,
GLenum destTarget = LOCAL_GL_TEXTURE_2D);
GLenum destTarget = LOCAL_GL_TEXTURE_2D) const;
void DrawBlitTextureToFramebuffer(GLuint srcTex, const gfx::IntSize& srcSize,
const gfx::IntSize& destSize,
GLenum srcTarget = LOCAL_GL_TEXTURE_2D) const;
bool BlitImageToFramebuffer(layers::Image* srcImage, const gfx::IntSize& destSize,
GLuint destFB, OriginPos destOrigin);
bool BlitImageToTexture(layers::Image* srcImage, const gfx::IntSize& destSize,
GLuint destTex, GLenum destTarget, OriginPos destOrigin);
OriginPos destOrigin);
private:
#ifdef XP_WIN
// GLBlitHelperD3D.cpp:
bool BlitImage(layers::GPUVideoImage* srcImage, const gfx::IntSize& destSize,
OriginPos destOrigin) const;
bool BlitImage(layers::D3D11YCbCrImage* srcImage, const gfx::IntSize& destSize,
OriginPos destOrigin) const;
bool BlitDescriptor(const layers::SurfaceDescriptorD3D10& desc,
const gfx::IntSize& destSize, OriginPos destOrigin) const;
bool BlitAngleYCbCr(const WindowsHandle (&handleList)[3],
const gfx::IntRect& clipRect,
const gfx::IntSize& ySize, const gfx::IntSize& uvSize,
const YUVColorSpace colorSpace,
const gfx::IntSize& destSize, OriginPos destOrigin) const;
bool BlitAnglePlanes(uint8_t numPlanes, const RefPtr<ID3D11Texture2D>* texD3DList,
const DrawBlitProg* prog, const DrawBlitProg::BaseArgs& baseArgs,
const DrawBlitProg::YUVArgs* const yuvArgs) const;
#endif
};
} // namespace gl

334
gfx/gl/GLBlitHelperD3D.cpp Normal file
Просмотреть файл

@ -0,0 +1,334 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set ts=8 sts=4 et sw=4 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "GLBlitHelper.h"
#include <d3d11.h>
#include "GLContext.h"
#include "GLLibraryEGL.h"
#include "GPUVideoImage.h"
#include "ScopedGLHelpers.h"
#include "mozilla/layers/D3D11YCbCrImage.h"
#include "mozilla/layers/TextureD3D11.h"
namespace mozilla {
namespace gl {
static EGLStreamKHR
StreamFromD3DTexture(ID3D11Texture2D* const texD3D,
const EGLAttrib* const postAttribs)
{
auto& egl = sEGLLibrary;
const auto& display = egl.Display();
const auto stream = egl.fCreateStreamKHR(display, nullptr);
MOZ_ASSERT(stream);
if (!stream)
return 0;
bool ok = true;
MOZ_ALWAYS_TRUE( ok &= bool(egl.fStreamConsumerGLTextureExternalAttribsNV(display,
stream,
nullptr)) );
MOZ_ALWAYS_TRUE( ok &= bool(egl.fCreateStreamProducerD3DTextureNV12ANGLE(display,
stream,
nullptr)) );
MOZ_ALWAYS_TRUE( ok &= bool(egl.fStreamPostD3DTextureNV12ANGLE(display, stream,
texD3D,
postAttribs)) );
if (ok)
return stream;
(void)egl.fDestroyStreamKHR(display, stream);
return 0;
}
static RefPtr<ID3D11Texture2D>
OpenSharedTexture(ID3D11Device* const d3d, const WindowsHandle handle)
{
RefPtr<ID3D11Texture2D> tex;
auto hr = d3d->OpenSharedResource((HANDLE)handle, __uuidof(ID3D11Texture2D),
(void**)(ID3D11Texture2D**)getter_AddRefs(tex));
if (FAILED(hr)) {
MOZ_ASSERT(false, "OpenSharedResource should not fail");
return nullptr;
}
return tex;
}
// -------------------------------------
class BindAnglePlanes final
{
const GLBlitHelper& mParent;
const uint8_t mNumPlanes;
const ScopedSaveMultiTex mMultiTex;
GLuint mTempTexs[3];
EGLStreamKHR mStreams[3];
RefPtr<IDXGIKeyedMutex> mMutexList[3];
bool mSuccess;
public:
BindAnglePlanes(const GLBlitHelper* const parent, const uint8_t numPlanes,
const RefPtr<ID3D11Texture2D>* const texD3DList,
const EGLAttrib* const* postAttribsList = nullptr)
: mParent(*parent)
, mNumPlanes(numPlanes)
, mMultiTex(mParent.mGL, mNumPlanes, LOCAL_GL_TEXTURE_EXTERNAL)
, mTempTexs{0}
, mStreams{0}
, mSuccess(true)
{
MOZ_RELEASE_ASSERT(numPlanes >= 1 && numPlanes <= 3);
const auto& gl = mParent.mGL;
auto& egl = sEGLLibrary;
const auto& display = egl.Display();
gl->fGenTextures(numPlanes, mTempTexs);
for (uint8_t i = 0; i < mNumPlanes; i++) {
gl->fActiveTexture(LOCAL_GL_TEXTURE0 + i);
gl->fBindTexture(LOCAL_GL_TEXTURE_EXTERNAL, mTempTexs[i]);
const EGLAttrib* postAttribs = nullptr;
if (postAttribsList) {
postAttribs = postAttribsList[i];
}
mStreams[i] = StreamFromD3DTexture(texD3DList[i], postAttribs);
mSuccess &= bool(mStreams[i]);
}
if (mSuccess) {
for (uint8_t i = 0; i < mNumPlanes; i++) {
MOZ_ALWAYS_TRUE( egl.fStreamConsumerAcquireKHR(display, mStreams[i]) );
auto& mutex = mMutexList[i];
texD3DList[i]->QueryInterface(_uuidof(IDXGIKeyedMutex),
(void**)getter_AddRefs(mutex));
if (mutex) {
const auto hr = mutex->AcquireSync(0, 100);
if (FAILED(hr)) {
NS_WARNING("BindAnglePlanes failed to acquire KeyedMutex.");
mSuccess = false;
}
}
}
}
}
~BindAnglePlanes()
{
const auto& gl = mParent.mGL;
auto& egl = sEGLLibrary;
const auto& display = egl.Display();
if (mSuccess) {
for (uint8_t i = 0; i < mNumPlanes; i++) {
MOZ_ALWAYS_TRUE( egl.fStreamConsumerReleaseKHR(display, mStreams[i]) );
if (mMutexList[i]) {
mMutexList[i]->ReleaseSync(0);
}
}
}
for (uint8_t i = 0; i < mNumPlanes; i++) {
(void)egl.fDestroyStreamKHR(display, mStreams[i]);
}
gl->fDeleteTextures(mNumPlanes, mTempTexs);
}
const bool& Success() const { return mSuccess; }
};
// -------------------------------------
ID3D11Device*
GLBlitHelper::GetD3D11() const
{
if (mD3D11)
return mD3D11;
if (!mGL->IsANGLE())
return nullptr;
auto& egl = sEGLLibrary;
EGLDeviceEXT deviceEGL = 0;
MOZ_ALWAYS_TRUE( egl.fQueryDisplayAttribEXT(egl.Display(), LOCAL_EGL_DEVICE_EXT,
(EGLAttrib*)&deviceEGL) );
if (!egl.fQueryDeviceAttribEXT(deviceEGL, LOCAL_EGL_D3D11_DEVICE_ANGLE,
(EGLAttrib*)(ID3D11Device**)getter_AddRefs(mD3D11)))
{
MOZ_ASSERT(false, "d3d9?");
return nullptr;
}
return mD3D11;
}
// -------------------------------------
bool
GLBlitHelper::BlitImage(layers::GPUVideoImage* const srcImage,
const gfx::IntSize& destSize, const OriginPos destOrigin) const
{
const auto& data = srcImage->GetData();
if (!data)
return false;
const auto& desc = data->SD();
const auto& subdescUnion = desc.subdesc();
switch (subdescUnion.type()) {
case subdescUnion.TSurfaceDescriptorD3D10:
{
const auto& subdesc = subdescUnion.get_SurfaceDescriptorD3D10();
return BlitDescriptor(subdesc, destSize, destOrigin);
}
case subdescUnion.TSurfaceDescriptorDXGIYCbCr:
{
const auto& subdesc = subdescUnion.get_SurfaceDescriptorDXGIYCbCr();
const auto& clipSize = subdesc.size();
const auto& ySize = subdesc.sizeY();
const auto& uvSize = subdesc.sizeCbCr();
const gfx::IntRect clipRect(0, 0, clipSize.width, clipSize.height);
const auto colorSpace = YUVColorSpace::BT601;
const WindowsHandle handles[3] = {
subdesc.handleY(),
subdesc.handleCb(),
subdesc.handleCr()
};
return BlitAngleYCbCr(handles, clipRect, ySize, uvSize, colorSpace, destSize,
destOrigin);
}
default:
gfxCriticalError() << "Unhandled subdesc type: " << uint32_t(subdescUnion.type());
return false;
}
}
// -------------------------------------
bool
GLBlitHelper::BlitImage(layers::D3D11YCbCrImage* const srcImage,
const gfx::IntSize& destSize, const OriginPos destOrigin) const
{
const auto& data = srcImage->GetData();
if (!data)
return false;
const auto& clipRect = srcImage->mPictureRect;
const auto& colorSpace = srcImage->mColorSpace;
const WindowsHandle handles[3] = {
(WindowsHandle)data->mHandles[0],
(WindowsHandle)data->mHandles[1],
(WindowsHandle)data->mHandles[2]
};
return BlitAngleYCbCr(handles, srcImage->mPictureRect, srcImage->mYSize,
srcImage->mCbCrSize, srcImage->mColorSpace, destSize,
destOrigin);
}
// -------------------------------------
bool
GLBlitHelper::BlitDescriptor(const layers::SurfaceDescriptorD3D10& desc,
const gfx::IntSize& destSize, OriginPos destOrigin) const
{
const auto& d3d = GetD3D11();
if (!d3d)
return false;
const auto& handle = desc.handle();
const auto& format = desc.format();
const auto& clipSize = desc.size();
const auto srcOrigin = OriginPos::BottomLeft;
const gfx::IntRect clipRect(0, 0, clipSize.width, clipSize.height);
const auto colorSpace = YUVColorSpace::BT601;
if (format != gfx::SurfaceFormat::NV12) {
gfxCriticalError() << "Non-NV12 format for SurfaceDescriptorD3D10: "
<< uint32_t(format);
return nullptr;
}
const auto tex = OpenSharedTexture(d3d, handle);
const RefPtr<ID3D11Texture2D> texList[2] = { tex, tex };
const EGLAttrib postAttribs0[] = {
LOCAL_EGL_NATIVE_BUFFER_PLANE_OFFSET_IMG, 0,
LOCAL_EGL_NONE
};
const EGLAttrib postAttribs1[] = {
LOCAL_EGL_NATIVE_BUFFER_PLANE_OFFSET_IMG, 1,
LOCAL_EGL_NONE
};
const EGLAttrib* const postAttribsList[2] = { postAttribs0, postAttribs1 };
// /layers/d3d11/CompositorD3D11.cpp uses bt601 for EffectTypes::NV12.
//return BlitAngleNv12(tex, YUVColorSpace::BT601, destSize, destOrigin);
const BindAnglePlanes bindPlanes(this, 2, texList, postAttribsList);
D3D11_TEXTURE2D_DESC texDesc = {0};
tex->GetDesc(&texDesc);
const gfx::IntSize ySize(texDesc.Width, texDesc.Height);
const gfx::IntSize divisors(2, 2);
MOZ_ASSERT(ySize.width % divisors.width == 0);
MOZ_ASSERT(ySize.height % divisors.height == 0);
const gfx::IntSize uvSize(ySize.width / divisors.width,
ySize.height / divisors.height);
const bool yFlip = destOrigin != srcOrigin;
const DrawBlitProg::BaseArgs baseArgs = { destSize, yFlip, clipRect, ySize };
const DrawBlitProg::YUVArgs yuvArgs = { uvSize, divisors, colorSpace };
const auto& prog = GetDrawBlitProg(DrawBlitType::TexExtNV12);
MOZ_RELEASE_ASSERT(prog);
prog->Draw(baseArgs, &yuvArgs);
return true;
}
// --
bool
GLBlitHelper::BlitAngleYCbCr(const WindowsHandle (&handleList)[3],
const gfx::IntRect& clipRect,
const gfx::IntSize& ySize, const gfx::IntSize& uvSize,
const YUVColorSpace colorSpace,
const gfx::IntSize& destSize, OriginPos destOrigin) const
{
const auto& d3d = GetD3D11();
if (!d3d)
return false;
const auto srcOrigin = OriginPos::BottomLeft;
gfx::IntSize divisors;
if (!GuessDivisors(ySize, uvSize, &divisors))
return false;
const RefPtr<ID3D11Texture2D> texList[3] = {
OpenSharedTexture(d3d, handleList[0]),
OpenSharedTexture(d3d, handleList[1]),
OpenSharedTexture(d3d, handleList[2])
};
const BindAnglePlanes bindPlanes(this, 3, texList);
const bool yFlip = destOrigin != srcOrigin;
const DrawBlitProg::BaseArgs baseArgs = { destSize, yFlip, clipRect, ySize };
const DrawBlitProg::YUVArgs yuvArgs = { uvSize, divisors, colorSpace };
const auto& prog = GetDrawBlitProg(DrawBlitType::TexExtPlanarYUV);
MOZ_RELEASE_ASSERT(prog);
prog->Draw(baseArgs, &yuvArgs);
return true;
}
} // namespace gl
} // namespace mozilla

Просмотреть файл

@ -1417,6 +1417,22 @@ public:
return retval;
}
void SetEnabled(const GLenum cap, const bool val) {
if (val) {
fEnable(cap);
} else {
fDisable(cap);
}
}
bool PushEnabled(const GLenum cap, const bool newVal) {
const bool oldVal = fIsEnabled(cap);
if (oldVal != newVal) {
SetEnabled(cap, newVal);
}
return oldVal;
}
realGLboolean fIsProgram(GLuint program) {
BEFORE_GL_CALL;
realGLboolean retval = mSymbols.fIsProgram(program);

Просмотреть файл

@ -114,7 +114,7 @@ protected:
friend class GLContextEGLFactory;
public:
const EGLConfig mConfig;
const EGLConfig mConfig;
protected:
EGLSurface mSurface;
public:

Просмотреть файл

@ -610,6 +610,7 @@ GLLibraryEGL::EnsureInitialized(bool forceAccel, nsACString* const out_failureId
if (IsExtensionSupported(KHR_stream_consumer_gltexture)) {
const GLLibraryLoader::SymLoadStruct streamConsumerSymbols[] = {
SYMBOL(StreamConsumerGLTextureExternalKHR),
SYMBOL(StreamConsumerAcquireKHR),
SYMBOL(StreamConsumerReleaseKHR),
END_OF_SYMBOLS

Просмотреть файл

@ -300,6 +300,9 @@ public:
WRAP( fQueryStreamKHR(dpy, stream, attribute, value) )
// KHR_stream_consumer_gltexture
EGLBoolean fStreamConsumerGLTextureExternalKHR(EGLDisplay dpy, EGLStreamKHR stream) const
WRAP( fStreamConsumerGLTextureExternalKHR(dpy, stream) )
EGLBoolean fStreamConsumerAcquireKHR(EGLDisplay dpy, EGLStreamKHR stream) const
WRAP( fStreamConsumerAcquireKHR(dpy, stream) )
@ -467,6 +470,8 @@ private:
EGLenum attribute,
EGLint* value);
// KHR_stream_consumer_gltexture
EGLBoolean (GLAPIENTRY * fStreamConsumerGLTextureExternalKHR)(EGLDisplay dpy,
EGLStreamKHR stream);
EGLBoolean (GLAPIENTRY * fStreamConsumerAcquireKHR)(EGLDisplay dpy,
EGLStreamKHR stream);
EGLBoolean (GLAPIENTRY * fStreamConsumerReleaseKHR)(EGLDisplay dpy,

Просмотреть файл

@ -23,7 +23,7 @@ class HeapCopyOfStackArray
{
public:
template<size_t N>
MOZ_IMPLICIT HeapCopyOfStackArray(ElemType (&array)[N])
MOZ_IMPLICIT HeapCopyOfStackArray(const ElemType (&array)[N])
: mArrayLength(N)
, mArrayData(MakeUnique<ElemType[]>(N))
{

Просмотреть файл

@ -423,75 +423,6 @@ ScopedVertexAttribPointer::UnwrapImpl()
mGL->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mBoundBuffer);
}
ScopedGLDrawState::ScopedGLDrawState(GLContext* aGL)
: blend (aGL, LOCAL_GL_BLEND, false)
, cullFace (aGL, LOCAL_GL_CULL_FACE, false)
, depthTest (aGL, LOCAL_GL_DEPTH_TEST, false)
, dither (aGL, LOCAL_GL_DITHER, false)
, polyOffsFill(aGL, LOCAL_GL_POLYGON_OFFSET_FILL, false)
, sampleAToC (aGL, LOCAL_GL_SAMPLE_ALPHA_TO_COVERAGE, false)
, sampleCover (aGL, LOCAL_GL_SAMPLE_COVERAGE, false)
, scissor (aGL, LOCAL_GL_SCISSOR_TEST, false)
, stencil (aGL, LOCAL_GL_STENCIL_TEST, false)
, mGL(aGL)
{
mGL->GetUIntegerv(LOCAL_GL_CURRENT_PROGRAM, &boundProgram);
mGL->GetUIntegerv(LOCAL_GL_ARRAY_BUFFER_BINDING, &boundBuffer);
mGL->GetUIntegerv(LOCAL_GL_MAX_VERTEX_ATTRIBS, &maxAttrib);
attrib_enabled = MakeUnique<GLint[]>(maxAttrib);
for (GLuint i = 0; i < maxAttrib; i++) {
mGL->fGetVertexAttribiv(i, LOCAL_GL_VERTEX_ATTRIB_ARRAY_ENABLED, &attrib_enabled[i]);
mGL->fDisableVertexAttribArray(i);
}
// Only Attrib0's client side state affected
mGL->fGetVertexAttribiv(0, LOCAL_GL_VERTEX_ATTRIB_ARRAY_SIZE, &attrib0_size);
mGL->fGetVertexAttribiv(0, LOCAL_GL_VERTEX_ATTRIB_ARRAY_STRIDE, &attrib0_stride);
mGL->fGetVertexAttribiv(0, LOCAL_GL_VERTEX_ATTRIB_ARRAY_TYPE, &attrib0_type);
mGL->fGetVertexAttribiv(0, LOCAL_GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, &attrib0_normalized);
mGL->fGetVertexAttribiv(0, LOCAL_GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &attrib0_bufferBinding);
mGL->fGetVertexAttribPointerv(0, LOCAL_GL_VERTEX_ATTRIB_ARRAY_POINTER, &attrib0_pointer);
mGL->fGetBooleanv(LOCAL_GL_COLOR_WRITEMASK, colorMask);
mGL->fGetIntegerv(LOCAL_GL_VIEWPORT, viewport);
mGL->fGetIntegerv(LOCAL_GL_SCISSOR_BOX, scissorBox);
}
ScopedGLDrawState::~ScopedGLDrawState()
{
MOZ_ASSERT(mGL->IsCurrent());
mGL->fScissor(scissorBox[0], scissorBox[1],
scissorBox[2], scissorBox[3]);
mGL->fViewport(viewport[0], viewport[1],
viewport[2], viewport[3]);
mGL->fColorMask(colorMask[0],
colorMask[1],
colorMask[2],
colorMask[3]);
for (unsigned int i = 0; i < maxAttrib; i++) {
if (attrib_enabled[i])
mGL->fEnableVertexAttribArray(i);
else
mGL->fDisableVertexAttribArray(i);
}
mGL->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, attrib0_bufferBinding);
mGL->fVertexAttribPointer(0,
attrib0_size,
attrib0_type,
attrib0_normalized,
attrib0_stride,
attrib0_pointer);
mGL->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, boundBuffer);
mGL->fUseProgram(boundProgram);
}
////////////////////////////////////////////////////////////////////////
// ScopedPackState

Просмотреть файл

@ -122,7 +122,7 @@ protected:
public:
explicit ScopedTexture(GLContext* aGL);
GLuint Texture() { return mTexture; }
GLuint Texture() const { return mTexture; }
protected:
void UnwrapImpl();
@ -309,39 +309,6 @@ protected:
void UnwrapImpl();
};
struct ScopedGLDrawState
{
explicit ScopedGLDrawState(GLContext* gl);
~ScopedGLDrawState();
GLuint boundProgram;
GLuint boundBuffer;
ScopedGLState blend;
ScopedGLState cullFace;
ScopedGLState depthTest;
ScopedGLState dither;
ScopedGLState polyOffsFill;
ScopedGLState sampleAToC;
ScopedGLState sampleCover;
ScopedGLState scissor;
ScopedGLState stencil;
GLuint maxAttrib;
UniquePtr<GLint[]> attrib_enabled;
GLint attrib0_size;
GLint attrib0_stride;
GLint attrib0_type;
GLint attrib0_normalized;
GLint attrib0_bufferBinding;
void* attrib0_pointer;
realGLboolean colorMask[4];
GLint viewport[4];
GLint scissorBox[4];
GLContext* const mGL;
};
struct ScopedPackState
: public ScopedGLWrapper<ScopedPackState>
{

Просмотреть файл

@ -65,7 +65,9 @@ SharedSurface::ProdCopy(SharedSurface* src, SharedSurface* dest,
GLuint destTex = dest->ProdTexture();
GLenum destTarget = dest->ProdTextureTarget();
gl->BlitHelper()->BlitFramebufferToTexture(0, destTex,
const ScopedBindFramebuffer bindFB(gl, 0);
gl->BlitHelper()->BlitFramebufferToTexture(destTex,
src->mSize,
dest->mSize,
destTarget,
@ -110,7 +112,9 @@ SharedSurface::ProdCopy(SharedSurface* src, SharedSurface* dest,
GLuint srcTex = src->ProdTexture();
GLenum srcTarget = src->ProdTextureTarget();
gl->BlitHelper()->BlitTextureToFramebuffer(srcTex, 0,
const ScopedBindFramebuffer bindFB(gl, 0);
gl->BlitHelper()->BlitTextureToFramebuffer(srcTex,
src->mSize,
dest->mSize,
srcTarget,
@ -158,9 +162,9 @@ SharedSurface::ProdCopy(SharedSurface* src, SharedSurface* dest,
if (dest->mAttachType == AttachmentType::GLRenderbuffer) {
GLuint destRB = dest->ProdRenderbuffer();
ScopedFramebufferForRenderbuffer destWrapper(gl, destRB);
gl->BlitHelper()->BlitTextureToFramebuffer(srcTex, destWrapper.FB(),
src->mSize, dest->mSize, srcTarget);
const ScopedBindFramebuffer bindFB(gl, destWrapper.FB());
gl->BlitHelper()->BlitTextureToFramebuffer(srcTex, src->mSize, dest->mSize,
srcTarget);
return;
}
@ -175,9 +179,10 @@ SharedSurface::ProdCopy(SharedSurface* src, SharedSurface* dest,
if (dest->mAttachType == AttachmentType::GLTexture) {
GLuint destTex = dest->ProdTexture();
GLenum destTarget = dest->ProdTextureTarget();
const ScopedBindFramebuffer bindFB(gl, srcWrapper.FB());
gl->BlitHelper()->BlitFramebufferToTexture(srcWrapper.FB(), destTex,
src->mSize, dest->mSize, destTarget);
gl->BlitHelper()->BlitFramebufferToTexture(destTex, src->mSize, dest->mSize,
destTarget);
return;
}

Просмотреть файл

@ -471,8 +471,8 @@ SharedSurface_D3D11Interop::ProducerReleaseImpl()
MOZ_ASSERT(mLockedForGL);
if (mProdTex) {
mGL->BlitHelper()->DrawBlitTextureToFramebuffer(mProdTex, mInteropFB, mSize,
mSize);
const ScopedBindFramebuffer bindFB(mGL, mInteropFB);
mGL->BlitHelper()->DrawBlitTextureToFramebuffer(mProdTex, mSize, mSize);
}
if (mNeedsFinish) {

Просмотреть файл

@ -69,6 +69,7 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
'WGLLibrary.h',
]
UNIFIED_SOURCES += [
'GLBlitHelperD3D.cpp',
'GLContextProviderWGL.cpp',
'SharedSurfaceANGLE.cpp',
'SharedSurfaceD3D11Interop.cpp',

Просмотреть файл

@ -97,7 +97,7 @@ D3D11YCbCrImage::SetData(KnowsCompositor* aAllocator,
aData.mCbCrStride,
aData.mCbCrStride * aData.mCbCrSize.height);
return true;
}
@ -113,6 +113,15 @@ D3D11YCbCrImage::GetTextureClient(KnowsCompositor* aForwarder)
return mTextureClient;
}
const DXGIYCbCrTextureData*
D3D11YCbCrImage::GetData() const
{
if (!mTextureClient)
return nullptr;
return static_cast<DXGIYCbCrTextureData*>(mTextureClient->GetInternalData());
}
already_AddRefed<SourceSurface>
D3D11YCbCrImage::GetAsSourceSurface()
{

Просмотреть файл

@ -12,10 +12,14 @@
#include "ImageContainer.h"
namespace mozilla {
namespace gl {
class GLBlitHelper;
}
namespace layers {
class ImageContainer;
class DXGIYCbCrTextureClient;
class DXGIYCbCrTextureData;
class D3D11YCbCrRecycleAllocator : public TextureClientRecycleAllocator
{
@ -46,6 +50,7 @@ protected:
class D3D11YCbCrImage : public Image
{
friend class gl::GLBlitHelper;
public:
D3D11YCbCrImage();
virtual ~D3D11YCbCrImage();
@ -65,6 +70,8 @@ public:
gfx::IntRect GetPictureRect() override { return mPictureRect; }
private:
const DXGIYCbCrTextureData* GetData() const;
gfx::IntSize mYSize;
gfx::IntSize mCbCrSize;
gfx::IntRect mPictureRect;

Просмотреть файл

@ -78,12 +78,11 @@ GLImage::GetAsSourceSurface()
}
const gl::OriginPos destOrigin = gl::OriginPos::TopLeft;
if (!sSnapshotContext->BlitHelper()->BlitImageToFramebuffer(this, size,
autoFBForTex.FB(),
destOrigin))
{
return nullptr;
const ScopedBindFramebuffer bindFB(sSnapshotContext, autoFBForTex.FB());
if (!sSnapshotContext->BlitHelper()->BlitImageToFramebuffer(this, size, destOrigin)) {
return nullptr;
}
}
RefPtr<gfx::DataSourceSurface> source =

Просмотреть файл

@ -16,11 +16,15 @@ namespace mozilla {
namespace dom {
class VideoDecoderManagerChild;
}
namespace gl {
class GLBlitHelper;
}
namespace layers {
// Image class that refers to a decoded video frame within
// the GPU process.
class GPUVideoImage final : public Image {
friend class gl::GLBlitHelper;
public:
GPUVideoImage(dom::VideoDecoderManagerChild* aManager,
const SurfaceDescriptorGPUVideo& aSD,
@ -45,12 +49,21 @@ public:
gfx::IntSize GetSize() override { return mSize; }
virtual already_AddRefed<gfx::SourceSurface> GetAsSourceSurface() override
{
private:
GPUVideoTextureData* GetData() const {
if (!mTextureClient) {
return nullptr;
}
GPUVideoTextureData* data = mTextureClient->GetInternalData()->AsGPUVideoTextureData();
return mTextureClient->GetInternalData()->AsGPUVideoTextureData();
}
public:
virtual already_AddRefed<gfx::SourceSurface> GetAsSourceSurface() override
{
GPUVideoTextureData* data = GetData();
if (!data) {
return nullptr;
}
return data->GetAsSourceSurface();
}

Просмотреть файл

@ -48,6 +48,9 @@ protected:
RefPtr<dom::VideoDecoderManagerChild> mManager;
SurfaceDescriptorGPUVideo mSD;
gfx::IntSize mSize;
public:
const decltype(mSD)& SD() const { return mSD; }
};
} // namespace layers

Просмотреть файл

@ -18,6 +18,10 @@
#include <vector>
namespace mozilla {
namespace gl {
class GLBlitHelper;
}
namespace layers {
class MOZ_RAII AutoTextureLock
@ -128,6 +132,7 @@ CreateD3D11extureClientWithDevice(gfx::IntSize aSize, gfx::SurfaceFormat aFormat
class DXGIYCbCrTextureData : public TextureData
{
friend class gl::GLBlitHelper;
public:
static DXGIYCbCrTextureData*
Create(IDirect3DTexture9* aTextureY,

Просмотреть файл

@ -89,7 +89,7 @@ union GPUVideoSubDescriptor {
struct SurfaceDescriptorGPUVideo {
uint64_t handle;
GPUVideoSubDescriptor desc;
GPUVideoSubDescriptor subdesc;
};
struct RGBDescriptor {

Просмотреть файл

@ -1111,47 +1111,29 @@ gfxUtils::EncodeSourceSurface(SourceSurface* aSurface,
aBinaryOrData, aFile, nullptr);
}
/* From Rec601:
[R] [1.1643835616438356, 0.0, 1.5960267857142858] [ Y - 16]
[G] = [1.1643835616438358, -0.3917622900949137, -0.8129676472377708] x [Cb - 128]
[B] [1.1643835616438356, 2.017232142857143, 8.862867620416422e-17] [Cr - 128]
For [0,1] instead of [0,255], and to 5 places:
[R] [1.16438, 0.00000, 1.59603] [ Y - 0.06275]
[G] = [1.16438, -0.39176, -0.81297] x [Cb - 0.50196]
[B] [1.16438, 2.01723, 0.00000] [Cr - 0.50196]
From Rec709:
[R] [1.1643835616438356, 4.2781193979771426e-17, 1.7927410714285714] [ Y - 16]
[G] = [1.1643835616438358, -0.21324861427372963, -0.532909328559444] x [Cb - 128]
[B] [1.1643835616438356, 2.1124017857142854, 0.0] [Cr - 128]
For [0,1] instead of [0,255], and to 5 places:
[R] [1.16438, 0.00000, 1.79274] [ Y - 0.06275]
[G] = [1.16438, -0.21325, -0.53291] x [Cb - 0.50196]
[B] [1.16438, 2.11240, 0.00000] [Cr - 0.50196]
*/
static const float kRec601[9] = {
1.16438f, 0.00000f, 1.59603f,
1.16438f,-0.39176f,-0.81297f,
1.16438f, 2.01723f, 0.00000f,
// https://jdashg.github.io/misc/colors/from-coeffs.html
const float kBT601NarrowYCbCrToRGB_RowMajor[16] = {
1.16438f, 0.00000f, 1.59603f,-0.87420f,
1.16438f,-0.39176f,-0.81297f, 0.53167f,
1.16438f, 2.01723f, 0.00000f,-1.08563f,
0.00000f, 0.00000f, 0.00000f, 1.00000f
};
static const float kRec709[9] = {
1.16438f, 0.00000f, 1.79274f,
1.16438f,-0.21325f,-0.53291f,
1.16438f, 2.11240f, 0.00000f,
const float kBT709NarrowYCbCrToRGB_RowMajor[16] = {
1.16438f, 0.00000f, 1.79274f,-0.97295f,
1.16438f,-0.21325f,-0.53291f, 0.30148f,
1.16438f, 2.11240f, 0.00000f,-1.13340f,
0.00000f, 0.00000f, 0.00000f, 1.00000f
};
/* static */ const float*
gfxUtils::YuvToRgbMatrix4x3RowMajor(YUVColorSpace aYUVColorSpace)
{
#define X(x) { x[0], x[1], x[2], 0.0f, \
x[3], x[4], x[5], 0.0f, \
x[6], x[7], x[8], 0.0f }
#define X(x) { x[0], x[1], x[ 2], 0.0f, \
x[4], x[5], x[ 6], 0.0f, \
x[8], x[9], x[10], 0.0f }
static const float rec601[12] = X(kRec601);
static const float rec709[12] = X(kRec709);
static const float rec601[12] = X(kBT601NarrowYCbCrToRGB_RowMajor);
static const float rec709[12] = X(kBT709NarrowYCbCrToRGB_RowMajor);
#undef X
@ -1169,12 +1151,36 @@ gfxUtils::YuvToRgbMatrix4x3RowMajor(YUVColorSpace aYUVColorSpace)
/* static */ const float*
gfxUtils::YuvToRgbMatrix3x3ColumnMajor(YUVColorSpace aYUVColorSpace)
{
#define X(x) { x[0], x[3], x[6], \
x[1], x[4], x[7], \
x[2], x[5], x[8] }
#define X(x) { x[0], x[4], x[ 8], \
x[1], x[5], x[ 9], \
x[2], x[6], x[10] }
static const float rec601[9] = X(kRec601);
static const float rec709[9] = X(kRec709);
static const float rec601[9] = X(kBT601NarrowYCbCrToRGB_RowMajor);
static const float rec709[9] = X(kBT709NarrowYCbCrToRGB_RowMajor);
#undef X
switch (aYUVColorSpace) {
case YUVColorSpace::BT601:
return rec601;
case YUVColorSpace::BT709:
return rec709;
default: // YUVColorSpace::UNKNOWN
MOZ_ASSERT(false, "unknown aYUVColorSpace");
return rec601;
}
}
/* static */ const float*
gfxUtils::YuvToRgbMatrix4x4ColumnMajor(YUVColorSpace aYUVColorSpace)
{
#define X(x) { x[0], x[4], x[ 8], x[12], \
x[1], x[5], x[ 9], x[13], \
x[2], x[6], x[10], x[14], \
x[3], x[7], x[11], x[15] }
static const float rec601[16] = X(kBT601NarrowYCbCrToRGB_RowMajor);
static const float rec709[16] = X(kBT709NarrowYCbCrToRGB_RowMajor);
#undef X

Просмотреть файл

@ -158,6 +158,7 @@ public:
static const float* YuvToRgbMatrix4x3RowMajor(mozilla::YUVColorSpace aYUVColorSpace);
static const float* YuvToRgbMatrix3x3ColumnMajor(mozilla::YUVColorSpace aYUVColorSpace);
static const float* YuvToRgbMatrix4x4ColumnMajor(mozilla::YUVColorSpace aYUVColorSpace);
/**
* Creates a copy of aSurface, but having the SurfaceFormat aFormat.