mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-11-04 18:29:29 +02:00
This patch corrects a few different issues related to recycling MacIOSurface objects. 1) When recycling a surface, we must check that the cached surfaces match all of the requested parameters, not just the size. If we do not, we should just flush the whole cache immediately since they should all be created with the same parameters. 2) Allocations can fail, and we should check for failing to get a surface from the allocator and fall back if so. 3) Locking can fail, and we should check that return value at all of the call sites. This may help resolve a number of otherwise difficult to understand crash signatures. It may also solve display corruption issues in rare cases where the parameters that changed were roughly equivalent such that everything appears to work, but they differ enough to change the presentation. Differential Revision: https://phabricator.services.mozilla.com/D222775
165 lines
5.6 KiB
C++
165 lines
5.6 KiB
C++
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* vim: set ts=8 sts=2 et sw=2 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 "RenderMacIOSurfaceTextureHost.h"
|
|
|
|
#ifdef XP_MACOSX
|
|
# include "GLContextCGL.h"
|
|
#else
|
|
# include "GLContextEAGL.h"
|
|
#endif
|
|
|
|
#include "mozilla/gfx/Logging.h"
|
|
#include "ScopedGLHelpers.h"
|
|
|
|
namespace mozilla {
|
|
namespace wr {
|
|
|
|
static bool CreateTextureForPlane(uint8_t aPlaneID, gl::GLContext* aGL,
|
|
MacIOSurface* aSurface, GLuint* aTexture) {
|
|
MOZ_ASSERT(aGL && aSurface && aTexture);
|
|
|
|
aGL->fGenTextures(1, aTexture);
|
|
ActivateBindAndTexParameteri(aGL, LOCAL_GL_TEXTURE0,
|
|
LOCAL_GL_TEXTURE_RECTANGLE_ARB, *aTexture);
|
|
aGL->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB, LOCAL_GL_TEXTURE_WRAP_T,
|
|
LOCAL_GL_CLAMP_TO_EDGE);
|
|
aGL->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB, LOCAL_GL_TEXTURE_WRAP_S,
|
|
LOCAL_GL_CLAMP_TO_EDGE);
|
|
|
|
gfx::SurfaceFormat readFormat = gfx::SurfaceFormat::UNKNOWN;
|
|
bool result = aSurface->BindTexImage(aGL, aPlaneID, &readFormat);
|
|
// If this is a yuv format, the Webrender only supports YUV422 interleaving
|
|
// format.
|
|
MOZ_ASSERT(aSurface->GetFormat() != gfx::SurfaceFormat::YUV422 ||
|
|
readFormat == gfx::SurfaceFormat::YUV422);
|
|
|
|
return result;
|
|
}
|
|
|
|
RenderMacIOSurfaceTextureHost::RenderMacIOSurfaceTextureHost(
|
|
MacIOSurface* aSurface)
|
|
: mSurface(aSurface), mTextureHandles{0, 0, 0} {
|
|
MOZ_COUNT_CTOR_INHERITED(RenderMacIOSurfaceTextureHost, RenderTextureHost);
|
|
}
|
|
|
|
RenderMacIOSurfaceTextureHost::~RenderMacIOSurfaceTextureHost() {
|
|
MOZ_COUNT_DTOR_INHERITED(RenderMacIOSurfaceTextureHost, RenderTextureHost);
|
|
DeleteTextureHandle();
|
|
}
|
|
|
|
GLuint RenderMacIOSurfaceTextureHost::GetGLHandle(uint8_t aChannelIndex) const {
|
|
MOZ_ASSERT(mSurface);
|
|
MOZ_ASSERT((mSurface->GetPlaneCount() == 0)
|
|
? (aChannelIndex == mSurface->GetPlaneCount())
|
|
: (aChannelIndex < mSurface->GetPlaneCount()));
|
|
return mTextureHandles[aChannelIndex];
|
|
}
|
|
|
|
gfx::IntSize RenderMacIOSurfaceTextureHost::GetSize(
|
|
uint8_t aChannelIndex) const {
|
|
MOZ_ASSERT(mSurface);
|
|
MOZ_ASSERT((mSurface->GetPlaneCount() == 0)
|
|
? (aChannelIndex == mSurface->GetPlaneCount())
|
|
: (aChannelIndex < mSurface->GetPlaneCount()));
|
|
|
|
if (!mSurface) {
|
|
return gfx::IntSize();
|
|
}
|
|
return gfx::IntSize(mSurface->GetDevicePixelWidth(aChannelIndex),
|
|
mSurface->GetDevicePixelHeight(aChannelIndex));
|
|
}
|
|
|
|
size_t RenderMacIOSurfaceTextureHost::Bytes() {
|
|
return mSurface->GetAllocSize();
|
|
}
|
|
|
|
wr::WrExternalImage RenderMacIOSurfaceTextureHost::Lock(uint8_t aChannelIndex,
|
|
gl::GLContext* aGL) {
|
|
if (mGL.get() != aGL) {
|
|
// release the texture handle in the previous gl context
|
|
DeleteTextureHandle();
|
|
mGL = aGL;
|
|
mGL->MakeCurrent();
|
|
}
|
|
|
|
if (!mSurface || !mGL || !mGL->MakeCurrent()) {
|
|
return InvalidToWrExternalImage();
|
|
}
|
|
|
|
if (!mTextureHandles[0]) {
|
|
#ifdef XP_MACOSX
|
|
MOZ_ASSERT(gl::GLContextCGL::Cast(mGL.get())->GetCGLContext());
|
|
#else
|
|
MOZ_ASSERT(gl::GLContextEAGL::Cast(mGL.get())->GetEAGLContext());
|
|
#endif
|
|
|
|
// The result of GetPlaneCount() is 0 for single plane format, but it will
|
|
// be 2 if the format has 2 planar data.
|
|
CreateTextureForPlane(0, mGL, mSurface, &(mTextureHandles[0]));
|
|
for (size_t i = 1; i < mSurface->GetPlaneCount(); ++i) {
|
|
CreateTextureForPlane(i, mGL, mSurface, &(mTextureHandles[i]));
|
|
}
|
|
}
|
|
|
|
const auto uvs = GetUvCoords(GetSize(aChannelIndex));
|
|
return NativeTextureToWrExternalImage(GetGLHandle(aChannelIndex), uvs.first.x,
|
|
uvs.first.y, uvs.second.x,
|
|
uvs.second.y);
|
|
}
|
|
|
|
void RenderMacIOSurfaceTextureHost::Unlock() {}
|
|
|
|
void RenderMacIOSurfaceTextureHost::DeleteTextureHandle() {
|
|
if (mTextureHandles[0] != 0 && mGL && mGL->MakeCurrent()) {
|
|
// Calling glDeleteTextures on 0 isn't an error. So, just make them a single
|
|
// call.
|
|
mGL->fDeleteTextures(3, mTextureHandles);
|
|
for (size_t i = 0; i < 3; ++i) {
|
|
mTextureHandles[i] = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
size_t RenderMacIOSurfaceTextureHost::GetPlaneCount() const {
|
|
size_t planeCount = mSurface->GetPlaneCount();
|
|
return planeCount > 0 ? planeCount : 1;
|
|
}
|
|
|
|
gfx::SurfaceFormat RenderMacIOSurfaceTextureHost::GetFormat() const {
|
|
return mSurface->GetFormat();
|
|
}
|
|
|
|
gfx::ColorDepth RenderMacIOSurfaceTextureHost::GetColorDepth() const {
|
|
return mSurface->GetColorDepth();
|
|
}
|
|
|
|
gfx::YUVRangedColorSpace RenderMacIOSurfaceTextureHost::GetYUVColorSpace()
|
|
const {
|
|
return ToYUVRangedColorSpace(mSurface->GetYUVColorSpace(),
|
|
mSurface->GetColorRange());
|
|
}
|
|
|
|
bool RenderMacIOSurfaceTextureHost::MapPlane(RenderCompositor* aCompositor,
|
|
uint8_t aChannelIndex,
|
|
PlaneInfo& aPlaneInfo) {
|
|
if (!aChannelIndex) {
|
|
if (NS_WARN_IF(!mSurface->Lock())) {
|
|
return false;
|
|
}
|
|
}
|
|
aPlaneInfo.mData = mSurface->GetBaseAddressOfPlane(aChannelIndex);
|
|
aPlaneInfo.mStride = mSurface->GetBytesPerRow(aChannelIndex);
|
|
aPlaneInfo.mSize =
|
|
gfx::IntSize(mSurface->GetDevicePixelWidth(aChannelIndex),
|
|
mSurface->GetDevicePixelHeight(aChannelIndex));
|
|
return true;
|
|
}
|
|
|
|
void RenderMacIOSurfaceTextureHost::UnmapPlanes() { mSurface->Unlock(); }
|
|
|
|
} // namespace wr
|
|
} // namespace mozilla
|