mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-23 04:41:11 +00:00
4685d5aacf
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/D222205
173 lines
6.6 KiB
C++
173 lines
6.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/. */
|
|
|
|
#ifndef MacIOSurface_h__
|
|
#define MacIOSurface_h__
|
|
#ifdef XP_DARWIN
|
|
# include <CoreVideo/CoreVideo.h>
|
|
# include <IOSurface/IOSurfaceRef.h>
|
|
# include <QuartzCore/QuartzCore.h>
|
|
# include <dlfcn.h>
|
|
|
|
# include "mozilla/gfx/Types.h"
|
|
# include "mozilla/Maybe.h"
|
|
# include "CFTypeRefPtr.h"
|
|
|
|
namespace mozilla {
|
|
namespace gl {
|
|
class GLContext;
|
|
}
|
|
} // namespace mozilla
|
|
|
|
# ifdef XP_MACOSX
|
|
struct _CGLContextObject;
|
|
|
|
typedef _CGLContextObject* CGLContextObj;
|
|
# endif
|
|
typedef uint32_t IOSurfaceID;
|
|
|
|
# ifdef XP_MACOSX
|
|
# import <OpenGL/OpenGL.h>
|
|
# else
|
|
# include "GLTypes.h"
|
|
typedef realGLboolean GLboolean;
|
|
# include <OpenGLES/ES2/gl.h>
|
|
# endif
|
|
|
|
# include "2D.h"
|
|
# include "mozilla/RefCounted.h"
|
|
# include "mozilla/RefPtr.h"
|
|
|
|
class MacIOSurface final
|
|
: public mozilla::external::AtomicRefCounted<MacIOSurface> {
|
|
public:
|
|
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(MacIOSurface)
|
|
typedef mozilla::gfx::SourceSurface SourceSurface;
|
|
typedef mozilla::gfx::DrawTarget DrawTarget;
|
|
typedef mozilla::gfx::BackendType BackendType;
|
|
typedef mozilla::gfx::IntSize IntSize;
|
|
typedef mozilla::gfx::ChromaSubsampling ChromaSubsampling;
|
|
typedef mozilla::gfx::YUVColorSpace YUVColorSpace;
|
|
typedef mozilla::gfx::ColorSpace2 ColorSpace2;
|
|
typedef mozilla::gfx::TransferFunction TransferFunction;
|
|
typedef mozilla::gfx::ColorRange ColorRange;
|
|
typedef mozilla::gfx::ColorDepth ColorDepth;
|
|
|
|
// The usage count of the IOSurface is increased by 1 during the lifetime
|
|
// of the MacIOSurface instance.
|
|
// MacIOSurface holds a reference to the corresponding IOSurface.
|
|
|
|
static already_AddRefed<MacIOSurface> CreateIOSurface(int aWidth, int aHeight,
|
|
bool aHasAlpha = true);
|
|
static already_AddRefed<MacIOSurface> CreateBiPlanarSurface(
|
|
const IntSize& aYSize, const IntSize& aCbCrSize,
|
|
ChromaSubsampling aChromaSubsampling, YUVColorSpace aColorSpace,
|
|
TransferFunction aTransferFunction, ColorRange aColorRange,
|
|
ColorDepth aColorDepth);
|
|
static already_AddRefed<MacIOSurface> CreateSinglePlanarSurface(
|
|
const IntSize& aSize, YUVColorSpace aColorSpace,
|
|
TransferFunction aTransferFunction, ColorRange aColorRange);
|
|
static void ReleaseIOSurface(MacIOSurface* aIOSurface);
|
|
static already_AddRefed<MacIOSurface> LookupSurface(
|
|
IOSurfaceID aSurfaceID, bool aHasAlpha = true,
|
|
mozilla::gfx::YUVColorSpace aColorSpace =
|
|
mozilla::gfx::YUVColorSpace::Identity);
|
|
|
|
explicit MacIOSurface(CFTypeRefPtr<IOSurfaceRef> aIOSurfaceRef,
|
|
bool aHasAlpha = true,
|
|
mozilla::gfx::YUVColorSpace aColorSpace =
|
|
mozilla::gfx::YUVColorSpace::Identity);
|
|
|
|
~MacIOSurface();
|
|
IOSurfaceID GetIOSurfaceID() const;
|
|
void* GetBaseAddress() const;
|
|
void* GetBaseAddressOfPlane(size_t planeIndex) const;
|
|
size_t GetPlaneCount() const;
|
|
OSType GetPixelFormat() const;
|
|
// GetWidth() and GetHeight() return values in "display pixels". A
|
|
// "display pixel" is the smallest fully addressable part of a display.
|
|
// But in HiDPI modes each "display pixel" corresponds to more than one
|
|
// device pixel. Use GetDevicePixel**() to get device pixels.
|
|
size_t GetWidth(size_t plane = 0) const;
|
|
size_t GetHeight(size_t plane = 0) const;
|
|
IntSize GetSize(size_t plane = 0) const {
|
|
return IntSize(GetWidth(plane), GetHeight(plane));
|
|
}
|
|
size_t GetDevicePixelWidth(size_t plane = 0) const;
|
|
size_t GetDevicePixelHeight(size_t plane = 0) const;
|
|
size_t GetBytesPerRow(size_t plane = 0) const;
|
|
size_t GetAllocSize() const;
|
|
bool Lock(bool aReadOnly = true);
|
|
void Unlock(bool aReadOnly = true);
|
|
bool IsLocked() const { return mIsLocked; }
|
|
void IncrementUseCount();
|
|
void DecrementUseCount();
|
|
bool HasAlpha() const { return mHasAlpha; }
|
|
mozilla::gfx::SurfaceFormat GetFormat() const;
|
|
mozilla::gfx::SurfaceFormat GetReadFormat() const;
|
|
mozilla::gfx::ColorDepth GetColorDepth() const;
|
|
// This would be better suited on MacIOSurfaceImage type, however due to the
|
|
// current data structure, this is not possible as only the IOSurfaceRef is
|
|
// being used across.
|
|
void SetYUVColorSpace(YUVColorSpace aColorSpace) {
|
|
mColorSpace = aColorSpace;
|
|
}
|
|
YUVColorSpace GetYUVColorSpace() const { return mColorSpace; }
|
|
bool IsFullRange() const {
|
|
OSType format = GetPixelFormat();
|
|
return (format == kCVPixelFormatType_420YpCbCr8BiPlanarFullRange ||
|
|
format == kCVPixelFormatType_420YpCbCr10BiPlanarFullRange ||
|
|
format == kCVPixelFormatType_422YpCbCr10BiPlanarFullRange ||
|
|
format == kCVPixelFormatType_422YpCbCr8FullRange);
|
|
}
|
|
mozilla::gfx::ColorRange GetColorRange() const {
|
|
if (IsFullRange()) return mozilla::gfx::ColorRange::FULL;
|
|
return mozilla::gfx::ColorRange::LIMITED;
|
|
}
|
|
|
|
// Bind this IOSurface to a texture using the most efficient mechanism
|
|
// available on the current platform.
|
|
//
|
|
// Note that on iOS simulator, due to incomplete support for
|
|
// texImageIOSurface, this will only use texImage2D to upload, and cannot be
|
|
// used to read-back the GL texture to an IOSurface.
|
|
bool BindTexImage(mozilla::gl::GLContext* aGL, size_t aPlane,
|
|
mozilla::gfx::SurfaceFormat* aOutReadFormat = nullptr);
|
|
|
|
already_AddRefed<SourceSurface> GetAsSurface();
|
|
|
|
// Creates a DrawTarget that wraps the data in the IOSurface. Rendering to
|
|
// this DrawTarget directly manipulates the contents of the IOSurface.
|
|
// Only call when the surface is already locked for writing!
|
|
// The returned DrawTarget must only be used while the surface is still
|
|
// locked.
|
|
// Also, only call this if you're reasonably sure that the DrawTarget of the
|
|
// selected backend supports the IOSurface's SurfaceFormat.
|
|
already_AddRefed<DrawTarget> GetAsDrawTargetLocked(BackendType aBackendType);
|
|
|
|
static size_t GetMaxWidth();
|
|
static size_t GetMaxHeight();
|
|
static mozilla::Maybe<OSType> ChoosePixelFormat(
|
|
mozilla::gfx::ChromaSubsampling aChromaSubsampling,
|
|
mozilla::gfx::ColorRange aColorRange,
|
|
mozilla::gfx::ColorDepth aColorDepth);
|
|
|
|
CFTypeRefPtr<IOSurfaceRef> GetIOSurfaceRef() { return mIOSurfaceRef; }
|
|
|
|
void SetColorSpace(mozilla::gfx::ColorSpace2) const;
|
|
|
|
ColorSpace2 mColorPrimaries = ColorSpace2::UNKNOWN;
|
|
|
|
private:
|
|
CFTypeRefPtr<IOSurfaceRef> mIOSurfaceRef;
|
|
const bool mHasAlpha;
|
|
YUVColorSpace mColorSpace = YUVColorSpace::Identity;
|
|
bool mIsLocked = false;
|
|
};
|
|
|
|
#endif
|
|
#endif
|