gecko-dev/gfx/2d/MacIOSurface.cpp

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

320 строки
11 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 "MacIOSurface.h"
#include <OpenGL/gl.h>
#include <OpenGL/CGLIOSurface.h>
#include <QuartzCore/QuartzCore.h>
#include "GLConsts.h"
#include "GLContextCGL.h"
#include "mozilla/Assertions.h"
#include "mozilla/RefPtr.h"
using namespace mozilla;
MacIOSurface::MacIOSurface(CFTypeRefPtr<IOSurfaceRef> aIOSurfaceRef,
double aContentsScaleFactor, bool aHasAlpha,
gfx::YUVColorSpace aColorSpace)
: mIOSurfaceRef(std::move(aIOSurfaceRef)),
mContentsScaleFactor(aContentsScaleFactor),
mHasAlpha(aHasAlpha),
mColorSpace(aColorSpace) {
IncrementUseCount();
}
MacIOSurface::~MacIOSurface() {
MOZ_RELEASE_ASSERT(!IsLocked(), "Destroying locked surface");
DecrementUseCount();
}
/* static */
already_AddRefed<MacIOSurface> MacIOSurface::CreateIOSurface(
int aWidth, int aHeight, double aContentsScaleFactor, bool aHasAlpha) {
if (aContentsScaleFactor <= 0) return nullptr;
CFMutableDictionaryRef props = ::CFDictionaryCreateMutable(
kCFAllocatorDefault, 4, &kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
if (!props) return nullptr;
MOZ_ASSERT((size_t)aWidth <= GetMaxWidth());
MOZ_ASSERT((size_t)aHeight <= GetMaxHeight());
int32_t bytesPerElem = 4;
size_t intScaleFactor = ceil(aContentsScaleFactor);
aWidth *= intScaleFactor;
aHeight *= intScaleFactor;
CFNumberRef cfWidth = ::CFNumberCreate(nullptr, kCFNumberSInt32Type, &aWidth);
CFNumberRef cfHeight =
::CFNumberCreate(nullptr, kCFNumberSInt32Type, &aHeight);
CFNumberRef cfBytesPerElem =
::CFNumberCreate(nullptr, kCFNumberSInt32Type, &bytesPerElem);
::CFDictionaryAddValue(props, kIOSurfaceWidth, cfWidth);
::CFRelease(cfWidth);
::CFDictionaryAddValue(props, kIOSurfaceHeight, cfHeight);
::CFRelease(cfHeight);
::CFDictionaryAddValue(props, kIOSurfaceBytesPerElement, cfBytesPerElem);
::CFRelease(cfBytesPerElem);
::CFDictionaryAddValue(props, kIOSurfaceIsGlobal, kCFBooleanTrue);
CFTypeRefPtr<IOSurfaceRef> surfaceRef =
CFTypeRefPtr<IOSurfaceRef>::WrapUnderCreateRule(::IOSurfaceCreate(props));
::CFRelease(props);
if (!surfaceRef) {
return nullptr;
}
Bug 1207245 - part 6 - rename nsRefPtr<T> to RefPtr<T>; r=ehsan; a=Tomcat The bulk of this commit was generated with a script, executed at the top level of a typical source code checkout. The only non-machine-generated part was modifying MFBT's moz.build to reflect the new naming. CLOSED TREE makes big refactorings like this a piece of cake. # The main substitution. find . -name '*.cpp' -o -name '*.cc' -o -name '*.h' -o -name '*.mm' -o -name '*.idl'| \ xargs perl -p -i -e ' s/nsRefPtr\.h/RefPtr\.h/g; # handle includes s/nsRefPtr ?</RefPtr</g; # handle declarations and variables ' # Handle a special friend declaration in gfx/layers/AtomicRefCountedWithFinalize.h. perl -p -i -e 's/::nsRefPtr;/::RefPtr;/' gfx/layers/AtomicRefCountedWithFinalize.h # Handle nsRefPtr.h itself, a couple places that define constructors # from nsRefPtr, and code generators specially. We do this here, rather # than indiscriminantly s/nsRefPtr/RefPtr/, because that would rename # things like nsRefPtrHashtable. perl -p -i -e 's/nsRefPtr/RefPtr/g' \ mfbt/nsRefPtr.h \ xpcom/glue/nsCOMPtr.h \ xpcom/base/OwningNonNull.h \ ipc/ipdl/ipdl/lower.py \ ipc/ipdl/ipdl/builtin.py \ dom/bindings/Codegen.py \ python/lldbutils/lldbutils/utils.py # In our indiscriminate substitution above, we renamed # nsRefPtrGetterAddRefs, the class behind getter_AddRefs. Fix that up. find . -name '*.cpp' -o -name '*.h' -o -name '*.idl' | \ xargs perl -p -i -e 's/nsRefPtrGetterAddRefs/RefPtrGetterAddRefs/g' if [ -d .git ]; then git mv mfbt/nsRefPtr.h mfbt/RefPtr.h else hg mv mfbt/nsRefPtr.h mfbt/RefPtr.h fi --HG-- rename : mfbt/nsRefPtr.h => mfbt/RefPtr.h
2015-10-18 08:24:48 +03:00
RefPtr<MacIOSurface> ioSurface =
new MacIOSurface(std::move(surfaceRef), aContentsScaleFactor, aHasAlpha);
return ioSurface.forget();
}
/* static */
already_AddRefed<MacIOSurface> MacIOSurface::LookupSurface(
IOSurfaceID aIOSurfaceID, double aContentsScaleFactor, bool aHasAlpha,
gfx::YUVColorSpace aColorSpace) {
if (aContentsScaleFactor <= 0) return nullptr;
CFTypeRefPtr<IOSurfaceRef> surfaceRef =
CFTypeRefPtr<IOSurfaceRef>::WrapUnderCreateRule(
::IOSurfaceLookup(aIOSurfaceID));
if (!surfaceRef) return nullptr;
RefPtr<MacIOSurface> ioSurface = new MacIOSurface(
std::move(surfaceRef), aContentsScaleFactor, aHasAlpha, aColorSpace);
return ioSurface.forget();
}
IOSurfaceID MacIOSurface::GetIOSurfaceID() const {
return ::IOSurfaceGetID(mIOSurfaceRef.get());
}
void* MacIOSurface::GetBaseAddress() const {
return ::IOSurfaceGetBaseAddress(mIOSurfaceRef.get());
}
void* MacIOSurface::GetBaseAddressOfPlane(size_t aPlaneIndex) const {
return ::IOSurfaceGetBaseAddressOfPlane(mIOSurfaceRef.get(), aPlaneIndex);
}
size_t MacIOSurface::GetWidth(size_t plane) const {
size_t intScaleFactor = ceil(mContentsScaleFactor);
return GetDevicePixelWidth(plane) / intScaleFactor;
}
size_t MacIOSurface::GetHeight(size_t plane) const {
size_t intScaleFactor = ceil(mContentsScaleFactor);
return GetDevicePixelHeight(plane) / intScaleFactor;
}
size_t MacIOSurface::GetPlaneCount() const {
return ::IOSurfaceGetPlaneCount(mIOSurfaceRef.get());
}
/*static*/
size_t MacIOSurface::GetMaxWidth() {
return ::IOSurfaceGetPropertyMaximum(kIOSurfaceWidth);
}
/*static*/
size_t MacIOSurface::GetMaxHeight() {
return ::IOSurfaceGetPropertyMaximum(kIOSurfaceHeight);
}
size_t MacIOSurface::GetDevicePixelWidth(size_t plane) const {
return ::IOSurfaceGetWidthOfPlane(mIOSurfaceRef.get(), plane);
}
size_t MacIOSurface::GetDevicePixelHeight(size_t plane) const {
return ::IOSurfaceGetHeightOfPlane(mIOSurfaceRef.get(), plane);
}
size_t MacIOSurface::GetBytesPerRow(size_t plane) const {
return ::IOSurfaceGetBytesPerRowOfPlane(mIOSurfaceRef.get(), plane);
}
OSType MacIOSurface::GetPixelFormat() const {
return ::IOSurfaceGetPixelFormat(mIOSurfaceRef.get());
}
void MacIOSurface::IncrementUseCount() {
::IOSurfaceIncrementUseCount(mIOSurfaceRef.get());
}
void MacIOSurface::DecrementUseCount() {
::IOSurfaceDecrementUseCount(mIOSurfaceRef.get());
}
void MacIOSurface::Lock(bool aReadOnly) {
MOZ_RELEASE_ASSERT(!mIsLocked, "double MacIOSurface lock");
::IOSurfaceLock(mIOSurfaceRef.get(), aReadOnly ? kIOSurfaceLockReadOnly : 0,
nullptr);
mIsLocked = true;
}
void MacIOSurface::Unlock(bool aReadOnly) {
MOZ_RELEASE_ASSERT(mIsLocked, "MacIOSurface unlock without being locked");
::IOSurfaceUnlock(mIOSurfaceRef.get(), aReadOnly ? kIOSurfaceLockReadOnly : 0,
nullptr);
mIsLocked = false;
}
using mozilla::gfx::IntSize;
using mozilla::gfx::SourceSurface;
using mozilla::gfx::SurfaceFormat;
Bug 1528881 - Part 4: gfx/2d: Make some global functions static. r=lsalzman And #include "BufferUnrotate.h" in BufferUnrotate.cpp for BufferUnrotate() function prototype. clang's -Wmissing-prototypes option identifies global functions that can be made static (because they're only called from one compilation unit) or removed (if they're never called). gfx/2d/BufferUnrotate.cpp:17:6 [-Wmissing-prototypes] no previous prototype for function 'BufferUnrotate' gfx/2d/DrawTargetCairo.cpp:195:6 [-Wmissing-prototypes] no previous prototype for function 'ReleaseData' gfx/2d/DrawTargetCairo.cpp:201:18 [-Wmissing-prototypes] no previous prototype for function 'CopyToImageSurface' gfx/2d/DrawTargetCairo.cpp:239:18 [-Wmissing-prototypes] no previous prototype for function 'GetAsImageSurface' gfx/2d/DrawTargetCairo.cpp:251:18 [-Wmissing-prototypes] no previous prototype for function 'CreateSubImageForData' gfx/2d/DrawTargetCairo.cpp:272:18 [-Wmissing-prototypes] no previous prototype for function 'ExtractSubImage' gfx/2d/DrawTargetCairo.cpp:308:18 [-Wmissing-prototypes] no previous prototype for function 'GetCairoSurfaceForSourceSurface' gfx/2d/DrawTargetRecording.cpp:26:6 [-Wmissing-prototypes] no previous prototype for function 'RecordingSourceSurfaceUserDataFunc' gfx/2d/DrawTargetRecording.cpp:272:6 [-Wmissing-prototypes] no previous prototype for function 'RecordingFontUserDataDestroyFunc' gfx/2d/DrawTargetWrapAndRecord.cpp:26:6 [-Wmissing-prototypes] no previous prototype for function 'WrapAndRecordSourceSurfaceUserDataFunc' gfx/2d/DrawTargetWrapAndRecord.cpp:358:6 [-Wmissing-prototypes] no previous prototype for function 'WrapAndRecordFontUserDataDestroyFunc' gfx/2d/FilterNodeSoftware.cpp:1816:6 [-Wmissing-prototypes] no previous prototype for function 'IsAllZero' gfx/2d/FilterNodeSoftware.cpp:183:37 [-Wmissing-prototypes] no previous prototype for function 'CloneAligned' gfx/2d/MacIOSurface.cpp:442:6 [-Wmissing-prototypes] no previous prototype for function 'MacIOSurfaceBufferDeallocator' gfx/2d/QuartzSupport.mm:38:6 [-Wmissing-prototypes] no previous prototype for function 'cgdata_release_callback' gfx/2d/ScaledFontMac.cpp:191:10 [-Wmissing-prototypes] no previous prototype for function 'CalcTableChecksum' gfx/2d/ScaledFontMac.cpp:224:5 [-Wmissing-prototypes] no previous prototype for function 'maxPow2LessThan' gfx/2d/unittest/TestCairo.cpp:12:6 [-Wmissing-prototypes] no previous prototype for function 'TryCircle' Differential Revision: https://phabricator.services.mozilla.com/D20263 --HG-- extra : rebase_source : b42bce33ed899caeb89e462d99a5cde29a9bb559 extra : intermediate-source : 7923cc86a6394bcd2fb3b7e38f458a5180d31e11 extra : source : 02388f2454e8842d2c023bf9f9fab222d8130093
2019-02-17 05:08:30 +03:00
static void MacIOSurfaceBufferDeallocator(void* aClosure) {
MOZ_ASSERT(aClosure);
delete[] static_cast<unsigned char*>(aClosure);
}
already_AddRefed<SourceSurface> MacIOSurface::GetAsSurface() {
Lock();
size_t bytesPerRow = GetBytesPerRow();
size_t ioWidth = GetDevicePixelWidth();
size_t ioHeight = GetDevicePixelHeight();
unsigned char* ioData = (unsigned char*)GetBaseAddress();
auto* dataCpy =
new unsigned char[bytesPerRow * ioHeight / sizeof(unsigned char)];
for (size_t i = 0; i < ioHeight; i++) {
memcpy(dataCpy + i * bytesPerRow, ioData + i * bytesPerRow, ioWidth * 4);
}
Unlock();
SurfaceFormat format = HasAlpha() ? mozilla::gfx::SurfaceFormat::B8G8R8A8
: mozilla::gfx::SurfaceFormat::B8G8R8X8;
RefPtr<mozilla::gfx::DataSourceSurface> surf =
mozilla::gfx::Factory::CreateWrappingDataSourceSurface(
dataCpy, bytesPerRow, IntSize(ioWidth, ioHeight), format,
&MacIOSurfaceBufferDeallocator, static_cast<void*>(dataCpy));
return surf.forget();
}
already_AddRefed<mozilla::gfx::DrawTarget> MacIOSurface::GetAsDrawTargetLocked(
mozilla::gfx::BackendType aBackendType) {
MOZ_RELEASE_ASSERT(
IsLocked(),
"Only call GetAsDrawTargetLocked while the surface is locked.");
size_t bytesPerRow = GetBytesPerRow();
size_t ioWidth = GetDevicePixelWidth();
size_t ioHeight = GetDevicePixelHeight();
unsigned char* ioData = (unsigned char*)GetBaseAddress();
SurfaceFormat format = GetFormat();
return mozilla::gfx::Factory::CreateDrawTargetForData(
aBackendType, ioData, IntSize(ioWidth, ioHeight), bytesPerRow, format);
}
SurfaceFormat MacIOSurface::GetFormat() const {
switch (GetPixelFormat()) {
case kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange:
case kCVPixelFormatType_420YpCbCr8BiPlanarFullRange:
return SurfaceFormat::NV12;
case kCVPixelFormatType_422YpCbCr8:
return SurfaceFormat::YUV422;
case kCVPixelFormatType_32BGRA:
return HasAlpha() ? SurfaceFormat::B8G8R8A8 : SurfaceFormat::B8G8R8X8;
default:
return HasAlpha() ? SurfaceFormat::R8G8B8A8 : SurfaceFormat::R8G8B8X8;
}
}
SurfaceFormat MacIOSurface::GetReadFormat() const {
SurfaceFormat format = GetFormat();
if (format == SurfaceFormat::YUV422) {
return SurfaceFormat::R8G8B8X8;
}
return format;
}
CGLError MacIOSurface::CGLTexImageIOSurface2D(CGLContextObj ctx, GLenum target,
GLenum internalFormat,
GLsizei width, GLsizei height,
GLenum format, GLenum type,
GLuint plane) const {
return ::CGLTexImageIOSurface2D(ctx, target, internalFormat, width, height,
format, type, mIOSurfaceRef.get(), plane);
}
CGLError MacIOSurface::CGLTexImageIOSurface2D(
mozilla::gl::GLContext* aGL, CGLContextObj ctx, size_t plane,
mozilla::gfx::SurfaceFormat* aOutReadFormat) {
MOZ_ASSERT(plane >= 0);
bool isCompatibilityProfile = aGL->IsCompatibilityProfile();
OSType pixelFormat = GetPixelFormat();
GLenum internalFormat;
GLenum format;
GLenum type;
if (pixelFormat == kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange ||
pixelFormat == kCVPixelFormatType_420YpCbCr8BiPlanarFullRange) {
MOZ_ASSERT(GetPlaneCount() == 2);
MOZ_ASSERT(plane < 2);
// The LOCAL_GL_LUMINANCE and LOCAL_GL_LUMINANCE_ALPHA are the deprecated
// format. So, use LOCAL_GL_RED and LOCAL_GL_RB if we use core profile.
// https://www.khronos.org/opengl/wiki/Image_Format#Legacy_Image_Formats
if (plane == 0) {
internalFormat = format =
(isCompatibilityProfile) ? (LOCAL_GL_LUMINANCE) : (LOCAL_GL_RED);
} else {
internalFormat = format =
(isCompatibilityProfile) ? (LOCAL_GL_LUMINANCE_ALPHA) : (LOCAL_GL_RG);
}
type = LOCAL_GL_UNSIGNED_BYTE;
if (aOutReadFormat) {
*aOutReadFormat = mozilla::gfx::SurfaceFormat::NV12;
}
} else if (pixelFormat == kCVPixelFormatType_422YpCbCr8) {
MOZ_ASSERT(plane == 0);
// The YCBCR_422_APPLE ext is only available in compatibility profile. So,
// we should use RGB_422_APPLE for core profile. The difference between
// YCBCR_422_APPLE and RGB_422_APPLE is that the YCBCR_422_APPLE converts
// the YCbCr value to RGB with REC 601 conversion. But the RGB_422_APPLE
// doesn't contain color conversion. You should do the color conversion by
// yourself for RGB_422_APPLE.
//
// https://www.khronos.org/registry/OpenGL/extensions/APPLE/APPLE_ycbcr_422.txt
// https://www.khronos.org/registry/OpenGL/extensions/APPLE/APPLE_rgb_422.txt
if (isCompatibilityProfile) {
format = LOCAL_GL_YCBCR_422_APPLE;
if (aOutReadFormat) {
*aOutReadFormat = mozilla::gfx::SurfaceFormat::R8G8B8X8;
}
} else {
format = LOCAL_GL_RGB_422_APPLE;
if (aOutReadFormat) {
*aOutReadFormat = mozilla::gfx::SurfaceFormat::YUV422;
}
}
internalFormat = LOCAL_GL_RGB;
type = LOCAL_GL_UNSIGNED_SHORT_8_8_APPLE;
} else {
MOZ_ASSERT(plane == 0);
internalFormat = HasAlpha() ? LOCAL_GL_RGBA : LOCAL_GL_RGB;
format = LOCAL_GL_BGRA;
type = LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV;
if (aOutReadFormat) {
*aOutReadFormat = HasAlpha() ? mozilla::gfx::SurfaceFormat::R8G8B8A8
: mozilla::gfx::SurfaceFormat::R8G8B8X8;
}
}
return CGLTexImageIOSurface2D(ctx, LOCAL_GL_TEXTURE_RECTANGLE_ARB,
internalFormat, GetDevicePixelWidth(plane),
GetDevicePixelHeight(plane), format, type,
plane);
}